Module

rendering.plugins.directives.figure

Figure and audio embed directives for Bengal.

Provides directives for semantic media elements:

  • Figure: Semantic image with caption (<figure>/<figcaption>)
  • Audio: Self-hosted audio files with HTML5 audio element

Architecture:

FigureDirective provides semantic HTML structure for images with
proper accessibility handling (required alt text).

AudioDirective provides native HTML5 audio playback with fallbacks.

Accessibility:

  • Alt text is required for figure images (WCAG 2.1 AA)
  • Empty alt ("") supported for decorative images
  • Title required for audio elements

Related:

  • bengal/rendering/plugins/directives/base.py: BengalDirective
  • RFC: plan/active/rfc-media-embed-directives.md

Classes

FigureOptions dataclass
Options for semantic figure/image directive.
0

Options for semantic figure/image directive.

Inherits from DirectiveOptions

Attributes

Name Type Description
alt str

Required - Alt text for accessibility (empty string for decorative)

caption str

Optional caption text (markdown supported in render)

width str

Width (px or %)

height str

Height (px or %)

align str

Alignment - left, center, right

link str

URL to link image to

target str

Link target - _self, _blank (default: _self)

loading str

Loading strategy - lazy, eager (default: lazy)

css_class str

Additional CSS classes

_field_aliases ClassVar[dict[str, str]]
_allowed_values ClassVar[dict[str, list[str]]]
FigureDirective
Semantic figure directive for images with captions. Provides proper HTML5 semantic structure using…
3

Semantic figure directive for images with captions.

Provides proper HTML5 semantic structure using <figure> and <figcaption> elements with full accessibility support.

Syntax:

:::{figure} /images/architecture.png
:alt: System Architecture Diagram
:caption: High-level system architecture showing data flow
:width: 80%
:align: center
:::

Options:

:alt: (required) Alt text for image - empty string for decorative
:caption: Optional caption text below image
:width: Width (px or %)
:height: Height (px or %)
:align: Alignment - left, center, right
:link: URL to link image to
:target: Link target - _self, _blank (default: _self)
:loading: Loading strategy - lazy, eager (default: lazy)
:class: Additional CSS classes

Output:

<figure class="figure align-center" style="width: 80%">
  <img src="..." alt="..." loading="lazy">
  <figcaption>Caption text here</figcaption>
</figure>

Accessibility:

  • Alt text required (empty string allowed for decorative images)
  • Proper semantic structure with <figure>/<figcaption>
  • Caption provides additional context

Why not cards? The card workaround documented in Hugo migration lacks:

  • Semantic HTML (<figure> + <figcaption>)
  • Proper accessibility patterns (alt text handling)
  • Caption styling separate from body text
  • Standard width/align controls expected by content authors
Inherits from BengalDirective

Attributes

Name Type Description
NAMES ClassVar[list[str]]
TOKEN_TYPE ClassVar[str]
OPTIONS_CLASS ClassVar[type[DirectiveOptions]]
DIRECTIVE_NAMES ClassVar[list[str]]
PATH_PATTERN ClassVar[re.Pattern[str]]

Methods 3

validate_source
Validate image path/URL.
1 str | None
def validate_source(self, image_path: str) -> str | None

Validate image path/URL.

Parameters 1
image_path str
Returns

str | None

parse_directive
Build figure token.
5 DirectiveToken
def parse_directive(self, title: str, options: FigureOptions, content: str, children: list[Any], state: Any) -> DirectiveToken

Build figure token.

Parameters 5
title str
options FigureOptions
content str
children list[Any]
state Any
Returns

DirectiveToken

render
Render figure to HTML.
2 str
def render(self, renderer: Any, text: str, **attrs: Any) -> str

Render figure to HTML.

Parameters 2
renderer Any
text str
Returns

str

AudioOptions dataclass
Options for self-hosted audio embed.
0

Options for self-hosted audio embed.

Inherits from DirectiveOptions

Attributes

Name Type Description
title str

Required - Accessible title for audio element

controls bool

Show audio controls (default: true)

autoplay bool

Auto-start audio (not recommended) (default: false)

loop bool

Loop audio (default: false)

muted bool

Start muted (default: false)

preload str

Preload mode - none, metadata, auto (default: metadata)

css_class str

Additional CSS classes

_field_aliases ClassVar[dict[str, str]]
_allowed_values ClassVar[dict[str, list[str]]]
AudioDirective
Self-hosted audio directive using HTML5 audio element. Provides native audio playback for local or…
4

Self-hosted audio directive using HTML5 audio element.

Provides native audio playback for local or CDN-hosted audio files. Supports controls and accessibility requirements.

Syntax:

:::{audio} /assets/podcast-ep1.mp3
:title: Episode 1: Getting Started
:controls: true
:::

Options:

:title: (required) Accessible title for audio
:controls: Show audio controls (default: true)
:autoplay: Auto-start audio (not recommended) (default: false)
:loop: Loop audio (default: false)
:muted: Start muted (default: false)
:preload: Preload mode - none, metadata, auto (default: metadata)
:class: Additional CSS classes

Output:

<figure class="audio-embed">
  <audio title="..." controls preload="metadata">
    <source src="..." type="audio/mpeg">
    <p>Fallback text with download link</p>
  </audio>
</figure>

Supported formats (auto-detected from extension):

  • .mp3 (audio/mpeg)
  • .ogg (audio/ogg)
  • .wav (audio/wav)
  • .flac (audio/flac)
  • .m4a (audio/mp4)
  • .aac (audio/aac)
Inherits from BengalDirective

Attributes

Name Type Description
NAMES ClassVar[list[str]]
TOKEN_TYPE ClassVar[str]
OPTIONS_CLASS ClassVar[type[DirectiveOptions]]
DIRECTIVE_NAMES ClassVar[list[str]]
PATH_PATTERN ClassVar[re.Pattern[str]]
MIME_TYPES ClassVar[dict[str, str]]

Methods 3

validate_source
Validate audio path/URL.
1 str | None
def validate_source(self, audio_path: str) -> str | None

Validate audio path/URL.

Parameters 1
audio_path str
Returns

str | None

parse_directive
Build audio embed token.
5 DirectiveToken
def parse_directive(self, title: str, options: AudioOptions, content: str, children: list[Any], state: Any) -> DirectiveToken

Build audio embed token.

Parameters 5
title str
options AudioOptions
content str
children list[Any]
state Any
Returns

DirectiveToken

render
Render audio embed to HTML.
2 str
def render(self, renderer: Any, text: str, **attrs: Any) -> str

Render audio embed to HTML.

Parameters 2
renderer Any
text str
Returns

str

Internal Methods 1
_get_mime_type
Get MIME type from audio path extension.
1 str
def _get_mime_type(self, audio_path: str) -> str

Get MIME type from audio path extension.

Parameters 1
audio_path str
Returns

str