Skip to main content

Post-process sphinxcontrib-rust RST output, converting leftover markdown to proper RST via pandoc.

Project description

sphinx-rustdoc-postprocess

Post-process sphinxcontrib-rust RST output, converting leftover markdown fragments (code fences, tables, links, headings, inline code) to proper RST via pandoc.

The problem

sphinxcontrib-rust generates RST files from Rust crates, but rustdoc doc-comments are written in markdown. The generated RST ends up with markdown fragments embedded verbatim inside directive bodies, which Sphinx cannot render correctly.

For a real-world example, see rgpot (source), which uses this extension to document its Rust core library alongside C++ API docs.

Before (raw sphinxcontrib-rust output)

Given Rust doc-comments like these in lib.rs:

//! ## Module Overview
//!
//! | Module | Purpose |
//! |--------|---------|
//! | [`types`] | `#[repr(C)]` data structures for force/energy I/O |
//! | [`tensor`] | DLPack tensor helpers |

sphinxcontrib-rust produces RST with the markdown still intact inside directives:

.. py:module:: rgpot_core

   ## Module Overview

   | Module | Purpose |
   |--------|---------|
   | [`types`] | `#[repr(C)]` data structures for force/energy I/O |
   | [`tensor`] | DLPack tensor helpers |

This renders incorrectly in Sphinx: headings inside directives break the document structure, markdown tables appear as literal pipe characters, and single-backtick code is not valid RST.

After (postprocessed output)

After this extension runs, the same file becomes:

.. py:module:: rgpot_core

   **Module Overview**

   +------------+----------------------------------------------------+
   | Module     | Purpose                                            |
   +============+====================================================+
   | ``types``  | ``#[repr(C)]`` data structures for force/energy IO |
   +------------+----------------------------------------------------+
   | ``tensor`` | DLPack tensor helpers                              |
   +------------+----------------------------------------------------+

Similarly, markdown code fences:

```c
rgpot_status_t s = rgpot_potential_calculate(pot, &input, &output);
if (s != RGPOT_SUCCESS) {
    fprintf(stderr, "rgpot error: %s\n", rgpot_last_error());
}
```

become proper RST code-block directives:

.. code-block:: c

   rgpot_status_t s = rgpot_potential_calculate(pot, &input, &output);
   if (s != RGPOT_SUCCESS) {
       fprintf(stderr, "rgpot error: %s\n", rgpot_last_error());
   }

And markdown links like [metatensor](https://docs.metatensor.org/) become `metatensor <https://docs.metatensor.org/>`_, while rustdoc intra-doc links like [`types`] become types .

Installation

pip install sphinx-rustdoc-postprocess

Pandoc must be available on your PATH. See pandoc.org for installation instructions.

Usage

Add to your Sphinx conf.py:

extensions = [
    "sphinxcontrib_rust",
    "sphinx_rustdoc_postprocess",
]

The extension hooks into builder-inited at priority 600 (after sphinxcontrib-rust's default 500), so it automatically runs on the generated RST files before Sphinx reads them.

Configuration

Config value Default Description
rustdoc_postprocess_rst_dir "crates" Subdirectory of srcdir to scan for RST files
rustdoc_postprocess_toctree_target "" RST file to inject a toctree snippet into (empty = skip)
rustdoc_postprocess_toctree_rst "" RST snippet to append to the target file (empty = skip)

Full configuration example

# conf.py
import os

extensions = [
    "sphinxcontrib_rust",
    "sphinx_rustdoc_postprocess",
]

# sphinxcontrib-rust settings
rust_crates = {
    "my_crate": os.path.abspath("../../my-crate/"),
}
rust_doc_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "crates")
rust_rustdoc_fmt = "rst"

# Inject a toctree entry for the Rust docs into an existing index page
rustdoc_postprocess_toctree_target = "api/index.rst"
rustdoc_postprocess_toctree_rst = """

Rust API
--------

.. toctree::
   :maxdepth: 2

   ../crates/my_crate/lib
"""

What gets converted

Markdown construct RST output
```lang code fences .. code-block:: lang directives
\vert table \vert pipe tables RST grid tables (via pandoc)
[text](url) links `text <url>`_
[`Name`] intra-doc links ``Name``
`code` inline code ``code``
## Heading ATX headings **Heading** (bold, since RST headings can't nest in directives)

Development

pixi install
pixi run test

A pre-commit job is setup on CI to enforce consistent styles, so it is best to set it up locally as well (using uvx for isolation):

# Run before committing
uvx pre-commit run --all-files

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sphinx_rustdoc_postprocess-0.1.0.tar.gz (88.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sphinx_rustdoc_postprocess-0.1.0-py3-none-any.whl (7.8 kB view details)

Uploaded Python 3

File details

Details for the file sphinx_rustdoc_postprocess-0.1.0.tar.gz.

File metadata

File hashes

Hashes for sphinx_rustdoc_postprocess-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6da5c09df398159edc2c18e53c9fe524ece87bffed8bde9e3f826a7a37aa96c6
MD5 869be9958f9628ad97859b386ca4c6d9
BLAKE2b-256 14022f77f4bcb709891aeb9f970b9038f8c135a06e36affdc57e487c91b8b9d3

See more details on using hashes here.

File details

Details for the file sphinx_rustdoc_postprocess-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for sphinx_rustdoc_postprocess-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 43dbf9e8e3a1115005b6523d5f06a33fb715cada953d70b79118372c100ae321
MD5 d6889336f59438ce27cd42d372ae6b47
BLAKE2b-256 cb659e4d9d8a49201572d197995675a6aac184645e3f1ec4670f66247a4c88ac

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page