refactor: 4개 검사 엔진을 YAML 기반 표준 규칙으로 리팩토링
- YAML 규칙 파일 4개 신규 생성 (html_css, accessibility, seo, performance_security) W3C, WCAG 2.0/2.1/2.2, OWASP, Google Search Essentials 공식 표준 기반 - rules/__init__.py: YAML 로더 + 캐싱 + 리로드 모듈 - html_css.py: 30개 폐기 요소, 100+개 폐기 속성을 YAML에서 동적 로드 - accessibility.py: WCAG 버전 선택 지원 (wcag_version 파라미터) - seo.py: title/description 길이, OG 필수 태그 등 임계값 YAML 로드 - performance_security.py: COOP/COEP/CORP 검사 추가, 정보 노출 헤더 검사 추가, TTFB/페이지 크기 임계값 YAML 로드 - PyYAML 의존성 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
830
backend/app/rules/accessibility.yaml
Normal file
830
backend/app/rules/accessibility.yaml
Normal file
@ -0,0 +1,830 @@
|
||||
# ============================================================
|
||||
# WCAG Accessibility Rules
|
||||
# Based on: W3C WCAG 2.0, 2.1, 2.2 + axe-core Rule Mapping
|
||||
# ============================================================
|
||||
|
||||
metadata:
|
||||
name: "WCAG Accessibility Standards"
|
||||
version: "1.0.0"
|
||||
last_updated: "2026-02-13"
|
||||
sources:
|
||||
- name: "Web Content Accessibility Guidelines (WCAG) 2.2"
|
||||
url: "https://www.w3.org/TR/WCAG22/"
|
||||
version: "2.2"
|
||||
date: "2023-10-05"
|
||||
- name: "Web Content Accessibility Guidelines (WCAG) 2.1"
|
||||
url: "https://www.w3.org/TR/WCAG21/"
|
||||
version: "2.1"
|
||||
date: "2018-06-05"
|
||||
- name: "Web Content Accessibility Guidelines (WCAG) 2.0"
|
||||
url: "https://www.w3.org/TR/WCAG20/"
|
||||
version: "2.0"
|
||||
date: "2008-12-11"
|
||||
- name: "axe-core Rule Descriptions"
|
||||
url: "https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md"
|
||||
- name: "axe-core API Documentation"
|
||||
url: "https://www.deque.com/axe/core-documentation/api-documentation/"
|
||||
|
||||
# ============================================================
|
||||
# axe-core Tag Mapping
|
||||
# These tags control which rules axe-core runs
|
||||
# IMPORTANT: Tags are NOT inclusive - wcag2aa only runs AA rules,
|
||||
# NOT A rules. Combine tags for full compliance testing.
|
||||
# ============================================================
|
||||
axe_core_tags:
|
||||
wcag20:
|
||||
- tag: "wcag2a"
|
||||
description: "WCAG 2.0 Level A rules only"
|
||||
- tag: "wcag2aa"
|
||||
description: "WCAG 2.0 Level AA rules only"
|
||||
- tag: "wcag2aaa"
|
||||
description: "WCAG 2.0 Level AAA rules only"
|
||||
wcag21:
|
||||
- tag: "wcag21a"
|
||||
description: "WCAG 2.1 Level A rules only (new in 2.1)"
|
||||
- tag: "wcag21aa"
|
||||
description: "WCAG 2.1 Level AA rules only (new in 2.1)"
|
||||
wcag22:
|
||||
- tag: "wcag22aa"
|
||||
description: "WCAG 2.2 Level AA rules only (new in 2.2)"
|
||||
other:
|
||||
- tag: "best-practice"
|
||||
description: "Common accessibility best practices (not WCAG-specific)"
|
||||
- tag: "section508"
|
||||
description: "Section 508 compliance rules"
|
||||
|
||||
# Compliance presets (combine tags for full testing)
|
||||
compliance_presets:
|
||||
wcag_20_a:
|
||||
tags: ["wcag2a"]
|
||||
description: "WCAG 2.0 Level A compliance"
|
||||
wcag_20_aa:
|
||||
tags: ["wcag2a", "wcag2aa"]
|
||||
description: "WCAG 2.0 Level AA compliance"
|
||||
wcag_21_aa:
|
||||
tags: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"]
|
||||
description: "WCAG 2.1 Level AA compliance (most common requirement)"
|
||||
wcag_22_aa:
|
||||
tags: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"]
|
||||
description: "WCAG 2.2 Level AA compliance (latest standard)"
|
||||
wcag_22_full:
|
||||
tags: ["wcag2a", "wcag2aa", "wcag2aaa", "wcag21a", "wcag21aa", "wcag22aa"]
|
||||
description: "WCAG 2.2 all levels including AAA"
|
||||
|
||||
# ============================================================
|
||||
# WCAG 2.2 Complete Success Criteria
|
||||
# Total: 86 criteria (4.1.1 Parsing removed in 2.2)
|
||||
# Distribution: Level A (32), Level AA (24), Level AAA (30)
|
||||
# ============================================================
|
||||
|
||||
principles:
|
||||
# ========================================================
|
||||
# Principle 1: PERCEIVABLE
|
||||
# ========================================================
|
||||
- id: "perceivable"
|
||||
name: "Perceivable"
|
||||
description: "Information and user interface components must be presentable to users in ways they can perceive"
|
||||
|
||||
guidelines:
|
||||
# --- 1.1 Text Alternatives ---
|
||||
- id: "1.1"
|
||||
name: "Text Alternatives"
|
||||
description: "Provide text alternatives for any non-text content"
|
||||
criteria:
|
||||
- id: "1.1.1"
|
||||
name: "Non-text Content"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "All non-text content has a text alternative that serves the equivalent purpose"
|
||||
axe_rules: ["image-alt", "input-image-alt", "area-alt", "object-alt", "svg-img-alt"]
|
||||
|
||||
# --- 1.2 Time-based Media ---
|
||||
- id: "1.2"
|
||||
name: "Time-based Media"
|
||||
description: "Provide alternatives for time-based media"
|
||||
criteria:
|
||||
- id: "1.2.1"
|
||||
name: "Audio-only and Video-only (Prerecorded)"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "An alternative is provided for prerecorded audio-only and video-only media"
|
||||
axe_rules: ["audio-caption", "video-caption"]
|
||||
|
||||
- id: "1.2.2"
|
||||
name: "Captions (Prerecorded)"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Captions are provided for all prerecorded audio content in synchronized media"
|
||||
axe_rules: ["video-caption"]
|
||||
|
||||
- id: "1.2.3"
|
||||
name: "Audio Description or Media Alternative (Prerecorded)"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "An alternative for time-based media or audio description is provided"
|
||||
axe_rules: ["video-description"]
|
||||
|
||||
- id: "1.2.4"
|
||||
name: "Captions (Live)"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Captions are provided for all live audio content in synchronized media"
|
||||
|
||||
- id: "1.2.5"
|
||||
name: "Audio Description (Prerecorded)"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Audio description is provided for all prerecorded video content"
|
||||
|
||||
- id: "1.2.6"
|
||||
name: "Sign Language (Prerecorded)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Sign language interpretation is provided for prerecorded audio"
|
||||
|
||||
- id: "1.2.7"
|
||||
name: "Extended Audio Description (Prerecorded)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Extended audio description is provided when pauses are insufficient"
|
||||
|
||||
- id: "1.2.8"
|
||||
name: "Media Alternative (Prerecorded)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "A text alternative is provided for all prerecorded synchronized media"
|
||||
|
||||
- id: "1.2.9"
|
||||
name: "Audio-only (Live)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "A text alternative is provided for live audio-only content"
|
||||
|
||||
# --- 1.3 Adaptable ---
|
||||
- id: "1.3"
|
||||
name: "Adaptable"
|
||||
description: "Create content that can be presented in different ways without losing information"
|
||||
criteria:
|
||||
- id: "1.3.1"
|
||||
name: "Info and Relationships"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Information, structure, and relationships can be programmatically determined"
|
||||
axe_rules: ["aria-required-parent", "aria-required-children", "definition-list", "dlitem", "list", "listitem", "th-has-data-cells", "td-headers-attr", "p-as-heading"]
|
||||
|
||||
- id: "1.3.2"
|
||||
name: "Meaningful Sequence"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Correct reading sequence can be programmatically determined"
|
||||
|
||||
- id: "1.3.3"
|
||||
name: "Sensory Characteristics"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Instructions do not rely solely on sensory characteristics"
|
||||
|
||||
- id: "1.3.4"
|
||||
name: "Orientation"
|
||||
level: "AA"
|
||||
since: "2.1"
|
||||
description: "Content does not restrict viewing to a single display orientation"
|
||||
|
||||
- id: "1.3.5"
|
||||
name: "Identify Input Purpose"
|
||||
level: "AA"
|
||||
since: "2.1"
|
||||
description: "Input field purpose can be programmatically determined"
|
||||
axe_rules: ["autocomplete-valid"]
|
||||
|
||||
- id: "1.3.6"
|
||||
name: "Identify Purpose"
|
||||
level: "AAA"
|
||||
since: "2.1"
|
||||
description: "The purpose of UI components, icons, and regions can be programmatically determined"
|
||||
|
||||
# --- 1.4 Distinguishable ---
|
||||
- id: "1.4"
|
||||
name: "Distinguishable"
|
||||
description: "Make it easier for users to see and hear content"
|
||||
criteria:
|
||||
- id: "1.4.1"
|
||||
name: "Use of Color"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Color is not the only visual means of conveying information"
|
||||
axe_rules: ["link-in-text-block"]
|
||||
|
||||
- id: "1.4.2"
|
||||
name: "Audio Control"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Mechanism to pause/stop/control volume of auto-playing audio"
|
||||
axe_rules: ["no-autoplay-audio"]
|
||||
|
||||
- id: "1.4.3"
|
||||
name: "Contrast (Minimum)"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Text has contrast ratio of at least 4.5:1 (3:1 for large text)"
|
||||
axe_rules: ["color-contrast"]
|
||||
|
||||
- id: "1.4.4"
|
||||
name: "Resize Text"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Text can be resized up to 200% without loss of content or functionality"
|
||||
axe_rules: ["meta-viewport-large"]
|
||||
|
||||
- id: "1.4.5"
|
||||
name: "Images of Text"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Text is used instead of images of text where possible"
|
||||
|
||||
- id: "1.4.6"
|
||||
name: "Contrast (Enhanced)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Text has contrast ratio of at least 7:1 (4.5:1 for large text)"
|
||||
axe_rules: ["color-contrast-enhanced"]
|
||||
|
||||
- id: "1.4.7"
|
||||
name: "Low or No Background Audio"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Prerecorded speech audio has low or no background noise"
|
||||
|
||||
- id: "1.4.8"
|
||||
name: "Visual Presentation"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Text blocks have configurable visual presentation"
|
||||
|
||||
- id: "1.4.9"
|
||||
name: "Images of Text (No Exception)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Images of text are only used for pure decoration or essential cases"
|
||||
|
||||
- id: "1.4.10"
|
||||
name: "Reflow"
|
||||
level: "AA"
|
||||
since: "2.1"
|
||||
description: "Content can reflow without scrolling in two dimensions at 320px/256px"
|
||||
|
||||
- id: "1.4.11"
|
||||
name: "Non-text Contrast"
|
||||
level: "AA"
|
||||
since: "2.1"
|
||||
description: "UI components and graphics have contrast ratio of at least 3:1"
|
||||
|
||||
- id: "1.4.12"
|
||||
name: "Text Spacing"
|
||||
level: "AA"
|
||||
since: "2.1"
|
||||
description: "Content adapts to specified text spacing without loss"
|
||||
|
||||
- id: "1.4.13"
|
||||
name: "Content on Hover or Focus"
|
||||
level: "AA"
|
||||
since: "2.1"
|
||||
description: "Hoverable/focusable additional content is dismissible, hoverable, persistent"
|
||||
|
||||
# ========================================================
|
||||
# Principle 2: OPERABLE
|
||||
# ========================================================
|
||||
- id: "operable"
|
||||
name: "Operable"
|
||||
description: "User interface components and navigation must be operable"
|
||||
|
||||
guidelines:
|
||||
# --- 2.1 Keyboard Accessible ---
|
||||
- id: "2.1"
|
||||
name: "Keyboard Accessible"
|
||||
description: "Make all functionality available from a keyboard"
|
||||
criteria:
|
||||
- id: "2.1.1"
|
||||
name: "Keyboard"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "All functionality is operable through a keyboard interface"
|
||||
axe_rules: ["scrollable-region-focusable"]
|
||||
|
||||
- id: "2.1.2"
|
||||
name: "No Keyboard Trap"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Keyboard focus can be moved away from any component"
|
||||
|
||||
- id: "2.1.3"
|
||||
name: "Keyboard (No Exception)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "All functionality is operable through keyboard without exception"
|
||||
|
||||
- id: "2.1.4"
|
||||
name: "Character Key Shortcuts"
|
||||
level: "A"
|
||||
since: "2.1"
|
||||
description: "Single character key shortcuts can be turned off or remapped"
|
||||
axe_rules: ["accesskeys"]
|
||||
|
||||
# --- 2.2 Enough Time ---
|
||||
- id: "2.2"
|
||||
name: "Enough Time"
|
||||
description: "Provide users enough time to read and use content"
|
||||
criteria:
|
||||
- id: "2.2.1"
|
||||
name: "Timing Adjustable"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Time limits can be turned off, adjusted, or extended"
|
||||
axe_rules: ["meta-refresh"]
|
||||
|
||||
- id: "2.2.2"
|
||||
name: "Pause, Stop, Hide"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Moving, blinking, scrolling, or auto-updating content can be controlled"
|
||||
axe_rules: ["blink", "marquee"]
|
||||
|
||||
- id: "2.2.3"
|
||||
name: "No Timing"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Timing is not an essential part of the activity"
|
||||
|
||||
- id: "2.2.4"
|
||||
name: "Interruptions"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Interruptions can be postponed or suppressed"
|
||||
|
||||
- id: "2.2.5"
|
||||
name: "Re-authenticating"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Data is preserved when re-authenticating after session expiry"
|
||||
|
||||
- id: "2.2.6"
|
||||
name: "Timeouts"
|
||||
level: "AAA"
|
||||
since: "2.1"
|
||||
description: "Users are warned about data loss from inactivity timeouts"
|
||||
|
||||
# --- 2.3 Seizures and Physical Reactions ---
|
||||
- id: "2.3"
|
||||
name: "Seizures and Physical Reactions"
|
||||
description: "Do not design content that causes seizures or physical reactions"
|
||||
criteria:
|
||||
- id: "2.3.1"
|
||||
name: "Three Flashes or Below Threshold"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Pages do not contain content that flashes more than three times per second"
|
||||
|
||||
- id: "2.3.2"
|
||||
name: "Three Flashes"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Pages do not contain any content that flashes more than three times per second"
|
||||
|
||||
- id: "2.3.3"
|
||||
name: "Animation from Interactions"
|
||||
level: "AAA"
|
||||
since: "2.1"
|
||||
description: "Motion animation triggered by interaction can be disabled"
|
||||
|
||||
# --- 2.4 Navigable ---
|
||||
- id: "2.4"
|
||||
name: "Navigable"
|
||||
description: "Provide ways to help users navigate, find content, and determine where they are"
|
||||
criteria:
|
||||
- id: "2.4.1"
|
||||
name: "Bypass Blocks"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Mechanism available to bypass blocks of content repeated on pages"
|
||||
axe_rules: ["bypass", "region"]
|
||||
|
||||
- id: "2.4.2"
|
||||
name: "Page Titled"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Web pages have titles that describe topic or purpose"
|
||||
axe_rules: ["document-title"]
|
||||
|
||||
- id: "2.4.3"
|
||||
name: "Focus Order"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Focus order preserves meaning and operability"
|
||||
axe_rules: ["tabindex"]
|
||||
|
||||
- id: "2.4.4"
|
||||
name: "Link Purpose (In Context)"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Link purpose can be determined from link text or context"
|
||||
axe_rules: ["link-name"]
|
||||
|
||||
- id: "2.4.5"
|
||||
name: "Multiple Ways"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "More than one way available to locate a page in a set"
|
||||
|
||||
- id: "2.4.6"
|
||||
name: "Headings and Labels"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Headings and labels describe topic or purpose"
|
||||
axe_rules: ["empty-heading"]
|
||||
|
||||
- id: "2.4.7"
|
||||
name: "Focus Visible"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Keyboard focus indicator is visible"
|
||||
|
||||
- id: "2.4.8"
|
||||
name: "Location"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Information about the user's location within a set of pages is available"
|
||||
|
||||
- id: "2.4.9"
|
||||
name: "Link Purpose (Link Only)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Link purpose can be determined from link text alone"
|
||||
|
||||
- id: "2.4.10"
|
||||
name: "Section Headings"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Section headings are used to organize content"
|
||||
|
||||
- id: "2.4.11"
|
||||
name: "Focus Not Obscured (Minimum)"
|
||||
level: "AA"
|
||||
since: "2.2"
|
||||
description: "Focused component is not entirely hidden by author-created content"
|
||||
|
||||
- id: "2.4.12"
|
||||
name: "Focus Not Obscured (Enhanced)"
|
||||
level: "AAA"
|
||||
since: "2.2"
|
||||
description: "No part of the focused component is hidden by author-created content"
|
||||
|
||||
- id: "2.4.13"
|
||||
name: "Focus Appearance"
|
||||
level: "AAA"
|
||||
since: "2.2"
|
||||
description: "Focus indicator meets minimum area and contrast requirements"
|
||||
|
||||
# --- 2.5 Input Modalities ---
|
||||
- id: "2.5"
|
||||
name: "Input Modalities"
|
||||
description: "Make it easier to operate through various inputs beyond keyboard"
|
||||
criteria:
|
||||
- id: "2.5.1"
|
||||
name: "Pointer Gestures"
|
||||
level: "A"
|
||||
since: "2.1"
|
||||
description: "Multipoint/path-based gestures have single-pointer alternatives"
|
||||
|
||||
- id: "2.5.2"
|
||||
name: "Pointer Cancellation"
|
||||
level: "A"
|
||||
since: "2.1"
|
||||
description: "Functions using single pointer can be cancelled"
|
||||
|
||||
- id: "2.5.3"
|
||||
name: "Label in Name"
|
||||
level: "A"
|
||||
since: "2.1"
|
||||
description: "Visible label is part of the accessible name"
|
||||
axe_rules: ["label-title-only"]
|
||||
|
||||
- id: "2.5.4"
|
||||
name: "Motion Actuation"
|
||||
level: "A"
|
||||
since: "2.1"
|
||||
description: "Motion-activated functions have UI alternatives and can be disabled"
|
||||
|
||||
- id: "2.5.5"
|
||||
name: "Target Size (Enhanced)"
|
||||
level: "AAA"
|
||||
since: "2.1"
|
||||
description: "Target size is at least 44 by 44 CSS pixels"
|
||||
|
||||
- id: "2.5.6"
|
||||
name: "Concurrent Input Mechanisms"
|
||||
level: "A"
|
||||
since: "2.1"
|
||||
description: "Content does not restrict use of available input modalities"
|
||||
|
||||
- id: "2.5.7"
|
||||
name: "Dragging Movements"
|
||||
level: "AA"
|
||||
since: "2.2"
|
||||
description: "Drag functions have single-pointer alternatives"
|
||||
|
||||
- id: "2.5.8"
|
||||
name: "Target Size (Minimum)"
|
||||
level: "AA"
|
||||
since: "2.2"
|
||||
description: "Target size is at least 24 by 24 CSS pixels"
|
||||
axe_rules: ["target-size"]
|
||||
|
||||
# ========================================================
|
||||
# Principle 3: UNDERSTANDABLE
|
||||
# ========================================================
|
||||
- id: "understandable"
|
||||
name: "Understandable"
|
||||
description: "Information and the operation of user interface must be understandable"
|
||||
|
||||
guidelines:
|
||||
# --- 3.1 Readable ---
|
||||
- id: "3.1"
|
||||
name: "Readable"
|
||||
description: "Make text content readable and understandable"
|
||||
criteria:
|
||||
- id: "3.1.1"
|
||||
name: "Language of Page"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Default human language of each page can be programmatically determined"
|
||||
axe_rules: ["html-has-lang", "html-lang-valid"]
|
||||
|
||||
- id: "3.1.2"
|
||||
name: "Language of Parts"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Language of each passage or phrase can be programmatically determined"
|
||||
axe_rules: ["valid-lang"]
|
||||
|
||||
- id: "3.1.3"
|
||||
name: "Unusual Words"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Mechanism is available for unusual words or jargon"
|
||||
|
||||
- id: "3.1.4"
|
||||
name: "Abbreviations"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Mechanism for identifying expanded form of abbreviations"
|
||||
|
||||
- id: "3.1.5"
|
||||
name: "Reading Level"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Supplemental content for text beyond lower secondary education level"
|
||||
|
||||
- id: "3.1.6"
|
||||
name: "Pronunciation"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Mechanism for identifying pronunciation of ambiguous words"
|
||||
|
||||
# --- 3.2 Predictable ---
|
||||
- id: "3.2"
|
||||
name: "Predictable"
|
||||
description: "Make web pages appear and operate in predictable ways"
|
||||
criteria:
|
||||
- id: "3.2.1"
|
||||
name: "On Focus"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Receiving focus does not initiate a change of context"
|
||||
|
||||
- id: "3.2.2"
|
||||
name: "On Input"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Changing a UI component setting does not automatically cause a change of context"
|
||||
|
||||
- id: "3.2.3"
|
||||
name: "Consistent Navigation"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Navigation repeated on pages occurs in the same relative order"
|
||||
|
||||
- id: "3.2.4"
|
||||
name: "Consistent Identification"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Components with the same functionality are identified consistently"
|
||||
|
||||
- id: "3.2.5"
|
||||
name: "Change on Request"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Changes of context are initiated only by user request"
|
||||
|
||||
- id: "3.2.6"
|
||||
name: "Consistent Help"
|
||||
level: "A"
|
||||
since: "2.2"
|
||||
description: "Help mechanisms occur in the same relative order across pages"
|
||||
|
||||
# --- 3.3 Input Assistance ---
|
||||
- id: "3.3"
|
||||
name: "Input Assistance"
|
||||
description: "Help users avoid and correct mistakes"
|
||||
criteria:
|
||||
- id: "3.3.1"
|
||||
name: "Error Identification"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Input errors are automatically detected and described to the user"
|
||||
axe_rules: ["aria-input-field-name"]
|
||||
|
||||
- id: "3.3.2"
|
||||
name: "Labels or Instructions"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Labels or instructions are provided when content requires user input"
|
||||
axe_rules: ["label", "input-button-name", "select-name"]
|
||||
|
||||
- id: "3.3.3"
|
||||
name: "Error Suggestion"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Error suggestions are provided when errors are detected and suggestions are known"
|
||||
|
||||
- id: "3.3.4"
|
||||
name: "Error Prevention (Legal, Financial, Data)"
|
||||
level: "AA"
|
||||
since: "2.0"
|
||||
description: "Submissions are reversible, checked, or confirmed for legal/financial/data"
|
||||
|
||||
- id: "3.3.5"
|
||||
name: "Help"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Context-sensitive help is available"
|
||||
|
||||
- id: "3.3.6"
|
||||
name: "Error Prevention (All)"
|
||||
level: "AAA"
|
||||
since: "2.0"
|
||||
description: "Submissions are reversible, checked, or confirmed for all user input"
|
||||
|
||||
- id: "3.3.7"
|
||||
name: "Redundant Entry"
|
||||
level: "A"
|
||||
since: "2.2"
|
||||
description: "Previously entered information is auto-populated or available for selection"
|
||||
|
||||
- id: "3.3.8"
|
||||
name: "Accessible Authentication (Minimum)"
|
||||
level: "AA"
|
||||
since: "2.2"
|
||||
description: "Cognitive function test is not required for authentication"
|
||||
|
||||
- id: "3.3.9"
|
||||
name: "Accessible Authentication (Enhanced)"
|
||||
level: "AAA"
|
||||
since: "2.2"
|
||||
description: "No cognitive function test is required for authentication (no exceptions)"
|
||||
|
||||
# ========================================================
|
||||
# Principle 4: ROBUST
|
||||
# ========================================================
|
||||
- id: "robust"
|
||||
name: "Robust"
|
||||
description: "Content must be robust enough to be interpreted by a wide variety of user agents"
|
||||
|
||||
guidelines:
|
||||
# --- 4.1 Compatible ---
|
||||
- id: "4.1"
|
||||
name: "Compatible"
|
||||
description: "Maximize compatibility with current and future user agents"
|
||||
criteria:
|
||||
# Note: 4.1.1 Parsing was REMOVED in WCAG 2.2
|
||||
# It was deemed obsolete as modern browsers handle parsing errors gracefully
|
||||
|
||||
- id: "4.1.2"
|
||||
name: "Name, Role, Value"
|
||||
level: "A"
|
||||
since: "2.0"
|
||||
description: "Name, role, and value of all UI components can be programmatically determined"
|
||||
axe_rules: ["aria-allowed-attr", "aria-allowed-role", "aria-hidden-body", "aria-hidden-focus", "aria-roles", "aria-valid-attr", "aria-valid-attr-value", "button-name", "frame-title", "image-alt", "input-button-name", "input-image-alt", "label", "link-name", "select-name"]
|
||||
|
||||
- id: "4.1.3"
|
||||
name: "Status Messages"
|
||||
level: "AA"
|
||||
since: "2.1"
|
||||
description: "Status messages can be programmatically determined without receiving focus"
|
||||
axe_rules: ["aria-progressbar-name"]
|
||||
|
||||
# ============================================================
|
||||
# Version Diff Summary
|
||||
# What's new in each version
|
||||
# ============================================================
|
||||
version_diff:
|
||||
removed_in_22:
|
||||
- id: "4.1.1"
|
||||
name: "Parsing"
|
||||
reason: "Modern browsers handle parsing errors; criterion was obsolete"
|
||||
|
||||
new_in_21:
|
||||
level_a:
|
||||
- "1.3.4 Orientation" # Note: Listed as A in some sources, AA in W3C spec
|
||||
- "2.1.4 Character Key Shortcuts"
|
||||
- "2.5.1 Pointer Gestures"
|
||||
- "2.5.2 Pointer Cancellation"
|
||||
- "2.5.3 Label in Name"
|
||||
- "2.5.4 Motion Actuation"
|
||||
- "2.5.6 Concurrent Input Mechanisms"
|
||||
level_aa:
|
||||
- "1.3.4 Orientation"
|
||||
- "1.3.5 Identify Input Purpose"
|
||||
- "1.4.10 Reflow"
|
||||
- "1.4.11 Non-text Contrast"
|
||||
- "1.4.12 Text Spacing"
|
||||
- "1.4.13 Content on Hover or Focus"
|
||||
level_aaa:
|
||||
- "1.3.6 Identify Purpose"
|
||||
- "2.2.6 Timeouts"
|
||||
- "2.3.3 Animation from Interactions"
|
||||
- "2.5.5 Target Size (Enhanced)"
|
||||
|
||||
new_in_22:
|
||||
level_a:
|
||||
- "3.2.6 Consistent Help"
|
||||
- "3.3.7 Redundant Entry"
|
||||
level_aa:
|
||||
- "2.4.11 Focus Not Obscured (Minimum)"
|
||||
- "2.5.7 Dragging Movements"
|
||||
- "2.5.8 Target Size (Minimum)"
|
||||
- "3.3.8 Accessible Authentication (Minimum)"
|
||||
level_aaa:
|
||||
- "2.4.12 Focus Not Obscured (Enhanced)"
|
||||
- "2.4.13 Focus Appearance"
|
||||
- "3.3.9 Accessible Authentication (Enhanced)"
|
||||
|
||||
# ============================================================
|
||||
# Additional axe-core Best Practice Rules
|
||||
# (Not mapped to specific WCAG criteria but recommended)
|
||||
# ============================================================
|
||||
best_practices:
|
||||
- id: "landmark-one-main"
|
||||
description: "Document should have one main landmark"
|
||||
severity: "major"
|
||||
|
||||
- id: "landmark-complementary-is-top-level"
|
||||
description: "Aside/complementary should be top-level"
|
||||
severity: "minor"
|
||||
|
||||
- id: "landmark-no-duplicate-banner"
|
||||
description: "Document should have at most one banner landmark"
|
||||
severity: "major"
|
||||
|
||||
- id: "landmark-no-duplicate-contentinfo"
|
||||
description: "Document should have at most one contentinfo landmark"
|
||||
severity: "major"
|
||||
|
||||
- id: "landmark-no-duplicate-main"
|
||||
description: "Document should have at most one main landmark"
|
||||
severity: "major"
|
||||
|
||||
- id: "page-has-heading-one"
|
||||
description: "Page should contain a level-one heading"
|
||||
severity: "major"
|
||||
|
||||
- id: "heading-order"
|
||||
description: "Heading levels should increase by one"
|
||||
severity: "minor"
|
||||
|
||||
- id: "scope-attr-valid"
|
||||
description: "scope attribute should be used correctly"
|
||||
severity: "minor"
|
||||
|
||||
- id: "skip-link"
|
||||
description: "Skip navigation link should be provided"
|
||||
severity: "minor"
|
||||
|
||||
- id: "tabindex"
|
||||
description: "Tabindex should not be greater than zero"
|
||||
severity: "major"
|
||||
|
||||
- id: "duplicate-id-active"
|
||||
description: "Active elements should not have duplicate IDs"
|
||||
severity: "critical"
|
||||
|
||||
- id: "duplicate-id-aria"
|
||||
description: "ARIA IDs should be unique"
|
||||
severity: "critical"
|
||||
|
||||
- id: "frame-tested"
|
||||
description: "Frames should be tested with axe-core"
|
||||
severity: "minor"
|
||||
|
||||
- id: "aria-text"
|
||||
description: "Elements with role=text should have no focusable descendants"
|
||||
severity: "minor"
|
||||
Reference in New Issue
Block a user