From f6866dd7e6bee197ac9ace856da038c9cca0a64c Mon Sep 17 00:00:00 2001 From: kirbylife <gabriel13m@gmail.com> Date: Sun, 7 Mar 2021 18:50:42 -0600 Subject: [PATCH] Initial commit --- .gitignore | 2 ++ Cargo.toml | 10 +++++++++ src/lib.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6207cbf --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "cssifier" +version = "0.1.0" +authors = ["kirbylife <gabriel13m@gmail.com>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +regex = "1.0" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..43370e0 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,66 @@ +use regex::Regex; + +fn cssifier(xpath: &'static str) -> Option<String> { + let reg = Regex::new(r#"(?P<node>(^id\(["']?(?P<idvalue>\s*[\w/:][-/\w\s,:;.]*)["']?\)|(?P<nav>//?)(?P<tag>([a-zA-Z][a-zA-Z0-9]{0,10}|\*))(\[((?P<matched>(?P<mattr>@?[.a-zA-Z_:][-\w:.]*(\(\))?)=["'](?P<mvalue>\s*[\w/:][-/\w\s,:;.]*))["']|(?P<contained>contains\((?P<cattr>@?[.a-zA-Z_:][-\w:.]*(\(\))?),\s*["'](?P<cvalue>\s*[\w/:][-/\w\s,:;.]*)["']\)))\])?(\[(?P<nth>\d)\])?))"#).unwrap(); + let mut css = String::new(); + let mut position = 0; + + while position < xpath.len() { + let node = reg.captures(&xpath[position..])?; + let find = reg.find(&xpath[position..])?; + + let nav = match position { + 0 => "", + _ => { + if node.name("nav")?.as_str() != "//" { + " " + } else { + " > " + } + } + }; + + let tag = if node.name("tag")?.as_str() == "*" { + "" + } else { + match node.name("tag") { + Some(tag) => tag.as_str(), + _ => "", + } + }; + + let attr = if node.name("idvalue").is_some() { + format!("#{}", node.name("idvalue")?.as_str().replace(" ", "#")) + } else if node.name("matched").is_some() { + let mattr = node.name("mattr")?.as_str(); + let mvalue = node.name("mvalue")?.as_str(); + + if mattr == "@id" { + format!("#{}", mvalue.replace(" ", "#")) + } else if mattr == "@class" { + format!(".{}", mvalue.replace(" ", ".")) + } else if mattr == "text()" || mattr == "." { + format!(":contains(^{}$)", mvalue) + } else { + String::from("") + } + } else { + String::from("") + }; + css = format!("{}{}{}{}", css, nav, tag, attr); + position += find.end(); + } + + Some(css) +} + +#[cfg(test)] +mod tests { + use crate::cssifier; + + #[test] + fn it_works() { + assert_eq!(cssifier("//a/b").unwrap(), "a b"); + assert_eq!(cssifier("//a/b[@id='hello']").unwrap(), "a b#hello"); + } +}