feat: add image search with Bing, DuckDuckGo, and Qwant engines
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 25s

Three new image search engines:
- bing_images: Bing Images via RSS endpoint
- ddg_images: DuckDuckGo Images via VQD API
- qwant_images: Qwant Images via v3 search API

Frontend:
- Image grid layout with responsive columns
- image_item template with thumbnail, title, and source metadata
- Hover animations and lazy loading
- Grid activates automatically when category=images

Backend:
- category=images routes to image engines via planner
- Image engines registered in factory and engine allowlist
- extractImgSrc helper for parsing thumbnail URLs from HTML
- IsImageSearch flag on PageData for template layout switching
This commit is contained in:
Franz Kafka 2026-03-22 16:49:24 +00:00
parent a316763aca
commit 2b072e4de3
11 changed files with 687 additions and 4 deletions

View file

@ -52,6 +52,7 @@ type PageData struct {
UnresponsiveEngines [][2]string
PageNumbers []PageNumber
ShowHeader bool
IsImageSearch bool
// New fields for three-column layout
Categories []string
CategoryIcons map[string]string
@ -106,13 +107,13 @@ func init() {
}
tmplFull = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS,
"base.html", "results.html", "results_inner.html", "result_item.html", "video_item.html",
"base.html", "results.html", "results_inner.html", "result_item.html", "video_item.html", "image_item.html",
))
tmplIndex = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS,
"base.html", "index.html",
))
tmplFragment = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS,
"results.html", "results_inner.html", "result_item.html", "video_item.html",
"results.html", "results_inner.html", "result_item.html", "video_item.html", "image_item.html",
))
tmplPreferences = template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS,
"base.html", "preferences.html",
@ -168,6 +169,7 @@ func FromResponse(resp contracts.SearchResponse, query string, pageno int, activ
"weather": "🌤️",
},
ActiveCategory: activeCategory,
IsImageSearch: activeCategory == "images",
// Time filters
TimeFilters: []FilterOption{