Skip to content

Commit 9ca9d3a

Browse files
committed
Add RSS/Atom feed
1 parent cc1aea5 commit 9ca9d3a

8 files changed

Lines changed: 96 additions & 3 deletions

File tree

config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,6 @@
5050
"trim_blocks": True,
5151
"lstrip_blocks": True,
5252
}
53+
54+
# RSS settings
55+
rss_root_urls = ["@root/blog//"]

inc/foot.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
- [RSS](feed.xml)
12
- [ORCiD](https://orcid.org/0000-0003-3230-6090/)
23
- [zirk.us](https://zirk.us/@joemull)
34
- [LinkedIn](https://www.linkedin.com/in/jhmuller/)

inc/site-description.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
I write about my work as a programmer and teacher and about the shenanigans that happen in academic publishing.

lib/meteor/extensions/rss.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import datetime
2+
import hashlib
3+
import uuid
4+
5+
import ark
6+
import holly
7+
import os
8+
from feedgenerator import Atom1Feed
9+
from jinja2 import filters
10+
11+
12+
def get_ark_node_description(node):
13+
stripped = filters.do_striptags(node.html)
14+
truncated = stripped[:97].rsplit(" ", 1)[0] + "..."
15+
return truncated
16+
17+
18+
def get_child_nodes(feed, node):
19+
nodes = []
20+
for child in node.children:
21+
if child.has_children:
22+
nodes.extend(get_child_nodes(feed, child))
23+
elif not child.get("is_tag_base") and not child.get("is_tag_index"):
24+
nodes.append(child)
25+
return nodes
26+
27+
28+
def get_nodes(feed):
29+
nodes = []
30+
for root_url in ark.site.config.get("rss_root_urls", []):
31+
node = ark.nodes.node(root_url)
32+
nodes.extend(get_child_nodes(feed, node))
33+
default_date = datetime.date(2000, 1, 1)
34+
nodes.sort(key=lambda node: node.filepath)
35+
nodes.sort(key=lambda node: node.get("date") or default_date, reverse=True)
36+
nodes = nodes[:10]
37+
return nodes
38+
39+
40+
@ark.events.register(ark.events.Event.EXIT_BUILD)
41+
def generate_feed():
42+
config = ark.site.config
43+
title = config.get("title", "")
44+
relative_link = "feed.xml"
45+
description = filters.do_striptags(
46+
ark.site.includes().get("site_description", ""),
47+
)
48+
homepage = config.get("homepage", "")
49+
if not homepage:
50+
raise Exception(
51+
"There must be a homepage specified in config.py to generate the RSS feed."
52+
)
53+
rss_link = os.path.join(homepage, relative_link)
54+
feed = Atom1Feed(
55+
title=title,
56+
link=rss_link,
57+
description=description,
58+
language=config.get("lang"),
59+
)
60+
nodes = get_nodes(feed)
61+
path = ark.site.out(relative_link)
62+
for node in nodes:
63+
author = node.get("author") or config.get("default_author", "")
64+
node_path = ark.utils.rewrite_urls(f"'{node.url}'", path).strip("'")
65+
url = os.path.join(homepage, node_path)
66+
item_license = config.get("default_license", "")
67+
feed.add_item(
68+
title=node.get("title"),
69+
author_name=author,
70+
link=url,
71+
description=get_ark_node_description(node),
72+
pubdate=node.get("date"),
73+
content=node.html,
74+
)
75+
76+
xml = feed.writeString("utf-8")
77+
if not os.path.isdir(os.path.dirname(path)):
78+
os.makedirs(os.path.dirname(path))
79+
with open(path, "w") as file:
80+
file.write(xml)

lib/meteor/templates/node.jinja

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
{{- site.title -}}
1717
{%- endif -%}
1818
</title>
19+
<link
20+
type="application/atom+xml"
21+
rel="alternate"
22+
href="@root/feed.xml"
23+
title="{{ site.title }}"
24+
/>
1925
<link
2026
rel="preload"
2127
href="@root/fonts/source-sans/SourceSans3-VariableFont_wght.ttf"
@@ -44,8 +50,8 @@
4450

4551
<link rel="icon" href="@root/images/favicon.svg" />
4652
<meta name="author" content="{{ node.author or site.default_author }}" />
47-
{% if node.meta_description %}
48-
<meta name="description" content="{{ node.meta_description.strip() }}" />
53+
{% if inc.site_description %}
54+
<meta name="description" content="{{ inc.site_description|striptags }}" />
4955
{% else %}
5056
<meta
5157
name="description"

requirements.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
ark
2+
feedgenerator
23
holly
34
lightningcss
45
marko

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ ark==7.7.0
1010
# via -r requirements.in
1111
colorama==0.4.6
1212
# via ark
13+
feedgenerator==2.2.1
14+
# via -r requirements.in
1315
holly==2.0.0
1416
# via -r requirements.in
1517
ibis==3.3.0

src/blog/index.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
---
22
title: Blog
3-
meta_description: I write about my work as a programmer and teacher and about the shenanigans that happen in academic publishing.
43
---

0 commit comments

Comments
 (0)