or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-tools.mdcontent-generation.mdcontent-management.mdcontent-reading.mdindex.mdmain-application.mdplugin-system.mdsettings-configuration.mdutilities.md

content-generation.mddocs/

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

```