Module

rendering.renderer

Renderer for converting pages to final HTML output.

Handles individual page rendering using templates, markdown processing, and content transformation. Integrates with template engine for Jinja2 rendering and provides error handling with graceful degradation.

Key Concepts:

  • Template rendering: Jinja2 template rendering with page context
  • Markdown processing: Markdown to HTML conversion
  • Content transformation: Link rewriting, image processing, etc.
  • Error handling: Graceful error handling with error pages

Related Modules:

  • bengal.rendering.template_engine: Template engine for Jinja2 rendering
  • bengal.rendering.parsers.mistune: Markdown parser
  • bengal.rendering.link_transformer: Link transformation logic

See Also:

  • bengal/rendering/renderer.py: Renderer class for rendering logic
  • plan/active/rfc-template-performance-optimization.md: Performance RFC

Classes

Renderer
Renders individual pages using templates and content processing. Handles template rendering, conte…
8

Renders individual pages using templates and content processing.

Handles template rendering, content processing (H1 stripping), and error collection. Integrates with template engine for Jinja2 rendering and provides graceful error handling.

Creation:

Direct instantiation: Renderer(template_engine, build_stats=None)
  • Created by RenderingPipeline for page rendering
  • Requires TemplateEngine instance

Attributes

Name Type Description
template_engine

TemplateEngine instance for Jinja2 rendering

site

Site instance (accessed via template_engine.site)

build_stats

Optional BuildStats for error collection

Relationships
  • Uses: TemplateEngine for template rendering - Uses: BuildStats for error collection - Used by: RenderingPipeline for page rendering Thread Safety: Thread-safe. Each thread should have its own Renderer instance.

Methods 2

render_content
Render raw content (already parsed HTML). Automatically strips the first H1 ta…
1 str
def render_content(self, content: str) -> str

Render raw content (already parsed HTML).

Automatically strips the first H1 tag to avoid duplication with the template-rendered title.

Parameters 1
content str

Parsed HTML content

Returns

str

Content with first H1 removed

render_page
Render a complete page with template. Architecture: 1. Builds initial context …
2 str
def render_page(self, page: Page, content: str | None = None) -> str

Render a complete page with template.

Architecture:

  1. Builds initial context (metadata, TOC, content)
  2. Adds specialized context based on page type:
    • Generated pages (tags/archives): Adds filteredpostslist
    • Section pages: Adds section-specificposts
    • Root index: Adds top-level pages
  3. Renders using Jinja2 template

Conflict Prevention:

Logic strictly separates "Root Index" (home page) from "Generated Index" (tag pages). Tag pages often have source paths liketags/foo/index.md(is_index_page=True) but must NOT use the root home page logic which overwrites theirpostslist.

Parameters 2
page Page

Page to render

content str | None

Optional pre-rendered content (uses page.parsed_ast if not provided)

Returns

str

Fully rendered HTML page

Internal Methods 6
__init__
Initialize the renderer.
2 None
def __init__(self, template_engine: Any, build_stats: Any = None) -> None

Initialize the renderer.

Parameters 2
template_engine Any

Template engine instance

build_stats Any

Optional BuildStats object for error collection

_strip_first_h1
Remove the first H1 tag from HTML content. This prevents duplication when temp…
1 str
def _strip_first_h1(self, content: str) -> str

Remove the first H1 tag from HTML content.

This prevents duplication when templates render {{ page.title }} as H1 and the markdown also contains an H1 heading.

Parameters 1
content str

HTML content

Returns

str

Content with first H1 tag removed

_add_generated_page_context
Add special context variables for generated pages (archives, tags, etc.).
2 None
def _add_generated_page_context(self, page: Page, context: dict[str, Any]) -> None

Add special context variables for generated pages (archives, tags, etc.).

Parameters 2
page Page

Page being rendered

context dict[str, Any]

Template context to update

_get_template_name
Determine which template to use for a page. Priority order: 1. Explicit templa…
1 str
def _get_template_name(self, page: Page) -> str

Determine which template to use for a page.

Priority order:

  1. Explicit template in frontmatter (template: doc.html)
  2. Content type strategy (delegates to strategy.get_template())
  3. Section-based auto-detection (e.g.,docs.html,docs/single.html)
  4. Default fallback (page.htmlorindex.html)

Note: We use a simple, explicit template selection strategy without complex type/kind/layout hierarchies.

Parameters 1
page Page

Page to get template for

Returns

str

Template name

_template_exists
Check if a template exists in any template directory.
1 bool
def _template_exists(self, template_name: str) -> bool

Check if a template exists in any template directory.

Parameters 1
template_name str

Template filename or path

Returns

bool

True if template exists, False otherwise

_render_fallback
Render a fallback HTML page with basic styling. When the main template fails, …
2 str
def _render_fallback(self, page: Page, content: str) -> str

Render a fallback HTML page with basic styling.

When the main template fails, we still try to produce a usable page with basic CSS and structure (though without partials/navigation).

Parameters 2
page Page

Page to render

content str

Page content

Returns

str

Fallback HTML page with minimal styling