Module

contracts.rules_accessibility

Accessibility contract checks for templates.

Checks:

  • a11y_interactive: htmx URL attrs on non-interactive elements
  • a11y_label: form fields without associated labels
  • a11y_alt: images without alt attribute
  • a11y_heading: heading levels that skip
  • a11y_landmark: layout templates missing

Functions

check_accessibility 2 list[ContractIssue]
Warn about htmx URL attrs on non-interactive elements without role/tabindex.
def check_accessibility(source: str, template_name: str) -> list[ContractIssue]
Parameters
Name Type Description
source str
template_name str
Returns
list[ContractIssue]
_normalize_for_matching 1 str
Replace Kida expressions with a wildcard sentinel for matching.
def _normalize_for_matching(value: str) -> str
Parameters
Name Type Description
value str
Returns
str
check_label_association 2 list[ContractIssue]
Warn when form fields lack an associated label. Valid associations (any one is…
def check_label_association(source: str, template_name: str) -> list[ContractIssue]

Warn when form fields lack an associated label.

Valid associations (any one is sufficient):

  • <label for="id"> matching the element's id
  • The element is wrapped inside a<label>tag
  • The element hasaria-label or aria-labelledby

Exempt elements:

  • <input type="hidden|submit|button|image|reset">
Parameters
Name Type Description
source str
template_name str
Returns
list[ContractIssue]
check_image_alt 2 list[ContractIssue]
Warn when tags lack an alt attribute.
def check_image_alt(source: str, template_name: str) -> list[ContractIssue]
Parameters
Name Type Description
source str
template_name str
Returns
list[ContractIssue]
check_heading_order 2 list[ContractIssue]
Warn when heading levels skip (e.g. h1 → h3 with no h2).
def check_heading_order(source: str, template_name: str) -> list[ContractIssue]
Parameters
Name Type Description
source str
template_name str
Returns
list[ContractIssue]
check_landmarks 1 list[ContractIssue]
Warn when layout templates have no or role="main" landmark.
def check_landmarks(layout_sources: dict[str, str]) -> list[ContractIssue]
Parameters
Name Type Description
layout_sources dict[str, str]

Mapping of layout template name → source for templates that serve as layouts (contain{% block %}). Only layout templates are checked because pages inherit their landmark structure from the layout.

Returns
list[ContractIssue]