Skip to main content

sphinx-syntax-example

PyPI Docs CI

A Sphinx extension adding the syntax-example directive, which shows a block of markup as both its raw source and its rendered result.

The directive renders its content twice, stacked inside one framed box: a syntax-highlighted source pane showing what to type, and a render pane showing what it produces. It is useful for documentation that teaches a markup syntax, where readers need to see the input alongside the output.

Installation

Requires Python 3.11+ and Sphinx 7.2+.

pip install sphinx-syntax-example

Then add it to the extensions list in your conf.py:

extensions = [
    # ...
    "sphinx_syntax_example",
]

The extension ships a small, theme-agnostic stylesheet that is registered automatically on HTML builds (it defines its own colours with fallbacks that pick up the active theme's variables when present, and looks right on Furo in both light and dark modes).

Usage

Write a syntax-example directive with the markup you want to demonstrate as its content. An optional argument sets the title shown above the block (defaulting to Example):

.. syntax-example:: An optional title

   Any **reStructuredText** or MyST markup here.

The block above produces a framed box titled An optional title, containing the highlighted source Any **reStructuredText** or MyST markup here. and, below it, that markup rendered (with reStructuredText in bold).

Options and arguments

Part Description
(argument) The title shown as a rubric above the block. Defaults to Example; inline markup is parsed.
:highlight: Override the source pane's highlight language (for example :highlight: python).

If :highlight: is omitted, the language is inferred from the document's format via the project's configured source-suffix mapping (sphinx.util.get_filetype over source_suffix — the same knowledge Sphinx's router uses to pick the parser). A Markdown document yields a myst lexer when one is registered (as myst-parser registers) else markdown, and everything else yields rst. A :highlight: value naming a lexer added with app.add_lexer — one that exists only for your project, and so is invisible to Pygments' global registry — is honoured too. An unknown value falls back to the inferred language (with a verbose-level note) rather than failing a strict -W build.

Numbering

Config value Default Description
syntax_example_numbering False Number the examples in each document.

Titles are unnumbered by default. Set syntax_example_numbering = True in conf.py to have the default title become a numbered label, with any argument carried as a subtitle:

.. syntax-example::          →  Example 1
.. syntax-example:: Custom   →  Example 2: Custom

The counter restarts at 1 in each document, and each registered directive name counts independently, so a downstream alias never shares the run. Numbering only decorates a non-empty default title: a subclass whose default_title is "" is unaffected by the config value.

Either way the extension keeps no cross-document state. The counter lives in env.temp_data, which Sphinx replaces for each source file it reads — and a document is exactly the unit of both parallel reading and incremental rebuilding, so re-reading one changed file reproduces the numbers of a full build and nothing crosses between parallel workers.

Subclassing

Downstream packages that want an aliased directive (for example .. need-example:: with its own label, a different class prefix, or no title at all) subclass SyntaxExampleDirective and register the subclass under the alias name in a setup(app) of their own. Behaviour is customised through small named seams and class attributes, never by re-implementing run:

  • the class attributes default_title, wrapper_classes, source_classes and render_classes — the single source of the CSS classes on the three parts, applied by run itself;
  • default_language — how the source language is inferred;
  • format_title — the title/numbering seam (return None to drop the title, as a numbering-free myst-example would, or ignore syntax_example_numbering to number on your own terms);
  • build_title_node — how the resolved title becomes a node (return None to suppress the rubric element entirely);
  • build_wrapper_node and build_render_node — the node type and any extra attributes on the two containers, for a subclass needing something other than a plain container;
  • source_text — what the source pane shows;
  • render_into — what is nested-parsed into the render pane.

Two helpers exist for those overrides to call: per_document_number() returns the next number in the current document (keyed by the registered directive name, so aliases count independently), and nested_parse_text(text, container) parses a string of markup into a node using the host document's own parser.

source_text and render_into together are the seam for a "shown source differs from rendered output" directive: override source_text to return the shown text, and render_into to render the alternative output.

from docutils.parsers.rst import directives

from sphinx_syntax_example import SyntaxExampleDirective


class NumberedExample(SyntaxExampleDirective):
    """Numbered unconditionally, regardless of syntax_example_numbering."""

    def format_title(self, raw_title):
        return f"{raw_title or 'Example'} {self.per_document_number()}"


class AltOutputExample(SyntaxExampleDirective):
    """Shows verbatim source, renders something else.

    Takes the alternative markup from an ``:alt-output:`` option.
    """

    option_spec = {
        **SyntaxExampleDirective.option_spec,
        "alt-output": directives.unchanged,
    }

    def render_into(self, container):
        alternative = self.options.get("alt-output")
        if alternative is None:
            super().render_into(container)
        else:
            self.nested_parse_text(alternative, container)


def setup(app):
    app.add_directive("numbered-example", NumberedExample)
    app.add_directive("alt-example", AltOutputExample)

build_wrapper_node and build_render_node exist for renderers that must not emit a docutils container. A myst-parser-style example returns a sphinx-design div (is_div=True, design_component="div") instead, so that extension's container visitor writes <div class="myst-example docutils"> without the container class — keeping Bootstrap- and pydata-theme .container layout rules off the frame:

from docutils import nodes

from sphinx_syntax_example import SyntaxExampleDirective


class DivExample(SyntaxExampleDirective):
    wrapper_classes = ("myst-example",)
    render_classes = ("myst-example-render",)

    def build_wrapper_node(self):
        return nodes.container(is_div=True, design_component="div")

    def build_render_node(self):
        return nodes.container(is_div=True, design_component="div")

Return the bare node: these seams choose the node type and its extra attributes, and run applies the class attributes to whatever comes back (merging with any class the factory set). So an override neither has to repeat the classes nor can accidentally drop them and render unstyled.

The full override surface is documented in the module docstring.

The bespoke "example" directives shipped by sphinx-needs and myst-parser (each rendering source next to output) can be replaced by a subclass of this directive.

Contributing

See CONTRIBUTING.md.

Metadata

Release files for sphinx-syntax-example 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sphinx-syntax-example 0.2.0
File Size Uploaded Provenance Actions
sphinx_syntax_example-0.2.0.tar.gz 28.4 kB With provenance Details for sphinx_syntax_example-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for sphinx-syntax-example 0.2.0
File Interpreter ABI Platform Actions
sphinx_syntax_example-0.2.0-py3-none-any.whl Python 3 none any Details for sphinx_syntax_example-0.2.0-py3-none-any.whl

Total release size: 44.5 kB

Release files / sphinx_syntax_example-0.2.0.tar.gz

Download URL sphinx_syntax_example-0.2.0.tar.gz
Size 28.4 kB
Tags Source
SHA-256 checksum
How to use checksums
616d8862aec6e7818efcb2fdbd3cd9bcd8e5be47cc3d21300f9557719f7b07a9
BLAKE2b-256 checksum
How to use checksums
e2e4fe443fdf8a13e2a53daa309eaaa983996a614990b4d2ace37f6804ce928d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

Release files / sphinx_syntax_example-0.2.0-py3-none-any.whl

Download URL sphinx_syntax_example-0.2.0-py3-none-any.whl
Size 16.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e2ff213562e5c2148f2bd76a904dd90153329e83ef3883b2949bcdaaff9af4b4
BLAKE2b-256 checksum
How to use checksums
86ffa6c6ab520fefd9f786b1c86480524929ed5a02077e4d2dc4a437a15a76ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

Security for sphinx-syntax-example 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for sphinx_syntax_example-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page