How the self_check.py Script Validates Diagrams in diagram-design
The self_check.py script validates diagram HTML files by parsing the document with a custom HTMLParser subclass, detecting unsafe tags and external references, verifying SVG accessibility compliance, enforcing canonical script integrity, and validating motion-specific contracts when animation markup is present.
The self_check.py script is a zero-dependency validator shipped with the diagram-design skill that ensures generated diagram HTML files comply with strict safety and accessibility standards. When an installed agent produces a diagram, running this script against the output verifies adherence to the accessible-SVG contract, single-file safety rules, and structural motion requirements. The validation pipeline mirrors the repository-side gates implemented in lint-skin.py and verify-motion.py, providing immediate feedback during development.
Parsing the HTML Document Structure
The validation process begins with a custom HTMLParser subclass called DiagramParser defined in skills/diagram-design/scripts/self_check.py. During initialization at DiagramParser.__init__ (lines 34-44), the parser prepares collections to store document metadata while traversing the DOM tree.
As the parser walks the document in handle_starttag (lines 57-66), it populates several critical data structures:
unsafe– disallowed tags and executable attributesreferences– every URL-bearing attribute for external link validationsvgs– metadata about each top-level<svg>elementscripts– body content and attributes of<script>blocksstyles– raw CSS from<style>tags- Motion-related sets including
roots,items,actions,controls, andstatuses
Detecting Unsafe Tags and Attributes
The validator enforces a strict security model by flagging potentially dangerous HTML elements. In handle_starttag, the script immediately identifies forbidden tags such as <embed>, <object>, and <iframe>.
Additionally, any attribute starting with on (e.g., onclick, onload) is flagged as an event handler that could execute arbitrary JavaScript. These restrictions ensure that diagram files remain safe, single-file documents without external dependencies or executable code paths beyond the approved controller.
Validating External References
Every reference to external resources undergoes scrutiny in the reference_error function (lines 79-97). The parser examines attributes including src, href, xlink:href, poster, srcset, action, and formaction.
The validation logic distinguishes three cases:
- Local or fragment references – ignored as safe internal navigation
- Executable URLs –
javascript:ordata:text/htmlschemes are immediately flagged as errors - Remote URLs – allowed only for the approved Google Fonts
/css2endpoint viais_approved_google_fonts_stylesheet; all other remote resources trigger validation errors
This ensures diagrams remain self-contained while permitting standardized font loading.
Verifying SVG Accessibility Compliance
The check_svgs function (lines 14-45) enforces the accessible-SVG contract on every non-hidden SVG element. The parser extracts top-level <svg> elements, ignoring those with aria-hidden="true".
For each accessible SVG, the validator confirms:
- Presence of
role="img" - The first child element is
<title> - Non-empty text content in both
<title>and<desc>elements - ID attributes use proper prefixes (not bare "title" or "desc")
aria-labelledbycorrectly references the title ID followed by the description ID
These checks prevent silent or unlabeled graphics that would fail screen reader accessibility standards.
Enforcing Single Canonical Script Rules
The check_scripts function (lines 47-62) ensures that when a <script> tag exists, it represents exactly the approved motion controller. The validation requires:
- Exactly one script element in the document
- The script carries only the
data-diagram-controlsattribute (no other attributes permitted) - The script body exactly matches the canonical controller stored in
assets/template-motion.html
The canonical controller is loaded via canonical_controller and normalized for comparison. This prevents agents from shipping mutated or malicious controller code while permitting the specific interactive behaviors defined in the template.
Validating Motion-Specific Contracts
When the parser detects motion markup (attributes like data-motion-root, data-motion-item, or data-motion-action), the check_motion function (lines 69-112) enforces the structural motion contract. This validation only activates when motion elements are present.
Root and Mode Validation:
- Exactly one element must have
data-motion-root data-motion-modemust be one ofnone,reveal,step, orloopdata-step-countmust be a decimal integer within the mode's allowed range (0-8)
Item Constraints:
- Maximum of 12 motion items permitted
- Each item's
data-stepmust be a decimal integer - Semantic items require
aria-labelattributes - Decorative items must carry both
aria-hidden="true"andfocusable="false"
Visibility and Step Requirements:
- No items with
display:none,visibility:hidden, oropacity:0at step 0 - Step values must form a contiguous set from 1 to count
- Maximum two items allowed per step
Controlled Mode Requirements (for step or reveal with script):
- Exactly one control group must exist
- All six actions required:
play,pause,replay,prev,next - Status element must be a
<div>withrole="status",aria-live="polite", andaria-atomic="true" - CSS must include
prefers-reduced-motionmedia query,@media printrules, and a<noscript>explanation block
Error Aggregation and Reporting
The verify function (lines 53-65) and main entry point (lines 68-86) coordinate the final validation output. All collected warnings and errors merge into a single list for reporting.
The script prints results in a machine-parseable format:
python3 skills/diagram-design/scripts/self_check.py diagram1.html diagram2.html
Typical output:
OK diagram1.html
FAIL diagram2.html
- <embed> is not allowed in a diagram file
- svg 1 needs role=img
- remote stylesheet is not the approved Google Fonts /css2 URL: https://example.com/style.css
- data-motion-mode must be one of ['none', 'reveal', 'step', 'loop']; got 'invalid'
The script exits with status code 1 when any errors are present, enabling integration with CI pipelines as referenced in .github/workflows/ci.yml. Clean documents yield exit code 0 with an OK prefix.
Summary
self_check.pyprovides zero-dependency validation of diagram HTML files through a seven-stage pipeline implemented inskills/diagram-design/scripts/self_check.py- Security checks in
handle_starttagblock unsafe tags like<iframe>and event handlers whilereference_errorrestricts external URLs to approved Google Fonts endpoints - Accessibility validation via
check_svgsenforces ARIA labeling, proper DOM order, and semantic requirements for non-hidden SVG elements - Script integrity enforced by
check_scriptsrequires the canonical motion controller fromassets/template-motion.htmlto appear unchanged when present - Motion contracts validated by
check_motionensure proper step sequencing, item budgets, control groups, and CSS fallbacks for animated diagrams - CI-ready reporting through the
verifyfunction provides non-zero exit codes and detailed error messages for automated testing workflows
Frequently Asked Questions
What specific security threats does self_check.py prevent?
The script prevents cross-site scripting (XSS) vectors by blocking <embed>, <object>, and <iframe> tags, rejecting event handler attributes (any attribute starting with on), and prohibiting executable URL schemes like javascript: or data:text/html in the reference_error function. These checks ensure diagram files cannot execute arbitrary code or load unauthorized external content.
Why does the validator reject most remote URLs but allow Google Fonts?
The is_approved_google_fonts_stylesheet function explicitly whitelists only the Google Fonts /css2 endpoint to support typography while maintaining the single-file safety contract. All other remote references are flagged because they introduce external dependencies that could break offline viewing, compromise privacy, or serve as attack vectors if the third-party domain is compromised.
How does the script detect and validate animated diagrams?
The parser watches for motion-specific data attributes during the HTML traversal. When data-motion-root, data-motion-item, or related attributes appear, the check_motion function activates to validate the structural motion contract, verifying step counts, item budgets, ARIA labeling for semantic items, and the presence of required control groups and CSS fallbacks for reduced motion and print media.
Can self_check.py be integrated into automated testing pipelines?
Yes. The script is designed for CI integration through its exit code behavior and machine-parseable output format. When verify detects any errors, the main function exits with status code 1, failing the build; successful validation returns 0. This enables use in GitHub Actions workflows or other automated gates to prevent non-compliant diagrams from reaching 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 →