aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-04-03 16:02:30 +0800
committerRunxi Yu <me@runxiyu.org>2025-04-03 16:02:55 +0800
commit9031a7d5d50f303d5a7016cab7a40e7782ca7cdb (patch)
treefbcf1000910b9fff87fb233c7b5f08bce20c3d5e
parentresources: Embed git2d (diff)
downloadforge-9031a7d5d50f303d5a7016cab7a40e7782ca7cdb.tar.gz
forge-9031a7d5d50f303d5a7016cab7a40e7782ca7cdb.tar.zst
forge-9031a7d5d50f303d5a7016cab7a40e7782ca7cdb.zip
HTTP: Make README rendering more composable
-rw-r--r--readme_to_html.go67
1 files changed, 31 insertions, 36 deletions
diff --git a/readme_to_html.go b/readme_to_html.go
index 6d7bbbc..e0212e9 100644
--- a/readme_to_html.go
+++ b/readme_to_html.go
@@ -18,51 +18,46 @@ import (
var markdownConverter = goldmark.New(goldmark.WithExtensions(extension.GFM))
+// escapeHTML just escapes a string and wraps it in [template.HTML].
+func escapeHTML(s string) template.HTML {
+ return template.HTML(html.EscapeString(s)) //#nosec G203
+}
+
// renderReadmeAtTree looks for README files in the supplied Git tree and
// returns its filename and rendered (and sanitized) HTML.
-func renderReadmeAtTree(tree *object.Tree) (readmeFilename string, readmeRenderedSafeHTML template.HTML) {
- var readmeRenderedUnsafe bytes.Buffer
- var readmeFile *object.File
- var readmeFileContents string
- var err error
-
- if readmeFile, err = tree.File("README"); err == nil {
- if readmeFileContents, err = readmeFile.Contents(); err != nil {
- return "Error fetching README", escapeHTML("Unable to fetch contents of README: " + err.Error())
- }
-
- return "README", template.HTML("<pre>" + html.EscapeString(readmeFileContents) + "</pre>") //#nosec G203
- }
-
- if readmeFile, err = tree.File("README.md"); err == nil {
- if readmeFileContents, err = readmeFile.Contents(); err != nil {
- return "Error fetching README", escapeHTML("Unable to fetch contents of README: " + err.Error())
+func renderReadmeAtTree(tree *object.Tree) (string, template.HTML) {
+ for _, name := range []string{"README", "README.md", "README.org"} {
+ file, err := tree.File(name)
+ if err != nil {
+ continue
}
-
- if err = markdownConverter.Convert(stringToBytes(readmeFileContents), &readmeRenderedUnsafe); err != nil {
- return "Error fetching README", escapeHTML("Unable to render README: " + err.Error())
+ contents, err := file.Contents()
+ if err != nil {
+ return "Error fetching README", escapeHTML("Unable to fetch contents of " + name + ": " + err.Error())
}
-
- return "README.md", template.HTML(bluemonday.UGCPolicy().SanitizeBytes(readmeRenderedUnsafe.Bytes())) //#nosec G203
+ return renderReadme([]byte(contents), name)
}
+ return "", ""
+}
- if readmeFile, err = tree.File("README.org"); err == nil {
- if readmeFileContents, err = readmeFile.Contents(); err != nil {
- return "Error fetching README", escapeHTML("Unable to fetch contents of README: " + err.Error())
+// renderReadme renders and sanitizes README content from a byte slice and filename.
+func renderReadme(data []byte, filename string) (string, template.HTML) {
+ switch strings.ToLower(filename) {
+ case "readme":
+ return "README", template.HTML("<pre>" + html.EscapeString(string(data)) + "</pre>") //#nosec G203
+ case "readme.md":
+ var buf bytes.Buffer
+ if err := markdownConverter.Convert(data, &buf); err != nil {
+ return "Error fetching README", escapeHTML("Unable to render README: " + err.Error())
}
-
- orgHTML, err := org.New().Parse(strings.NewReader(readmeFileContents), readmeFilename).Write(org.NewHTMLWriter())
+ return "README.md", template.HTML(bluemonday.UGCPolicy().SanitizeBytes(buf.Bytes())) //#nosec G203
+ case "readme.org":
+ htmlStr, err := org.New().Parse(strings.NewReader(string(data)), filename).Write(org.NewHTMLWriter())
if err != nil {
return "Error fetching README", escapeHTML("Unable to render README: " + err.Error())
}
-
- return "README.org", template.HTML(bluemonday.UGCPolicy().Sanitize(orgHTML)) //#nosec G203
+ return "README.org", template.HTML(bluemonday.UGCPolicy().Sanitize(htmlStr)) //#nosec G203
+ default:
+ return filename, template.HTML("<pre>" + html.EscapeString(string(data)) + "</pre>") //#nosec G203
}
-
- return "", ""
-}
-
-// escapeHTML just escapes a string and wraps it in [template.HTML].
-func escapeHTML(s string) template.HTML {
- return template.HTML(html.EscapeString(s)) //#nosec G203
}