Skip to content

Commit 22cea9b

Browse files
committed
Allow publishing category feeds
In some cases, one needs to have custom feeds pertaining to a particular topic (such as for planet aggregations) and thus having category feeds is useful. This adds `category_feeds` and `category_feeds_dir` config options
1 parent dc41368 commit 22cea9b

File tree

5 files changed

+102
-48
lines changed

5 files changed

+102
-48
lines changed

docs/configuration.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,18 @@ Will result in:
426426

427427
Default: `None`.
428428

429+
### Category feeds
430+
431+
Enables generating separate feeds for each category.
432+
433+
Default: `false`.
434+
435+
### Category feeds directory
436+
437+
Directory to put category feeds into
438+
439+
Default: `rss_dir`.
440+
429441
----
430442

431443
## Integration

docs/schema.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,18 @@
127127
"markdownDescription": "https://guts.github.io/mkdocs-rss-plugin/configuration/#url-parameters",
128128
"type": "object",
129129
"default": null
130+
},
131+
"category_feeds": {
132+
"title": "Separate feeds for each category",
133+
"markdownDescription": "https://guts.github.io/mkdocs-rss-plugin/configuration/#category_feeds",
134+
"type": "boolean",
135+
"default": false
136+
},
137+
"category_feeds_dir": {
138+
"title": "Directory to put category feeds into",
139+
"markdownDescription": "https://guts.github.io/mkdocs-rss-plugin/configuration/#category_feeds_directory",
140+
"type": "string",
141+
"default": "rss"
130142
}
131143
},
132144
"additionalProperties": false

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ plugins:
3232
utm_source: "documentation"
3333
utm_medium: "RSS"
3434
utm_campaign: "feed-syndication"
35+
category_feeds: false
36+
category_feeds_dir: rss
3537
- search
3638

3739
theme:

mkdocs_rss_plugin/plugin.py

Lines changed: 74 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# ##################################
66

77
# standard library
8+
import os
89
import logging
910
from copy import deepcopy
1011
from datetime import datetime
@@ -58,6 +59,8 @@ class GitRssPlugin(BasePlugin):
5859
("match_path", config_options.Type(str, default=".*")),
5960
("pretty_print", config_options.Type(bool, default=False)),
6061
("url_parameters", config_options.Type(dict, default=None)),
62+
("category_feeds", config_options.Type(bool, default=False)),
63+
("category_feeds_dir", config_options.Type(str, default="rss"))
6164
)
6265

6366
def __init__(self):
@@ -71,9 +74,13 @@ def __init__(self):
7174
self.meta_default_time = None
7275
# pages storage
7376
self.pages_to_filter = []
77+
# config
78+
self.category_feeds = False
79+
self.category_feeds_dir = "rss"
7480
# prepare output feeds
7581
self.feed_created = dict
7682
self.feed_updated = dict
83+
self.category_feed = dict
7784

7885
def on_config(self, config: config_options.Config) -> dict:
7986
"""The config event is the first event called on build and
@@ -123,6 +130,9 @@ def on_config(self, config: config_options.Config) -> dict:
123130
# pattern to match pages included in output
124131
self.match_path_pattern = compile(self.config.get("match_path"))
125132

133+
self.category_feeds = self.config.get("category_feeds")
134+
self.category_feeds_dir = self.config.get("category_feeds_dir")
135+
126136
# date handling
127137
if self.config.get("date_from_meta") is not None:
128138
self.src_date_created = self.config.get("date_from_meta").get(
@@ -162,6 +172,7 @@ def on_config(self, config: config_options.Config) -> dict:
162172
# create 2 final dicts
163173
self.feed_created = deepcopy(base_feed)
164174
self.feed_updated = deepcopy(base_feed)
175+
self.category_feed = deepcopy(base_feed)
165176

166177
# final feed url
167178
if base_feed.get("html_url"):
@@ -272,6 +283,41 @@ def on_page_content(
272283
)
273284
)
274285

286+
def render_feed(self, pretty_print: bool, feed_name: str, feed: dict):
287+
if pretty_print:
288+
# load Jinja environment and template
289+
env = Environment(
290+
autoescape=select_autoescape(["html", "xml"]),
291+
loader=FileSystemLoader(self.tpl_folder),
292+
)
293+
294+
template = env.get_template(self.tpl_file.name)
295+
296+
# write feed to file
297+
with feed_name.open(mode="w", encoding="UTF8") as fifeed:
298+
fifeed.write(template.render(feed=feed))
299+
else:
300+
# load Jinja environment and template
301+
env = Environment(
302+
autoescape=select_autoescape(["html", "xml"]),
303+
loader=FileSystemLoader(self.tpl_folder),
304+
lstrip_blocks=True,
305+
trim_blocks=True,
306+
)
307+
template = env.get_template(self.tpl_file.name)
308+
309+
# write feed to file stripping out spaces and new lines
310+
with feed_name.open(mode="w", encoding="UTF8") as fifeed:
311+
prev_char = ""
312+
for char in template.render(feed=feed):
313+
if char == "\n":
314+
continue
315+
if char == " " and prev_char == " ":
316+
prev_char = char
317+
continue
318+
prev_char = char
319+
fifeed.write(char)
320+
275321
def on_post_build(self, config: config_options.Config) -> dict:
276322
"""The post_build event does not alter any variables. \
277323
Use this event to call post-build scripts. \
@@ -312,52 +358,32 @@ def on_post_build(self, config: config_options.Config) -> dict:
312358
)
313359
)
314360

315-
# write feeds according to the pretty print option
316-
if pretty_print:
317-
# load Jinja environment and template
318-
env = Environment(
319-
autoescape=select_autoescape(["html", "xml"]),
320-
loader=FileSystemLoader(self.tpl_folder),
321-
)
322-
323-
template = env.get_template(self.tpl_file.name)
324-
325-
# write feeds to files
326-
with out_feed_created.open(mode="w", encoding="UTF8") as fifeed_created:
327-
fifeed_created.write(template.render(feed=self.feed_created))
328-
329-
with out_feed_updated.open(mode="w", encoding="UTF8") as fifeed_updated:
330-
fifeed_updated.write(template.render(feed=self.feed_updated))
331-
332-
else:
333-
# load Jinja environment and template
334-
env = Environment(
335-
autoescape=select_autoescape(["html", "xml"]),
336-
loader=FileSystemLoader(self.tpl_folder),
337-
lstrip_blocks=True,
338-
trim_blocks=True,
339-
)
340-
template = env.get_template(self.tpl_file.name)
361+
# Render main feeds
362+
self.render_feed(pretty_print, out_feed_created, self.feed_created)
363+
self.render_feed(pretty_print, out_feed_updated, self.feed_updated)
364+
365+
# Render category feeds if enabled
366+
if self.category_feeds:
367+
feeds = {}
368+
# collect feeds of pages per category
369+
for page in self.pages_to_filter:
370+
for category in page.categories:
371+
feeds.setdefault(category, []).append(page)
372+
373+
# Ensure target directory exists
374+
path = Path(config.get("site_dir")) / self.category_feeds_dir
375+
os.makedirs(path, exist_ok=True)
376+
377+
for category, pages in feeds.items():
378+
# Create a feed per category
379+
filename = f"{category}.xml"
380+
feed = deepcopy(self.category_feed)
381+
feed.get("entries").extend(
382+
self.util.filter_pages(
383+
pages=pages,
384+
length = self.config.get("length", 20),
385+
attribute = "created"
386+
)
387+
)
388+
self.render_feed(pretty_print, path / filename, feed)
341389

342-
# write feeds to files stripping out spaces and new lines
343-
with out_feed_created.open(mode="w", encoding="UTF8") as fifeed_created:
344-
prev_char = ""
345-
for char in template.render(feed=self.feed_created):
346-
if char == "\n":
347-
continue
348-
if char == " " and prev_char == " ":
349-
prev_char = char
350-
continue
351-
prev_char = char
352-
fifeed_created.write(char)
353-
354-
with out_feed_updated.open(mode="w", encoding="UTF8") as fifeed_updated:
355-
for char in template.render(feed=self.feed_updated):
356-
if char == "\n":
357-
prev_char = char
358-
continue
359-
if char == " " and prev_char == " ":
360-
prev_char = char
361-
continue
362-
prev_char = char
363-
fifeed_updated.write(char)

tests/test_config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ def test_plugin_config_defaults(self):
6868
"pretty_print": False,
6969
"match_path": ".*",
7070
"url_parameters": None,
71+
"category_feeds": False,
72+
"category_feeds_dir": "rss",
7173
}
7274

7375
# load

0 commit comments

Comments
 (0)