fix: add Thumbnail field and video result template
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 23s

MainResult: add Thumbnail field (used by YouTube, images, etc.)
video_item.html: new partial for video results with thumbnail display
views.go: add templateForResult func + video_item.html to template parse
results_inner.html: dispatch to video_item when Template="videos"
kafka.css: add .video-result flex layout with thumbnail styling
This commit is contained in:
Franz Kafka 2026-03-22 02:06:41 +00:00
parent a97fb4daf9
commit 074123e188
5 changed files with 79 additions and 23 deletions

View file

@ -19,6 +19,7 @@ type MainResult struct {
Content string `json:"content"` Content string `json:"content"`
URL *string `json:"url"` URL *string `json:"url"`
Pubdate *string `json:"pubdate"` Pubdate *string `json:"pubdate"`
Thumbnail string `json:"thumbnail"`
Engine string `json:"engine"` Engine string `json:"engine"`
Score float64 `json:"score"` Score float64 `json:"score"`
@ -54,6 +55,7 @@ func (mr *MainResult) UnmarshalJSON(data []byte) error {
mr.Title = stringOrEmpty(m["title"]) mr.Title = stringOrEmpty(m["title"])
mr.Content = stringOrEmpty(m["content"]) mr.Content = stringOrEmpty(m["content"])
mr.Engine = stringOrEmpty(m["engine"]) mr.Engine = stringOrEmpty(m["engine"])
mr.Thumbnail = stringOrEmpty(m["thumbnail"])
mr.Category = stringOrEmpty(m["category"]) mr.Category = stringOrEmpty(m["category"])
mr.Priority = stringOrEmpty(m["priority"]) mr.Priority = stringOrEmpty(m["priority"])
@ -98,6 +100,7 @@ func (mr MainResult) MarshalJSON() ([]byte, error) {
"content": mr.Content, "content": mr.Content,
"url": mr.URL, "url": mr.URL,
"pubdate": mr.Pubdate, "pubdate": mr.Pubdate,
"thumbnail": mr.Thumbnail,
"engine": mr.Engine, "engine": mr.Engine,
"score": mr.Score, "score": mr.Score,
"category": mr.Category, "category": mr.Category,

View file

@ -805,3 +805,26 @@ html[data-theme="light"] {
opacity: 1; opacity: 1;
} }
} }
/* Video result cards */
.video-result {
display: flex;
gap: 1rem;
align-items: flex-start;
}
.video-result .result_thumbnail {
flex-shrink: 0;
width: 180px;
}
.video-result .result_thumbnail img {
width: 100%;
height: auto;
border-radius: var(--radius);
}
.video-result .result_content_wrapper {
flex: 1;
min-width: 0;
}

View file

@ -52,7 +52,7 @@
<div id="urls" role="main"> <div id="urls" role="main">
{{if .Results}} {{if .Results}}
{{range .Results}} {{range .Results}}
{{template "result_item" .}} {{template (templateForResult .Template) .}}
{{end}} {{end}}
{{else if not .Answers}} {{else if not .Answers}}
<div class="no_results"> <div class="no_results">

View file

@ -0,0 +1,22 @@
{{define "video_item"}}
<article class="result video-result">
{{if .Thumbnail}}
<div class="result_thumbnail">
<a href="{{.URL}}" target="_blank" rel="noopener noreferrer">
<img src="{{.Thumbnail}}" alt="{{.Title}}" loading="lazy">
</a>
</div>
{{end}}
<div class="result_content_wrapper">
<h3 class="result_header">
<a href="{{.URL}}" target="_blank" rel="noopener noreferrer">{{.Title}}</a>
</h3>
{{if .Content}}
<p class="result_content">{{.Content}}</p>
{{end}}
{{if .Engine}}
<div class="result_engine"><span class="engine">{{.Engine}}</span></div>
{{end}}
</div>
</article>
{{end}}

View file

@ -63,16 +63,24 @@ func init() {
funcMap := template.FuncMap{ funcMap := template.FuncMap{
"urlquery": template.URLQueryEscaper, "urlquery": template.URLQueryEscaper,
// templateForResult returns the template name to use for a result.
// Defaults to "result_item"; use "video_item" for video results.
"templateForResult": func(tmpl string) string {
if tmpl == "videos" {
return "video_item"
}
return "result_item"
},
} }
tmplFull = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS, tmplFull = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS,
"base.html", "results.html", "results_inner.html", "result_item.html", "base.html", "results.html", "results_inner.html", "result_item.html", "video_item.html",
)) ))
tmplIndex = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS, tmplIndex = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS,
"base.html", "index.html", "base.html", "index.html",
)) ))
tmplFragment = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS, tmplFragment = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS,
"results_inner.html", "result_item.html", "results_inner.html", "result_item.html", "video_item.html",
)) ))
} }