diff --git a/accessibility-rs/src/engine/audit/wcag.rs b/accessibility-rs/src/engine/audit/wcag.rs index 5543fee..0f54a48 100644 --- a/accessibility-rs/src/engine/audit/wcag.rs +++ b/accessibility-rs/src/engine/audit/wcag.rs @@ -36,7 +36,7 @@ impl WCAGAAA { "WCAGAAA", rule.principle.as_str(), rule.guideline.as_str(), - rule.rule_id.as_str(), + &rule.rule_id.into_str(), ] .join("."), rule.issue_type.as_str(), diff --git a/accessibility-rs/src/engine/rules/rule.rs b/accessibility-rs/src/engine/rules/rule.rs index 5e52977..f4d8564 100644 --- a/accessibility-rs/src/engine/rules/rule.rs +++ b/accessibility-rs/src/engine/rules/rule.rs @@ -37,11 +37,47 @@ impl Validation { } } +#[derive(Debug, Clone)] +/// techniques for a rule +pub enum Technique { + /// a single technique + Single(Techniques), + /// multiple techniques + Multi(Vec), +} + +impl Technique { + /// technique(s) into string + pub fn into_str(&self) -> String { + match self { + Technique::Multi(tech) => tech + .iter() + .map(|x| x.as_str()) + .collect::>() + .join(",") + .into(), + Technique::Single(tech) => tech.as_str().into(), + } + } +} + +impl From for Technique { + fn from(t: Techniques) -> Self { + Technique::Single(t) + } +} + +impl From> for Technique { + fn from(t: Vec) -> Self { + Technique::Multi(t) + } +} + /// the rule validation method that should be performed. #[derive(Debug)] pub struct Rule { /// the message id of the rule to point to the locale - pub rule_id: Techniques, + pub rule_id: Technique, /// the type of rule pub issue_type: IssueType, /// validate a test returns (valid, rule, selectors) @@ -57,7 +93,7 @@ pub struct Rule { impl Rule { /// a new rule type pub fn new( - rule_id: Techniques, + rule_id: Technique, issue_type: IssueType, principle: Principle, guideline: Guideline, diff --git a/accessibility-rs/src/engine/rules/techniques.rs b/accessibility-rs/src/engine/rules/techniques.rs index e2c0ca5..7405fe9 100644 --- a/accessibility-rs/src/engine/rules/techniques.rs +++ b/accessibility-rs/src/engine/rules/techniques.rs @@ -1,6 +1,6 @@ use strum_macros::IntoStaticStr; -#[derive(PartialOrd, Ord, std::cmp::Eq, PartialEq, Hash, Debug, IntoStaticStr)] +#[derive(PartialOrd, Ord, std::cmp::Eq, PartialEq, Hash, Debug, IntoStaticStr, Clone)] /// techniques for WCAG pub enum Techniques { /// diff --git a/accessibility-rs/src/engine/rules/wcag_rule_map.rs b/accessibility-rs/src/engine/rules/wcag_rule_map.rs index b72df7c..0adc4b0 100644 --- a/accessibility-rs/src/engine/rules/wcag_rule_map.rs +++ b/accessibility-rs/src/engine/rules/wcag_rule_map.rs @@ -16,11 +16,11 @@ lazy_static! { pub static ref RULES_A: BTreeMap<&'static str, Vec> = vec![ ("html", Vec::from([ - Rule::new(Techniques::H57, IssueType::Error, Principle::Understandable, Guideline::Readable, "1", |nodes, _lang| { + Rule::new(Techniques::H57.into(), IssueType::Error, Principle::Understandable, Guideline::Readable, "1", |nodes, _lang| { let n = nodes[0].0; Validation::new_issue(!n.attr("lang").unwrap_or_default().is_empty() || !n.attr("xml:lang").unwrap_or_default().is_empty(), "2") }), - Rule::new(Techniques::H57, IssueType::Error, Principle::Understandable, Guideline::Readable, "1", |nodes, _lang| { + Rule::new(Techniques::H57.into(), IssueType::Error, Principle::Understandable, Guideline::Readable, "1", |nodes, _lang| { let lang = nodes[0].0.attr("lang").unwrap_or_default(); let alphabetic = lang.chars().all(|x| x.is_alphabetic()); // @@ -32,7 +32,7 @@ lazy_static! { alphabetic && lang.len() < 12 }, "3.Lang") }), - Rule::new(Techniques::H57, IssueType::Error, Principle::Understandable, Guideline::Readable, "1", |nodes, _lang| { + Rule::new(Techniques::H57.into(), IssueType::Error, Principle::Understandable, Guideline::Readable, "1", |nodes, _lang| { let lang = nodes[0].0.attr("xml:lang").unwrap_or_default(); let alphabetic = lang.chars().all(|x| x == '_' || x.is_alphabetic()); // @@ -44,7 +44,7 @@ lazy_static! { alphabetic && lang.len() < 12 }, "3.XmlLang") }), - Rule::new(Techniques::F77, IssueType::Error, Principle::Robust, Guideline::Compatible, "1", |nodes, lang| { + Rule::new(Techniques::F77.into(), IssueType::Error, Principle::Robust, Guideline::Compatible, "1", |nodes, lang| { let mut id_map: HashMap<&str, u8> = HashMap::new(); let mut valid = true; @@ -84,7 +84,7 @@ lazy_static! { }), ])), ("meta", Vec::from([ - Rule::new(Techniques::F40, IssueType::Error, Principle::Operable, Guideline::EnoughTime, "1", |nodes, _lang| { + Rule::new(Techniques::F40.into(), IssueType::Error, Principle::Operable, Guideline::EnoughTime, "1", |nodes, _lang| { let mut valid = true; for node in nodes { @@ -100,7 +100,7 @@ lazy_static! { Validation::new_issue(valid, "2") }), - Rule::new(Techniques::F41, IssueType::Error, Principle::Understandable, Guideline::EnoughTime, "1", |nodes, _lang| { + Rule::new(Techniques::F41.into(), IssueType::Error, Principle::Understandable, Guideline::EnoughTime, "1", |nodes, _lang| { let mut valid = true; for node in nodes { @@ -118,30 +118,30 @@ lazy_static! { }), ])), ("title", Vec::from([ - Rule::new(Techniques::H25, IssueType::Error, Principle::Operable, Guideline::Navigable, "1", |nodes, _lang| { + Rule::new(Techniques::H25.into(), IssueType::Error, Principle::Operable, Guideline::Navigable, "1", |nodes, _lang| { Validation::new_issue(!nodes.is_empty(), "1.NoTitleEl") }), - Rule::new(Techniques::H25, IssueType::Error, Principle::Operable, Guideline::Navigable, "1", |nodes, _lang| { + Rule::new(Techniques::H25.into(), IssueType::Error, Principle::Operable, Guideline::Navigable, "1", |nodes, _lang| { Validation::new_issue(nodes.is_empty() || nodes[0].0.html().is_empty(), "1.EmptyTitle") }), ])), ("blink", Vec::from([ - Rule::new(Techniques::F47, IssueType::Error, Principle::Operable, Guideline::EnoughTime, "2", |nodes, _lang| { + Rule::new(Techniques::F47.into(), IssueType::Error, Principle::Operable, Guideline::EnoughTime, "2", |nodes, _lang| { Validation::new_issue(nodes.is_empty(), "") }), ])), ("iframe", Vec::from([ - Rule::new(Techniques::H64, IssueType::Error, Principle::Operable, Guideline::Navigable, "1", |nodes, _lang| { + Rule::new(Techniques::H64.into(), IssueType::Error, Principle::Operable, Guideline::Navigable, "1", |nodes, _lang| { validate_missing_attr(nodes, "title", "1") }), ])), ("frame", Vec::from([ - Rule::new(Techniques::H64, IssueType::Error, Principle::Operable, Guideline::Navigable, "1", |nodes, _lang| { + Rule::new(Techniques::H64.into(), IssueType::Error, Principle::Operable, Guideline::Navigable, "1", |nodes, _lang| { validate_missing_attr(nodes, "title", "1") }), ])), ("form", Vec::from([ - Rule::new(Techniques::H32, IssueType::Error, Principle::Operable, Guideline::Predictable, "2", |nodes, _lang| { + Rule::new(Techniques::H32.into(), IssueType::Error, Principle::Operable, Guideline::Predictable, "2", |nodes, _lang| { let mut valid = false; let mut elements = Vec::new(); let selector = unsafe { Selector::parse("button[type=submit]").unwrap_unchecked() }; @@ -161,7 +161,7 @@ lazy_static! { Validation::new(valid, "2", elements, Default::default()) }), - Rule::new(Techniques::H36, IssueType::Error, Principle::Perceivable, Guideline::TextAlternatives, "1", |nodes, _lang| { + Rule::new(Techniques::H36.into(), IssueType::Error, Principle::Perceivable, Guideline::TextAlternatives, "1", |nodes, _lang| { let mut valid = false; let mut elements = Vec::new(); let selector = unsafe { Selector::parse("input[type=image][name=submit]").unwrap_unchecked() }; @@ -183,7 +183,7 @@ lazy_static! { }), ])), ("a", Vec::from([ - Rule::new(Techniques::H30, IssueType::Error, Principle::Perceivable, Guideline::TextAlternatives, "1", |nodes, _lang| { + Rule::new(Techniques::H30.into(), IssueType::Error, Principle::Perceivable, Guideline::TextAlternatives, "1", |nodes, _lang| { let mut valid = true; let selector = unsafe { Selector::parse("img").unwrap_unchecked() }; let mut elements = Vec::new(); @@ -203,7 +203,7 @@ lazy_static! { Validation::new(valid, "2", elements, Default::default()) }), - Rule::new(Techniques::H91, IssueType::Error, Principle::Robust, Guideline::Compatible, "2", |nodes, _lang| { + Rule::new(Techniques::H91.into(), IssueType::Error, Principle::Robust, Guideline::Compatible, "2", |nodes, _lang| { let mut valid = true; let mut elements = Vec::new(); @@ -222,7 +222,7 @@ lazy_static! { } Validation::new(valid, "A.NoContent", elements, Default::default()) }), - Rule::new(Techniques::H91, IssueType::Error, Principle::Robust, Guideline::Compatible, "2", |nodes, _lang| { + Rule::new(Techniques::H91.into(), IssueType::Error, Principle::Robust, Guideline::Compatible, "2", |nodes, _lang| { let mut valid = true; let mut elements = Vec::new(); for ele in nodes { @@ -237,7 +237,7 @@ lazy_static! { }), ])), ("img", Vec::from([ - Rule::new(Techniques::H37, IssueType::Error, Principle::Perceivable, Guideline::TextAlternatives, "1", |nodes, _lang| { + Rule::new(Techniques::H37.into(), IssueType::Error, Principle::Perceivable, Guideline::TextAlternatives, "1", |nodes, _lang| { let mut valid = true; let mut elements = Vec::new(); @@ -254,32 +254,32 @@ lazy_static! { }), ])), ("h1", Vec::from([ - Rule::new(Techniques::H42, IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { + Rule::new(Techniques::H42.into(), IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { validate_empty_nodes(nodes, "2") }), ])), ("h2", Vec::from([ - Rule::new(Techniques::H42, IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { + Rule::new(Techniques::H42.into(), IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { validate_empty_nodes(nodes, "2") }), ])), ("h3", Vec::from([ - Rule::new(Techniques::H42, IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { + Rule::new(Techniques::H42.into(), IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { validate_empty_nodes(nodes, "2") }), ])), ("h4", Vec::from([ - Rule::new(Techniques::H42, IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { + Rule::new(Techniques::H42.into(), IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { validate_empty_nodes(nodes, "2") }), ])), ("h5", Vec::from([ - Rule::new(Techniques::H42, IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { + Rule::new(Techniques::H42.into(), IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { validate_empty_nodes(nodes, "2") }), ])), ("h6", Vec::from([ - Rule::new(Techniques::H42, IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { + Rule::new(Techniques::H42.into(), IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { validate_empty_nodes(nodes, "2") }), ])), diff --git a/accessibility-rs/src/i18n/locales.rs b/accessibility-rs/src/i18n/locales.rs index 8f2e3bd..5e4fd8b 100644 --- a/accessibility-rs/src/i18n/locales.rs +++ b/accessibility-rs/src/i18n/locales.rs @@ -84,7 +84,7 @@ pub fn get_message_i18n_str_raw( pub fn get_message_i18n_str(rule: &Rule, section: &str) -> String { get_message_i18n_str_raw( &rule.guideline, - rule.rule_id.as_str(), + &rule.rule_id.into_str(), rule.success_criteria, section, ) diff --git a/accessibility-rs/tests/unit/html.rs b/accessibility-rs/tests/unit/html.rs index 4722457..11f233f 100644 --- a/accessibility-rs/tests/unit/html.rs +++ b/accessibility-rs/tests/unit/html.rs @@ -27,7 +27,6 @@ fn _audit_duplicate_element_id() { assert_eq!(valid, false) } - #[test] /// duplicate html elements with locale "ja" fn _audit_duplicate_element_id_ja() { @@ -41,9 +40,9 @@ fn _audit_duplicate_element_id_ja() {
"###, - "", - false, - "ja" + "", + false, + "ja", )); let mut valid = true;