blob: 3b99949364d1029abf9fb0343ecddcf6ce0cd5a9 [file]
"""
Pelican plugin to generate a combined posts page with pagination.
Combines articles (solr/news, solr/security) with pages (solr/blogposts),
sorts them newest-first, and generates paginated output.
"""
from pelican import signals
from pelican.generators import Generator
from pelican.paginator import Paginator
from pelican.writers import Writer
import os
import logging
logger = logging.getLogger(__name__)
class CombinedPostsGenerator(Generator):
"""
Generator for creating a combined posts page with pagination.
Combines articles from 'solr/news' and 'solr/security' categories
with pages from 'solr/blogposts' category, sorts newest-first,
and generates paginated HTML pages.
"""
def generate_output(self, writer):
"""Generate paginated combined posts pages."""
# Get all articles and pages
articles = self.context.get('articles', [])
pages = self.context.get('pages', [])
# Filter and combine
# Include articles from news and security categories
combined_articles = [
a for a in articles
if hasattr(a, 'category') and a.category and
a.category.name in ['solr/news', 'solr/security']
]
# Include pages from blogposts category
combined_pages = [
p for p in pages
if hasattr(p, 'category') and p.category and
p.category.name == 'solr/blogposts'
]
# Combine all
combined_posts = combined_articles + combined_pages
# Sort by date, newest first
combined_posts.sort(key=lambda x: x.date, reverse=True)
# Get pagination settings
per_page = self.settings.get('COMBINED_POSTS_PER_PAGE', 20)
# Create paginator
paginator = Paginator('posts', 'posts{number}.html',
combined_posts, self.settings, per_page)
# Get the template
template = self.get_template('posts')
# Generate each page
for page_num in range(1, paginator.num_pages + 1):
posts_page = paginator.page(page_num)
# Build context
context = self.context.copy()
context.update({
'posts': posts_page.object_list,
'posts_page': posts_page,
'posts_paginator': paginator,
'page': posts_page, # For breadcrumb/metadata
'title': 'Posts',
'slug': 'posts',
})
# Determine output path
if page_num == 1:
output_path = os.path.join(self.output_path, 'posts.html')
url = 'posts.html'
else:
output_path = os.path.join(
self.output_path,
f'posts{page_num}.html'
)
url = f'posts{page_num}.html'
# Ensure output directory exists
os.makedirs(os.path.dirname(output_path), exist_ok=True)
# Render and write
output = template.render(context)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(output)
# Log
logger.info(f'Writing {url} ({page_num}/{paginator.num_pages})')
class SecurityNewsGenerator(Generator):
"""
Generator for creating a paginated security news page.
Lists only articles from the 'solr/security' category, sorted newest-first,
and generates security-news.html (+ security-newsN.html).
"""
def generate_output(self, writer):
"""Generate paginated security news pages."""
articles = self.context.get('articles', [])
security_articles = [
a for a in articles
if hasattr(a, 'category') and a.category and
a.category.name == 'solr/security'
]
security_articles.sort(key=lambda x: x.date, reverse=True)
per_page = self.settings.get('COMBINED_POSTS_PER_PAGE', 20)
paginator = Paginator('security-news', 'security-news{number}.html',
security_articles, self.settings, per_page)
template = self.get_template('security-news')
for page_num in range(1, paginator.num_pages + 1):
posts_page = paginator.page(page_num)
context = self.context.copy()
context.update({
'posts': posts_page.object_list,
'posts_page': posts_page,
'posts_paginator': paginator,
'page': posts_page,
'title': 'Solr Security News',
'slug': 'security-news',
})
if page_num == 1:
output_path = os.path.join(self.output_path, 'security-news.html')
url = 'security-news.html'
else:
output_path = os.path.join(
self.output_path,
f'security-news{page_num}.html'
)
url = f'security-news{page_num}.html'
os.makedirs(os.path.dirname(output_path), exist_ok=True)
output = template.render(context)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(output)
logger.info(f'Writing {url} ({page_num}/{paginator.num_pages})')
def get_generators(pelican):
"""Register the CombinedPostsGenerator and SecurityNewsGenerator."""
return [CombinedPostsGenerator, SecurityNewsGenerator]
def register():
"""Plugin registration hook."""
signals.get_generators.connect(get_generators)