use selectors::attr::AttrSelectorOperator;
use super::error::Error;
use super::xpath_expr::{XPathExpr, xpath_literal};
pub(crate) fn attrib_operator(
xpath: &mut XPathExpr,
attrib: &str,
operator: AttrSelectorOperator,
value: &str,
) -> Result<(), Error> {
match operator {
AttrSelectorOperator::Equal => attrib_equals(xpath, attrib, value),
AttrSelectorOperator::DashMatch => attrib_dashmatch(xpath, attrib, value),
AttrSelectorOperator::Includes => attrib_includes(xpath, attrib, value),
AttrSelectorOperator::Prefix => attrib_prefixmatch(xpath, attrib, value),
AttrSelectorOperator::Suffix => attrib_suffixmatch(xpath, attrib, value),
AttrSelectorOperator::Substring => attrib_substringmatch(xpath, attrib, value),
}
Ok(())
}
pub(crate) fn attrib_equals(xpath: &mut XPathExpr, name: &str, value: &str) {
xpath.add_condition(&format!("{name} = {}", xpath_literal(value)));
}
pub(crate) fn attrib_includes(xpath: &mut XPathExpr, name: &str, value: &str) {
let matchable = !value.is_empty()
&& !value
.chars()
.any(|c| matches!(c, ' ' | '\t' | '\r' | '\n' | '\u{c}'));
if matchable {
xpath.add_condition(&format!(
"contains(concat(' ', normalize-space({name}), ' '), {})",
xpath_literal(&format!(" {value} "))
));
} else {
xpath.add_condition("0");
}
}
pub(crate) fn attrib_dashmatch(xpath: &mut XPathExpr, name: &str, value: &str) {
xpath.add_or_condition(&format!(
"{name} = {} or starts-with({name}, {})",
xpath_literal(value),
xpath_literal(&format!("{value}-"))
));
}
pub(crate) fn attrib_prefixmatch(xpath: &mut XPathExpr, name: &str, value: &str) {
if !value.is_empty() {
xpath.add_condition(&format!("starts-with({name}, {})", xpath_literal(value)));
} else {
xpath.add_condition("0");
}
}
pub(crate) fn attrib_suffixmatch(xpath: &mut XPathExpr, name: &str, value: &str) {
if !value.is_empty() {
let offset = value.chars().count() - 1;
xpath.add_condition(&format!(
"substring({name}, string-length({name})-{offset}) = {}",
xpath_literal(value)
));
} else {
xpath.add_condition("0");
}
}
pub(crate) fn attrib_substringmatch(xpath: &mut XPathExpr, name: &str, value: &str) {
if !value.is_empty() {
xpath.add_condition(&format!("contains({name}, {})", xpath_literal(value)));
} else {
xpath.add_condition("0");
}
}