add inventory
This commit is contained in:
parent
47a260b7ee
commit
444dadedba
11
Cargo.toml
11
Cargo.toml
|
@ -3,7 +3,14 @@ name = "zephyr"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
[features]
|
||||||
|
default = []
|
||||||
|
|
||||||
|
inventory = ["dep:inventory"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
once_cell = "1.10.0"
|
inventory = { version = "0.3", optional = true }
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "inventory"
|
||||||
|
required-features = ["inventory"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
// this list would ideally be generated on the fly out of the written html,
|
// this list of used classes would ideally be parsed out of the written html,
|
||||||
// but i don't want to unneeded dependencies to this crate
|
// but i don't want to over complicate this example
|
||||||
let classes = [
|
let classes = [
|
||||||
"mt[10rem]",
|
"mt[10rem]",
|
||||||
"color[#e20f00]",
|
"color[#e20f00]",
|
||||||
|
@ -11,7 +11,7 @@ fn main() {
|
||||||
];
|
];
|
||||||
|
|
||||||
let z = zephyr::Zephyr::new();
|
let z = zephyr::Zephyr::new();
|
||||||
let css = z.generate_css(&classes);
|
let css = z.generate_classes(classes);
|
||||||
|
|
||||||
let html = format!(
|
let html = format!(
|
||||||
r#"
|
r#"
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
//! for situations where you have a set of components,
|
||||||
|
//! and you want to register the classes you use from different files without too much complexity
|
||||||
|
|
||||||
|
use zephyr::{register_class, Zephyr};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let z = Zephyr::new();
|
||||||
|
let generated_css = z.generate_from_inventory();
|
||||||
|
|
||||||
|
let head = head(&generated_css);
|
||||||
|
|
||||||
|
let header = header();
|
||||||
|
let body = body();
|
||||||
|
|
||||||
|
let html = format!(
|
||||||
|
r#"
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
{head}
|
||||||
|
<body>
|
||||||
|
{header}
|
||||||
|
{body}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
|
||||||
|
std::fs::write("./examples/index.html", html).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn head(generated_css: &str) -> String {
|
||||||
|
format!(
|
||||||
|
r#"
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<style>{generated_css}</style>
|
||||||
|
</head>
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header() -> String {
|
||||||
|
let class = register_class!("color[#e20f00] color[green]hover content['*']$before");
|
||||||
|
format!(
|
||||||
|
r#"
|
||||||
|
<p class="{class}">
|
||||||
|
this text is red, but green on hover
|
||||||
|
</p>
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn body() -> String {
|
||||||
|
let class = register_class!("mt[10rem] content[attr(after)]$after color[red]$after");
|
||||||
|
format!(
|
||||||
|
r#"
|
||||||
|
<p class="{class}" after="hi, this is an after text">
|
||||||
|
this text has a lot of margin
|
||||||
|
</p>
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
pub use inventory::submit;
|
||||||
|
|
||||||
|
use crate::Zephyr;
|
||||||
|
|
||||||
|
pub struct AddClassToInventory {
|
||||||
|
class: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddClassToInventory {
|
||||||
|
pub const fn new(class: &'static str) -> Self {
|
||||||
|
Self { class }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory::collect!(AddClassToInventory);
|
||||||
|
|
||||||
|
impl Zephyr {
|
||||||
|
pub fn generate_from_inventory(&self) -> String {
|
||||||
|
self.generate_classes(
|
||||||
|
inventory::iter::<AddClassToInventory>
|
||||||
|
.into_iter()
|
||||||
|
.map(|a| a.class),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! register_class {
|
||||||
|
($c:literal) => {{
|
||||||
|
const C: &'static str = $c;
|
||||||
|
$crate::inventory::submit! {
|
||||||
|
$crate::inventory::AddClassToInventory::new(C)
|
||||||
|
}
|
||||||
|
C
|
||||||
|
}};
|
||||||
|
}
|
19
src/lib.rs
19
src/lib.rs
|
@ -8,6 +8,10 @@ mod class;
|
||||||
mod defaults;
|
mod defaults;
|
||||||
mod parse;
|
mod parse;
|
||||||
|
|
||||||
|
#[cfg(feature = "inventory")]
|
||||||
|
#[macro_use]
|
||||||
|
pub mod inventory;
|
||||||
|
|
||||||
pub struct Zephyr {
|
pub struct Zephyr {
|
||||||
/// for non-value rules
|
/// for non-value rules
|
||||||
pub rules: HashMap<String, String>,
|
pub rules: HashMap<String, String>,
|
||||||
|
@ -41,12 +45,13 @@ impl Zephyr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_css(&self, classes: &[&str]) -> String {
|
pub fn generate_classes<'a>(&self, classes: impl IntoIterator<Item = &'a str>) -> String {
|
||||||
// TODO when we have media queries, we can do something to group them together
|
// TODO when we have media queries, we can do something to group them by the query, and then emit those together
|
||||||
|
|
||||||
classes
|
classes
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|s| s.split_ascii_whitespace())
|
.flat_map(|s| s.split_ascii_whitespace())
|
||||||
|
// TODO skip duplicates, use hashset or smth
|
||||||
.flat_map(|c| self.generate_class(c))
|
.flat_map(|c| self.generate_class(c))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("")
|
.join("")
|
||||||
|
@ -104,19 +109,19 @@ mod tests {
|
||||||
fn generate_classes_works() {
|
fn generate_classes_works() {
|
||||||
let z = Zephyr::new();
|
let z = Zephyr::new();
|
||||||
|
|
||||||
let classes = z.generate_css(&["flex-row"]);
|
let classes = z.generate_classes(["flex-row"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes,
|
classes,
|
||||||
r#".flex-row { display: flex; flex-direction: row; }"#
|
r#".flex-row { display: flex; flex-direction: row; }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let classes = z.generate_css(&["m[3rem]hover,focus$placeholder"]);
|
let classes = z.generate_classes(["m[3rem]hover,focus$placeholder"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes,
|
classes,
|
||||||
r#".m\[3rem\]hover,focus\$placeholder:hover:focus::placeholder { margin: 3rem; }"#
|
r#".m\[3rem\]hover,focus\$placeholder:hover:focus::placeholder { margin: 3rem; }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let classes = z.generate_css(&["flex|hover,focus$placeholder"]);
|
let classes = z.generate_classes(["flex|hover,focus$placeholder"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes,
|
classes,
|
||||||
r#".flex\|hover,focus\$placeholder:hover:focus::placeholder { display: flex; }"#
|
r#".flex\|hover,focus\$placeholder:hover:focus::placeholder { display: flex; }"#
|
||||||
|
@ -127,8 +132,8 @@ mod tests {
|
||||||
fn generate_multiple_works() {
|
fn generate_multiple_works() {
|
||||||
let z = Zephyr::new();
|
let z = Zephyr::new();
|
||||||
|
|
||||||
let classes_joined = z.generate_css(&["flex-row mt[1rem]"]);
|
let classes_joined = z.generate_classes(["flex-row mt[1rem]"]);
|
||||||
let classes_separate = z.generate_css(&["flex-row", "mt[1rem]"]);
|
let classes_separate = z.generate_classes(["flex-row", "mt[1rem]"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes_joined,
|
classes_joined,
|
||||||
r#".flex-row { display: flex; flex-direction: row; }.mt\[1rem\] { margin-top: 1rem; }"#
|
r#".flex-row { display: flex; flex-direction: row; }.mt\[1rem\] { margin-top: 1rem; }"#
|
||||||
|
|
Loading…
Reference in New Issue