diff --git a/internal/views/templates/result_item.html b/internal/views/templates/result_item.html
index 33f5e8c..3b0b52f 100644
--- a/internal/views/templates/result_item.html
+++ b/internal/views/templates/result_item.html
@@ -4,7 +4,7 @@
{{.SafeTitle}}
diff --git a/internal/views/views.go b/internal/views/views.go
index 9715ff7..e7ce360 100644
--- a/internal/views/views.go
+++ b/internal/views/views.go
@@ -23,6 +23,7 @@ import (
"html/template"
"io/fs"
"net/http"
+ "net/url"
"strconv"
"strings"
@@ -71,6 +72,8 @@ 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
+ // Domain is the hostname extracted from the result URL, used for favicon proxying.
+ Domain string
// SafeTitle and SafeContent are HTML-unescaped versions for rendering.
// The API returns HTML entities which Go templates escape by default.
SafeTitle template.HTML
@@ -205,14 +208,19 @@ func FromResponse(resp contracts.SearchResponse, query string, pageno int, activ
tmplName = "video_item"
}
// Sanitize URLs to prevent javascript:/data: scheme injection.
+ var domain string
if r.URL != nil {
safe := util.SanitizeResultURL(*r.URL)
r.URL = &safe
+ if u, err := url.Parse(safe); err == nil {
+ domain = u.Hostname()
+ }
}
r.Thumbnail = util.SanitizeResultURL(r.Thumbnail)
pd.Results[i] = ResultView{
MainResult: r,
TemplateName: tmplName,
+ Domain: domain,
SafeTitle: template.HTML(html.UnescapeString(r.Title)),
SafeContent: template.HTML(html.UnescapeString(r.Content)),
}