~netlandish/linktaco-blog

3c835904c2cde1d0d4a1860654c2c87d067825a7 — Peter Sanchez 16 days ago ed0bbd3
Updating webring data generation process to using hugo data files
6 files changed, 157 insertions(+), 2 deletions(-)

M .gitignore
A go.mod
A go.sum
M layouts/_default/baseof.html
A layouts/partials/webring-out.html
A openring.go
M .gitignore => .gitignore +1 -1
@@ 3,4 3,4 @@ resources/
test-article.md
.hugo_build.lock
wring.sh
layouts/partials/webring-out.html
data/openring.toml

A go.mod => go.mod +18 -0
@@ 0,0 1,18 @@
module git.code.netlandish.com/~netlandish/linktaco-blog

go 1.23.4

require (
	github.com/BurntSushi/toml v1.4.0
	github.com/SlyMarbo/rss v1.0.5
	github.com/mattn/go-runewidth v0.0.16
	github.com/microcosm-cc/bluemonday v1.0.27
)

require (
	github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
	github.com/aymerick/douceur v0.2.0 // indirect
	github.com/gorilla/css v1.0.1 // indirect
	github.com/rivo/uniseg v0.2.0 // indirect
	golang.org/x/net v0.26.0 // indirect
)

A go.sum => go.sum +18 -0
@@ 0,0 1,18 @@
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/SlyMarbo/rss v1.0.5 h1:DPcZ4aOXXHJ5yNLXY1q/57frIixMmAvTtLxDE3fsMEI=
github.com/SlyMarbo/rss v1.0.5/go.mod h1:w6Bhn1BZs91q4OlEnJVZEUNRJmlbFmV7BkAlgCN8ofM=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=

M layouts/_default/baseof.html => layouts/_default/baseof.html +1 -1
@@ 73,7 73,7 @@

  <footer>
    {{ block "webring" . }}
    {{ partial "webring-out.html" }}
    {{ partial "webring-out.html" . }}
    {{ end }}
    <div class="footer">
      <span>Follow Us On:</span>

A layouts/partials/webring-out.html => layouts/partials/webring-out.html +21 -0
@@ 0,0 1,21 @@
{{ if and $.Site.Data.openring $.Site.Data.openring.Articles }}
{{ $articles := $.Site.Data.openring.Articles }}
    <section class="webring">
      <h2>
        Articles from blogs we recommend
        <small class="attribution">Generated by <a href="https://git.sr.ht/~sircmpwn/openring">openring</a></small>
      </h2>
      <section class="articles xrow xis-center">
        {{range $articles}}
        <div class="card article">
          <h4><a href="{{ .Link }}" target="_blank" rel="noopener">{{ .Title }}</a></h4>
          <p>{{ .Summary }}</p>
          <footer>
            via <a href="{{ .SourceLink }}" target="_blank" rel="noopener">{{ .SourceTitle }}</a><br />
	    {{ .Date.Format "Jan 2, 2006" }}
          </footer>
        </div>
	{{ end }}
      </section>
    </section>
{{ end }}

A openring.go => openring.go +98 -0
@@ 0,0 1,98 @@
package main

import (
	"flag"
	"html"
	"log"
	"net/url"
	"os"
	"sort"
	"time"

	"github.com/BurntSushi/toml"
	"github.com/SlyMarbo/rss"
	"github.com/mattn/go-runewidth"
	"github.com/microcosm-cc/bluemonday"
)

type Article struct {
	Date        time.Time
	Link        string
	SourceLink  string
	SourceTitle string
	Summary     string
	Title       string
}

func main() {
	var narticles, summaryLen int
	var sources []*url.URL
	flag.IntVar(&narticles, "n", 3, "number of output articles")
	flag.IntVar(&summaryLen, "l", 256, "maximum summary length")
	flag.Func("s", "source URL", func(s string) error {
		u, err := url.Parse(s)
		if err != nil {
			return err
		}
		sources = append(sources, u)
		return nil
	})
	flag.Parse()

	if len(flag.Args()) > 0 {
		log.Fatalf("Usage: %s [-s https://source.rss...] > out.toml", os.Args[0])
	}

	log.Println("Fetching feeds...")
	var feeds []*rss.Feed
	for _, source := range sources {
		feed, err := rss.Fetch(source.String())
		if err != nil {
			log.Printf("Error fetching %s: %s", source.String(), err.Error())
			continue
		}
		feeds = append(feeds, feed)
		log.Printf("Fetched %s", feed.Title)
	}
	if len(feeds) == 0 {
		log.Fatal("Expected at least one feed to successfully fetch")
	}

	policy := bluemonday.StrictPolicy()

	var articles []Article
	for _, feed := range feeds {
		if len(feed.Items) == 0 {
			log.Printf("Warning: feed %s has no items", feed.Title)
			continue
		}
		item := feed.Items[0]
		rawSummary := item.Summary
		if len(rawSummary) == 0 {
			rawSummary = html.UnescapeString(item.Content)
		}
		summary := runewidth.Truncate(
			policy.Sanitize(rawSummary), summaryLen, "…")
		articles = append(articles, Article{
			Date:        item.Date,
			SourceLink:  feed.Link,
			SourceTitle: html.UnescapeString(feed.Title),
			Summary:     summary,
			Title:       html.UnescapeString(item.Title),
			Link:        item.Link,
		})
	}
	sort.Slice(articles, func(i, j int) bool {
		return articles[i].Date.After(articles[j].Date)
	})
	if len(articles) < narticles {
		narticles = len(articles)
	}
	articles = articles[:narticles]

	if err := toml.NewEncoder(os.Stdout).Encode(struct {
		Articles []Article
	}{articles}); err != nil {
		log.Fatal(err)
	}
}

Do not follow this link