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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sphinx_rustdoc_postprocess-0.1.0.tar.gz.
File metadata
- Download URL: sphinx_rustdoc_postprocess-0.1.0.tar.gz
- Upload date:
- Size: 88.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6da5c09df398159edc2c18e53c9fe524ece87bffed8bde9e3f826a7a37aa96c6
|
|
| MD5 |
869be9958f9628ad97859b386ca4c6d9
|
|
| BLAKE2b-256 |
14022f77f4bcb709891aeb9f970b9038f8c135a06e36affdc57e487c91b8b9d3
|
File details
Details for the file sphinx_rustdoc_postprocess-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sphinx_rustdoc_postprocess-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43dbf9e8e3a1115005b6523d5f06a33fb715cada953d70b79118372c100ae321
|
|
| MD5 |
d6889336f59438ce27cd42d372ae6b47
|
|
| BLAKE2b-256 |
cb659e4d9d8a49201572d197995675a6aac184645e3f1ec4670f66247a4c88ac
|