Skip to content

Commit

Permalink
chore(innate): add multiple rule categories
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mendez committed Oct 3, 2023
1 parent 67ce666 commit d05ff6d
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 17 deletions.
12 changes: 11 additions & 1 deletion kayle_innate/src/engine/issue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,23 @@ pub struct Issue {

impl Issue {
/// create a new issue
pub fn new(message: &'static str, context: &str, code: &str, issue_type: &'static str) -> Issue {
pub fn new(
message: &'static str,
context: &str,
code: &str,
issue_type: &'static str,
) -> Issue {
Issue {
message,
context: context.into(),
runner: "kayle",
code: code.into(),
issue_type,
type_code: match issue_type {
"error" => 0,
"warning" => 1,
_ => 2,
},
..Default::default()
}
}
Expand Down
22 changes: 20 additions & 2 deletions kayle_innate/src/engine/rules/ids.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
use std::vec;

#[derive(PartialOrd, Ord, std::cmp::Eq, PartialEq, Hash, Debug)]
pub enum RuleID {
/// no empty titles
F25,
H25,
}

impl RuleID {
/// get rule id to string
pub fn as_str(&self) -> &'static str {
match self {
RuleID::F25 => "F25",
RuleID::H25 => "H25",
}
}
/// get pairs for a rule
pub fn pairs(&self) -> Vec<&'static str> {
match self {
RuleID::H25 => vec!["H25.1.NoTitleEl", "H25.1.EmptyTitle"],
}
}
// /// get the value of the rule id with the pair
// pub fn index(&self, i: usize) -> String {
// let pair = self.pairs();

// if pair.len() <= i {
// self.as_str().to_owned() + pair[i]
// } else {
// self.as_str().into()
// }
// }
}
78 changes: 68 additions & 10 deletions kayle_innate/src/engine/rules/wcag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,37 @@ impl Criteria {
}
}

/// wcag principle to follow
enum Principle {
Perceivable,
Operable,
Understandable,
Robust,
}

impl Principle {
pub fn as_str(&self) -> &'static str {
match self {
Principle::Perceivable => "Principle1",
Principle::Operable => "Principle2",
Principle::Understandable => "Principle3",
Principle::Robust => "Principle4",
}
}
}

/// wcag principle to follow
enum Guideline {
Navigable,
}

impl Guideline {
pub fn as_str(&self) -> &'static str {
match self {
Guideline::Navigable => "Guideline2_4",
}
}
}

/// the rule validation method that should be performed.
struct Rule {
Expand All @@ -33,20 +64,35 @@ struct Rule {
/// the type of rule
pub criteria: Criteria,
/// validate a test
pub validate:
fn(&String, &Vec<scraper::node::Element>, css: &cssparser::Parser<'_, '_>) -> bool,
pub validate: fn(
&String,
&Vec<scraper::node::Element>,
css: &cssparser::Parser<'_, '_>,
) -> (bool, &'static str),
/// the principle type
pub principle: Principle,
/// the guideline to follow
pub guideline: Guideline,
}

impl Rule {
/// a new rule type
pub fn new(
rule_id: RuleID,
criteria: Criteria,
validate: fn(&String, &Vec<scraper::node::Element>, &cssparser::Parser<'_, '_>) -> bool,
principle: Principle,
guideline: Guideline,
validate: fn(
&String,
&Vec<scraper::node::Element>,
&cssparser::Parser<'_, '_>,
) -> (bool, &'static str),
) -> Rule {
Rule {
rule_id,
criteria,
guideline,
principle,
validate,
}
}
Expand All @@ -55,9 +101,14 @@ impl Rule {
lazy_static! {
/// a list of rules that should be applied for WCAG1
static ref RULES_A: BTreeMap<&'static str, Vec<Rule>> =
vec![("title", Vec::from([Rule::new(RuleID::F25, Criteria::Error, |_rule, elements, _css_parser| {
!elements.is_empty()
})]))]
vec![("title", Vec::from([
Rule::new(RuleID::H25, Criteria::Error, Principle::Operable, Guideline::Navigable, |_rule, elements, _css_parser| {
(!elements.is_empty(), "1.NoTitleEl")
}),
// Rule::new(RuleID::H25, Criteria::Error, Principle::Operable, Guideline::Navigable, |_rule, elements, _css_parser| {
// (!elements.is_empty(), "1.EmptyTitle")
// }),
]))]
.into_iter()
.collect();
}
Expand Down Expand Up @@ -89,17 +140,24 @@ impl WCAG3AA {
match rules {
Some(rules) => {
for rule in rules {
let valid = (rule.validate)(&node.0, &node.1, &_css);
let (valid, section) = (rule.validate)(&node.0, &node.1, &_css);

if !valid {
// get locales prior or from document
let message = get_message(&rule.rule_id, &Langs::En.as_str());
let message =
get_message(&rule.rule_id, &section, &Langs::En.as_str());
// todo: add rest of properties
let issue = Issue::new(
message,
&node.0,
&["WCAGAA", rule.rule_id.as_str()].join("_"),
rule.criteria.as_str()
&[
"WCAGAAA",
rule.principle.as_str(),
rule.guideline.as_str(),
rule.rule_id.as_str(),
]
.join("."),
rule.criteria.as_str(),
);
issues.push(issue);
}
Expand Down
10 changes: 6 additions & 4 deletions kayle_innate/src/i18n/locales.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ impl Messages {
}

/// parse
pub fn get_message(rule_id: &RuleID, lang: &str) -> &'static str {
let message = LOCALES.get(&rule_id);
pub fn get_message(rule_id: &RuleID, section: &str, lang: &str) -> &'static str {
let k = &[rule_id.as_str(), section].join(".");
let message = LOCALES.get(&k.as_str());

match message {
Some(m) => match lang {
Expand All @@ -96,10 +97,11 @@ pub fn get_message(rule_id: &RuleID, lang: &str) -> &'static str {

lazy_static! {
/// message for an issue
pub static ref LOCALES: BTreeMap<RuleID, Messages> = {
pub static ref LOCALES: BTreeMap<&'static str, Messages> = {
BTreeMap::from([
// empty titles
(RuleID::F25, Messages::new(&"Failure of Success Criterion 2.4.2 due to the title of a Web page not identifying the contents", "", ""))
(RuleID::H25.pairs()[0], Messages::new(&"A title should be provided for the document, using a non-empty title element in the head section.", "", "")),
(RuleID::H25.pairs()[1], Messages::new(&"The title element in the head section should be non-empty.", "", ""))
])
};
}

0 comments on commit d05ff6d

Please sign in to comment.