Skip to content

Commit

Permalink
chore(innate): cleanup wcag
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mendez committed Oct 3, 2023
1 parent a28c2a3 commit 327069f
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 154 deletions.
9 changes: 8 additions & 1 deletion kayle_innate/src/engine/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
// accessibility rules todo:
/// rules or techniques
pub mod ids;
/// the rule to follow
pub mod rule;
/// wcag audit
pub mod wcag;
/// the base of the wcag set
pub mod wcag_base;
/// rules to map to
pub mod wcag_rule_map;
44 changes: 44 additions & 0 deletions kayle_innate/src/engine/rules/rule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::engine::rules::ids::Techniques;
use crate::engine::rules::wcag_base::{Criteria, Guideline, Principle};
use crate::ElementRef;

/// 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(
&String,
&Vec<ElementRef<'_>>,
css: &cssparser::Parser<'_, '_>,
) -> (bool, &'static str, Vec<&'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: Techniques,
criteria: Criteria,
principle: Principle,
guideline: Guideline,
validate: fn(
&String,
&Vec<ElementRef<'_>>,
&cssparser::Parser<'_, '_>,
) -> (bool, &'static str, Vec<&'static str>),
) -> Rule {
Rule {
rule_id,
criteria,
guideline,
principle,
validate,
}
}
}
150 changes: 4 additions & 146 deletions kayle_innate/src/engine/rules/wcag.rs
Original file line number Diff line number Diff line change
@@ -1,163 +1,21 @@
use crate::engine::rules::ids::Techniques;
use super::wcag_rule_map::RULES_A;
use crate::i18n::locales::{get_message, Langs};
use crate::{console_log, engine::issue::Issue};
use scraper::Selector;
use scraper::{ElementRef, Html};
use std::collections::BTreeMap;

/// the success criteria to use
#[derive(Debug)]
enum Criteria {
/// a hard error that should be fixed
Error,
/// a warning that may be an issue
Warning,
/// a generic notice to help accessibility needs
Notice,
}

impl Criteria {
/// get rule id to string
pub fn as_str(&self) -> &'static str {
match self {
Criteria::Error => "error",
Criteria::Warning => "warning",
Criteria::Notice => "notice",
}
}
}

/// 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 {
/// Provide ways to help users navigate, find content, and determine where they are.
Navigable,
/// Make Web pages appear and operate in predictable ways.
Predictable,
}

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

/// the rule validation method that should be performed.
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(
&String,
&Vec<ElementRef<'_>>,
css: &cssparser::Parser<'_, '_>,
) -> (bool, &'static str, Vec<&'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: Techniques,
criteria: Criteria,
principle: Principle,
guideline: Guideline,
validate: fn(
&String,
&Vec<ElementRef<'_>>,
&cssparser::Parser<'_, '_>,
) -> (bool, &'static str, Vec<&'static str>),
) -> Rule {
Rule {
rule_id,
criteria,
guideline,
principle,
validate,
}
}
}

// todo: validate each element and add a shape that can prevent repitiion
lazy_static! {
/// a list of rules that should be applied for WCAG1
static ref RULES_A: BTreeMap<&'static str, Vec<Rule>> =
vec![
// empty titles
("title", Vec::from([
Rule::new(Techniques::H25, Criteria::Error, Principle::Operable, Guideline::Navigable, |_rule, nodes, _css_parser| {
(!nodes.is_empty(), "1.NoTitleEl", Default::default())
}),
Rule::new(Techniques::H25, Criteria::Error, Principle::Understandable, Guideline::Predictable, |_rule, nodes, _css_parser| {
(nodes.is_empty() || nodes[0].html().is_empty(), "2", Default::default())
}),
])),
// missing label
("form", Vec::from([
Rule::new(Techniques::H32, Criteria::Error, Principle::Operable, Guideline::Predictable, |_rule, nodes, _css_parser| {
// check the first element for now
let mut valid = false;

for ele in nodes {
let selector = unsafe { Selector::parse("button[type=submit]").unwrap_unchecked() };
valid = match ele.select(&selector).next() {
Some(_) => true,
_ => false
};
}

(valid, "2", Default::default())
}),
]))
]
.into_iter()
.collect();
}
use scraper::ElementRef;

/// baseline for all rules
#[derive(Default)]
pub struct WCAG3AA {}
pub struct WCAG3AA;

/// wcag rules to test for
impl WCAG3AA {
/// init the rules
pub fn audit(
// allow tree mutation until threads or setup the tree with initial elements.
mut tree: std::collections::BTreeMap<String, Vec<ElementRef<'_>>>,
tree: std::collections::BTreeMap<String, Vec<ElementRef<'_>>>,
_css: cssparser::Parser<'_, '_>,
// todo: get configs like viewport
) -> Vec<Issue> {
// pre populate must have keys
if !tree.contains_key("title") {
tree.insert("title".into(), Default::default());
}

let mut issues: Vec<Issue> = Vec::new();

// go through nodes and map to validation rules
Expand Down
61 changes: 61 additions & 0 deletions kayle_innate/src/engine/rules/wcag_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/// the success criteria to use
#[derive(Debug)]
pub enum Criteria {
/// a hard error that should be fixed
Error,
/// a warning that may be an issue
Warning,
/// a generic notice to help accessibility needs
Notice,
}

impl Criteria {
/// get rule id to string
pub fn as_str(&self) -> &'static str {
match self {
Criteria::Error => "error",
Criteria::Warning => "warning",
Criteria::Notice => "notice",
}
}
}

/// wcag principle to follow
pub enum Principle {
/// Provide text alternatives for any non-text content so that it can be changed into other forms people need, such as large print, braille, speech, symbols or simpler language.
Perceivable,
/// Make all functionality available from a keyboard.
Operable,
/// Make text content readable and understandable.
Understandable,
/// Maximize compatibility with current and future user agents, including assistive technologies.
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
pub enum Guideline {
/// Provide ways to help users navigate, find content, and determine where they are.
Navigable,
/// Make Web pages appear and operate in predictable ways.
Predictable,
}

impl Guideline {
pub fn as_str(&self) -> &'static str {
match self {
Guideline::Navigable => "Guideline2_4",
Guideline::Predictable => "Guideline3_2",
}
}
}
42 changes: 42 additions & 0 deletions kayle_innate/src/engine/rules/wcag_rule_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use crate::engine::rules::ids::Techniques;
use crate::engine::rules::rule::Rule;
use crate::engine::rules::wcag_base::{Criteria, Guideline, Principle};
use scraper::Selector;
use std::collections::BTreeMap;

// todo: validate each element and add a shape that can prevent repitiion
lazy_static! {
/// a list of rules that should be applied for WCAG1
pub static ref RULES_A: BTreeMap<&'static str, Vec<Rule>> =
vec![
// empty titles
("title", Vec::from([
Rule::new(Techniques::H25, Criteria::Error, Principle::Operable, Guideline::Navigable, |_rule, nodes, _css_parser| {
(!nodes.is_empty(), "1.NoTitleEl", Default::default())
}),
Rule::new(Techniques::H25, Criteria::Error, Principle::Understandable, Guideline::Predictable, |_rule, nodes, _css_parser| {
(nodes.is_empty() || nodes[0].html().is_empty(), "2", Default::default())
}),
])),
// missing label
("form", Vec::from([
Rule::new(Techniques::H32, Criteria::Error, Principle::Operable, Guideline::Predictable, |_rule, nodes, _css_parser| {
// check the first element for now
let mut valid = false;

for ele in nodes {
// todo: static selectors
let selector = unsafe { Selector::parse("button[type=submit]").unwrap_unchecked() };
valid = match ele.select(&selector).next() {
Some(_) => true,
_ => false
};
}

(valid, "2", Default::default())
}),
]))
]
.into_iter()
.collect();
}
12 changes: 5 additions & 7 deletions kayle_innate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,11 @@ pub fn parse_accessibility_tree(
let t = now();
// parse doc will start from html downwards
// accessibility tree for ordered element mappings
let mut accessibility_tree: BTreeMap<String, Vec<ElementRef<'_>>> = BTreeMap::new();
let mut accessibility_tree: BTreeMap<String, Vec<ElementRef<'_>>> =
BTreeMap::from([("title".into(), Default::default())]);

for node in html.tree.nodes() {
let h = scraper::element_ref::ElementRef::wrap(node);

match h {
match scraper::element_ref::ElementRef::wrap(node) {
Some(element) => {
let element_name = element.value().name();

Expand All @@ -234,13 +233,12 @@ pub fn parse_accessibility_tree(
/// audit a web page passing the html and css rules.
pub fn _audit_not_ready(html: &str, _css_rules: &str) -> Result<JsValue, JsValue> {
set_panic_hook();
// parse document and get lifetimes for nodes
let h = Box::new(scraper::Html::parse_document(html));
let html = Box::new(scraper::Html::parse_document(html));
// TODO: if the css rules are empty extract the css from the HTML
let css_rules = &mut cssparser::ParserInput::new(&_css_rules);
// TODO: build the rules to css blocks that selectors can be used to find the element of the style.
let mut _css_parser = cssparser::Parser::new(css_rules);
let _tree = parse_accessibility_tree(&h);
let _tree = parse_accessibility_tree(&html);
let _audit = engine::rules::wcag::WCAG3AA::audit(_tree, _css_parser);

// todo: map to JsValues instead of serde
Expand Down

0 comments on commit 327069f

Please sign in to comment.