accessibility_rs/engine/audit/
wcag.rs1use crate::engine::issue::Issue;
2use crate::engine::rules::rule::RuleValidation;
3use crate::engine::rules::wcag_rule_map::RULES_A;
4use crate::Auditor;
5#[cfg(feature = "rayon")]
6use rayon::prelude::*;
7
8#[derive(Default)]
9pub struct WCAGAAA;
11
12impl WCAGAAA {
14 #[cfg(not(feature = "tokio"))]
16 pub fn run_audit(auditor: (Auditor<'_>, Option<taffy::TaffyTree>)) -> Vec<Issue> {
17 use crate::engine::audit::audit_utils::push_issue_base;
18 let mut issues: Vec<Issue> = Vec::new();
19
20 for node in auditor.0.tree.iter() {
21 match RULES_A.get(&*node.0) {
22 Some(rules) => {
23 for rule in rules {
24 match (rule.validate)(&node.1, &auditor.0) {
25 RuleValidation::Single(validation) => push_issue_base(
26 validation,
27 rule,
28 &node.0,
29 &auditor.0.locale,
30 &mut issues,
31 ),
32 RuleValidation::Multi(validation) => {
33 for v in validation {
34 push_issue_base(
35 v,
36 rule,
37 &node.0,
38 &auditor.0.locale,
39 &mut issues,
40 )
41 }
42 }
43 };
44 }
45 }
46 _ => (),
47 }
48 }
49
50 issues
51 }
52
53 #[cfg(feature = "tokio")]
55 pub async fn run_audit(auditor: (Auditor<'_>, Option<taffy::TaffyTree>)) -> Vec<Issue> {
56 use crate::engine::audit::audit_utils::push_issue_base;
57 use tokio_stream::{self as stream, StreamExt};
58 let mut issues: Vec<Issue> = Vec::new();
59 let stream = stream::iter(auditor.0.tree.iter());
60 tokio::pin!(stream);
61
62 while let Some(node) = stream.next().await {
63 match RULES_A.get(&*node.0) {
64 Some(rules) => {
65 for rule in rules {
66 match (rule.validate)(&node.1, &auditor.0) {
67 RuleValidation::Single(validation) => push_issue_base(
68 validation,
69 rule,
70 &node.0,
71 &auditor.0.locale,
72 &mut issues,
73 ),
74 RuleValidation::Multi(validation) => {
75 for v in validation {
76 push_issue_base(
77 v,
78 rule,
79 &node.0,
80 &auditor.0.locale,
81 &mut issues,
82 )
83 }
84 }
85 };
86 }
87 }
88 _ => (),
89 }
90 }
91
92 issues
93 }
94
95 #[cfg(all(feature = "rayon", not(feature = "spider"), not(feature = "tokio")))]
97 pub fn audit(auditor: (Auditor<'_>, Option<taffy::TaffyTree>)) -> Vec<Issue> {
98 use crate::engine::audit::audit_utils::evaluate_rules_in_parallel;
99
100 if auditor.0.document.tree.nodes().len() <= 5500 {
101 WCAGAAA::run_audit(auditor)
102 } else {
103 let (s, r) = crossbeam_channel::unbounded();
104
105 auditor.0.tree.par_iter().for_each(|node| {
106 if let Some(rules) = RULES_A.get(&*node.0) {
107 evaluate_rules_in_parallel(rules, &node, &auditor.0, &s);
108 }
109 });
110
111 drop(s);
112
113 r.iter().collect()
114 }
115 }
116
117 #[cfg(all(
119 not(feature = "rayon"),
120 not(feature = "spider"),
121 not(feature = "tokio")
122 ))]
123 pub fn audit(auditor: (Auditor<'_>, Option<taffy::TaffyTree>)) -> Vec<Issue> {
124 WCAGAAA::run_audit(auditor)
125 }
126
127 #[cfg(feature = "tokio")]
129 pub async fn audit(auditor: (Auditor<'_>, Option<taffy::TaffyTree>)) -> Vec<Issue> {
130 WCAGAAA::run_audit(auditor).await
131 }
132}