How to Validate Generated Diagrams with self_check.py in the Diagram-Design Repository

The self_check.py script is a zero-dependency validator that parses HTML diagram files to enforce security, accessibility, and motion-contract rules, exiting with status 0 on success or 1 with detailed error messages.

The cathrynlavery/diagram-design repository includes a lightweight validation tool at skills/diagram-design/scripts/self_check.py that allows developers to validate generated diagrams locally before CI submission. This standalone script ensures your SVG output meets the repository's strict accessible-SVG and motion-contract standards without requiring the full linter stack.

What self_check.py Validates

The validator uses Python's built-in HTMLParser to walk the document tree and enforce six distinct categories of rules. When you validate generated diagrams with self_check.py, it performs comprehensive checks against the same standards enforced by the production linters (lint-skin.py and verify-motion.py).

Security and Safety Checks

The script blocks unsafe HTML elements and attributes that could introduce XSS vulnerabilities or external dependencies. In skills/diagram-design/scripts/self_check.py (lines 92-99), the parser disallows <base>, <embed>, <object>, <iframe>, and any attribute starting with on (such as onclick). Additionally, lines 48-65 prevent remote resource loading by blocking CSS @import statements, url() functions containing non-fragment values, image-set() declarations, and any remote URL that is not the approved Google Fonts stylesheet.

SVG Accessibility Requirements

For accessibility compliance, the validator requires at least one SVG element that is not aria-hidden and includes specific attributes defined in lines 81-112. Your diagram must contain an SVG with role="img", a <title> element as its first child, a non-empty <desc> element, and matching aria-labelledby IDs that use the diagram-specific prefix.

Script Integrity Verification

Lines 14-30 enforce strict controls on JavaScript inclusion. The document may contain at most one <script> tag, which must carry only the canonical data-diagram-controls attribute. The script body must exactly match the canonical controller found in template-motion.html to prevent unauthorized code execution.

Motion Contract Compliance

If your diagram includes motion markup (identified by data-motion-root or data-motion-item attributes), the validator checks the motion contract implementation in lines 136-188. This includes validating the animation mode (none, reveal, step, or loop), ensuring step counts fall between 1 and 8, verifying item budgets, checking semantic step continuity, confirming proper playback controls, and validating the presence of reduced-motion and print fallbacks.

Running the Validator

Validating a Single Diagram

Execute the script with the path to your generated HTML file:

python3 skills/diagram-design/scripts/self_check.py path/to/my-diagram.html

A valid file produces the output:


OK path/to/my-diagram.html

Batch Validation Multiple Files

Process multiple diagrams simultaneously by passing glob patterns or multiple paths:

python3 skills/diagram-design/scripts/self_check.py diagrams/*.html

When validation fails, the script returns structured error messages:


FAIL diagrams/bad-diagram.html
  - <iframe> is not allowed in a diagram file
  - remote stylesheet is not the approved Google Fonts /css2 URL: https://example.com/style.css
  - svg 1 needs role=img
  - svg 1 title must be its first child

Integrating with CI Pipelines

Add the validator to your continuous integration workflow to block invalid diagrams at build time. The script returns exit code 1 on failure, causing the job to fail automatically:

- name: Validate generated diagrams
  run: |
    python3 skills/diagram-design/scripts/self_check.py $(git ls-files '*/generated/*.html')

Anatomy of a Valid Diagram

The following HTML structure satisfies all self_check.py requirements:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Demo</title>
  <link href="https://fonts.googleapis.com/css2?family=Geist&display=swap" rel="stylesheet">
</head>
<body>
  <svg role="img" aria-labelledby="demo-title demo-desc">
    <title id="demo-title">Demo Diagram</title>
    <desc id="demo-desc">A simple accessible diagram.</desc>
    <rect width="100" height="100" fill="#f5f5f5"/>
  </svg>
  <script data-diagram-controls>
    (() => { /* controller body – must match template-motion.html */ })();
  </script>
</body>
</html>

Running self_check.py on this file outputs OK because it contains no unsafe elements, uses only approved remote resources, implements proper SVG accessibility patterns, and includes the canonical script controller.

Summary

  • Zero-dependency validation: The script requires only Python's standard library, using HTMLParser to analyze diagram files without external packages.
  • Security enforcement: Blocks unsafe elements like <iframe> and on* event handlers while restricting remote resources to approved Google Fonts URLs.
  • Accessibility mandates: Requires role="img", proper <title> and <desc> placement, and valid aria-labelledby references.
  • Motion contract validation: Verifies animation modes, step limits, and accessibility fallbacks for diagrams with motion markup.
  • CI-ready exit codes: Returns 0 for valid diagrams and 1 with descriptive error messages for invalid files.
  • Script integrity: Ensures JavaScript matches the canonical controller in template-motion.html exactly.

Frequently Asked Questions

What exit codes does self_check.py return?

The script exits with status 0 when validation succeeds, printing OK <filepath>. If any check fails, it exits with status 1 and prints a FAIL <filepath> message followed by a bulleted list of specific violations.

Can I use self_check.py without installing dependencies?

Yes. The validator is designed to run with zero dependencies beyond Python's standard library. It uses the built-in html.parser.HTMLParser class rather than external parsing libraries, making it suitable for lightweight local validation or containerized CI environments.

How does self_check.py differ from lint-skin.py?

While self_check.py located in skills/diagram-design/scripts/ provides a fast, portable subset of validation rules, lint-skin.py in the repository root offers comprehensive linting including additional CSS safety checks and skin validation. Use self_check.py for rapid local feedback and lint-skin.py for full repository gate checks.

What should I do if the script check fails?

If the validator reports script integrity errors, compare your diagram's <script> tag content against the canonical controller in skills/diagram-design/assets/template-motion.html. The script body must match exactly, and the tag must use only the data-diagram-controls attribute without inline event handlers or external src references.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →