~hristoast/hristoast

b0152dfbad24a3f0154dc4afebe74540fa903b73 — Hristos N. Triantafillou 9 months ago 4de9422
Update soupault to 2.2.0, use a lua-based feed generator

Also sneak in some new path regexes for my blog indexes.
6 files changed, 103 insertions(+), 78 deletions(-)

M .build.yml
M Makefile
A plugins/atom.lua
D scripts/json2feed.py
M soupault.conf
M templates/main.html
M .build.yml => .build.yml +2 -5
@@ 1,9 1,8 @@
image: archlinux
environment:
  feedgen_version: 0.9.0
  pystache_version: 0.5.4
  soupault_sha: d72fd56bbc8e8cfa4b909c7ad5a65ac0ab06db95b7b093af583d24cadaf3ffd7
  soupault_version: 2.1.0
  soupault_sha: fd3dbcac5d4edd4a8ecabe03714a0c9f2a47011c33fcfa7811e21a8a832b08da
  soupault_version: 2.2.0
packages:
  - highlight
  - make


@@ 24,8 23,6 @@ tasks:
  - install-soupault: |
      tar xvf soupault-$soupault_version-linux-x86_64.tar.gz
      sudo mv -v ./soupault-$soupault_version-linux-x86_64/soupault /usr/bin/
  - pip-install-feedgen: |
      sudo pip3 install feedgen==$feedgen_version pystache==$pystache_version
  - build: |
      cd ./hristoast
      make prod-site

M Makefile => Makefile +1 -3
@@ 4,9 4,7 @@ SOUPAULT := soupault
.DEFAULT_GOAL:= rebuild-staging

prod-site:
	$(SOUPAULT)
	$(SOUPAULT) --index-only
	$(proj_dir)/scripts/json2feed.py index.json > $(proj_dir)/build/feed.xml
	$(SOUPAULT) --profile live

staging-site:
	$(SOUPAULT)

A plugins/atom.lua => plugins/atom.lua +80 -0
@@ 0,0 1,80 @@
-- Atom feed generator
-- Still somewhat experimental -- do not steal for your site just yet

Plugin.require_version("2.2.0")

data = config

date_input_formats = soupault_config["index"]["date_formats"]

feed_file = config["feed_file"]

data["site_url"] = soupault_config["custom_options"]["site_url"]
data["feed_id"] = soupault_config["custom_options"]["site_url"]


function in_section(entry)
  return (entry["nav_path"][1] == config["use_section"])
end

entries = {}

-- Original, unfiltered entries inded
local n = 1

-- Index of the new array of entries we are building
local m = 1

local count = size(site_index)
while (n <= count) do
  entry = site_index[n]
  if in_section(entry) then
    if entry["date"] then
      entry["date"] = Date.reformat(entry["date"], date_input_formats, "%Y-%m-%dT%H:%M:%S%:z")
    end
    entries[m] = entry
    m = m + 1
  end
  n = n + 1
end

if (soupault_config["index"]["sort_descending"] or
   (not Table.has_key(soupault_config["index"], "sort_descending")))
then
  data["feed_last_updated"] = entries[1]["date"]
else
  data["feed_last_updated"] = entries[size(entries)]["date"]
end

data["entries"] = entries

feed_template = [[
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>{{feed_id}}</id>
  <title>{{feed_title}}</title>
  <updated>{{feed_last_updated}}</updated>
  <author>
    <name>{{feed_author}}</name>
    <email>{{feed_author_email}}</email>
  </author>
  <generator uri="https://soupault.neocities.org" version="{{soupault_version}}">soupault</generator>
  <logo>{{feed_logo}}</logo>
  <subtitle>{{feed_subtitle}}</subtitle>
  {%- for e in entries -%}
  <entry>
    <id>{{site_url}}{{e.url}}</id>
    <title>{{e.title}}</title>
    <updated>{{e.date}}</updated>
    <content type="html">
    {{e.excerpt | escape}}
    </content>
    <link href="{{site_url}}{{e.url}}" rel="alternate"/>
  </entry>
  {%- endfor %}
</feed>
]]

feed = String.render_template(feed_template, data)

Sys.write_file(Sys.join_path(soupault_config["settings"]["build_dir"], feed_file), String.trim(feed))

D scripts/json2feed.py => scripts/json2feed.py +0 -68
@@ 1,68 0,0 @@
#!/usr/bin/env python3

# Adapted from:
# https://github.com/dmbaturin/baturin.org/blob/be8feeb8cf369ce73f601a3e4fc9f43f22b9d758/scripts/json2feed.py

import sys
import json
import dateutil.tz
import dateutil.parser

from datetime import datetime
from feedgen.feed import FeedGenerator


base_url = "https://hristos.co"

default_date = datetime(1970, 1, 1, tzinfo=dateutil.tz.gettz("Etc/UTC"))

feed_id = base_url + "/feed.xml"
feed_author = "Hristos N Triantafillou"
feed_title = feed_author + "'s blog"
feed_subtitle = "On programming and things related and not"
feed_logo = base_url + "/img/slime.png"
feed_language = "en"
feed_author_email = "me@hristos.co"


def get_date(ds):
    try:
        return dateutil.parser.parse(ds, default=default_date).isoformat()
    except Exception:
        return default_date


fg = FeedGenerator()
fg.id(feed_id)
fg.title(feed_title)
fg.subtitle(feed_subtitle)
fg.author({"name": feed_author, "email": feed_author_email})
# fg.link( href=, rel='alternate' )
fg.logo(feed_logo)
fg.language(feed_language)

index_file = sys.argv[1]

with open(index_file, "r") as f:
    entries = json.load(f)

for entry in reversed(entries):
    entry["author"] = feed_author

    if not entry["title"] or not entry["date"]:
        continue

    fe = fg.add_entry()

    url = base_url + entry["url"]

    fe.id(url)
    fe.link(href=url, rel="alternate")
    fe.title(entry["title"])
    fe.content(entry["excerpt"], type="html")
    fe.updated(get_date(entry["date"]))


atomfeed = fg.atom_str(pretty=True).decode()

print(atomfeed)

M soupault.conf => soupault.conf +19 -1
@@ 15,6 15,9 @@
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

[custom_options]
  site_url = "https://hristos.co"

[settings]
  # debug = true
  # verbose = true


@@ 33,8 36,9 @@
[index]
  index = true
  dump_json = "index.json"
  path_regex = "site\\/blog\\/(.*)\\.html"
  path_regex = "^site\\/(audio\\/covers|blog)\\/(.*)\\.html$"
  sort_by = "date"
  date_formats = ["%F"]

[index.fields]
  date = { selector = [ "#post-date", "time" ] }


@@ 42,11 46,13 @@
  title = { selector = [ "#title", "h1" ] }

[index.views.index]
  path_regex = "^site\\/(audio\\/covers|blog)\\/(.*)\\.html$"
  index_processor = "scripts/index.py"
  index_selector = "div#blog-index"
  section = "blog"

[index.views.blog]
  path_regex = "^site\\/(audio\\/covers|blog)\\/(.*)\\.html$"
  index_selector = "div#blog-all"
  index_item_template = """
<div class="entry">


@@ 57,6 63,18 @@
</div>
"""

[widgets.atom]
  widget = "atom"
  profile = "live"
  page = "blog/index.html"
  use_section = "blog"
  feed_file = "atom.xml"
  feed_author = "Hristos"
  feed_author_email = "me@hristos.co"
  feed_title = "Hristos"
  feed_subtitle = "Hristos"
  feed_logo = "https://hristos.co/img/slime.png"

[widgets.asciinema-player-css]
  widget = "insert-if"
  html = "<link rel='stylesheet' type='text/css' href='/asciinema/asciinema-player.css' />"

M templates/main.html => templates/main.html +1 -1
@@ 22,7 22,7 @@
            <a href="/blog/">Blog</a>
          </li>
          <li>
            <a href="/feed.xml">RSS</a>
            <a href="/atom.xml">RSS</a>
          </li>
          <li>
            <a href="/contact/">Contact</a>