Skip to content

Repository files navigation

Sphinx UMLet Extension — Overview and Usage

This directory contains a small Sphinx extension that integrates UMLet diagrams into Sphinx builds. The extension locates .uxf source files, converts them to SVG during the Sphinx build, and emits the correct HTML image references in the generated pages.

Purpose

  • Make UMLet feel like a native Sphinx asset type so authors only need to write a simple directive in RST and the extension does the rest (resolve source, convert, register dependencies, and produce document-relative URIs).

Example RST usage

.. uml:: models/applications
     :alt: Applications Architecture
     :align: center
     :width: 100%

What the extension does

  • Resolve the .uxf source path relative to the current document.
  • Register the UXF file as a dependency in the Sphinx environment for incremental builds.
  • Convert UXF → SVG during the build and write the SVG under app.outdir, preserving the source-relative directory structure.
  • Emit an HTML <img> element whose src is a document-relative URI pointing at the generated SVG.

Important: path distinctions

  • The extension treats the following independently:
    1. Source filesystem path (e.g. source/nodes/models/applications.uxf).
    2. Output filesystem path (e.g. build/html/nodes/models/applications.svg).
    3. Document-relative URI used in HTML (e.g. from build/html/nodes/index.html the correct URI is models/applications.svg).

Installation / Enable

  1. Ensure the extension package is available under source/_extension/umlet.
  2. Add the extension to extensions in conf.py:
extensions = [
        "_extension.umlet",
]

Usage and build

  1. Place your .uxf files in the source/ tree where appropriate. The directive argument is interpreted relative to the RST document containing the directive.

    Example source layout:

    source/ └── nodes/ ├── index.rst (contains the directive) └── models/ └── applications.uxf

  2. In index.rst use the directive shown above.

  3. Build the docs as usual:

make html

After a successful build the generated SVG will be placed under build/html/... and the produced HTML will contain an <img> tag with a document-relative src, for example:

<img alt="Applications Architecture" class="align-center" width="100%" src="models/applications.svg" />

Directive options

  • :alt: — alternative text for the image
  • :align: — alignment class (for example center)
  • :width: — width value (e.g. 100%, 600px)
  • :height: — height value
  • :class: — additional classes applied to the image element

Development notes

  • Conversion happens during the Sphinx build stage; the directive does not invoke UMLet directly while parsing.
  • The extension records UXF dependencies in env so Sphinx incremental builds avoid unnecessary conversions.
  • Generated files are never written into the source/ directory. Output is under app.outdir (use Path(app.srcdir) and Path(app.outdir) in code; do not hard-code build/html).
  • The extension keeps a custom node (UMLetAsset) and produces HTML directly. It does not convert assets into nodes.image to avoid interfering with Sphinx's image post-processing.

Error handling and logging

  • If a .uxf file is missing the extension will produce a Sphinx warning/error tied to the document rather than allowing raw exceptions to escape.
  • If the UMLet conversion fails the log will include source and output paths, the command used, the return code and stderr to help debugging.

Files and responsibilities (summary)

  • __init__.py — register node, directive and event handlers
  • asset.pyUMLetAsset node definition
  • directive.py.. uml:: directive and registration of assets in env
  • events.py — generate SVGs at the correct build stage and manage environment data
  • renderer.py — UXF → SVG execution logic (independent of specific Snap revisions)
  • html.py — HTML emitter for UMLetAsset

If you want, I can add a minimal .uxf example and a local testing guide for running UMLet (JAR or Snap) to the README.

Use the current document's docname / source path information provided by Sphinx rather than manually assuming a fixed directory.


7. Output Path

The generated SVG must preserve the source-relative directory.

Example:

source/
└── nodes/
    ├── index.rst
    └── models/
        ├── applications.uxf
        └── cluster.uxf

must generate:

build/html/
└── nodes/
    ├── index.html
    └── models/
        ├── applications.svg
        └── cluster.svg

Never generate:

build/html/models/applications.svg

for the above source structure.


8. URI Generation

Filesystem paths and HTML URIs must be calculated independently.

For:

build/html/nodes/index.html

and:

build/html/nodes/models/applications.svg

the URI is:

models/applications.svg

The extension should use Sphinx's URI/path utilities where appropriate.

Do not manually prepend the document name.

Do not produce:

nodes/models/applications.svg

when the current HTML document is already inside:

nodes/

The generated src must always be relative to the current output document.


9. Example

Input:

source/nodes/index.rst
source/nodes/models/applications.uxf

RST:

.. uml:: models/applications
   :alt: Applications Architecture
   :align: center
   :width: 100%

Output:

build/html/nodes/index.html
build/html/nodes/models/applications.svg

HTML:

<img
    alt="Applications Architecture"
    class="align-center"
    width="100%"
    src="models/applications.svg"
/>

10. Incremental Builds

The extension should support Sphinx incremental builds.

Do not blindly regenerate every UML diagram on every build.

The implementation should compare:

UXF modification time
SVG modification time

or use appropriate Sphinx environment dependency tracking.

If:

applications.uxf

has not changed and:

applications.svg

already exists, the renderer should normally avoid unnecessary conversion.

If the UXF changes, the SVG must be regenerated.

If the SVG is deleted, it must be regenerated.

If a document is removed, its associated environment information should be purged.


11. Parallel Builds

The extension must be designed with Sphinx parallel builds in mind.

The setup metadata should accurately declare:

"parallel_read_safe": True

and:

"parallel_write_safe": True

only if the implementation is actually safe.

Avoid global mutable state.

Do not use module-level dictionaries as the source of truth for assets.

Store persistent information in the Sphinx environment where appropriate.


12. Error Handling

If a UXF file does not exist, produce a proper Sphinx warning/error associated with the document.

Example:

UMLet file not found: models/applications.uxf

Do not allow raw Python exceptions such as:

FileNotFoundError

to escape unless it represents a genuine programming error.

If UMLet conversion fails, provide:

  • source UXF path
  • output SVG path
  • UMLet command
  • process return code
  • stderr

This should make debugging easy.


13. Logging

Use Sphinx's logging API:

from sphinx.util import logging

logger = logging.getLogger(__name__)

Do not use print() for normal logging.

Examples:

logger.info(
    "Generating UMLet asset: %s",
    source_path,
)
logger.info(
    "UMLet output: %s",
    output_path,
)
logger.warning(
    "UMLet file not found: %s",
    source_path,
)

All code comments and docstrings must be written in International English.


14. Do Not Reintroduce nodes.image

The following pattern must NOT be used:

image = nodes.image(
    uri=svg_uri,
)

This previously caused Sphinx HTML post-processing to fail with:

KeyError: 'candidates'

The correct design is:

UMLetAsset
    ↓
HTML translator
    ↓
<img ...>

15. Compatibility

The current project uses:

Ubuntu 24.04
Python 3.12
Sphinx 9.1
Docutils 0.22
UMLet 15.1
pydata-sphinx-theme

The extension must work with the project's current Sphinx version.

The active HTML translator may be a theme-specific translator such as:

BootstrapHTML5Translator

Therefore the extension must not assume that the active translator is exactly:

HTML5Translator

Use Sphinx's supported node registration mechanisms rather than replacing the entire HTML translator.


16. Expected File Structure

The final implementation should look like:

source/
└── _extension/
    └── umlet/
        ├── __init__.py
        ├── asset.py
        ├── directive.py
        ├── events.py
        ├── html.py
        └── renderer.py

Responsibilities:

__init__.py
    Extension registration

asset.py
    UMLetAsset Docutils node

directive.py
    .. uml:: directive

events.py
    Sphinx build lifecycle
    Asset generation
    Environment management

renderer.py
    UMLet execution
    UXF → SVG conversion

html.py
    UMLetAsset → HTML rendering

17. Development Rules

When modifying the extension:

  1. Preserve the separation between source paths, output paths and HTML URIs.
  2. Never write generated files into source/.
  3. Never convert UMLetAsset into nodes.image.
  4. Never hard-code build/html.
  5. Never hard-code a Snap revision such as /snap/umlet-standalone/54.
  6. Use pathlib.Path.
  7. Use Sphinx logging.
  8. Use Sphinx/Docutils APIs instead of manipulating generated HTML after rendering.
  9. Keep the extension independent from the active Sphinx theme.
  10. Keep the implementation compatible with incremental Sphinx builds.
  11. Keep parallel build safety in mind.
  12. Add tests for path resolution and URI generation before changing those algorithms.
  13. All code comments and docstrings must use International English.
  14. Do not introduce unnecessary dependencies.

18. Primary Development Goal

The extension should make UMLet feel like a native Sphinx asset type.

The author should only need to write:

.. uml:: models/applications
   :alt: Applications Architecture
   :align: center
   :width: 100%

Everything else must be automatic:

Resolve UXF
    ↓
Register dependency
    ↓
Generate SVG
    ↓
Place SVG in build output
    ↓
Calculate document-relative URI
    ↓
Render HTML

The implementation should favour a clean Sphinx-native architecture over shortcuts or post-processing generated HTML.

About

sphinx-umlet extension to support UXF file

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages