From 19a51d5f71914055e6abe597497fee9742fdb3b5 Mon Sep 17 00:00:00 2001 From: annieversary Date: Wed, 6 Jul 2022 15:05:57 +0100 Subject: [PATCH] implement literal values --- src/class.rs | 2 ++ src/lib.rs | 12 ++++++++++++ src/parse.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/src/class.rs b/src/class.rs index f492932..1dfa52d 100644 --- a/src/class.rs +++ b/src/class.rs @@ -44,6 +44,8 @@ impl<'a> Class<'a> { .replace('|', "\\|") .replace('(', "\\(") .replace(')', "\\)") + .replace('{', "\\{") + .replace('}', "\\}") .replace('.', "\\.") .replace('#', "\\#") .replace('$', "\\$") diff --git a/src/lib.rs b/src/lib.rs index fa835c4..36300ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -195,4 +195,16 @@ mod tests { r#".border\[1px_solid_black\]{border:1px solid black;}"# ); } + + #[test] + fn generate_literals_works() { + let z = Zephyr::new(); + + // the curly brackets indicate that the value should not go through replacements + let classes = z.generate_classes(["border{1px_solid_black}", "w{full}"]); + assert_eq!( + classes, + r#".border\{1px_solid_black\}{border:1px_solid_black;}.w\{full\}{width:full;}"# + ); + } } diff --git a/src/parse.rs b/src/parse.rs index 9282aba..2012905 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,6 +1,9 @@ use crate::class::Class; +// TODO return error pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { + // this code is kinda repetitive but idk + let (class, pseudo) = if let Some((class, pseudo)) = original.split_once('$') { (class, Some(pseudo)) } else { @@ -24,6 +27,31 @@ pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { }); } + match (pos(class, '{'), pos(class, '}')) { + (Some(start), Some(end)) if start <= end => { + let mods = if end + 1 == class.len() { + vec![] + } else { + class[end + 1..].split(',').collect() + }; + + return Some(Class { + name: &class[0..start], + value: Some(&class[start + 1..end]), + modifiers: mods.into(), + pseudo, + original, + value_literal: true, + }); + } + // go to [...] case + (None, None) => {} + _ => { + // TODO return an error here + return None; + } + }; + match (pos(class, '['), pos(class, ']')) { (Some(start), Some(end)) if start <= end => { let mods = if end + 1 == class.len() { @@ -78,6 +106,22 @@ mod tests { }) ); } + fn check_literal( + class: &str, + (name, value, modifiers, pseudo): (&str, Option<&str>, Vec<&str>, Option<&str>), + ) { + assert_eq!( + parse_class(class), + Some(Class { + name, + value, + modifiers: modifiers.into(), + pseudo, + original: class, + value_literal: true, + }) + ); + } #[test] fn parse_works() { @@ -97,6 +141,15 @@ mod tests { ); } + #[test] + fn parse_literal_values() { + // testing out weird unicode stuffs + check_literal( + "hello{hey_hello}", + ("hello", Some("hey_hello"), vec![], None), + ); + } + #[test] fn parse_modifier() { check("a[b]hover", ("a", Some("b"), vec!["hover"], None));