accessibility_rs/engine/audit/
tree.rs1use crate::engine::styles::layout::leaf;
2use accessibility_scraper::ElementRef;
3use accessibility_scraper::Html;
4use accessibility_tree::style::StyleSet;
5use std::collections::BTreeMap;
6use std::collections::HashSet;
7use taffy::prelude::*;
8
9lazy_static! {
10 static ref NODE_IGNORE: HashSet<&'static str> =
11 HashSet::from(["meta", "style", "link", "script", "head", "html", "body"]);
12}
13
14pub fn parse_accessibility_tree<'a, 'b, 'c>(
16 document: &'a Html,
17 _author: &StyleSet,
18) -> (
19 BTreeMap<&'a str, Vec<(ElementRef<'a>, Option<NodeId>)>>,
20 Option<TaffyTree>,
21) {
22 let mut accessibility_tree: BTreeMap<&str, Vec<(ElementRef<'_>, Option<NodeId>)>> =
23 BTreeMap::from(if document.root_element().value().name() == "html" {
24 [("title".into(), Default::default())]
25 } else {
26 [(Default::default(), Default::default())]
27 });
28 for node in document.tree.nodes() {
29 match ElementRef::wrap(node) {
30 Some(element) => {
31 let name = element.value().name();
32 accessibility_tree
33 .entry(name)
34 .and_modify(|n| n.push((element, None)))
35 .or_insert(Vec::from([(element, None)]));
36 }
37 _ => (),
38 };
39 }
40
41 (accessibility_tree, None)
42}
43
44pub fn parse_accessibility_tree_bounded<'a, 'b, 'c>(
46 document: &'a Html,
47 author: &StyleSet,
48) -> (
49 BTreeMap<&'a str, Vec<(ElementRef<'a>, Option<NodeId>)>>,
50 Option<TaffyTree>,
51) {
52 let mut taffy = TaffyTree::new();
53 let mut accessibility_tree: BTreeMap<&str, Vec<(ElementRef<'_>, Option<NodeId>)>> =
54 BTreeMap::from(if document.root_element().value().name() == "html" {
55 [("title".into(), Default::default())]
56 } else {
57 [(Default::default(), Default::default())]
58 });
59 let mut layout_leafs: Vec<NodeId> = vec![];
60
61 for node in document.tree.nodes() {
63 match ElementRef::wrap(node) {
64 Some(element) => {
65 let name = element.value().name();
66 let layout_leaf = {
67 if NODE_IGNORE.contains(name) {
68 taffy.new_leaf(Default::default()).unwrap()
69 } else {
70 leaf(&element, &author, document, &mut taffy)
71 }
72 };
73 accessibility_tree
74 .entry(name)
75 .and_modify(|n| n.push((element, Some(layout_leaf))))
76 .or_insert(Vec::from([(element, Some(layout_leaf))]));
77 }
78 _ => (),
79 };
80 }
81
82 match accessibility_tree.get("body") {
83 Some(node) => {
84 for child in node[0].0.children() {
85 match ElementRef::wrap(child) {
86 Some(element) => {
87 if !NODE_IGNORE.contains(element.value().name()) {
88 let leaf = leaf(&element, &author, document, &mut taffy);
89
90 layout_leafs.push(leaf)
91 }
92 }
93 _ => (),
94 }
95 }
96 }
97 _ => (),
98 };
99
100 let root_node = taffy
101 .new_with_children(
102 Style {
103 flex_direction: FlexDirection::Column,
104 size: Size {
106 width: length(800.0),
107 height: length(600.0),
108 },
109 ..Default::default()
110 },
111 &layout_leafs,
112 )
113 .unwrap();
114
115 taffy.compute_layout(root_node, Size::MAX_CONTENT).unwrap();
116
117 (accessibility_tree, Some(taffy))
118}