nandi/gleanpublic Fork 0
d1ec121
Commits
Clone
git clone https://git.rickub.com/nandi/glean.git
git clone ssh://git@rickub.com/nandi/glean.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Fix feed favicon handling and DRYUnverified

Julien Robert committed 2026-04-22T14:59:36+02:00 Browse files
d1ec121 parent: 0438036
modified internal/tmpl/article_detail.html +1 -1
@@ -16,7 +16,7 @@
1616 {{if .Article.Published.Valid}}<span>{{.Article.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
1717 {{if .Feed}}
1818 <a href="/articles?feed={{.Feed.FeedURL}}" class="inline-flex items-center gap-1 hover:text-spot-green transition">
19- {{if .Feed.FaviconURL.Valid}}<img src="{{.Feed.FaviconURL.String}}" class="w-4 h-4 rounded">{{end}}
19+ {{if .Feed}}{{template "favicon" dict "src" .Feed.FaviconURL.String "size" "w-4 h-4"}}{{end}}
2020 {{if .Feed.Title.Valid}}{{.Feed.Title.String}}{{else}}{{.Feed.FeedURL}}{{end}}
2121 </a>
2222 {{end}}
@@ -16,7 +16,7 @@
16 {{if .Article.Published.Valid}}<span>{{.Article.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}16 {{if .Article.Published.Valid}}<span>{{.Article.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
17 {{if .Feed}}17 {{if .Feed}}
18 <a href="/articles?feed={{.Feed.FeedURL}}" class="inline-flex items-center gap-1 hover:text-spot-green transition">18 <a href="/articles?feed={{.Feed.FeedURL}}" class="inline-flex items-center gap-1 hover:text-spot-green transition">
19- {{if .Feed.FaviconURL.Valid}}<img src="{{.Feed.FaviconURL.String}}" class="w-4 h-4 rounded">{{end}}19+ {{if .Feed}}{{template "favicon" dict "src" .Feed.FaviconURL.String "size" "w-4 h-4"}}{{end}}
20 {{if .Feed.Title.Valid}}{{.Feed.Title.String}}{{else}}{{.Feed.FeedURL}}{{end}}20 {{if .Feed.Title.Valid}}{{.Feed.Title.String}}{{else}}{{.Feed.FeedURL}}{{end}}
21 </a>21 </a>
22 {{end}}22 {{end}}
modified internal/tmpl/articles.html +1 -1
@@ -8,7 +8,7 @@
88 </div>
99 <div class="flex items-center justify-between">
1010 <div class="flex items-center gap-3">
11- {{if .Feed.FaviconURL.Valid}}<img src="{{.Feed.FaviconURL.String}}" class="w-8 h-8 rounded shrink-0" loading="lazy">{{end}}
11+ {{template "favicon" dict "src" .Feed.FaviconURL.String "size" "w-8 h-8"}}
1212 <div>
1313 <h1 class="text-2xl font-bold text-spot-text">{{if .Feed.Title.Valid}}{{.Feed.Title.String}}{{else}}{{.Feed.FeedURL}}{{end}}</h1>
1414 {{if .Feed.SiteURL.Valid}}<a href="{{.Feed.SiteURL.String}}" target="_blank" rel="noopener noreferrer" class="text-xs text-spot-secondary hover:text-spot-green transition">{{.Feed.SiteURL.String}}</a>{{end}}
@@ -8,7 +8,7 @@
8 </div>8 </div>
9 <div class="flex items-center justify-between">9 <div class="flex items-center justify-between">
10 <div class="flex items-center gap-3">10 <div class="flex items-center gap-3">
11- {{if .Feed.FaviconURL.Valid}}<img src="{{.Feed.FaviconURL.String}}" class="w-8 h-8 rounded shrink-0" loading="lazy">{{end}}11+ {{template "favicon" dict "src" .Feed.FaviconURL.String "size" "w-8 h-8"}}
12 <div>12 <div>
13 <h1 class="text-2xl font-bold text-spot-text">{{if .Feed.Title.Valid}}{{.Feed.Title.String}}{{else}}{{.Feed.FeedURL}}{{end}}</h1>13 <h1 class="text-2xl font-bold text-spot-text">{{if .Feed.Title.Valid}}{{.Feed.Title.String}}{{else}}{{.Feed.FeedURL}}{{end}}</h1>
14 {{if .Feed.SiteURL.Valid}}<a href="{{.Feed.SiteURL.String}}" target="_blank" rel="noopener noreferrer" class="text-xs text-spot-secondary hover:text-spot-green transition">{{.Feed.SiteURL.String}}</a>{{end}}14 {{if .Feed.SiteURL.Valid}}<a href="{{.Feed.SiteURL.String}}" target="_blank" rel="noopener noreferrer" class="text-xs text-spot-secondary hover:text-spot-green transition">{{.Feed.SiteURL.String}}</a>{{end}}
modified internal/tmpl/partials/article-card.html +1 -1
@@ -7,7 +7,7 @@
77 <a href="/articles/{{.ID}}" class="font-bold text-spot-text hover:text-spot-green transition text-lg leading-tight">{{.Title}}</a>
88 </div>
99 <div class="text-sm text-spot-secondary mt-1 flex items-center gap-2">
10- {{if .FeedFaviconURL.Valid}}<img src="{{.FeedFaviconURL.String}}" class="w-4 h-4 rounded shrink-0" loading="lazy">{{end}}
10+ {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-4 h-4"}}
1111 {{if .Author.Valid}}{{if .Author.String}}<span>{{.Author.String}}</span>{{end}}{{end}}
1212 {{if .Published.Valid}}<span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
1313 <span class="text-spot-muted"><a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-green transition">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a></span>
@@ -7,7 +7,7 @@
7 <a href="/articles/{{.ID}}" class="font-bold text-spot-text hover:text-spot-green transition text-lg leading-tight">{{.Title}}</a>7 <a href="/articles/{{.ID}}" class="font-bold text-spot-text hover:text-spot-green transition text-lg leading-tight">{{.Title}}</a>
8 </div>8 </div>
9 <div class="text-sm text-spot-secondary mt-1 flex items-center gap-2">9 <div class="text-sm text-spot-secondary mt-1 flex items-center gap-2">
10- {{if .FeedFaviconURL.Valid}}<img src="{{.FeedFaviconURL.String}}" class="w-4 h-4 rounded shrink-0" loading="lazy">{{end}}10+ {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-4 h-4"}}
11 {{if .Author.Valid}}{{if .Author.String}}<span>{{.Author.String}}</span>{{end}}{{end}}11 {{if .Author.Valid}}{{if .Author.String}}<span>{{.Author.String}}</span>{{end}}{{end}}
12 {{if .Published.Valid}}<span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}12 {{if .Published.Valid}}<span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
13 <span class="text-spot-muted"><a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-green transition">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a></span>13 <span class="text-spot-muted"><a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-green transition">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a></span>
added internal/tmpl/partials/favicon.html +8 -0
new file mode 100644
@@ -0,0 +1,8 @@
1+{{define "favicon"}}
2+{{if .src}}
3+<img src="{{.src}}" class="{{.size}} rounded shrink-0" loading="lazy" onerror="this.classList.add('hidden');this.nextElementSibling.classList.remove('hidden')">
4+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="{{.size}} shrink-0 hidden"><circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
5+{{else}}
6+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="{{.size}} shrink-0"><circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
7+{{end}}
8+{{end}}
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,8 @@
1+{{define "favicon"}}
2+{{if .src}}
3+<img src="{{.src}}" class="{{.size}} rounded shrink-0" loading="lazy" onerror="this.classList.add('hidden');this.nextElementSibling.classList.remove('hidden')">
4+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="{{.size}} shrink-0 hidden"><circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
5+{{else}}
6+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="{{.size}} shrink-0"><circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
7+{{end}}
8+{{end}}
\ No newline at end of file\ No newline at end of file
modified internal/tmpl/partials/feed-item.html +1 -1
@@ -1,7 +1,7 @@
11 {{define "feed-item.html"}}
22 <div class="feed-item px-5 py-4 flex items-center justify-between gap-3 hover:bg-spot-hover-50 transition rounded-xl">
33 <a href="/articles?feed={{.FeedURL}}" class="min-w-0 flex-1 flex items-center gap-3">
4- {{if .FaviconURL.Valid}}<img src="{{.FaviconURL.String}}" class="w-5 h-5 rounded shrink-0" loading="lazy">{{else}}<span class="shrink-0 w-5 h-5 flex items-center justify-center text-spot-muted"><svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">{{template "icon-globe"}}</svg></span>{{end}}
4+ {{template "favicon" dict "src" .FaviconURL.String "size" "w-5 h-5"}}
55 <div class="min-w-0 flex-1">
66 <div class="flex items-center gap-2 flex-wrap">
77 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>
@@ -1,7 +1,7 @@
1 {{define "feed-item.html"}}1 {{define "feed-item.html"}}
2 <div class="feed-item px-5 py-4 flex items-center justify-between gap-3 hover:bg-spot-hover-50 transition rounded-xl">2 <div class="feed-item px-5 py-4 flex items-center justify-between gap-3 hover:bg-spot-hover-50 transition rounded-xl">
3 <a href="/articles?feed={{.FeedURL}}" class="min-w-0 flex-1 flex items-center gap-3">3 <a href="/articles?feed={{.FeedURL}}" class="min-w-0 flex-1 flex items-center gap-3">
4- {{if .FaviconURL.Valid}}<img src="{{.FaviconURL.String}}" class="w-5 h-5 rounded shrink-0" loading="lazy">{{else}}<span class="shrink-0 w-5 h-5 flex items-center justify-center text-spot-muted"><svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">{{template "icon-globe"}}</svg></span>{{end}}4+ {{template "favicon" dict "src" .FaviconURL.String "size" "w-5 h-5"}}
5 <div class="min-w-0 flex-1">5 <div class="min-w-0 flex-1">
6 <div class="flex items-center gap-2 flex-wrap">6 <div class="flex items-center gap-2 flex-wrap">
7 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>7 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>
modified internal/tmpl/partials/recommendation-card.html +1 -1
@@ -2,7 +2,7 @@
22 <div class="recommendation-card bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition">
33 <div class="flex items-center justify-between gap-2">
44 <a href="/articles?feed={{.feed_url}}" class="min-w-0 flex items-center gap-2 flex-1">
5- {{if .favicon_url}}<img src="{{.favicon_url}}" class="w-4 h-4 rounded shrink-0" loading="lazy">{{end}}
5+ {{template "favicon" dict "src" .favicon_url "size" "w-4 h-4"}}
66 <div class="min-w-0">
77 <div class="font-bold text-sm text-spot-text truncate">{{if .title}}{{.title}}{{else}}{{.feed_url}}{{end}}</div>
88 {{if .description}}<p class="text-xs text-spot-secondary truncate mt-0.5">{{.description}}</p>{{end}}
@@ -2,7 +2,7 @@
2 <div class="recommendation-card bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition">2 <div class="recommendation-card bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition">
3 <div class="flex items-center justify-between gap-2">3 <div class="flex items-center justify-between gap-2">
4 <a href="/articles?feed={{.feed_url}}" class="min-w-0 flex items-center gap-2 flex-1">4 <a href="/articles?feed={{.feed_url}}" class="min-w-0 flex items-center gap-2 flex-1">
5- {{if .favicon_url}}<img src="{{.favicon_url}}" class="w-4 h-4 rounded shrink-0" loading="lazy">{{end}}5+ {{template "favicon" dict "src" .favicon_url "size" "w-4 h-4"}}
6 <div class="min-w-0">6 <div class="min-w-0">
7 <div class="font-bold text-sm text-spot-text truncate">{{if .title}}{{.title}}{{else}}{{.feed_url}}{{end}}</div>7 <div class="font-bold text-sm text-spot-text truncate">{{if .title}}{{.title}}{{else}}{{.feed_url}}{{end}}</div>
8 {{if .description}}<p class="text-xs text-spot-secondary truncate mt-0.5">{{.description}}</p>{{end}}8 {{if .description}}<p class="text-xs text-spot-secondary truncate mt-0.5">{{.description}}</p>{{end}}
modified internal/tmpl/profile.html +1 -1
@@ -26,7 +26,7 @@
2626 <div class="bg-spot-surface rounded-xl divide-y divide-spot-divider mb-6">
2727 {{range .Subscriptions}}
2828 <a href="/articles?feed={{.FeedURL}}" class="flex items-center gap-3 px-5 py-3 hover:bg-spot-hover-50 transition first:rounded-t-xl last:rounded-b-xl">
29- {{if .FaviconURL.Valid}}<img src="{{.FaviconURL.String}}" class="w-5 h-5 rounded shrink-0" loading="lazy">{{else}}<span class="shrink-0 w-5 h-5 flex items-center justify-center text-spot-muted"><svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">{{template "icon-globe"}}</svg></span>{{end}}
29+ {{template "favicon" dict "src" .FaviconURL.String "size" "w-5 h-5"}}
3030 <div class="min-w-0 flex-1">
3131 <div class="flex items-center gap-2 flex-wrap">
3232 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>
@@ -26,7 +26,7 @@
26 <div class="bg-spot-surface rounded-xl divide-y divide-spot-divider mb-6">26 <div class="bg-spot-surface rounded-xl divide-y divide-spot-divider mb-6">
27 {{range .Subscriptions}}27 {{range .Subscriptions}}
28 <a href="/articles?feed={{.FeedURL}}" class="flex items-center gap-3 px-5 py-3 hover:bg-spot-hover-50 transition first:rounded-t-xl last:rounded-b-xl">28 <a href="/articles?feed={{.FeedURL}}" class="flex items-center gap-3 px-5 py-3 hover:bg-spot-hover-50 transition first:rounded-t-xl last:rounded-b-xl">
29- {{if .FaviconURL.Valid}}<img src="{{.FaviconURL.String}}" class="w-5 h-5 rounded shrink-0" loading="lazy">{{else}}<span class="shrink-0 w-5 h-5 flex items-center justify-center text-spot-muted"><svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">{{template "icon-globe"}}</svg></span>{{end}}29+ {{template "favicon" dict "src" .FaviconURL.String "size" "w-5 h-5"}}
30 <div class="min-w-0 flex-1">30 <div class="min-w-0 flex-1">
31 <div class="flex items-center gap-2 flex-wrap">31 <div class="flex items-center gap-2 flex-wrap">
32 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>32 <span class="font-bold text-spot-text truncate">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</span>