5
5
# ##################################
6
6
7
7
# standard library
8
+ import os
8
9
import logging
9
10
from copy import deepcopy
10
11
from datetime import datetime
@@ -58,6 +59,8 @@ class GitRssPlugin(BasePlugin):
58
59
("match_path" , config_options .Type (str , default = ".*" )),
59
60
("pretty_print" , config_options .Type (bool , default = False )),
60
61
("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" ))
61
64
)
62
65
63
66
def __init__ (self ):
@@ -71,9 +74,13 @@ def __init__(self):
71
74
self .meta_default_time = None
72
75
# pages storage
73
76
self .pages_to_filter = []
77
+ # config
78
+ self .category_feeds = False
79
+ self .category_feeds_dir = "rss"
74
80
# prepare output feeds
75
81
self .feed_created = dict
76
82
self .feed_updated = dict
83
+ self .category_feed = dict
77
84
78
85
def on_config (self , config : config_options .Config ) -> dict :
79
86
"""The config event is the first event called on build and
@@ -123,6 +130,9 @@ def on_config(self, config: config_options.Config) -> dict:
123
130
# pattern to match pages included in output
124
131
self .match_path_pattern = compile (self .config .get ("match_path" ))
125
132
133
+ self .category_feeds = self .config .get ("category_feeds" )
134
+ self .category_feeds_dir = self .config .get ("category_feeds_dir" )
135
+
126
136
# date handling
127
137
if self .config .get ("date_from_meta" ) is not None :
128
138
self .src_date_created = self .config .get ("date_from_meta" ).get (
@@ -162,6 +172,7 @@ def on_config(self, config: config_options.Config) -> dict:
162
172
# create 2 final dicts
163
173
self .feed_created = deepcopy (base_feed )
164
174
self .feed_updated = deepcopy (base_feed )
175
+ self .category_feed = deepcopy (base_feed )
165
176
166
177
# final feed url
167
178
if base_feed .get ("html_url" ):
@@ -272,6 +283,41 @@ def on_page_content(
272
283
)
273
284
)
274
285
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
+
275
321
def on_post_build (self , config : config_options .Config ) -> dict :
276
322
"""The post_build event does not alter any variables. \
277
323
Use this event to call post-build scripts. \
@@ -312,52 +358,32 @@ def on_post_build(self, config: config_options.Config) -> dict:
312
358
)
313
359
)
314
360
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 )
341
389
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 )
0 commit comments