Component way CSS
imbolc opened this issue · comments
Imbolc commented
I was thinking on a possibility of rendering a <style>
tag once with multiple component usage. Here's what I ended up with. What do you think on the approach? Would you consider adding something like this into the markup?
use std::any::type_name;
use std::cell::Cell;
use std::collections::HashSet;
#[derive(Default)]
pub struct CssOnce(Cell<HashSet<&'static str>>);
impl CssOnce {
fn new() -> Self {
Self::default()
}
fn insert<T>(&self) -> bool {
let mut inner = self.0.take();
let inserted = inner.insert(type_name::<T>());
self.0.set(inner);
inserted
}
}
macro_rules! css_once {
($rend:ident, $($str:tt)+) => {
if CssOnce::insert::<Self>($rend) {
markup::raw(concat!("<style>", $($str),+, "</style>\n"))
} else {
markup::raw("")
}
};
}
markup::define! {
Hello<'a>(
css: &'a CssOnce,
name: &'a str,
) {
@css_once!(css,
".hello { background: blue }"
".hello b { color: yellow }"
)
p.hello { "Hello, " b { @name } }
}
Body<'a>(
css: &'a CssOnce,
) {
@Hello {css, name: "World"}
@Hello {css, name: "Self"}
}
}
fn main() {
let css = CssOnce::new();
println!("{}", Body { css: &css });
}