sphinxcontrib-archware
A Sphinx extension that renders bytefield and register LaTeX diagrams as inline SVG in HTML output.
The directive body is raw LaTeX. The extension compiles it on the fly using your local TeX installation and splices the resulting SVG directly into the HTML page — no external images, no JavaScript.
For LaTeX output the source is passed through unchanged, so your PDF builds continue to use the native package rendering without any intermediate step.
Requirements
Requirement |
Notes |
|---|---|
Python >= 3.9 |
|
Sphinx >= 5.0 |
|
A TeX distribution |
|
|
Recommended path — see Build pipeline. Both included in a full TeX Live install. |
|
Fallback path. Converter can be Inkscape >= 1.0, dvisvgm >= 2.9, or pdf2svg. |
|
Available in TeX Live as part of |
|
Available in TeX Live as part of |
Installation
Install from PyPI:
pip install sphinxcontrib-archware
Then register the extension in conf.py:
extensions = [
"sphinxcontrib.archware",
]
The package lives under the sphinxcontrib namespace and is structured
as follows:
sphinxcontrib/
archware/
__init__.py ← Sphinx setup() entry point
pipeline.py ← shared LaTeX-to-SVG compilation pipeline
bytefield.py ← bytefield directive, node, and visitors
register.py ← register, regdesc, and listofregisters
Directives
.. bytefield::
Renders a bytefield packet or register diagram.
The directive body contains only the row commands
(\bitheader, \bitbox, \wordbox, etc.).
The \begin{bytefield}[options]{bitwidth} / \end{bytefield} wrapper
is added automatically from :bitwidth: and :options:.
Do not include the bytefield environment in the body.
.. bytefield::
:bitwidth: <n>
:options: <bytefield environment options>
:packages: <pkg1>, <pkg2>, ...
:align: left | center | right
:caption: <text>
:scale: <0-100>
:border: <TeX length>
\bitheader{...} \\
\bitbox{...}{...} ...
Option |
Type |
Default |
Description |
|---|---|---|---|
|
positive integer |
required |
Width of the diagram in bits. Used as the mandatory argument to
|
|
string |
(none) |
Inserted verbatim as the optional argument of the |
|
string |
(none) |
Comma-separated list of extra LaTeX packages to load,
e.g. |
|
|
|
Horizontal alignment of the diagram within the page. |
|
string |
(none) |
Text rendered as a |
|
integer 0-100 |
|
Scale factor as a percentage. |
|
TeX length |
|
Padding added around the diagram before the page is cropped by the
|
|
string |
(none) |
Sphinx cross-reference target. When set, the figure becomes the target
of a |
.. register::
Renders a hardware register diagram using the register LaTeX package.
Field names are typeset rotated at 45°, with bit positions and reset values
shown below each field.
The directive body contains only the row commands (\regfield,
\reglabel, \regnewline, etc.). The \begin{register} /
\end{register} wrapper is added automatically.
For HTML output the diagram is compiled using \begin{register*}
(unnumbered, no list-of-registers entry) to avoid float infrastructure
issues in the standalone document. For LaTeX output the numbered
\begin{register} float is emitted so that register numbering and
\listofregisters work correctly.
.. register::
:name: <register name>
:address: <memory offset>
:bitwidth: <n>
:color:
:options: <register package options>
:packages: <pkg1>, <pkg2>, ...
:align: left | center | right
:caption: <text>
:scale: <0-100>
:border: <TeX length>
\regfield{name}{length}{startbit}{reset}
\reglabel{Reset}\regnewline
...
Option |
Type |
Default |
Description |
|---|---|---|---|
|
string |
required |
Register name shown in the caption and the list of registers. |
|
string |
(none) |
Memory offset or address, e.g. |
|
positive integer |
|
Maximum number of bits per row (sets |
|
flag |
off |
Enables the |
|
string |
(none) |
Additional options forwarded to |
|
string |
(none) |
Comma-separated list of extra LaTeX packages to load. |
|
|
|
Horizontal alignment of the diagram within the page. |
|
string |
|
Override for the HTML |
|
integer 0-100 |
|
Scale factor as a percentage. |
|
TeX length |
|
Padding added around the diagram before the page is cropped. The
|
.. regdesc::
Documents the fields of the preceding register diagram using a plain RST definition list. The content is rendered as searchable, accessible HTML text — not baked into the SVG.
The body uses standard RST definition-list syntax: field name on one line,
description indented below. Inline markup (code, emphasis,
bold, hyperlinks) is fully supported and is preserved in LaTeX output.
For HTML output the list is rendered as a <dl class="regdesc"> element.
For LaTeX output it is wrapped in the register package’s regdesc /
reglist environments, with the longest field name used to set the
correct label margin.
.. regdesc::
FieldName
Description of the field. Inline markup is supported:
``code``, *emphasis*, **bold**.
AnotherField
Another description, possibly spanning multiple paragraphs.
.. listofregisters::
Inserts a list of all .. register:: directives in the document.
For HTML output a bullet list of internal hyperlinks is generated, each
linking to the corresponding diagram. For LaTeX output \listofregisters
is emitted, producing the numbered list provided by the register
package.
.. listofregisters::
The list is built at doctree-resolved time, so it reflects the final
order of registers in the document regardless of where the directive appears.
Examples
Fully working examples — covering every diagram from the bytefield and
register package documentation — are provided:
- Bytefield examples
- Basic bit fields
- IPv4 header
- IPv6 header
- TCP header
- UDP header
- Big-endian bit numbering
- Custom bit height
- Right word group
- Left word group
- Skipped words
- Selective borders
- Coloured bit boxes
- Rotated bit labels
- Description boxes
- Memory map
- MTP protocol (hyperref usage)
- Multiple bit-header ranges
- bitboxes shorthand
- Little-endian numbering with lsb offset
- Register examples
Build pipeline
For each diagram directive the extension runs the following steps at HTML write time:
.tex --> latex --> .dvi --> dvisvgm --> .svg (recommended)
--> pdflatex --> .pdf --> inkscape --> .svg
--> dvisvgm --pdf --> .svg
--> pdf2svg --> .svg
The extension tries latex + dvisvgm (DVI path) first, falling back
to pdflatex and then the available PDF-to-SVG converter only if
latex or dvisvgm is not found on PATH.
The DVI path is strongly recommended. dvisvgm reads DVI natively and
converts text glyphs to precise SVG paths, producing output that is faithful
to the original LaTeX rendering — particularly for small or rotated text such
as bit-header labels and the rotated field names produced by the register
package. The PDF path goes through an additional rasterisation step that can
introduce subtle degradation in text sharpness and positioning.
The pipeline is shared between the bytefield and register directives
and lives entirely in sphinxcontrib.archware.pipeline, which has no
knowledge of either LaTeX package.
Caching
Compiled artefacts are cached in _build/archware/cache/ using a SHA-256
hash of the full generated LaTeX source as the filename stem. All intermediate
files are kept alongside the final SVG:
_build/
archware/cache/
diagram-a3f1c8e2b4d70912.tex
diagram-a3f1c8e2b4d70912.dvi (or .pdf)
diagram-a3f1c8e2b4d70912.log
diagram-a3f1c8e2b4d70912.aux
diagram-a3f1c8e2b4d70912.svg
html/
latex/
The cache directory sits one level above the format-specific output
directories so it is shared between make html, make latexpdf, etc.,
and it is expected to be wiped by make clean
If a .svg file for a given hash already exists the entire compile +
convert pipeline is skipped, making incremental builds fast.
SVG inlining
The XML declaration (<?xml ... ?>) and DOCTYPE are stripped before the SVG
is written into the HTML body, as both are invalid inside an HTML5 document.
Each diagram is wrapped in a <figure> element:
<!-- bytefield -->
<figure class="archware-bytefield" style="text-align:center; ... ">
<svg ... > ... </svg>
<figcaption>Caption text</figcaption>
</figure>
<!-- register -->
<figure class="archware-register" id="function-class" ... >
<svg ... > ... </svg>
<figcaption>Function Class (0x0008)</figcaption>
</figure>
The HTML classes archware-bytefield and archware-register can be
styled by your Sphinx theme’s stylesheet to apply project-wide styling.
When a diagram is given the :name: option, the surrounding <figure>
receives a stable id attribute derived from that name and is used by
the listofregisters links and any :ref: cross-references.
LaTeX output
When building with the LaTeX writer (e.g. make latexpdf) the directive
body is emitted verbatim into the .tex source. Both the bytefield
and register packages are loaded automatically in the LaTeX preamble —
no changes to latex_elements are needed.
Global package options can be set in conf.py via the following
configuration values:
# Options forwarded to \usepackage[...]{bytefield}
bytefield_package_options = "bitheight=6ex, endianness=big"
# Options forwarded to \usepackage[...]{register}
register_package_options = "botcaption"
These apply globally to every diagram in the document. Per-diagram options
can still be set with :options: on individual directives.
For register diagrams Sphinx emits the numbered \begin{register}
float (not the starred form), so register numbering and \listofregisters
work correctly in the PDF output.
Dark mode support
The default stroke colour used by the bytefield and register LaTeX
packages is black, which is unreadable when the rendered SVG is embedded in
a page with a dark background. The archware_stroke_color config value
prepends \color{<name>} to the LaTeX body of every diagram, switching
the stroke (and any default-coloured text) to the chosen colour:
# Switch all bytefield / register strokes to white for dark themes
archware_stroke_color = "white"
# Or pick any other xcolor name
archware_stroke_color = "black"
The value is forwarded verbatim as the argument to \color{...}. Any
colour name understood by the xcolor LaTeX package may be used — the default xcolor name
list provides black, white, red, green, blue,
cyan, magenta, yellow, and several more. Loading xcolor
with one of its colour-set options (dvipsnames, svgnames,
x11names) in your preamble exposes a much larger palette.
Leave the value empty (the default) to disable the override and keep the native black stroke.
Referencing bytefield and register figures
The bytefield and register directives support cross-referencing through standard
Sphinx mechanisms.
While it is possible to use LaTeX \hyperref commands within the directives’ LaTeX code,
these references are only resolved during LaTeX compilation and are not part of HTML builds.
This approach is therefore not portable across Sphinx builders and is not recommended.
The recommended Sphinx-native approach is to use the :name: option provided by the directive.
When set, Sphinx assigns a stable document target to the generated figure,
making it available for cross-referencing in both HTML and LaTeX outputs.
For example, for bytefield directive defines the name “TCP header structure”:
.. bytefield::
:bitwidth: 32
:caption: TCP header
:name: TCP header structure
Hence the following usages of :ref: role:
.. note:: You can use ``:ref:`` to link to archware figures. E.g. :ref:`TCP header structure` and :ref:`Function Class`.
will render as:
Note
You can use :ref: to link to archware figures. E.g. TCP header and Function Class (0x0008).
This approach ensures that references are resolved uniformly across all Sphinx builders, including HTML and LaTeX, without relying on backend-specific hyperlink mechanisms.
Referencing bytefield and register figures
The bytefield and register directives support cross-referencing through standard
Sphinx mechanisms.
While it is possible to use LaTeX \hyperref commands within the directives’ LaTeX code,
these references are only resolved during LaTeX compilation and are not part of HTML builds.
This approach is therefore not portable across Sphinx builders and is not recommended.
The recommended Sphinx-native approach is to use the :name: option provided by the directive.
When set, Sphinx assigns a stable document target to the generated figure,
making it available for cross-referencing in both HTML and LaTeX outputs.
For example, for bytefield directive defines the name “TCP header structure”:
.. bytefield::
:bitwidth: 32
:caption: TCP header
:name: TCP header structure
Hence the following usages of :ref: role:
.. note:: You can use ``:ref:`` to link to archware figures. E.g. :ref:`TCP header structure` and :ref:`Function Class`.
will render as:
Note
You can use :ref: to link to archware figures. E.g. TCP header and Function Class (0x0008).
This approach ensures that references are resolved uniformly across all Sphinx builders, including HTML and LaTeX, without relying on backend-specific hyperlink mechanisms.
Troubleshooting
Neither latex nor pdflatex found on PATHInstall TeX Live or MiKTeX and ensure the binaries are on
PATH. On Debian / Ubuntu:sudo apt install texlive-latex-extra.SVG conversion failedInstall at least one of dvisvgm, Inkscape, or pdf2svg. On Debian / Ubuntu:
sudo apt install dvisvgmorsudo apt install inkscape.! LaTeX Error: File 'bytefield.sty' not foundThe
bytefieldLaTeX package is missing from your TeX installation. On Debian / Ubuntu:sudo apt install texlive-pictures. In MiKTeX the package manager installs it automatically on first use.! LaTeX Error: File 'register.sty' not foundThe
registerLaTeX package is missing from your TeX installation. On Debian / Ubuntu:sudo apt install texlive-science. In MiKTeX the package manager installs it automatically on first use.- Diagram is clipped
The
:border:option controls the padding added around the diagram before the page is cropped. The default is6pt. If labels, curly-brace group annotations, or rotated field names are still cut off, increase it on the affected directive:.. register:: :name: My Register :bitwidth: 32 :border: 14pt ...
Any valid TeX length is accepted (
8pt,0.5cm,2ex, etc.). Theregisterpackage’s rotated field names typically need more space thanbytefielddiagrams;12pt-16ptis a reasonable starting point.- Compilation errors during development
Every failed build preserves the
.texand.logfiles in_build/archware/cache/. Inspect the.logto find the LaTeX error. The.texfile contains the full standalone document that was submitted to the compiler and can be compiled independently for debugging.