Extract inline SVG rules to references/inline-svg.md for progressive disclosure. Add references/layout-legibility.md with 7 rules for readable SVG output (text sizing, contrast, margins, chart patterns, palettes) based on concrete failure modes from issue #4. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.9 KiB
name, description
| name | description |
|---|---|
| markdown-embedded-svg | Use when authoring or editing a Markdown file that contains (or should contain) SVG diagrams, charts, or any graphical representation. Trigger whenever (1) writing a report/document/README in Markdown that needs a diagram, flowchart, chart, or other visual, (2) considering adding `<svg>` markup to a `.md` file, (3) editing existing SVG inside Markdown, (4) a user asks for a "diagram", "visual", "chart", or "flowchart" inside a Markdown document. Markdown renderers (GitHub, Gitea, Obsidian, VS Code preview) sanitize inline SVG very differently from each other — GitHub strips it entirely, Gitea allows only `<svg>` + `<path>`, Obsidian (via DOMPurify) allows most of it. Apply this skill proactively before producing the SVG, not after. |
SVG in Markdown
Markdown renderers diverge dramatically on what SVG they allow. The safe default is not to embed SVG inline — it's to save the SVG as a separate .svg file and reference it with image-link syntax. Inline SVG should be treated as a special case the user explicitly asks for, not as the default.
This skill encodes the reasoning behind that choice, layout and legibility rules for readable output, and the per-renderer rules for when inline SVG is what's wanted.
Default approach: external .svg file + image link
For any new diagram going into a Markdown document:
- Generate the SVG as a standalone
.svgfile. Common conventions:docs/images/<slug>.svg,assets/<slug>.svg, or alongside the.mditself.- Match the project's existing convention if there is one.
- Reference it from the Markdown with image-link syntax:
 - The
.svgfile itself is a normal SVG document —<style>,<circle>,<g>, classes, gradients, animations, anything you'd write in any SVG. The renderer pipeline for standalone SVG files is much more permissive than the inline-Markdown sanitizer (especially on GitHub, where they're handled by entirely different code paths).
This recipe is the only approach that reliably produces a rendered diagram on GitHub (which strips inline SVG categorically — see below). It also works on Gitea and Obsidian and any other Markdown renderer that supports image links.
Use this default unless the user explicitly asks for inline SVG.
Why not inline SVG by default
Inline SVG fails silently and inconsistently across renderers. From source-code analysis (see research/2026-05-05-15-svg-sanitizer-allowlists/ if available locally):
- GitHub Markdown (
html-pipeline+rgrove/sanitize): the allow-list contains zero SVG elements.<svg>,<g>,<path>,<circle>— all stripped. Inline SVG never renders in a.mdfile on github.com. The element is removed; only its bare text-node children leak through. - Gitea (bluemonday default policy): allows only
<svg>and<path>. No<rect>, no<circle>, no<g>, no<text>, no gradients, no fills or strokes (thefillandstrokeattributes are also stripped). Self-hosted admins can extend the allow-list viaapp.ini's[markup.sanitizer.N]rules, but defaults are the rule. - Obsidian (DOMPurify defaults): allows most SVG —
<circle>,<rect>,<ellipse>,<g>,<text>,<defs>, gradients, paths, filters. Empirically confirmed not working in Obsidian:<use>,<style>element,<foreignObject>,<title>element.<script>, event handlers, andjavascript:URLs are stripped on every renderer including Obsidian. - VS Code Markdown preview (uses markdown-it + DOMPurify-like sanitization): permissive, similar to Obsidian for most things.
The strict cross-renderer intersection for inline SVG is effectively empty — there is no inline-SVG recipe that produces a rendered diagram on GitHub, Gitea, and Obsidian alike. This is why the default has to be the external file.
Layout and legibility
Renderer compatibility is only half the problem — the other half is producing SVG that's actually readable. Agent-generated SVGs commonly fail on text overflow, poor contrast, and missing margins. Read references/layout-legibility.md before generating any non-trivial SVG (charts, matrices, diagrams with labels). It covers:
- Estimating text width before sizing containers (SVG doesn't clip text)
- Contrast contracts for text over colored backgrounds (aim for 4.5:1)
- Background rects or halos for text on data-dependent surfaces
- Margin reservation for rotated labels
- The sparse-cells-plus-legend pattern for dense categorical charts
- Palette selection with declared text-color roles
When the user asks for inline SVG
If the user explicitly says "embed it inline", "put the SVG directly in the markdown", or similar — read references/inline-svg.md before proceeding. It contains the full per-renderer compatibility table, sanitizer survival rules, and inline-specific checklists. Pick the rule set that matches the target renderer; if the target is unknown, ask.
Default size
Generated SVG diagrams should not exceed 750 pixels in width by default — set width (and a matching viewBox) accordingly. Height is unconstrained — pick whatever the content needs. Wider SVGs blow out the column on most Markdown renderers. Override only when the user explicitly asks for wider.
Minimal example (external file recipe — the default)
The architecture is straightforward:

Each component handles its own state.
Where ./images/architecture.svg is a normal SVG file — use any elements you want; standalone SVG is not subject to the inline-Markdown sanitizer.
Pre-commit checklist
- SVG saved as a
.svgfile in a sensible location. - Markdown references it with
. width(the rendered width) ≤ 750px unless asked otherwise.
For inline SVG checklists, see references/inline-svg.md.