Extends Markdown with support for inline SVG images.
Project description
Inline SVG Extension for Markdown
A Python-Markdown extension that enables inline embedding of local SVG
files directly into rendered HTML. Unlike standard Markdown image
syntax—which outputs <img> tags. This extension inserts the actual SVG
markup, enabling:
- full CSS styling of embedded SVGs
- consistent scaling behaviour
figure+figcaptionsupport- improved control over accessibility and semantics
Features
Inline SVG injection
Embed SVG files using a syntax similar to normal images:

or without caption:
!(path/to/image.svg)
Automatic <figure> + <figcaption> wrapping
If a caption is provided, the output becomes:
<figure>
<svg> ... </svg>
<figcaption>Your caption</figcaption>
</figure>
Without a caption, only the SVG element is inserted.
Safe Placeholder Handling
The extension first inserts placeholder tokens, preventing Python-Markdown from escaping the SVG. Placeholders are later replaced with the final SVG markup in the postprocessor phase.
Internal Caching
SVG files are parsed once and stored in a global cache for the lifetime of the process, improving performance.
Installation
pip install markdown isvg
Use the extension:
import markdown
from isvg import InlineSVGExtension
md = markdown.Markdown(extensions=[InlineSVGExtension(root="assets/svg")])
html = md.convert("")
Usage
Basic Inline SVG
!(diagram.svg)
Inline SVG with Caption

Example HTML Output
<figure>
<svg xmlns="http://www.w3.org/2000/svg" ...> ... </svg>
<figcaption>Data Flow</figcaption>
</figure>
Configuration
root
Defines the base directory from which SVG paths are resolved. Defaults to
"", the current working directory.
InlineSVGExtension(root="/var/www/assets/svg")
A Markdown reference such as:

resolves to:
/var/www/assets/svg/ui/menu.svg
remove_prefix
If your Markdown is generated from a web source that prefixes URLs with /,
you can remove that prefix:
InlineSVGExtension(remove_prefix="/")

Becomes reference to:
images/logo.svg
remove_prefex defaults to "", which means no prefix is removed.
How it Works
- Reference detection
A lightweight custom parser matches
and!(file.svg). - Structured extraction
captionandhrefsections are parsed using a bracket-aware tokenizer, not regex grouping. This ensures correct handling of nested brackets. - Path rewriting
remove_prefixandrootare applied. - File validation
- Must exist
- Must end in
.svg - Must not be remote (
http/https///)
- Caching & XML parsing
SVGs are loaded with
xml.etree.ElementTreeand stored in a module-level cache for reuse. - Placeholder emission
A unique stable placeholder token (
\x02path\x03) prevents Markdown from interfering with raw XML. - Postprocessing Placeholders are replaced with the final SVG markup after Markdown rendering is complete.
Error Handling
The extension silently ignores:
- Non-SVG files
- Remote URLs (
http://,https://,//) - Missing paths
- Invalid or malformed SVGs
In such cases, the original Markdown text is left unchanged.
Security Considerations
Inlining SVGs introduces risks if files are not trusted. SVGs can contain:
- JavaScript
- External resource references
- Embedded HTML
- CSS injections
If processing user-provided content, sanitize SVGs beforehand using tools such as: external SVG sanitizers or whitelist-based filtering.
Testing
This project includes pytest-based unit tests located in the test/ directory.
Run the full suite with:
pytest test
The tests cover:
- Correct placeholder insertion
- Proper caption extraction
figure+figcaptiongeneration- SVG loading and caching behavior
- Error-handling paths (invalid SVG, missing files, remote URLs)
- Interactions with other Python-Markdown extensions
If you extend or modify the extension, adding tests in this folder is highly recommended.
Known Limitations
- A global cache is used, which persists for the lifetime of the process.
- Relative links inside SVGs are not rewritten.
- Interactions with other Markdown extensions may affect final output order.
License
This project is licensed under the GNU General Public License v3.0 (GPLv3). You may redistribute and/or modify it under the terms of the GPLv3.
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 isvg-1.0.3.tar.gz.
File metadata
- Download URL: isvg-1.0.3.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5067c42f06d0ed00a7962face20a596e3322e1955846aaccdb298b01eb1953d
|
|
| MD5 |
05fad102bcdc1b9dae6d37abb2046001
|
|
| BLAKE2b-256 |
ebec6f38a89fc0f3e379f513fd3e9b5f3a0a820caf1481cd89bcfdcd051d9471
|
File details
Details for the file isvg-1.0.3-py3-none-any.whl.
File metadata
- Download URL: isvg-1.0.3-py3-none-any.whl
- Upload date:
- Size: 17.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8789c33770202720213fd16c960594ff3594c245df0165c6b22c91e0b4600b97
|
|
| MD5 |
82ea2532a39601941d1713a7447e1196
|
|
| BLAKE2b-256 |
2a16a92f23684af036429a6948d285c290088494f235bb06a2939b93e1cde094
|