1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
use html5ever::rcdom::{Node, NodeData}; use crate::pattern::Pattern; fn is_multiple(tag_name: &str, attr_name: &str) -> bool { match (tag_name.to_lowercase().as_str(), attr_name.to_lowercase().as_str()) { (_, "class") | (_, "accesskey") | (_, "dropzone") | ("a", "rel") | ("a", "rev") | ("link", "rel") | ("link", "rev") | ("tr", "headers") | ("th", "headers") | ("form", "accept-charset") | ("object", "archive") | ("area", "rel") | ("icon", "sizes") | ("iframe", "sandbox") | ("output", "for") => true, _ => false } } fn match_list_attr<V: Pattern>(needle: &V, haystack: &str) -> bool { for part in haystack.split(char::is_whitespace) { let part = part.trim().to_lowercase(); if needle.matches(&part) { return true; } } false } pub(crate) fn list_aware_match<K: Pattern, V: Pattern>(node: &Node, attr_name: &K, attr_value: &V) -> bool { match node.data { NodeData::Element { ref name, ref attrs, ..} => { let attrs = attrs.borrow(); for attr in attrs.iter() { let k = attr.name.local.as_ref(); let v = attr.value.as_ref(); if attr_name.matches(k) { if is_multiple(name.local.as_ref(), &k) { if match_list_attr(attr_value, &v) { return true; } } else { if attr_value.matches(v) { return true; } } } } }, _ => (), } false }