Extends Markdown with support for inline SVG images https://pypi.org/project/iSVG/
Find a file
2025-12-06 07:48:43 +01:00
.idea Initial commit 2025-12-05 20:28:27 +01:00
test Support nested brackets in captions and href 2025-12-06 07:45:59 +01:00
.gitignore Initial commit 2025-12-05 20:28:27 +01:00
.gitlab-ci.yml Update module refs 2025-12-05 21:47:08 +01:00
isvg.py Ignore too many return statements for handleMatch 2025-12-06 07:48:43 +01:00
LICENSE Initial commit 2025-12-05 20:28:27 +01:00
pyproject.toml Support nested brackets in captions and href 2025-12-06 07:45:59 +01:00
README.md Support nested brackets in captions and href 2025-12-06 07:45:59 +01:00

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.