0
# Content Generation
1
2
Generator classes that process different content types and produce output files through theme rendering, pagination, and content organization. Generators form the core processing pipeline of Pelican's site generation.
3
4
## Capabilities
5
6
### Base Generator Class
7
8
Foundation class for all content generators providing common functionality for template rendering, context management, and output generation.
9
10
```python { .api }
11
class Generator:
12
"""
13
Base class for all content generators.
14
15
Parameters:
16
- context (dict): Shared context between all generators
17
- settings (dict): Site configuration dictionary
18
- path (str): Content source directory path
19
- theme (str): Theme directory path
20
- output_path (str): Output directory path
21
- readers_cache_name (str, optional): Cache name for readers
22
"""
23
def __init__(
24
self,
25
context: dict,
26
settings: dict,
27
path: str,
28
theme: str,
29
output_path: str,
30
readers_cache_name: str = "",
31
**kwargs
32
): ...
33
34
# Core attributes available after initialization
35
context: dict # Shared context dictionary
36
settings: dict # Site settings
37
path: str # Content source path
38
theme: str # Theme path
39
output_path: str # Output directory
40
readers: Readers # Content readers instance
41
env: Environment # Jinja2 template environment
42
43
def generate_context(self) -> None:
44
"""Generate content and populate context."""
45
46
def generate_output(self, writer) -> None:
47
"""Generate output files using provided writer."""
48
```
49
50
### Articles Generator
51
52
Generates blog articles with automatic categorization, tagging, pagination, and archive creation.
53
54
```python { .api }
55
class ArticlesGenerator(CachingGenerator):
56
"""
57
Generator for blog articles and related pages.
58
59
Processes article content files and generates:
60
- Individual article pages
61
- Category pages with article listings
62
- Tag pages with article listings
63
- Author pages with article listings
64
- Archive pages (yearly, monthly, daily)
65
- Article pagination
66
- RSS/Atom feeds
67
"""
68
69
# Content collections (populated after generate_context())
70
articles: list[Article] # Published articles
71
translations: list[Article] # Article translations
72
drafts: list[Article] # Draft articles
73
drafts_translations: list[Article] # Draft translations
74
hidden_articles: list[Article] # Hidden articles
75
hidden_translations: list[Article] # Hidden translations
76
77
# Organizational collections
78
categories: list[tuple[Category, list[Article]]] # Categories with articles
79
tags: list[tuple[Tag, list[Article]]] # Tags with articles
80
authors: list[tuple[Author, list[Article]]] # Authors with articles
81
82
# Date-based archives
83
dates: list[Article] # Articles sorted by date
84
85
def generate_feeds(self) -> None:
86
"""Generate RSS/Atom feeds for articles."""
87
88
def generate_articles(self, write: callable) -> None:
89
"""Generate individual article pages."""
90
91
def generate_period_archives(self, write: callable) -> None:
92
"""Generate date-based archive pages."""
93
94
def generate_direct_templates(self, write: callable) -> None:
95
"""Generate direct template pages (index, tags, categories, authors, archives)."""
96
97
def generate_tags(self, write: callable) -> None:
98
"""Generate tag pages with article listings."""
99
100
def generate_categories(self, write: callable) -> None:
101
"""Generate category pages with article listings."""
102
103
def generate_authors(self, write: callable) -> None:
104
"""Generate author pages with article listings."""
105
```
106
107
### Pages Generator
108
109
Generates static pages for non-blog content with support for hierarchical organization and custom templates.
110
111
```python { .api }
112
class PagesGenerator(CachingGenerator):
113
"""
114
Generator for static pages.
115
116
Processes page content files and generates:
117
- Individual page files
118
- Page hierarchies and navigation
119
- Custom page templates
120
"""
121
122
# Content collections (populated after generate_context())
123
pages: list[Page] # Published pages
124
translations: list[Page] # Page translations
125
hidden_pages: list[Page] # Hidden pages
126
hidden_translations: list[Page] # Hidden translations
127
draft_pages: list[Page] # Draft pages
128
draft_translations: list[Page] # Draft translations
129
130
def generate_pages(self, write: callable) -> None:
131
"""Generate individual page files."""
132
```
133
134
### Static Generator
135
136
Handles static files by copying them from source to output directory with optional processing and linking.
137
138
```python { .api }
139
class StaticGenerator(Generator):
140
"""
141
Generator for static files (images, CSS, JS, etc.).
142
143
Copies static files from source directories to output directory.
144
Handles file modification detection and selective copying.
145
"""
146
147
# File collections (populated after generate_context())
148
staticfiles: list[Static] # Static file objects
149
150
def generate_output(self, writer) -> None:
151
"""Copy static files to output directory."""
152
```
153
154
### Template Pages Generator
155
156
Generates pages directly from Jinja2 templates without content files, useful for dynamic pages and special layouts.
157
158
```python { .api }
159
class TemplatePagesGenerator(Generator):
160
"""
161
Generator for template-based pages.
162
163
Generates pages directly from Jinja2 templates specified in TEMPLATE_PAGES setting.
164
Useful for complex layouts, landing pages, or pages with dynamic content.
165
"""
166
167
def generate_output(self, writer) -> None:
168
"""Generate pages from templates."""
169
```
170
171
### Source File Generator
172
173
Copies original source files to output directory for transparency and debugging purposes.
174
175
```python { .api }
176
class SourceFileGenerator(Generator):
177
"""
178
Generator for source file copies.
179
180
Copies original content source files to output directory when OUTPUT_SOURCES is enabled.
181
Useful for debugging, transparency, or allowing readers to view source markup.
182
"""
183
184
def generate_output(self, writer) -> None:
185
"""Copy source files to output directory."""
186
```
187
188
### Caching Generator Base
189
190
Base class for generators that support content caching for improved performance on large sites.
191
192
```python { .api }
193
class CachingGenerator(Generator, FileStampDataCacher):
194
"""
195
Base class for generators with file caching support.
196
197
Provides caching functionality to avoid reprocessing unchanged content files.
198
Used by ArticlesGenerator and PagesGenerator for performance optimization.
199
"""
200
201
def generate_context(self) -> None:
202
"""Generate content with caching support."""
203
204
def check_disabled_readers(self) -> None:
205
"""Check for disabled readers and warn about unprocessed files."""
206
```
207
208
## Generator Pipeline
209
210
The generation process follows this sequence:
211
212
1. **Context Generation**: Each generator populates the shared context with content
213
2. **Content Processing**: Readers parse source files into Content objects
214
3. **Metadata Processing**: Content metadata is processed and normalized
215
4. **URL Generation**: URLs and save paths are generated for all content
216
5. **Template Rendering**: Content is rendered using Jinja2 templates
217
6. **Output Writing**: Rendered content is written to output files
218
219
## Usage Examples
220
221
### Custom Generator
222
223
```python
224
from pelican.generators import Generator
225
226
class CustomGenerator(Generator):
227
"""Custom generator for special content processing."""
228
229
def generate_context(self):
230
"""Generate custom content and add to context."""
231
# Process custom content files
232
custom_content = self.process_custom_files()
233
234
# Add to shared context
235
self.context['custom_content'] = custom_content
236
237
def generate_output(self, writer):
238
"""Generate custom output files."""
239
for content in self.context['custom_content']:
240
writer.write_file(
241
content.save_as,
242
self.get_template(content.template),
243
self.context,
244
content=content
245
)
246
247
def process_custom_files(self):
248
"""Process custom content files."""
249
# Custom file processing logic
250
return []
251
```
252
253
### Accessing Generated Content
254
255
```python
256
# In a plugin or custom generator
257
def process_articles_generator(generator):
258
"""Process articles after generation."""
259
260
# Access all articles
261
for article in generator.articles:
262
print(f"Article: {article.title}")
263
print(f"URL: {article.url}")
264
print(f"Category: {article.category.name}")
265
266
# Access categories with articles
267
for category, articles in generator.categories:
268
print(f"Category: {category.name} ({len(articles)} articles)")
269
270
# Access tags with articles
271
for tag, articles in generator.tags:
272
print(f"Tag: {tag.name} ({len(articles)} articles)")
273
274
# Register with plugin system
275
from pelican.plugins import signals
276
signals.all_generators_finalized.connect(process_articles_generator)
277
```
278
279
### Generator Configuration
280
281
```python
282
# In pelicanconf.py - configure generator behavior
283
284
# Article generator settings
285
ARTICLE_URL = '{date:%Y}/{date:%m}/{slug}.html'
286
ARTICLE_SAVE_AS = '{date:%Y}/{date:%m}/{slug}.html'
287
DEFAULT_PAGINATION = 10
288
PAGINATED_TEMPLATES = {
289
'index': None,
290
'tag': None,
291
'category': None,
292
'author': None,
293
}
294
295
# Static generator settings
296
STATIC_PATHS = ['images', 'css', 'js', 'downloads']
297
STATIC_EXCLUDES = ['.DS_Store']
298
299
# Template pages
300
TEMPLATE_PAGES = {
301
'special.html': 'special-page.html',
302
'landing.html': 'index.html'
303
}
304
305
# Source file output
306
OUTPUT_SOURCES = True
307
OUTPUT_SOURCES_EXTENSION = '.txt'
308
```
309
310
### Custom Content Processing
311
312
```python
313
from pelican.generators import ArticlesGenerator
314
315
class EnhancedArticlesGenerator(ArticlesGenerator):
316
"""Enhanced articles generator with custom processing."""
317
318
def generate_context(self):
319
"""Generate context with custom enhancements."""
320
super().generate_context()
321
322
# Add custom processing
323
self.process_related_articles()
324
self.generate_reading_time()
325
326
def process_related_articles(self):
327
"""Add related articles to each article."""
328
for article in self.articles:
329
# Find related articles by tags
330
related = []
331
for other in self.articles:
332
if other != article and set(article.tags) & set(other.tags):
333
related.append(other)
334
article.related_articles = related[:5] # Limit to 5
335
336
def generate_reading_time(self):
337
"""Calculate reading time for articles."""
338
for article in self.articles:
339
word_count = len(article.content.split())
340
reading_time = max(1, word_count // 200) # ~200 words per minute
341
article.reading_time = reading_time
342
```