use super::class::parse_single_class;
use proc_macro2::TokenStream;
use quote::quote;
use std::cell::RefCell;
use std::rc::Rc;
thread_local! {
static COMMON_CLASS_MATCHES: RefCell<Option<Rc<Vec<TokenStream>>>> = const { RefCell::new(None) };
}
fn get_cached_common_class_matches() -> Rc<Vec<TokenStream>> {
COMMON_CLASS_MATCHES.with(|cell| {
let mut borrow = cell.borrow_mut();
Rc::clone(borrow.get_or_insert_with(|| Rc::new(generate_common_class_matches())))
})
}
pub(crate) fn generate_dynamic_class_code(class_expr: &syn::Expr) -> TokenStream {
let common_classes = get_cached_common_class_matches();
let common_classes = &*common_classes;
quote! {
{
#[inline(never)]
fn __rsx_apply_class<E: Styled>(el: E, class: &str) -> E {
match class {
#(#common_classes)*
_ => el,
}
}
let __class_expr = #class_expr;
let __class_str: &str = __class_expr.as_ref();
if __class_str.is_empty() {
__el
} else {
__class_str.split_ascii_whitespace().fold(__el, __rsx_apply_class)
}
}
}
}
fn generate_common_class_matches() -> Vec<TokenStream> {
let common_classes = [
"flex",
"flex-col",
"flex-row",
"flex-1",
"flex-wrap",
"items-center",
"items-start",
"items-end",
"justify-center",
"justify-between",
"justify-start",
"justify-end",
"gap-1",
"gap-2",
"gap-3",
"gap-4",
"gap-6",
"gap-8",
"p-1",
"p-2",
"p-3",
"p-4",
"p-6",
"p-8",
"px-2",
"px-4",
"py-1",
"py-2",
"py-4",
"m-2",
"m-4",
"w-full",
"h-full",
"size-full",
"text-xs",
"text-sm",
"text-base",
"text-lg",
"text-xl",
"text-2xl",
"text-3xl",
"font-bold",
"border",
"border-2",
"rounded-sm",
"rounded-md",
"rounded-lg",
"rounded-full",
"cursor-pointer",
"overflow-hidden",
"overflow-scroll",
"absolute",
"relative",
"bg-white",
"bg-black",
"text-white",
"text-black",
];
let mut matches = Vec::with_capacity(common_classes.len());
for class_str in common_classes {
let method_call = parse_single_class(class_str);
matches.push(quote! {
#class_str => el #method_call,
});
}
matches
}