node_html_parser/css_select/
attributes.rs1use crate::css_select::types::{Adapter, AttributeAction, AttributeSelector};
2
3pub fn compose_attribute<'a, A: Adapter + 'a>(
4 next: Box<dyn Fn(&A::HTMLElement) -> bool + 'a>,
5 sel: &AttributeSelector,
6 adapter: &'a A,
7) -> Box<dyn Fn(&A::HTMLElement) -> bool + 'a> {
8 let name = sel.name.clone();
9 let action = sel.action.clone();
10 let value = sel.value.clone();
11 let ignore_case = sel.ignore_case;
12 Box::new(move |el| {
13 let attr = adapter.get_attribute(el, &name);
14 match action {
15 AttributeAction::Exists => {
16 if attr.is_some() {
17 return next(el);
18 } else {
19 return false;
20 }
21 }
22 AttributeAction::Equals => {
23 if let (Some(v), Some(val)) = (attr, value.as_ref()) {
24 let (a, b) = if ignore_case {
25 (v.to_ascii_lowercase(), val.to_ascii_lowercase())
26 } else {
27 (v.to_string(), val.to_string())
28 };
29 if a == b {
30 return next(el);
31 }
32 }
33 false
34 }
35 AttributeAction::Not => {
36 if let (Some(v), Some(val)) = (attr, value.as_ref()) {
37 let (a, b) = if ignore_case {
38 (v.to_ascii_lowercase(), val.to_ascii_lowercase())
39 } else {
40 (v.to_string(), val.to_string())
41 };
42 if a == b {
43 return false;
44 }
45 }
46 next(el)
47 }
48 AttributeAction::Start => {
49 if let (Some(v), Some(val)) = (attr, value.as_ref()) {
50 let (a, b) = if ignore_case {
51 (v.to_ascii_lowercase(), val.to_ascii_lowercase())
52 } else {
53 (v.to_string(), val.to_string())
54 };
55 if a.starts_with(&b) {
56 return next(el);
57 }
58 }
59 false
60 }
61 AttributeAction::End => {
62 if let (Some(v), Some(val)) = (attr, value.as_ref()) {
63 let (a, b) = if ignore_case {
64 (v.to_ascii_lowercase(), val.to_ascii_lowercase())
65 } else {
66 (v.to_string(), val.to_string())
67 };
68 if a.ends_with(&b) {
69 return next(el);
70 }
71 }
72 false
73 }
74 AttributeAction::Any => {
75 if let (Some(v), Some(val)) = (attr, value.as_ref()) {
76 let (a, b) = if ignore_case {
77 (v.to_ascii_lowercase(), val.to_ascii_lowercase())
78 } else {
79 (v.to_string(), val.to_string())
80 };
81 if a.contains(&b) {
82 return next(el);
83 }
84 }
85 false
86 }
87 AttributeAction::Hyphen => {
88 if let (Some(v), Some(val)) = (attr, value.as_ref()) {
89 let (a, b) = if ignore_case {
90 (v.to_ascii_lowercase(), val.to_ascii_lowercase())
91 } else {
92 (v.to_string(), val.to_string())
93 };
94 if a == b || a.starts_with(&format!("{}-", b)) {
95 return next(el);
96 }
97 }
98 false
99 }
100 AttributeAction::Element => {
101 if let (Some(v), Some(val)) = (attr, value.as_ref()) {
102 let (a, b) = if ignore_case {
103 (v.to_ascii_lowercase(), val.to_ascii_lowercase())
104 } else {
105 (v.to_string(), val.to_string())
106 };
107 if a.split_whitespace().any(|t| t == b) {
108 return next(el);
109 }
110 }
111 false
112 }
113 }
114 })
115}