fix bug in 'contains' condition and add doc

master
kirbylife 2021-03-14 17:57:02 -06:00
parent cfaf3c286c
commit 46fdefc893
3 changed files with 29 additions and 2 deletions

View File

@ -1,11 +1,12 @@
[package]
name = "cssifier"
version = "0.1.1"
version = "0.1.2"
authors = ["kirbylife <kirbylife@protonmail.com>"]
license = " GPL-3.0-or-later"
readme = "README.md"
homepage = "https://gitlab.com/kirbylife/cssifier"
repository = "https://gitlab.com/kirbylife/cssifier"
documentation = "https://docs.rs/cssifier"
description = "Simple crate to convert XPath selectors to CSS selectors"
keywords = ["cssifier", "xpath", "css", "selector"]
categories = ["parsing"]

View File

@ -21,6 +21,8 @@ cssifier("//a/b[contains(text(), 'hello')]")
```
### Known issues
- [x] bug in 'contains' condition
- [ ] invalid XPath return empty String
- [ ] Compatible with WASM
Contributors are welcome :).

View File

@ -1,5 +1,29 @@
use regex::Regex;
/// Convert the Xpath selectors to CSS selector
///
/// ## Things it supports
/// Any tag (including *), contains(), text(), indexed, any attribute (@id, @class, @anything).
///
/// ## Things it does not support
/// Move up to a parent tag (//a/../p) and maybe something else I'm not aware of...
///
/// ## Examples
///
/// Basic usage:
/// ```
/// cssifier("//a/p")
/// Some("a p")
///
/// cssifier("//a/p[@id='hello']")
/// Some("a b#hello")
///
/// cssfier("//a/p/[contains(text(), 'hello')]")
/// Some(a b:contains(hello))
///
/// cssifier("*random selector//*") // Invalid selectors throw a empty string (WIP)
/// Some("")
/// ```
pub fn cssifier(xpath: &'static str) -> Option<String> {
// Ultra magic regex to parse XPath selectors
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();
@ -60,7 +84,7 @@ pub fn cssifier(xpath: &'static str) -> Option<String> {
let cvalue = node.name("cvalue")?.as_str();
if cattr.starts_with("@") {
format!("{}*={}", cattr.replace("@", ""), cvalue)
format!("[{}*={}]", cattr.replace("@", ""), cvalue)
} else if cattr == "text()" {
format!(":contains({})", cvalue)
} else {