diff --git a/src/lib.rs b/src/lib.rs index 3424f94..2a8ab53 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,25 +54,54 @@ impl Parse for Argument { } struct BaseElement { - value: Expr, - params: Punctuated, + values: Vec, + params: Vec, } impl Parse for BaseElement { fn parse(input: ParseStream) -> Result { - let value: Expr = input.parse()?; - let _ = input.parse::(); - let params: Punctuated = Punctuated::parse_terminated(input)?; - Ok(BaseElement { value, params }) + let mut values = Vec::new(); + let mut params = Vec::new(); + while !input.is_empty() { + if input.peek(Ident) && input.peek2(Token![=]) { + let property: Property = input.parse()?; + params.push(property); + } else { + let value: Expr = input.parse()?; + values.push(value); + } + if input.peek(Token![,]) { + input.parse::()?; + } + } + Ok(BaseElement { values, params }) } } -fn heading(level: &str, item: TokenStream) -> TokenStream { - let BaseElement { value, params } = parse_macro_input!(item as BaseElement); +#[proc_macro] +pub fn paragraph(input: TokenStream) -> TokenStream { + base("p", input) +} + +#[proc_macro] +pub fn division(input: TokenStream) -> TokenStream { + base("div", input) +} + +fn base(elem: &str, item: TokenStream) -> TokenStream { + let BaseElement { values, params } = parse_macro_input!(item as BaseElement); + let values = values.iter(); + let formated_values = if values.len() > 1 { + let mut s = "\n".to_string(); + s.push_str("{}\n".repeat(values.len()).as_str()); + s + } else { + "{}".to_string() + }; let expanded = match params.is_empty() { false => { - let mut values = Vec::new(); + let mut options_values = Vec::new(); let formated_names = params .iter() @@ -80,18 +109,23 @@ fn heading(level: &str, item: TokenStream) -> TokenStream { .collect::>() .join(" "); - let format_string = format!("{{}}", level, level); + let format_string = + format!("<{} {formated_names}>{}", elem, formated_values, elem); for property in params { - values.push(property.value); + options_values.push(property.value); } - quote!(format!(#format_string, #(#values), *, #value)) + quote!(format!(#format_string, #(#options_values), *, #(#values), *)) } true => { - let format_string = format!("{{}}", level, level); - quote!(format!(#format_string, #value)) + let format_string = format!("<{}>{}", elem, formated_values, elem); + quote!(format!(#format_string, #(#values), *)) } }; TokenStream::from(expanded) } + +fn heading(level: &str, item: TokenStream) -> TokenStream { + base(format!("h{level}").as_str(), item) +}