4
4
# ########## Libraries #############
5
5
# ##################################
6
6
7
- # standard library
8
7
import logging
8
+
9
+ # standard library
10
+ import os
9
11
from copy import deepcopy
10
12
from datetime import datetime
11
13
from email .utils import formatdate
@@ -58,6 +60,8 @@ class GitRssPlugin(BasePlugin):
58
60
("match_path" , config_options .Type (str , default = ".*" )),
59
61
("pretty_print" , config_options .Type (bool , default = False )),
60
62
("url_parameters" , config_options .Type (dict , default = None )),
63
+ ("category_feeds" , config_options .Type (bool , default = False )),
64
+ ("category_feeds_dir" , config_options .Type (str , default = "rss" )),
61
65
)
62
66
63
67
def __init__ (self ):
@@ -71,9 +75,13 @@ def __init__(self):
71
75
self .meta_default_time = None
72
76
# pages storage
73
77
self .pages_to_filter = []
78
+ # config
79
+ self .category_feeds = False
80
+ self .category_feeds_dir = "rss"
74
81
# prepare output feeds
75
82
self .feed_created = dict
76
83
self .feed_updated = dict
84
+ self .category_feed = dict
77
85
78
86
def on_config (self , config : config_options .Config ) -> dict :
79
87
"""The config event is the first event called on build and
@@ -123,6 +131,9 @@ def on_config(self, config: config_options.Config) -> dict:
123
131
# pattern to match pages included in output
124
132
self .match_path_pattern = compile (self .config .get ("match_path" ))
125
133
134
+ self .category_feeds = self .config .get ("category_feeds" )
135
+ self .category_feeds_dir = self .config .get ("category_feeds_dir" )
136
+
126
137
# date handling
127
138
if self .config .get ("date_from_meta" ) is not None :
128
139
self .src_date_created = self .config .get ("date_from_meta" ).get (
@@ -162,6 +173,7 @@ def on_config(self, config: config_options.Config) -> dict:
162
173
# create 2 final dicts
163
174
self .feed_created = deepcopy (base_feed )
164
175
self .feed_updated = deepcopy (base_feed )
176
+ self .category_feed = deepcopy (base_feed )
165
177
166
178
# final feed url
167
179
if base_feed .get ("html_url" ):
@@ -272,6 +284,41 @@ def on_page_content(
272
284
)
273
285
)
274
286
287
+ def render_feed (self , pretty_print : bool , feed_name : str , feed : dict ):
288
+ if pretty_print :
289
+ # load Jinja environment and template
290
+ env = Environment (
291
+ autoescape = select_autoescape (["html" , "xml" ]),
292
+ loader = FileSystemLoader (self .tpl_folder ),
293
+ )
294
+
295
+ template = env .get_template (self .tpl_file .name )
296
+
297
+ # write feed to file
298
+ with feed_name .open (mode = "w" , encoding = "UTF8" ) as fifeed :
299
+ fifeed .write (template .render (feed = feed ))
300
+ else :
301
+ # load Jinja environment and template
302
+ env = Environment (
303
+ autoescape = select_autoescape (["html" , "xml" ]),
304
+ loader = FileSystemLoader (self .tpl_folder ),
305
+ lstrip_blocks = True ,
306
+ trim_blocks = True ,
307
+ )
308
+ template = env .get_template (self .tpl_file .name )
309
+
310
+ # write feed to file stripping out spaces and new lines
311
+ with feed_name .open (mode = "w" , encoding = "UTF8" ) as fifeed :
312
+ prev_char = ""
313
+ for char in template .render (feed = feed ):
314
+ if char == "\n " :
315
+ continue
316
+ if char == " " and prev_char == " " :
317
+ prev_char = char
318
+ continue
319
+ prev_char = char
320
+ fifeed .write (char )
321
+
275
322
def on_post_build (self , config : config_options .Config ) -> dict :
276
323
"""The post_build event does not alter any variables. \
277
324
Use this event to call post-build scripts. \
@@ -312,52 +359,37 @@ def on_post_build(self, config: config_options.Config) -> dict:
312
359
)
313
360
)
314
361
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 )
341
-
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 )
362
+ # Render main feeds
363
+ self .render_feed (pretty_print , out_feed_created , self .feed_created )
364
+ self .render_feed (pretty_print , out_feed_updated , self .feed_updated )
365
+
366
+ # Render category feeds if enabled
367
+ if self .category_feeds :
368
+ feeds = {}
369
+ # collect feeds of pages per category
370
+ for page in self .pages_to_filter :
371
+ for category in page .categories :
372
+ feeds .setdefault (category , []).append (page )
373
+
374
+ # Ensure target directory exists
375
+ path = Path (config .get ("site_dir" )) / self .category_feeds_dir
376
+ os .makedirs (path , exist_ok = True )
377
+
378
+ for category , pages in feeds .items ():
379
+ # Create a feed per category
380
+ filename = f"{ category } .xml"
381
+ feed = deepcopy (self .category_feed )
382
+ feed ["rss_url" ] = (
383
+ self .category_feed .get ("html_url" )
384
+ + self .category_feeds_dir
385
+ + "/"
386
+ + filename
387
+ )
388
+ feed .get ("entries" ).extend (
389
+ self .util .filter_pages (
390
+ pages = pages ,
391
+ length = self .config .get ("length" , 20 ),
392
+ attribute = "created" ,
393
+ )
394
+ )
395
+ self .render_feed (pretty_print , path / filename , feed )
0 commit comments