Skip to content

Commit

Permalink
chore(audit): add localization dynamic values setup
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mendez committed Oct 11, 2023
1 parent 2644363 commit e20f657
Show file tree
Hide file tree
Showing 8 changed files with 527 additions and 28 deletions.
445 changes: 441 additions & 4 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions accessibility-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ cssparser = { workspace = true }
slotmap = "1.0.6"
strum = "0.25"
strum_macros = "0.25"
rust-i18n = "2"

[dev-dependencies]
wasm-bindgen-test = "0.3.37"
Expand Down
14 changes: 11 additions & 3 deletions accessibility-rs/src/engine/audit/wcag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,20 @@ impl WCAG3AA {
match rules {
Some(rules) => {
for rule in rules {
let (valid, section, selector) = (rule.validate)(&node.0, &node.1);
let validation = (rule.validate)(&node.0, &node.1);
let valid = validation.valid;
let section = validation.id;
let selector = validation.elements;
let message = validation.message;

if !valid {
// get locales prior or from document
let message =
get_message(&rule.rule_id, &section, &Langs::En.as_str());
let message = if !message.is_empty() {
message
} else {
get_message(&rule.rule_id, &section, &Langs::En.as_str())
};

let issue = Issue::new(
message,
&node.0,
Expand Down
48 changes: 40 additions & 8 deletions accessibility-rs/src/engine/rules/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,52 @@ use crate::engine::rules::ids::Techniques;
use crate::engine::rules::wcag_base::{Criteria, Guideline, Principle};
use crate::ElementRef;

/// the validation response
#[derive(Default)]
pub struct Validation {
/// is valid
pub valid: bool,
/// the sub-technique
pub id: &'static str,
/// elements that match the issue
pub elements: Vec<&'static str>,
/// the message of the error
pub message: &'static str,
}

impl Validation {
/// helper to create validation
pub fn new(
valid: bool,
id: &'static str,
elements: Vec<&'static str>,
message: &'static str,
) -> Self {
Self {
valid,
id,
elements,
message,
}
}
/// basic validation
pub fn new_issue(valid: bool, id: &'static str) -> Self {
Self {
valid,
id,
..Default::default()
}
}
}

/// the rule validation method that should be performed.
pub struct Rule {
/// the message id of the rule to point to the locale
pub rule_id: Techniques,
/// the type of rule
pub criteria: Criteria,
/// validate a test returns (valid, rule, selectors)
pub validate: fn(
&str,
&Vec<(ElementRef<'_>, Option<DefaultKey>)>,
) -> (bool, &'static str, Vec<&'static str>),
pub validate: fn(&str, &Vec<(ElementRef<'_>, Option<DefaultKey>)>) -> Validation,
/// the principle type
pub principle: Principle,
/// the guideline to follow
Expand All @@ -28,10 +63,7 @@ impl Rule {
criteria: Criteria,
principle: Principle,
guideline: Guideline,
validate: fn(
&str,
&Vec<(ElementRef<'_>, Option<DefaultKey>)>,
) -> (bool, &'static str, Vec<&'static str>),
validate: fn(&str, &Vec<(ElementRef<'_>, Option<DefaultKey>)>) -> Validation,
) -> Rule {
Rule {
rule_id,
Expand Down
22 changes: 11 additions & 11 deletions accessibility-rs/src/engine/rules/wcag_rule_map.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::engine::rules::ids::Techniques;
use crate::engine::rules::rule::Rule;
use crate::engine::rules::rule::{Rule, Validation};
use crate::engine::rules::wcag_base::{Criteria, Guideline, Principle};
use accessibility_scraper::Selector;
use std::collections::BTreeMap;
Expand All @@ -11,12 +11,12 @@ lazy_static! {
vec![
("html", Vec::from([
Rule::new(Techniques::H57, Criteria::Error, Principle::Understandable, Guideline::Readable, |_rule, nodes| {
(!nodes[0].0.attr("lang").unwrap_or_default().is_empty(), "2", Default::default())
Validation::new_issue(!nodes[0].0.attr("lang").unwrap_or_default().is_empty(), "2")
}),
Rule::new(Techniques::H57, Criteria::Error, Principle::Understandable, Guideline::Readable, |_rule, nodes| {
let lang = nodes[0].0.attr("lang").unwrap_or_default();
// <https://www.rfc-editor.org/rfc/bcp/bcp47.txt>
(lang.chars().all(|x| x.is_alphanumeric()) && !lang.contains("_") && lang.len() < 12, "3.Lang", Default::default())
Validation::new_issue(lang.chars().all(|x| x.is_alphanumeric()) && !lang.contains("_") && lang.len() < 12, "3.Lang")
}),
])),
("meta", Vec::from([
Expand All @@ -34,7 +34,7 @@ lazy_static! {
}
}

(valid, "2", Default::default())
Validation::new_issue(valid, "2")
}),
Rule::new(Techniques::F41, Criteria::Error, Principle::Understandable, Guideline::EnoughTime, |_rule, nodes| {
let mut valid = true;
Expand All @@ -50,30 +50,30 @@ lazy_static! {
}
}

(valid, "2", Default::default())
Validation::new_issue(valid, "2")
}),
])),
("title", Vec::from([
Rule::new(Techniques::H25, Criteria::Error, Principle::Operable, Guideline::Navigable, |_rule, nodes| {
(!nodes.is_empty(), "1.NoTitleEl", Default::default())
Validation::new_issue(!nodes.is_empty(), "1.NoTitleEl")
}),
Rule::new(Techniques::H25, Criteria::Error, Principle::Understandable, Guideline::Predictable, |_rule, nodes| {
(nodes.is_empty() || nodes[0].0.html().is_empty(), "1.EmptyTitle", Default::default())
Validation::new_issue(nodes.is_empty() || nodes[0].0.html().is_empty(), "1.EmptyTitle")
}),
])),
("blink", Vec::from([
Rule::new(Techniques::F47, Criteria::Error, Principle::Operable, Guideline::EnoughTime, |_rule, nodes| {
(nodes.is_empty(), "", Default::default())
Validation::new_issue(nodes.is_empty(), "")
}),
])),
("iframe", Vec::from([
Rule::new(Techniques::H64, Criteria::Error, Principle::Operable, Guideline::Navigable, |_rule, nodes| {
(nodes.iter().all(|e| !e.0.attr("title").unwrap_or_default().is_empty()), "", Default::default())
Validation::new_issue(nodes.iter().all(|e| !e.0.attr("title").unwrap_or_default().is_empty()), "")
}),
])),
("frame", Vec::from([
Rule::new(Techniques::H64, Criteria::Error, Principle::Operable, Guideline::Navigable, |_rule, nodes| {
(nodes.iter().all(|e| !e.0.attr("title").unwrap_or_default().is_empty()), "", Default::default())
Validation::new_issue(nodes.iter().all(|e| !e.0.attr("title").unwrap_or_default().is_empty()), "")
}),
])),
("form", Vec::from([
Expand All @@ -90,7 +90,7 @@ lazy_static! {
};
}

(valid, "2", Default::default())
Validation::new_issue(valid, "2")
}),
]))
]
Expand Down
14 changes: 13 additions & 1 deletion accessibility-rs/src/i18n/locales.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl Messages {
}
}

/// parse
/// parse message translation
pub fn get_message(rule_id: &Techniques, section: &str, lang: &str) -> &'static str {
let rule_id = rule_id.as_str();
let message = if section.is_empty() {
Expand All @@ -101,6 +101,18 @@ pub fn get_message(rule_id: &Techniques, section: &str, lang: &str) -> &'static
}
}

/// get message config type
pub fn get_message_i18n(rule_id: &Techniques, section: &str, lang: &str) -> String {
let rule_id = rule_id.as_str();
let message = if section.is_empty() {
rule_id.to_string()
} else {
[rule_id, section].join(".").to_string()
};

message
}

lazy_static! {
/// message for an issue
pub static ref LOCALES: BTreeMap<&'static str, Messages> = {
Expand Down
4 changes: 4 additions & 0 deletions accessibility-rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate rust_i18n;

/// the main engine for audits.
mod engine;
Expand All @@ -12,6 +14,8 @@ pub use crate::engine::audit::auditor::Auditor;
pub use crate::engine::issue::Issue;
pub use accessibility_scraper::ElementRef;

i18n!();

/// configs for the audit
#[derive(Default)]
pub struct AuditConfig {
Expand Down
7 changes: 6 additions & 1 deletion accessibility-rs/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@ use mocks::mock;

#[test]
fn _audit() {
let _ = accessibility_rs::audit(&AuditConfig::new(mock::MOCK_WEBSITE_HTML, &mock::MOCK_CSS_RULES, false, "en"));
let _ = accessibility_rs::audit(&AuditConfig::new(
mock::MOCK_WEBSITE_HTML,
&mock::MOCK_CSS_RULES,
false,
"en",
));
}

0 comments on commit e20f657

Please sign in to comment.