use super::class::{ClassMode, parse_class_string_with_mode};
use super::runtime::generate_dynamic_class_code_with_mode;
use super::tables::{is_multi_arg_method, lookup_attr_flag_method, lookup_attr_method};
use crate::parser::RsxAttribute;
use proc_macro2::TokenStream;
use quote::quote;
#[derive(Clone, Copy, Default)]
pub(crate) struct AttrHints<'a> {
pub(crate) name: Option<&'a str>,
pub(crate) static_class: Option<&'a str>,
}
pub(crate) fn generate_attr_methods_with_mode(
attr: &RsxAttribute,
hints: AttrHints<'_>,
out: &mut Vec<TokenStream>,
mode: ClassMode,
) {
match attr {
RsxAttribute::Value { name, .. } if name == "id" || name == "key" || name == "base" => {}
RsxAttribute::Flag(name) => {
if name != "styled" {
let name_storage;
let name_str = if let Some(name) = hints.name {
name
} else {
name_storage = name.to_string();
&name_storage
};
if let Some(mapped) = lookup_attr_flag_method(name_str) {
let method_ident = syn::Ident::new(mapped, name.span());
out.push(quote! { .#method_ident() });
return;
}
out.push(quote! { .#name() });
}
}
RsxAttribute::Value { name, value } => {
if name == "class" {
if let Some(s) = hints.static_class {
out.extend(parse_class_string_with_mode(s, mode));
return;
}
if let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit_str),
..
}) = value
{
let s = lit_str.value();
out.extend(parse_class_string_with_mode(&s, mode));
return;
}
let dynamic_code = generate_dynamic_class_code_with_mode(value, mode);
out.push(quote! { .map(|__el| #dynamic_code) });
return;
}
if name == "visible" {
out.push(quote! { .when(#value, |__el| __el.visible()).when(!(#value), |__el| __el.invisible()) });
return;
}
let name_storage;
let name_str = if let Some(name) = hints.name {
name
} else {
name_storage = name.to_string();
&name_storage
};
if let Some(mapped) = lookup_attr_method(name_str) {
let method_ident = syn::Ident::new(mapped, name.span());
if is_multi_arg_method(mapped)
&& let syn::Expr::Tuple(tuple) = value
{
let args = &tuple.elems;
out.push(quote! { .#method_ident(#args) });
} else {
out.push(quote! { .#method_ident(#value) });
}
return;
}
out.push(quote! { .#name(#value) });
}
RsxAttribute::When { condition, closure } => {
out.push(quote! { .when(#condition, #closure) });
}
RsxAttribute::WhenSome { option, closure } => {
out.push(quote! { .when_some(#option, #closure) });
}
RsxAttribute::WhenClass {
condition,
class_lit,
} => {
let class_str = class_lit.value();
let class_methods: Vec<_> = parse_class_string_with_mode(&class_str, mode).collect();
out.push(quote! { .when(#condition, |__el| __el #(#class_methods)* ) });
}
}
}