Module

rendering.plugins.directives.steps

Steps directive for Mistune.

Provides visual step-by-step guides using nested directives.

Architecture:

Migrated to BengalDirective base class with DirectiveContract validation.
This demonstrates the contract system for enforcing valid nesting:
  • StepsDirective: requires_children=["step"]
  • StepDirective: requires_parent=["steps"]

Syntax (preferred - named closers, no colon counting): :::{steps} :start: 1

:::{step} Step Title
:description: Brief context before diving into the step content.
:duration: 5 min
Step 1 content with **markdown** and nested directives.
:::{/step}

:::{step} Optional Step
:optional:
This step can be skipped.
:::{/step}
:::{/steps}

Legacy syntax (fence-depth counting - still works): ::::{steps} :::{step} Step Title Step 1 content ::: ::::

Steps Container Options:

:class: - Custom CSS class for the steps container
:style: - Visual style (default, compact)
:start: - Start numbering from this value (default: 1)

Step Options:

:class: - Custom CSS class for the step
:description: - Lead-in text with special typography (rendered before main content)
:optional: - Mark step as optional/skippable (adds visual indicator)
:duration: - Estimated time for the step (e.g., "5 min", "1 hour")

Classes

StepOptions dataclass
Options for step directive.
0

Options for step directive.

Inherits from DirectiveOptions

Attributes

Name Type Description
css_class str

Custom CSS class for the step

description str

Lead-in text with special typography (rendered before main content)

optional bool

Mark step as optional/skippable (adds visual indicator)

duration str

Estimated time for the step (e.g., "5 min", "1 hour")

_field_aliases ClassVar[dict[str, str]]
StepDirective
Individual step directive (nested in steps). Syntax: :::{step} Optional Title :class: cust…
4

Individual step directive (nested in steps).

Syntax:

:::{step} Optional Title
:class: custom-class
Step content with **markdown** and nested directives.
:::

Contract:

MUST be nested inside a :::{steps} directive.
If used outside steps, a warning is logged.
Inherits from BengalDirective

Attributes

Name Type Description
NAMES ClassVar[list[str]]
TOKEN_TYPE ClassVar[str]
OPTIONS_CLASS ClassVar[type[DirectiveOptions]]
CONTRACT ClassVar[DirectiveContract]
DIRECTIVE_NAMES ClassVar[list[str]]

Methods 2

parse_directive
Build step token from parsed components. Title becomes the step heading, conte…
5 DirectiveToken
def parse_directive(self, title: str, options: StepOptions, content: str, children: list[Any], state: Any) -> DirectiveToken

Build step token from parsed components.

Title becomes the step heading, content is parsed as markdown. Description (if provided) renders as lead-in text with special typography. Optional and duration add visual indicators.

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

DirectiveToken

render
Render individual step to HTML. Step titles are rendered as headings (h2/h3/h4…
2 str
def render(self, renderer: Any, text: str, **attrs: Any) -> str

Render individual step to HTML.

Step titles are rendered as headings (h2/h3/h4) based on parent level. Step markers are rendered as anchor links for direct navigation. Descriptions are rendered as lead-in text with special typography. Optional steps get a visual indicator. Duration is shown as a time estimate badge.

Parameters 2
renderer Any
text str
Returns

str

Internal Methods 2
_parse_inline_markdown staticmethod
Parse inline markdown in step titles. Tries mistune's inline parser first, fal…
2 str
def _parse_inline_markdown(renderer: Any, text: str) -> str

Parse inline markdown in step titles.

Tries mistune's inline parser first, falls back to regex.

Parameters 2
renderer Any
text str
Returns

str

_slugify staticmethod
Convert text to URL-safe slug for anchor IDs. Converts to lowercase, replaces …
1 str
def _slugify(text: str) -> str

Convert text to URL-safe slug for anchor IDs.

Converts to lowercase, replaces spaces with hyphens, removes non-alphanumeric characters except hyphens.

Parameters 1
text str
Returns

str

StepsOptions dataclass
Options for steps container directive.
0

Options for steps container directive.

Inherits from DirectiveOptions

Attributes

Name Type Description
css_class str

Custom CSS class for the steps container

style str

Step style (compact, default)

start int

Start numbering from this value (default: 1)

_field_aliases ClassVar[dict[str, str]]
_allowed_values ClassVar[dict[str, list[str]]]
StepsDirective
Steps directive for visual step-by-step guides. Syntax (preferred - supports nested directives): …
4

Steps directive for visual step-by-step guides.

Syntax (preferred - supports nested directives): ::::{steps} :class: custom-class :style: compact

:::{step} Step 1 Title
Step 1 content with nested :::{tip} directives
:::

:::{step} Step 2 Title
Step 2 content
:::
::::

Note: Parent container (steps) uses 4 colons, nested steps use 3 colons.

Contract:

REQUIRES at least one :::{step} child directive.
If no steps found, a warning is logged.
Inherits from BengalDirective

Attributes

Name Type Description
NAMES ClassVar[list[str]]
TOKEN_TYPE ClassVar[str]
OPTIONS_CLASS ClassVar[type[DirectiveOptions]]
CONTRACT ClassVar[DirectiveContract]
DIRECTIVE_NAMES ClassVar[list[str]]

Methods 2

parse_directive
Build steps token from parsed components. Injects heading_level and step_numbe…
5 DirectiveToken
def parse_directive(self, title: str, options: StepsOptions, content: str, children: list[Any], state: Any) -> DirectiveToken

Build steps token from parsed components.

Injects heading_level and step_number into child step tokens for proper semantic HTML and anchor link support.

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

DirectiveToken

render
Render steps container to HTML. Wraps step list items in <ol> if present. Supp…
2 str
def render(self, renderer: Any, text: str, **attrs: Any) -> str

Render steps container to HTML.

Wraps step list items in <ol> if present. Supports custom start number for continuing numbered lists.

Parameters 2
renderer Any
text str
Returns

str

Internal Methods 2
_inject_step_metadata
Inject heading_level and step_number into step tokens. This allows step titles…
3 list[Any]
def _inject_step_metadata(self, children: list[Any], heading_level: int, start: int) -> list[Any]

Inject heading_level and step_number into step tokens.

This allows step titles to render as proper headings (h2/h3/h4) and step markers to be anchor links with the correct number.

Parameters 3
children list[Any]
heading_level int
start int
Returns

list[Any]

_detect_heading_level
Detect the current heading level from parser state. Steps should render step t…
1 int
def _detect_heading_level(self, state: Any) -> int

Detect the current heading level from parser state.

Steps should render step titles as headings one level deeper than the parent heading (h1 -> h2, h2 -> h3, etc.).

Returns the heading level (2-6) that steps should use. Defaults to h2 if no heading context found.

Parameters 1
state Any
Returns

int

Functions

render_step
Legacy render function for backward compatibility.
2 str
def render_step(renderer: Any, text: str, **attrs: Any) -> str

Legacy render function for backward compatibility.

Parameters 2

Name Type Default Description
renderer Any
text str

Returns

str

render_steps
Legacy render function for backward compatibility.
2 str
def render_steps(renderer: Any, text: str, **attrs: Any) -> str

Legacy render function for backward compatibility.

Parameters 2

Name Type Default Description
renderer Any
text str

Returns

str