feat(webui): allow details and summary tags

Amolith created

The Markdown sanitizer now preserves <details> and <summary> tags,
enabling collapsible sections in README files and blob views.

Added test coverage to verify these tags are properly preserved through
the sanitization process.

Closes: bug-f881844
Assisted-by: Claude Sonnet 4.5 via Crush

Change summary

pkg/web/sanitizer_test.go | 12 ++++++++++++
pkg/web/webui_helpers.go  |  2 +-
2 files changed, 13 insertions(+), 1 deletion(-)

Detailed changes

pkg/web/sanitizer_test.go 🔗

@@ -148,6 +148,18 @@ func TestSanitizerAllowedTags(t *testing.T) {
 	html, err = renderMarkdown(md, ctx)
 	is.NoErr(err)
 	is.True(strings.Contains(string(html), "<blockquote"))
+
+	// Test allowed details/summary (collapsible sections)
+	md = []byte(`<details>
+<summary>Click to expand</summary>
+
+Hidden content here
+
+</details>`)
+	html, err = renderMarkdown(md, ctx)
+	is.NoErr(err)
+	is.True(strings.Contains(string(html), "<details"))
+	is.True(strings.Contains(string(html), "<summary"))
 }
 
 func TestSanitizerHTTPSOnly(t *testing.T) {

pkg/web/webui_helpers.go 🔗

@@ -36,7 +36,7 @@ func getSanitizerPolicy() *bluemonday.Policy {
 			"ul", "ol", "li", "pre", "code", "blockquote",
 			"strong", "em", "del", "br", "hr",
 			"table", "thead", "tbody", "tr", "th", "td",
-			"center", "a", "img")
+			"center", "a", "img", "details", "summary")
 
 		// Allow id attributes on headings (generated by AutoHeadingID for anchor links)
 		policy.AllowAttrs("id").OnElements("h1", "h2", "h3", "h4", "h5", "h6")