CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pelican

Static site generator supporting Markdown and reStructuredText

Pending
Overview
Eval results
Files

content-generation.mddocs/

Content Generation

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.

Capabilities

Base Generator Class

Foundation class for all content generators providing common functionality for template rendering, context management, and output generation.

class Generator:
    """
    Base class for all content generators.
    
    Parameters:
    - context (dict): Shared context between all generators
    - settings (dict): Site configuration dictionary
    - path (str): Content source directory path
    - theme (str): Theme directory path
    - output_path (str): Output directory path
    - readers_cache_name (str, optional): Cache name for readers
    """
    def __init__(
        self,
        context: dict,
        settings: dict,
        path: str,
        theme: str,
        output_path: str,
        readers_cache_name: str = "",
        **kwargs
    ): ...
    
    # Core attributes available after initialization
    context: dict         # Shared context dictionary
    settings: dict        # Site settings
    path: str            # Content source path
    theme: str           # Theme path
    output_path: str     # Output directory
    readers: Readers     # Content readers instance
    env: Environment     # Jinja2 template environment

def generate_context(self) -> None:
        """Generate content and populate context."""
    
    def generate_output(self, writer) -> None:
        """Generate output files using provided writer."""

Articles Generator

Generates blog articles with automatic categorization, tagging, pagination, and archive creation.

class ArticlesGenerator(CachingGenerator):
    """
    Generator for blog articles and related pages.
    
    Processes article content files and generates:
    - Individual article pages
    - Category pages with article listings
    - Tag pages with article listings  
    - Author pages with article listings
    - Archive pages (yearly, monthly, daily)
    - Article pagination
    - RSS/Atom feeds
    """
    
    # Content collections (populated after generate_context())
    articles: list[Article]              # Published articles
    translations: list[Article]          # Article translations
    drafts: list[Article]               # Draft articles
    drafts_translations: list[Article]  # Draft translations
    hidden_articles: list[Article]      # Hidden articles
    hidden_translations: list[Article]  # Hidden translations
    
    # Organizational collections
    categories: list[tuple[Category, list[Article]]]  # Categories with articles
    tags: list[tuple[Tag, list[Article]]]            # Tags with articles
    authors: list[tuple[Author, list[Article]]]      # Authors with articles
    
    # Date-based archives
    dates: list[Article]                 # Articles sorted by date
    
    def generate_feeds(self) -> None:
        """Generate RSS/Atom feeds for articles."""
    
    def generate_articles(self, write: callable) -> None:
        """Generate individual article pages."""
    
    def generate_period_archives(self, write: callable) -> None:
        """Generate date-based archive pages."""
    
    def generate_direct_templates(self, write: callable) -> None:
        """Generate direct template pages (index, tags, categories, authors, archives)."""
    
    def generate_tags(self, write: callable) -> None:
        """Generate tag pages with article listings."""
    
    def generate_categories(self, write: callable) -> None:
        """Generate category pages with article listings."""
    
    def generate_authors(self, write: callable) -> None:
        """Generate author pages with article listings."""

Pages Generator

Generates static pages for non-blog content with support for hierarchical organization and custom templates.

class PagesGenerator(CachingGenerator):
    """
    Generator for static pages.
    
    Processes page content files and generates:
    - Individual page files
    - Page hierarchies and navigation
    - Custom page templates
    """
    
    # Content collections (populated after generate_context())
    pages: list[Page]                    # Published pages
    translations: list[Page]             # Page translations
    hidden_pages: list[Page]             # Hidden pages
    hidden_translations: list[Page]      # Hidden translations
    draft_pages: list[Page]              # Draft pages
    draft_translations: list[Page]       # Draft translations
    
    def generate_pages(self, write: callable) -> None:
        """Generate individual page files."""

Static Generator

Handles static files by copying them from source to output directory with optional processing and linking.

class StaticGenerator(Generator):
    """
    Generator for static files (images, CSS, JS, etc.).
    
    Copies static files from source directories to output directory.
    Handles file modification detection and selective copying.
    """
    
    # File collections (populated after generate_context())
    staticfiles: list[Static]            # Static file objects
    
    def generate_output(self, writer) -> None:
        """Copy static files to output directory."""

Template Pages Generator

Generates pages directly from Jinja2 templates without content files, useful for dynamic pages and special layouts.

class TemplatePagesGenerator(Generator):
    """
    Generator for template-based pages.
    
    Generates pages directly from Jinja2 templates specified in TEMPLATE_PAGES setting.
    Useful for complex layouts, landing pages, or pages with dynamic content.
    """
    
    def generate_output(self, writer) -> None:
        """Generate pages from templates."""

Source File Generator

Copies original source files to output directory for transparency and debugging purposes.

class SourceFileGenerator(Generator):
    """
    Generator for source file copies.
    
    Copies original content source files to output directory when OUTPUT_SOURCES is enabled.
    Useful for debugging, transparency, or allowing readers to view source markup.
    """
    
    def generate_output(self, writer) -> None:
        """Copy source files to output directory."""

Caching Generator Base

Base class for generators that support content caching for improved performance on large sites.

class CachingGenerator(Generator, FileStampDataCacher):
    """
    Base class for generators with file caching support.
    
    Provides caching functionality to avoid reprocessing unchanged content files.
    Used by ArticlesGenerator and PagesGenerator for performance optimization.
    """
    
    def generate_context(self) -> None:
        """Generate content with caching support."""
    
    def check_disabled_readers(self) -> None:
        """Check for disabled readers and warn about unprocessed files."""

Generator Pipeline

The generation process follows this sequence:

  1. Context Generation: Each generator populates the shared context with content
  2. Content Processing: Readers parse source files into Content objects
  3. Metadata Processing: Content metadata is processed and normalized
  4. URL Generation: URLs and save paths are generated for all content
  5. Template Rendering: Content is rendered using Jinja2 templates
  6. Output Writing: Rendered content is written to output files

Usage Examples

Custom Generator

from pelican.generators import Generator

class CustomGenerator(Generator):
    """Custom generator for special content processing."""
    
    def generate_context(self):
        """Generate custom content and add to context."""
        # Process custom content files
        custom_content = self.process_custom_files()
        
        # Add to shared context
        self.context['custom_content'] = custom_content
    
    def generate_output(self, writer):
        """Generate custom output files."""
        for content in self.context['custom_content']:
            writer.write_file(
                content.save_as,
                self.get_template(content.template),
                self.context,
                content=content
            )
    
    def process_custom_files(self):
        """Process custom content files."""
        # Custom file processing logic
        return []

Accessing Generated Content

# In a plugin or custom generator
def process_articles_generator(generator):
    """Process articles after generation."""
    
    # Access all articles
    for article in generator.articles:
        print(f"Article: {article.title}")
        print(f"URL: {article.url}")
        print(f"Category: {article.category.name}")
    
    # Access categories with articles
    for category, articles in generator.categories:
        print(f"Category: {category.name} ({len(articles)} articles)")
    
    # Access tags with articles
    for tag, articles in generator.tags:
        print(f"Tag: {tag.name} ({len(articles)} articles)")

# Register with plugin system
from pelican.plugins import signals
signals.all_generators_finalized.connect(process_articles_generator)

Generator Configuration

# In pelicanconf.py - configure generator behavior

# Article generator settings
ARTICLE_URL = '{date:%Y}/{date:%m}/{slug}.html'
ARTICLE_SAVE_AS = '{date:%Y}/{date:%m}/{slug}.html'
DEFAULT_PAGINATION = 10
PAGINATED_TEMPLATES = {
    'index': None,
    'tag': None,
    'category': None,
    'author': None,
}

# Static generator settings
STATIC_PATHS = ['images', 'css', 'js', 'downloads']
STATIC_EXCLUDES = ['.DS_Store']

# Template pages
TEMPLATE_PAGES = {
    'special.html': 'special-page.html',
    'landing.html': 'index.html'
}

# Source file output
OUTPUT_SOURCES = True
OUTPUT_SOURCES_EXTENSION = '.txt'

Custom Content Processing

from pelican.generators import ArticlesGenerator

class EnhancedArticlesGenerator(ArticlesGenerator):
    """Enhanced articles generator with custom processing."""
    
    def generate_context(self):
        """Generate context with custom enhancements."""
        super().generate_context()
        
        # Add custom processing
        self.process_related_articles()
        self.generate_reading_time()
    
    def process_related_articles(self):
        """Add related articles to each article."""
        for article in self.articles:
            # Find related articles by tags
            related = []
            for other in self.articles:
                if other != article and set(article.tags) & set(other.tags):
                    related.append(other)
            article.related_articles = related[:5]  # Limit to 5
    
    def generate_reading_time(self):
        """Calculate reading time for articles."""
        for article in self.articles:
            word_count = len(article.content.split())
            reading_time = max(1, word_count // 200)  # ~200 words per minute
            article.reading_time = reading_time

Install with Tessl CLI

npx tessl i tessl/pypi-pelican

docs

cli-tools.md

content-generation.md

content-management.md

content-reading.md

index.md

main-application.md

plugin-system.md

settings-configuration.md

utilities.md

tile.json