html_site_generator_macro/
lib.rs

1use proc_macro::{Span, TokenStream};
2use quote::quote;
3use syn::parse::Parser;
4use syn::{parse, parse_macro_input, DeriveInput, Ident, ItemStruct};
5
6#[proc_macro_attribute]
7pub fn add_attributes_field(args: TokenStream, input: TokenStream) -> TokenStream {
8    let mut item_struct = parse_macro_input!(input as ItemStruct);
9    let _ = parse_macro_input!(args as parse::Nothing);
10
11    if let syn::Fields::Named(ref mut fields) = item_struct.fields {
12        fields.named.push(
13            syn::Field::parse_named
14                .parse2(quote! {
15                    _attributes: crate::attributes::HtmlAttributes
16                })
17                .unwrap(),
18        );
19    }
20
21    return quote! {
22        #item_struct
23    }
24    .into();
25}
26
27#[proc_macro_derive(DeriveSetHtmlAttributes)]
28pub fn derive_set_html_attributes(input: TokenStream) -> TokenStream {
29    // Parse the input tokens into a syntax tree
30    let input = parse_macro_input!(input as DeriveInput);
31
32    let name = input.ident;
33
34    // TODO make it possible to get the name of the field in the derive macro call
35    let default_attributes_field = Ident::new("_attributes", Span::call_site().into());
36
37    // Build the output, possibly using quasi-quotation
38    let expanded = quote! {
39        impl crate::attributes::SetHtmlAttributes for #name {
40            fn get_attributes(&self) -> &crate::attributes::HtmlAttributes { &self. #default_attributes_field }
41            fn get_attributes_mut(&mut self) -> &mut crate::attributes::HtmlAttributes { &mut self. #default_attributes_field }
42        }
43    };
44
45    // Hand the output tokens back to the compiler
46    TokenStream::from(expanded)
47}