mirror of
https://github.com/aljazceru/njump.git
synced 2026-01-31 11:44:34 +01:00
Use a specific xss sanitizer for long form content
This commit is contained in:
9
go.mod
9
go.mod
@@ -7,12 +7,19 @@ require (
|
||||
github.com/die-net/lrucache v0.0.0-20220628165024-20a71bc65bf1
|
||||
github.com/lukevers/freetype-go v0.0.0-20150513150840-77e276735410
|
||||
github.com/mailru/easyjson v0.7.7
|
||||
github.com/microcosm-cc/bluemonday v1.0.24
|
||||
github.com/nbd-wtf/go-nostr v0.18.7
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/rs/zerolog v1.29.1
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/nbd-wtf/go-nostr v0.18.7 => github.com/nbd-wtf/go-nostr v0.18.8-0.20230531153548-b7ec430166bb
|
||||
|
||||
require (
|
||||
@@ -33,5 +40,5 @@ require (
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
)
|
||||
|
||||
12
go.sum
12
go.sum
@@ -1,6 +1,8 @@
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/apatters/go-wordwrap v1.0.0 h1:G6ni4Pt7/I4ED+A5ZvsK8e9XwETD04veDKxEL2QN830=
|
||||
github.com/apatters/go-wordwrap v1.0.0/go.mod h1:3sM7HcArQ+utXnjDQ4d1xjrd8b/wbKuDr/RmbiHgjwI=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
|
||||
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||
@@ -58,6 +60,8 @@ github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a/go.mod h1:JDGc
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
@@ -75,6 +79,8 @@ github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZb
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/microcosm-cc/bluemonday v1.0.24 h1:NGQoPtwGVcbGkKfvyYk1yRqknzBuoMiUrO6R7uFTPlw=
|
||||
github.com/microcosm-cc/bluemonday v1.0.24/go.mod h1:ArQySAMps0790cHSkdPEJ7bGkF2VePWH773hsJNSHf8=
|
||||
github.com/nbd-wtf/go-nostr v0.18.8-0.20230531153548-b7ec430166bb h1:28eaYF27FKWf5aO4plC0z0b4ht9FntbKC9IkAaQwxAs=
|
||||
github.com/nbd-wtf/go-nostr v0.18.8-0.20230531153548-b7ec430166bb/go.mod h1:F9y6+M8askJCjilLgMC3rD0moA6UtG1MCnyClNYXeys=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
@@ -121,8 +127,9 @@ golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -135,8 +142,9 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
||||
@@ -252,7 +252,8 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
funcMap := template.FuncMap{
|
||||
"basicFormatting": basicFormatting,
|
||||
"mdToHTML": mdToHTML,
|
||||
"sanitizeString": html.EscapeString,
|
||||
"escapeString": html.EscapeString,
|
||||
"sanitizeXSS": sanitizeXSS,
|
||||
}
|
||||
|
||||
tmpl := template.Must(
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<div class="field {{if not ( or (eq .type "other") (eq .type "address"))}}advanced{{end}}">
|
||||
<div class="label">Published at</div>
|
||||
{{.createdAt | sanitizeString}}
|
||||
{{.createdAt | escapeString}}
|
||||
</div>
|
||||
|
||||
<div class="field {{if not ( or (eq .type "other") (eq .type "address"))}}advanced{{end}}">
|
||||
<div class="label">Kind type</div>
|
||||
{{.kindID}}
|
||||
{{ if not (eq .kindNIP "")}}
|
||||
- <a href="https://github.com/nostr-protocol/nips/blob/master/{{.kindNIP | sanitizeString}}.md">{{.kindDescription | sanitizeString}}</a>
|
||||
- <a href="https://github.com/nostr-protocol/nips/blob/master/{{.kindNIP | escapeString}}.md">{{.kindDescription | escapeString}}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="field {{if not ( or (eq .type "other") (eq .type "address"))}}advanced{{end}}">
|
||||
<div class="label">Nevent</div>
|
||||
<div>{{.nevent | sanitizeString}}</div>
|
||||
<div>{{.nevent | escapeString}}</div>
|
||||
</div>
|
||||
|
||||
<div class="field {{if not ( or (eq .type "other") (eq .type "address"))}}advanced{{end}} boxed">
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<head>
|
||||
{{if eq .type "profile"}}
|
||||
<title>Nostr Public Key {{.npub}}</title>
|
||||
<meta property="og:site_name" content="{{.npub | sanitizeString}}" />
|
||||
<meta property="og:title" content="{{.title | sanitizeString}}" />
|
||||
<link rel="canonical" href="https://nostr.com/{{.npub | sanitizeString }}" />
|
||||
<meta property="og:site_name" content="{{.npub | escapeString}}" />
|
||||
<meta property="og:title" content="{{.title | escapeString}}" />
|
||||
<link rel="canonical" href="https://nostr.com/{{.npub | escapeString }}" />
|
||||
{{ if .metadata.Picture }}
|
||||
<meta property="og:image" content="{{.metadata.Picture | sanitizeString}}" />
|
||||
<meta property="og:image" content="{{.metadata.Picture | escapeString}}" />
|
||||
<meta
|
||||
property="twitter:image"
|
||||
content="{{.proxy}}{{.metadata.Picture | sanitizeString}}"
|
||||
content="{{.proxy}}{{.metadata.Picture | escapeString}}"
|
||||
/>
|
||||
{{end}} {{ if .metadata.About }}
|
||||
<meta
|
||||
property="og:description"
|
||||
content="{{.metadata.About | sanitizeString}}"
|
||||
content="{{.metadata.About | escapeString}}"
|
||||
/>
|
||||
{{end}}
|
||||
<meta property="twitter:card" content="summary" />
|
||||
@@ -21,45 +21,45 @@
|
||||
<!----------->
|
||||
{{ if eq .type "note" }}
|
||||
<title>Nostr Event {{.nevent}}</title>
|
||||
<meta property="og:site_name" content="{{.authorLong | sanitizeString}}" />
|
||||
<meta property="og:title" content="{{.title | sanitizeString}}" />
|
||||
<meta name="twitter:title" content="{{.twitterTitle | sanitizeString}}" />
|
||||
<link rel="canonical" href="https://nostr.com/{{.note | sanitizeString }}" />
|
||||
<meta property="og:site_name" content="{{.authorLong | escapeString}}" />
|
||||
<meta property="og:title" content="{{.title | escapeString}}" />
|
||||
<meta name="twitter:title" content="{{.twitterTitle | escapeString}}" />
|
||||
<link rel="canonical" href="https://nostr.com/{{.note | escapeString }}" />
|
||||
<!---->
|
||||
{{ if .textImageURL }}
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@nostrprotocol" />
|
||||
<meta property="og:image" content="{{.textImageURL | sanitizeString}}" />
|
||||
<meta name="twitter:image" content="{{.textImageURL | sanitizeString}}" />
|
||||
<meta property="og:image" content="{{.textImageURL | escapeString}}" />
|
||||
<meta name="twitter:image" content="{{.textImageURL | escapeString}}" />
|
||||
{{ else }}
|
||||
<!---->
|
||||
<meta property="twitter:card" content="summary" />
|
||||
{{ if .image }}
|
||||
<meta property="og:image" content="{{.image | sanitizeString}}" />
|
||||
<meta name="twitter:image" content="{{.proxy}}{{.image | sanitizeString}}" />
|
||||
<meta property="og:image" content="{{.image | escapeString}}" />
|
||||
<meta name="twitter:image" content="{{.proxy}}{{.image | escapeString}}" />
|
||||
{{end}} {{ if .video }}
|
||||
<meta property="og:video" content="{{.video | sanitizeString}}" />
|
||||
<meta property="og:video:secure_url" content="{{.video | sanitizeString}}" />
|
||||
<meta property="og:video" content="{{.video | escapeString}}" />
|
||||
<meta property="og:video:secure_url" content="{{.video | escapeString}}" />
|
||||
<meta
|
||||
property="og:video:type"
|
||||
content="video/{{.videoType | sanitizeString}}"
|
||||
content="video/{{.videoType | escapeString}}"
|
||||
/>
|
||||
{{end}}
|
||||
<!---->
|
||||
{{end}}
|
||||
<meta property="og:description" content="{{.description | sanitizeString}}" />
|
||||
<meta property="og:description" content="{{.description | escapeString}}" />
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="{{.description | sanitizeString}}"
|
||||
content="{{.description | escapeString}}"
|
||||
/>
|
||||
{{end}}
|
||||
<!----------->
|
||||
{{ if eq .type "address" }}
|
||||
<title>Nostr Address {{.naddr | sanitizeString }}</title>
|
||||
<title>Nostr Address {{.naddr | escapeString }}</title>
|
||||
{{end}}
|
||||
<!----------->
|
||||
{{ if eq .type "other" }}
|
||||
<title>Nostr Event {{.kindID }} - {{.kindDescription | sanitizeString }}</title>
|
||||
<title>Nostr Event {{.kindID }} - {{.kindDescription | escapeString }}</title>
|
||||
{{end}}
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
@@ -10,26 +10,26 @@
|
||||
<div class="container">
|
||||
<div class="column column_content">
|
||||
<div class="profile_intro">
|
||||
<a href="/{{.npub | sanitizeString}}">
|
||||
<a href="/{{.npub | escapeString}}">
|
||||
<div class="pic-wrapper">
|
||||
<img class="pic" src="{{.metadata.Picture | sanitizeString}}" />
|
||||
<img class="pic" src="{{.metadata.Picture | escapeString}}" />
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<div class="name">
|
||||
{{.metadata.Name | sanitizeString}}
|
||||
{{.metadata.Name | escapeString}}
|
||||
<span class="display"
|
||||
>{{.metadata.DisplayName | sanitizeString}}</span
|
||||
>{{.metadata.DisplayName | escapeString}}</span
|
||||
>
|
||||
</div>
|
||||
<div class="npub">{{.npubShort | sanitizeString}}</div>
|
||||
<div class="npub">{{.npubShort | escapeString}}</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="published_at">{{.createdAt | sanitizeString}}</div>
|
||||
<div class="published_at">{{.createdAt | escapeString}}</div>
|
||||
|
||||
{{ if .parentNevent }}
|
||||
<div class="reply_of">
|
||||
In reply to {{ printf "%s%s" "nostr:" .parentNevent | sanitizeString | basicFormatting }}
|
||||
In reply to {{ printf "%s%s" "nostr:" .parentNevent | escapeString | basicFormatting }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
@@ -37,12 +37,12 @@
|
||||
|
||||
<div class="field content">
|
||||
{{ if (not (eq .subject ""))}}
|
||||
<h1>{{.subject | sanitizeString}}</h1>
|
||||
<h1>{{.subject | escapeString}}</h1>
|
||||
{{ end }}
|
||||
{{ if (or (eq .kindID 30023) (eq .kindID 30024))}}
|
||||
{{.content | sanitizeString | mdToHTML }}
|
||||
{{.content | mdToHTML | sanitizeXSS }}
|
||||
{{ else }}
|
||||
{{.content | sanitizeString | basicFormatting }}
|
||||
{{.content | escapeString | basicFormatting }}
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<div class="field">
|
||||
<div class="label">Author Public key</div>
|
||||
{{.npub | sanitizeString}}
|
||||
{{.npub | escapeString}}
|
||||
</div>
|
||||
|
||||
<div class="field advanced-switch-wrapper">
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="profile_intro">
|
||||
<div class="info-wrapper">
|
||||
<div class="kind_desc">
|
||||
{{.kindDescription | sanitizeString}}
|
||||
{{.kindDescription | escapeString}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<div class="field">
|
||||
<div class="label">Author Public key</div>
|
||||
<a href="/{{.npub | sanitizeString}}">{{.npub | sanitizeString}}</a>
|
||||
<a href="/{{.npub | escapeString}}">{{.npub | escapeString}}</a>
|
||||
</div>
|
||||
|
||||
{{template "details.html" .}}
|
||||
|
||||
@@ -10,53 +10,53 @@
|
||||
<div class="container">
|
||||
<div class="column columnA">
|
||||
<div class="info-wrapper">
|
||||
{{.metadata.Name | sanitizeString}}
|
||||
{{.metadata.Name | escapeString}}
|
||||
<span class="display"
|
||||
>{{.metadata.DisplayName | sanitizeString}}</span
|
||||
>{{.metadata.DisplayName | escapeString}}</span
|
||||
>
|
||||
</div>
|
||||
<div class="pic-wrapper">
|
||||
<img class="pic" src="{{.metadata.Picture | sanitizeString}}" />
|
||||
<img class="pic" src="{{.metadata.Picture | escapeString}}" />
|
||||
</div>
|
||||
<div class="last_update">
|
||||
Last update:<br />
|
||||
{{.createdAt | sanitizeString}}
|
||||
{{.createdAt | escapeString}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column column_content">
|
||||
<div class="field info-wrapper">
|
||||
<div class="name">
|
||||
{{.metadata.Name | sanitizeString}}
|
||||
{{.metadata.Name | escapeString}}
|
||||
<span class="display"
|
||||
>{{.metadata.DisplayName | sanitizeString}}</span
|
||||
>{{.metadata.DisplayName | escapeString}}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field separator long"></div>
|
||||
<div class="field">
|
||||
<a href="{{.metadata.Website | sanitizeString}}"
|
||||
>{{.metadata.Website | sanitizeString}}</a
|
||||
<a href="{{.metadata.Website | escapeString}}"
|
||||
>{{.metadata.Website | escapeString}}</a
|
||||
>
|
||||
</div>
|
||||
<div class="field about">{{.metadata.About | sanitizeString | basicFormatting}}</div>
|
||||
<div class="field about">{{.metadata.About | escapeString | basicFormatting}}</div>
|
||||
<div class="field separator"></div>
|
||||
<div class="field">
|
||||
<div class="label">Public key</div>
|
||||
{{.npub | sanitizeString}}
|
||||
{{.npub | escapeString}}
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">NIP-05</div>
|
||||
{{.metadata.NIP05 | sanitizeString}}
|
||||
{{.metadata.NIP05 | escapeString}}
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">LN Address</div>
|
||||
{{.metadata.LUD16 | sanitizeString}}
|
||||
{{.metadata.LUD16 | escapeString}}
|
||||
</div>
|
||||
|
||||
<div class="field last_update">
|
||||
Last update:<br />
|
||||
{{.createdAt | sanitizeString}}
|
||||
{{.createdAt | escapeString}}
|
||||
</div>
|
||||
|
||||
<div class="field separator"></div>
|
||||
|
||||
8
utils.go
8
utils.go
@@ -10,6 +10,8 @@ import (
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/gomarkdown/markdown/html"
|
||||
"github.com/gomarkdown/markdown/parser"
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip10"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
@@ -271,3 +273,9 @@ func mdToHTML(md string) string {
|
||||
|
||||
return string(markdown.Render(doc, renderer))
|
||||
}
|
||||
|
||||
func sanitizeXSS(html string) string {
|
||||
p := bluemonday.UGCPolicy()
|
||||
p.AllowStyling()
|
||||
return p.Sanitize(html)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user