Files
g4borg 61af13521c 🤖 Restructure SVG skill: extract references, add legibility rules
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>
2026-05-19 20:46:12 +02:00

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.

For any new diagram going into a Markdown document:

  1. Generate the SVG as a standalone .svg file. Common conventions:
    • docs/images/<slug>.svg, assets/<slug>.svg, or alongside the .md itself.
    • Match the project's existing convention if there is one.
  2. Reference it from the Markdown with image-link syntax:
    ![Architecture overview](./images/architecture.svg)
    
  3. The .svg file 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 .md file 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 (the fill and stroke attributes are also stripped). Self-hosted admins can extend the allow-list via app.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, and javascript: 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:

![Architecture overview](./images/architecture.svg)

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 .svg file in a sensible location.
  • Markdown references it with ![alt](path.svg).
  • width (the rendered width) ≤ 750px unless asked otherwise.

For inline SVG checklists, see references/inline-svg.md.