How Diagram-Design Ensures WCAG Accessibility Compliance: A Deep Dive into the SVG Accessibility Contract
Diagram-Design enforces WCAG accessibility through an automated "accessible SVG contract" that requires every diagram to include role="img" on the root <svg> element, validated by a dedicated linter and unit test suite.
The cathrynlavery/diagram-design repository is an open-source diagramming tool that prioritizes inclusive design. Rather than relying on manual checks, the project embeds accessibility requirements directly into its CI pipeline. This article examines the technical implementation of WCAG compliance, from the linting rules in scripts/lint-skin.py to the verification tests that prevent regressions.
The Accessible SVG Contract: Core WCAG Requirement
The foundation of diagram-design's accessibility strategy is a mandatory SVG contract that addresses WCAG 2.1 Success Criterion 1.1.1 (Non-text Content). Every generated diagram must output an <svg> element with a valid ARIA role, enabling assistive technologies to recognize and announce the graphic correctly.
The contract specification lives in scripts/lint-skin.py, where the lint_accessible_svgs function validates each SVG node against this requirement. The implementation checks for the presence of role="img" and flags any violation as an a11y (accessibility) finding.
Linter Enforcement in scripts/lint-skin.py
The project's primary quality gate is scripts/lint-skin.py, a Python linter that runs automatically in CI. Within this file, line 340 contains the explicit accessibility check:
add(svg.line, svg.offset, 'diagram <svg> must carry role="img"')
This line generates a categorized finding whenever an SVG lacks the required role attribute. The linter collects these under the "a11y" category, making violations immediately identifiable in build logs.
Running the linter with the --all flag executes the full validation suite:
python3 scripts/lint-skin.py --all
Any a11y finding causes the CI pipeline to fail, blocking merges of non-compliant diagrams.
Linting Output Format
When the linter detects an accessibility violation, it produces output like:
a11y: diagram <svg> must carry role="img"
This format serves two purposes: it clearly identifies the issue category (a11y) and provides an actionable message for developers.
Unit Test Verification
Automated testing prevents contract drift. The file scripts/test-lint-a11y.py contains unit tests that verify the linter correctly identifies valid and invalid SVGs.
The test suite constructs explicit test cases:
VALID_SVG = '<svg xmlns="http://www.w3.org/2000/svg" role="img" …>'
INVALID_SVG = '<svg xmlns="http://www.w3.org/2000/svg" …>'
Tests assert that:
- The invalid SVG produces the finding
a11y: diagram <svg> must carry role="img" - The valid SVG produces no accessibility findings
This test coverage ensures the linter remains accurate as the codebase evolves.
WCAG-Compliant SVG Examples
Correct Implementation
<svg xmlns="http://www.w3.org/2000/svg"
role="img"
aria-label="UML class diagram showing inheritance between User and Admin entities">
<!-- diagram content -->
</svg>
This satisfies the accessible SVG contract by including role="img" and providing an aria-label for assistive technology announcement.
Incorrect Implementation (Fails Linter)
<svg xmlns="http://www.w3.org/2000/svg">
<!-- diagram content -->
</svg>
Running lint-skin.py on this output produces:
a11y: diagram <svg> must carry role="img"
The CI pipeline would reject this diagram.
Contributor Documentation and CI Integration
The project's README.md includes a dedicated section, "The accessible SVG contract (a11y)", that documents this requirement. Contributors are directed to run both the linter and unit tests before submitting changes:
python3 scripts/test-lint-a11y.py
python3 scripts/lint-skin.py --all --baseline
The .github/workflows/ci.yml configuration ensures these checks execute on every pull request, creating a continuous validation pipeline that guarantees WCAG compliance without manual oversight.
Summary
- Contract-based enforcement: Every SVG must carry
role="img"per the accessible SVG contract defined inscripts/lint-skin.py - Automated linting: The
lint_accessible_svgsfunction generates a11y findings for violations, with line 340 containing the explicit error message - Test coverage:
scripts/test-lint-a11y.pyvalidates linter behavior with explicit valid/invalid SVG test cases - CI integration: GitHub Actions runs
lint-skin.py --allto block non-compliant diagrams from merging - Contributor guidance: README documentation ensures the accessibility requirement is discoverable and actionable
Frequently Asked Questions
What WCAG success criterion does the accessible SVG contract address?
The contract primarily addresses WCAG 2.1 Success Criterion 1.1.1 (Non-text Content), which requires that all non-text content has a text alternative. By requiring role="img" on SVG elements, the contract enables assistive technologies to recognize diagrams as images and announce their aria-label or aria-labelledby attributes to users.
Can the linter detect other accessibility issues beyond the role attribute?
The current implementation in scripts/lint-skin.py focuses specifically on the role="img" requirement as the core contract. The test file scripts/test-lint-a11y.py suggests this is the primary automated check, though the README implies the contract may expand to cover color contrast and font requirements in future iterations.
What happens if a contributor submits a diagram without role="img"?
The CI pipeline configured in .github/workflows/ci.yml runs python3 scripts/lint-skin.py --all. Any a11y finding, including the missing role violation, causes the check to fail and blocks the pull request from merging. Contributors must fix the issue and re-run local tests before resubmission.
Is the accessible SVG contract customizable for different diagram types?
The contract applies universally to all SVG outputs from diagram-design. The lint_accessible_svgs function in scripts/lint-skin.py inspects every <svg> node without exception, ensuring consistent accessibility across the entire diagram library regardless of diagram complexity or visual style.
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 →