diff options
author | gennyble <gen@nyble.dev> | 2023-12-28 01:07:53 -0600 |
---|---|---|
committer | gennyble <gen@nyble.dev> | 2023-12-28 01:07:53 -0600 |
commit | a14a861d824230458333defd5cf43bafd2ca596d (patch) | |
tree | b5e2108e38268b02417e83c009545ac714032218 /src/lib.rs | |
parent | a567b9eb9930e3ec0d6da00f58d217843a732e2f (diff) | |
download | cutie-a14a861d824230458333defd5cf43bafd2ca596d.tar.gz cutie-a14a861d824230458333defd5cf43bafd2ca596d.zip |
query parsing, but this is not what i wanted actually
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 149 |
1 files changed, 8 insertions, 141 deletions
diff --git a/src/lib.rs b/src/lib.rs index f1010ae..df7eead 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,8 @@ use core::fmt; +use tag::Tag; + +mod query; +mod tag; pub struct Html { pub nodes: Vec<Node>, @@ -21,6 +25,10 @@ impl Html { } } + pub fn query<S: AsRef<str>>(&self, query: S) -> Option<&Node> { + todo!() + } + fn parse_node(raw: &str) -> Consumed { match Self::is_tag(raw) { Some(_) => { @@ -309,109 +317,6 @@ impl fmt::Display for Node { } } -#[derive(Clone, Debug, PartialEq)] -pub struct Tag { - pub name: String, - /// Everything inside the tag that's not it's name. Includes a - /// self-close if there is one. - pub body: Option<String>, - pub self_closing: bool, - pub children: Vec<Node>, -} - -impl Tag { - pub fn self_closing(&self) -> bool { - self.self_closing - } - - pub fn get_attribute<'a>(&'a self, key: &str) -> Option<&'a str> { - let body = match self.body.as_deref() { - None => return None, - Some(body) => body, - }; - - // get rid of potential self-close - let trimmed = if let Some(suffix) = body.trim().strip_suffix('/') { - suffix - } else { - body.trim() - }; - - let mut wrk = trimmed; - loop { - let key_end_idx = wrk.find(|c: char| c == ' ' || c == '='); - - match key_end_idx { - None => { - // boolean ends body - if wrk == key { - return Some(""); - } else { - break; - } - } - Some(idx) => match &wrk[idx..idx + 1] { - " " => { - // boolean - if &wrk[..idx] == key { - return Some(""); - } else { - wrk = &wrk[idx + 1..]; - } - } - "=" => { - // key-value - let found_name = &wrk[..idx]; - - // we're just assuming the attributes are properly - // formed right now. Skips the `=` and the `"` that - // should be there but we don't check for - wrk = &wrk[idx + 2..]; - let end = wrk.find('"').unwrap(); - let value = &wrk[..end]; - wrk = &wrk[end + 1..].trim_start(); - - if found_name == key { - return Some(value); - } - } - _ => unreachable!(), - }, - } - } - - None - } -} - -impl fmt::Display for Tag { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Tag { - name, - body, - self_closing, - children, - } = self; - - let formatted_body = if let Some(body) = body { - format!(" {body}") - } else { - String::from("") - }; - - if *self_closing { - // we ignore our children if we're self-closing. - write!(f, "<{name} {}/>", body.as_deref().unwrap_or_default()) - } else { - write!(f, "<{name}{formatted_body}>")?; - for child in children { - write!(f, "{}", child)?; - } - write!(f, "</{name}>") - } - } -} - #[macro_export] macro_rules! tag { ($name:expr) => { @@ -639,41 +544,3 @@ mod test { ) } } - -#[cfg(test)] -mod tag_test { - use crate::Tag; - - #[test] - fn tag_finds_boolen_attribute() { - let tag = Tag { - name: "div".into(), - body: Some("contenteditable".into()), - self_closing: false, - children: vec![], - }; - assert!(tag.get_attribute("contenteditable").is_some()) - } - - #[test] - fn tag_finds_kv_attribute() { - let tag = Tag { - name: "script".into(), - body: Some("src=\"script.js\"".into()), - self_closing: false, - children: vec![], - }; - assert_eq!(tag.get_attribute("src"), Some("script.js")) - } - - #[test] - fn tag_finds_boolean_in_centre() { - let tag = Tag { - name: "div".into(), - body: Some("id=\"divy\" contenteditable style=\"display: none;\"".into()), - self_closing: false, - children: vec![], - }; - assert!(tag.get_attribute("contenteditable").is_some()); - } -} |