From f7498d39a8306bad7e53408ad892c0382aff118d Mon Sep 17 00:00:00 2001 From: j-mendez Date: Fri, 13 Oct 2023 20:29:38 -0400 Subject: [PATCH] chore(selector): add fast selector pathing --- .../src/engine/rules/wcag_rule_map.rs | 79 ++++++++++++------- accessibility-rs/tests/unit/meta.rs | 1 + 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/accessibility-rs/src/engine/rules/wcag_rule_map.rs b/accessibility-rs/src/engine/rules/wcag_rule_map.rs index 9dc4c74..9436206 100644 --- a/accessibility-rs/src/engine/rules/wcag_rule_map.rs +++ b/accessibility-rs/src/engine/rules/wcag_rule_map.rs @@ -39,48 +39,69 @@ fn is_empty(nodes: &ElementNodes) -> bool { } /// get the unique selector for an element -fn get_unique_selector(ele: &ElementRef<'_>) -> String { +fn get_unique_selector(ele: &ElementRef<'_>, first_sweep: bool) -> String { if ele.has_attribute("id") { "#".to_string() + ele.attr("id").unwrap_or_default() } else { let mut selector = String::new(); let node_name = ele.value().name().to_string(); - if node_name == "BODY" { - selector = node_name; - } - - if selector.is_empty() && ele.has_attribute("class") { - let node_selector = ele.value().name().to_string() + &ele.local_name().to_string(); - let only_selector = match ele.tree().root().first_child() { - Some(child) => { - match ElementRef::wrap(child) { - Some(element) => { - match Selector::parse(node_selector.as_str()) { - Ok(s) => { - let e = element.select(&s); - e.count() == 1 + if first_sweep && (node_name == "body" || node_name == "html") { + node_name + } else { + if selector.is_empty() && ele.has_attribute("class") { + let node_selector = ele.value().name().to_string() + &ele.local_name().to_string(); + let only_selector = match ele.tree().root().first_child() { + Some(child) => { + match ElementRef::wrap(child) { + Some(element) => { + match Selector::parse(node_selector.as_str()) { + Ok(s) => { + let e = element.select(&s); + e.count() == 1 + } + _ => false } - _ => false } + _ => false } - _ => false } + _ => false + }; + if only_selector { + selector = node_selector; + } + } + + if first_sweep && !selector.is_empty() { + selector + } else { + match ele.parent_element() { + Some(p) => { + if selector.is_empty() { + get_unique_selector(&p, false) + } else { + selector + ">:nth-child(" + &get_sibling_position(ele).to_string() + ")" + } + }, + _ => ele.value().name().to_string() + ">:nth-child(" + &get_sibling_position(ele).to_string() + ")" } - _ => false - }; - if only_selector { - selector = node_selector; - } + } } - - // TODO: if id is not found recursively get all elements until complete if class does not match - if selector.is_empty() { - selector = ele.value().name().to_string(); + } +} + +/// get sibling position of element +fn get_sibling_position(ele: &ElementRef<'_>) -> u8 { + let mut i = 1; + + while let Some(e) = ele.prev_sibling() { + if e.value().is_element() { + i += 1; } - - selector } + + i } /// validate missing title @@ -91,7 +112,7 @@ fn validate_missing_title(nodes: &ElementNodes, id: &'static str) -> Validation nodes.iter().for_each(|e| { if e.0.attr("title").unwrap_or_default().is_empty() { valid = false; - elements.push(get_unique_selector(&e.0)) + elements.push(get_unique_selector(&e.0, true)) } }); diff --git a/accessibility-rs/tests/unit/meta.rs b/accessibility-rs/tests/unit/meta.rs index 1cca6ce..0973186 100644 --- a/accessibility-rs/tests/unit/meta.rs +++ b/accessibility-rs/tests/unit/meta.rs @@ -155,6 +155,7 @@ fn _iframe_missing_title() { let mut valid = true; for x in &audit { + println!("{:?}", x); if x.code == "WCAGAAA.Principle2.Guideline2_4.H64" { valid = false; break;