Skip to main content

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 + figcaption support
  • improved control over accessibility and semantics

Features

Inline SVG injection

Embed SVG files using a syntax similar to normal images:

![caption](path/to/image.svg)

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("![Logo](logo.svg)")

Usage

Basic Inline SVG

!(diagram.svg)

Inline SVG with Caption

![Data Flow](images/flow.svg)

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:

![icon](ui/menu.svg)

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="/")
![logo](/images/logo.svg)

Becomes reference to:

images/logo.svg

remove_prefex defaults to "", which means no prefix is removed.

How it Works

  1. Reference detection A lightweight custom parser matches ![caption](file.svg) and !(file.svg).
  2. Structured extraction caption and href sections are parsed using a bracket-aware tokenizer, not regex grouping. This ensures correct handling of nested brackets.
  3. Path rewriting remove_prefix and root are applied.
  4. File validation
    • Must exist
    • Must end in .svg
    • Must not be remote (http/https///)
  5. Caching & XML parsing SVGs are loaded with xml.etree.ElementTree and stored in a module-level cache for reuse.
  6. Placeholder emission A unique stable placeholder token (\x02path\x03) prevents Markdown from interfering with raw XML.
  7. 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 + figcaption generation
  • 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.

Metadata

Release files for iSVG 1.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for iSVG 1.0.3
File Size Uploaded
isvg-1.0.3.tar.gz 18.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for iSVG 1.0.3
File Interpreter ABI Platform
isvg-1.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 35.1 kB

Release files / isvg-1.0.3.tar.gz

Download URL isvg-1.0.3.tar.gz
Size 18.0 kB
Tags Source
SHA-256 checksum
How to use checksums
f5067c42f06d0ed00a7962face20a596e3322e1955846aaccdb298b01eb1953d
BLAKE2b-256 checksum
How to use checksums
ebec6f38a89fc0f3e379f513fd3e9b5f3a0a820caf1481cd89bcfdcd051d9471
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.1

Release files / isvg-1.0.3-py3-none-any.whl

Download URL isvg-1.0.3-py3-none-any.whl
Size 17.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8789c33770202720213fd16c960594ff3594c245df0165c6b22c91e0b4600b97
BLAKE2b-256 checksum
How to use checksums
2a16a92f23684af036429a6948d285c290088494f235bb06a2939b93e1cde094
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.1

Release history Release notifications | RSS feed

This release

1.0.3 This release

2 release files

1.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page