+3
-1
appview/pages/funcmap.go
+3
-1
appview/pages/funcmap.go
···
145
},
146
"markdown": func(text string) template.HTML {
147
rctx := &markup.RenderContext{RendererType: markup.RendererTypeDefault}
148
-
return template.HTML(bluemonday.UGCPolicy().Sanitize(rctx.RenderMarkdown(text)))
149
},
150
"isNil": func(t any) bool {
151
// returns false for other "zero" values
···
145
},
146
"markdown": func(text string) template.HTML {
147
rctx := &markup.RenderContext{RendererType: markup.RendererTypeDefault}
148
+
return template.HTML(
149
+
rctx.RenderMarkdown(text, bluemonday.UGCPolicy().Sanitize),
150
+
)
151
},
152
"isNil": func(t any) bool {
153
// returns false for other "zero" values
+10
-3
appview/pages/markup/markdown.go
+10
-3
appview/pages/markup/markdown.go
···
44
RendererType RendererType
45
}
46
47
-
func (rctx *RenderContext) RenderMarkdown(source string) string {
48
md := goldmark.New(
49
goldmark.WithExtensions(extension.GFM,
50
highlighting.NewHighlighting(
···
74
return source
75
}
76
77
var processed strings.Builder
78
-
if err := postProcess(rctx, strings.NewReader(buf.String()), &processed); err != nil {
79
return source
80
}
81
82
return processed.String()
83
}
84
85
-
func postProcess(ctx *RenderContext, input io.Reader, output io.Writer) error {
86
node, err := htmlparse.Parse(io.MultiReader(
87
strings.NewReader("<html><body>"),
88
input,
···
127
return nil
128
}
129
130
func visitNode(ctx *RenderContext, node *htmlparse.Node) {
131
switch node.Type {
132
case htmlparse.ElementNode:
···
44
RendererType RendererType
45
}
46
47
+
// RenderMarkdown renders the given markdown source into sanitized HTML. sanitizer is used to sanitize the HTML output.
48
+
func (rctx *RenderContext) RenderMarkdown(source string, sanitizer func(string) string) string {
49
md := goldmark.New(
50
goldmark.WithExtensions(extension.GFM,
51
highlighting.NewHighlighting(
···
75
return source
76
}
77
78
+
sanitizedHtml := sanitizer(buf.String())
79
+
80
var processed strings.Builder
81
+
if err := postProcessSanitizedHtml(rctx, strings.NewReader(sanitizedHtml), &processed); err != nil {
82
return source
83
}
84
85
return processed.String()
86
}
87
88
+
// postProcessSanitizedHtml processes the HTML output from the markdown renderer.
89
+
// WARNING: Do not insert raw HTML from user-controlled input. Sanitization already happened beforehand at this point.
90
+
func postProcessSanitizedHtml(ctx *RenderContext, input io.Reader, output io.Writer) error {
91
node, err := htmlparse.Parse(io.MultiReader(
92
strings.NewReader("<html><body>"),
93
input,
···
132
return nil
133
}
134
135
+
// visitNode is called on every node of a SANITIZED html document.
136
+
// WARNING: Do not insert raw HTML from user-controlled input. Sanitization already happened beforehand at this point.
137
func visitNode(ctx *RenderContext, node *htmlparse.Node) {
138
switch node.Type {
139
case htmlparse.ElementNode:
+4
-4
appview/pages/pages.go
+4
-4
appview/pages/pages.go
···
432
ext := filepath.Ext(params.ReadmeFileName)
433
switch ext {
434
case ".md", ".markdown", ".mdown", ".mkdn", ".mkd":
435
-
htmlString = p.rctx.RenderMarkdown(params.Readme)
436
params.Raw = false
437
-
params.HTMLReadme = template.HTML(p.rctx.Sanitize(htmlString))
438
default:
439
htmlString = string(params.Readme)
440
params.Raw = true
···
564
case markup.FormatMarkdown:
565
p.rctx.RepoInfo = params.RepoInfo
566
p.rctx.RendererType = markup.RendererTypeRepoMarkdown
567
-
htmlString := p.rctx.RenderMarkdown(params.Contents)
568
-
params.RenderedContents = template.HTML(p.rctx.Sanitize(htmlString))
569
}
570
}
571
···
432
ext := filepath.Ext(params.ReadmeFileName)
433
switch ext {
434
case ".md", ".markdown", ".mdown", ".mkdn", ".mkd":
435
+
htmlString = p.rctx.RenderMarkdown(params.Readme, p.rctx.Sanitize)
436
params.Raw = false
437
+
params.HTMLReadme = template.HTML(htmlString)
438
default:
439
htmlString = string(params.Readme)
440
params.Raw = true
···
564
case markup.FormatMarkdown:
565
p.rctx.RepoInfo = params.RepoInfo
566
p.rctx.RendererType = markup.RendererTypeRepoMarkdown
567
+
htmlString := p.rctx.RenderMarkdown(params.Contents, p.rctx.Sanitize)
568
+
params.RenderedContents = template.HTML(htmlString)
569
}
570
}
571