diff --git a/internal/views/templates/result_item.html b/internal/views/templates/result_item.html index cf1c33b..cc548e2 100644 --- a/internal/views/templates/result_item.html +++ b/internal/views/templates/result_item.html @@ -1,7 +1,7 @@ {{define "result_item"}}
- {{.Title}} + {{.SafeTitle}}
@@ -9,7 +9,7 @@ {{.Engine}}
{{if .Content}} -

{{.Content}}

+

{{.SafeContent}}

{{end}}
{{end}} diff --git a/internal/views/views.go b/internal/views/views.go index 4162a03..9bd0845 100644 --- a/internal/views/views.go +++ b/internal/views/views.go @@ -19,6 +19,7 @@ package views import ( "embed" "encoding/xml" + "html" "html/template" "io/fs" "net/http" @@ -70,6 +71,10 @@ type ResultView struct { // TemplateName is the actual template to dispatch to, computed from Template. // "videos" maps to "video_item", everything else maps to "result_item". TemplateName string + // SafeTitle and SafeContent are HTML-unescaped versions for rendering. + // The API returns HTML entities which Go templates escape by default. + SafeTitle template.HTML + SafeContent template.HTML } // PageNumber represents a numbered pagination button. @@ -205,7 +210,12 @@ func FromResponse(resp contracts.SearchResponse, query string, pageno int, activ r.URL = &safe } r.Thumbnail = util.SanitizeResultURL(r.Thumbnail) - pd.Results[i] = ResultView{MainResult: r, TemplateName: tmplName} + pd.Results[i] = ResultView{ + MainResult: r, + TemplateName: tmplName, + SafeTitle: template.HTML(html.UnescapeString(r.Title)), + SafeContent: template.HTML(html.UnescapeString(r.Content)), + } } // Convert answers (they're map[string]any — extract string values).