What Accessibility Features Are Included in Generated SVG Diagrams?
Generated SVG diagrams in the Diagram-Design repository must pass the lint_accessible_svgs validator in scripts/lint-skin.py, which enforces role="img", a first-child <title>, a <desc> element, and aria-labelledby referencing slug-prefixed IDs to satisfy WCAG 2.1 AA requirements.
The cathrynlavery/diagram-design toolchain treats accessibility as a non-negotiable output contract. Whenever a user runs the export-diagram command to produce an SVG, the resulting markup is scrutinized by the Python linter defined in scripts/lint-skin.py. These accessibility features in generated SVG diagrams ensure that every graphic is immediately consumable by screen readers without manual post-processing.
Semantic Role and ARIA Labeling
Every meaningful SVG must explicitly declare its semantic purpose to assistive technology. The linter enforces two complementary rules on the root <svg> element.
Mandatory role="img" Attribute
Inside scripts/lint-skin.py, lines 49–51, the lint_accessible_svgs function checks that svg.attrs.get("role") equals "img". If the attribute is missing or holds any other value, the linter raises an error and blocks the diagram from export.
aria-labelledby References
The root <svg> must carry an aria-labelledby attribute that references the IDs of both the <title> and <desc> elements. This programmatic link exposes the accessible name and description to screen readers. The linter validates these references at lines 52–55 and confirms ID resolution at lines 78–84.
Title and Description Structure
Beyond ARIA attributes, the document tree itself must contain specific semantic children in the correct order.
<title> Element Placement and Content
The <title> element must be the first child of the <svg> root and must contain non-empty text. At lines 96–104 in scripts/lint-skin.py, the linter checks for presence, verifies child order, and rejects empty title nodes.
<desc> Element for Extended Descriptions
Immediately following the title, a <desc> element supplies a longer human-readable explanation. The linter enforces its presence and forbids empty description strings at lines 108–112. This pairing satisfies WCAG 2.1 AA expectations for both a short name and a detailed text alternative.
ID Conventions and Uniqueness Validation
To keep generated diagrams deterministic and collision-free, the linter imposes a strict ID naming scheme across all exports.
Slug-Prefixed ID Naming
IDs for <title> and <desc> must be prefixed with the diagram's slug. For a diagram slugged example-flowchart, the expected IDs are example-flowchart-title and example-flowchart-desc. This rule is enforced at lines 122–134 of scripts/lint-skin.py.
Duplicate and Bare ID Detection
The linter scans the entire document for duplicate IDs at lines 38–44 and raises an error if any are found. Additionally, bare IDs such as id="title" or id="desc" are explicitly prohibited at lines 155–161; the slug prefix is required to avoid ambiguity.
Decorative SVG and Template Handling
Not every SVG is intended to convey meaning. The linter supports exemptions for decorative graphics and template placeholders.
Decorative Graphics with aria-hidden="true"
If an SVG is purely decorative, adding aria-hidden="true" to the root element triggers an early exit in the linter at lines 44–48. When this attribute is present, all other accessibility checks are suppressed and the file passes validation.
Template Placeholder IDs
During template generation, placeholder IDs formatted as [diagram-slug]-title are allowed through the allow_template_placeholders parameter. The linter handles these gracefully at lines 66–70, enabling reusable skins before a final slug is injected.
Valid SVG Examples
Below is a minimal valid SVG that satisfies the Diagram-Design accessibility contract for a diagram whose slug is example-flowchart:
<svg role="img"
aria-labelledby="example-flowchart-title example-flowchart-desc"
width="800" height="600"
xmlns="http://www.w3.org/2000/svg">
<title id="example-flowchart-title">Flowchart of Process</title>
<desc id="example-flowchart-desc">A step-by-step flowchart showing the stages of the process.</desc>
<!-- diagram graphics go here -->
</svg>
For purely decorative diagrams, suppress the accessibility checks as follows:
<svg aria-hidden="true" width="800" height="600" xmlns="http://www.w3.org/2000/svg">
<!-- purely decorative graphics -->
</svg>
Test and Enforcement Pipeline
The rules above are executable constraints, not guidelines. The lint_accessible_svgs function inside scripts/lint-skin.py is exercised by scripts/test-lint-a11y.py, which confirms that compliant SVGs are accepted and that every violation—missing roles, malformed IDs, empty titles—is caught before the export-diagram command finalizes output.
Summary
- Mandatory
role="img"is required on every meaningful SVG root element. <title>must be the first child of the<svg>and contain non-empty text.<desc>must provide an extended, non-empty description.aria-labelledbymust reference both the<title>and<desc>elements by their unique IDs.- Slug-prefixed IDs prevent collisions; bare IDs like
id="title"are forbidden. - Decorative SVGs can bypass all checks by setting
aria-hidden="true". - Template placeholders are permitted when
allow_template_placeholdersis enabled. - The entire contract is enforced by
scripts/lint-skin.pyand validated byscripts/test-lint-a11y.py.
Frequently Asked Questions
What happens if an SVG is missing the role="img" attribute?
The linter in scripts/lint-skin.py flags the omission as an error at lines 49–51. The SVG will fail validation and cannot be exported until the semantic role is added to the root element.
Can I use generic IDs such as id="title" in my SVG?
No. Bare IDs are explicitly rejected at lines 155–161. You must use the diagram slug as a prefix—for example, example-flowchart-title—to satisfy the linter and prevent ID collisions.
How does the linter handle decorative SVGs?
When the root <svg> element includes aria-hidden="true", the linter executes an early exit at lines 44–48 and skips all other accessibility checks, treating the graphic as purely decorative.
Where are these accessibility rules tested?
The test suite in scripts/test-lint-a11y.py validates the lint_accessible_svgs function, ensuring that compliant SVGs pass and that every rule violation is caught before the diagram reaches production.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →