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