1mod generate_builder;
24mod parser;
25
26#[proc_macro]
27pub fn html(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
28 if input.is_empty() {
29 return quote::quote! {
30 {
31 use html_context::*;
32
33 Fragment::builder("").finish()
34 }
35 }
36 .into();
37 }
38
39 let item = syn::parse_macro_input!(input as HtmlElement);
41
42 let builder = item.generate_builder();
43
44 quote::quote! {
45 {
46 use html_context::*;
47
48 #builder
49 }
50 }
51 .into()
52}
53
54enum HtmlElement {
55 Tagged(HtmlElementTag),
56 Fragmented(HtmlElementFragment),
57 Block(syn::Block),
58 Format(HtmlElementFormat),
59}
60
61#[allow(dead_code)]
62struct HtmlElementTag {
63 opening_tag: HtmlOpeningTag,
64 children: Vec<HtmlElement>,
65 closing_tag: Option<HtmlClosingTag>,
66}
67
68#[allow(dead_code)]
69struct HtmlElementFragment {
70 opening_fragment: HtmlOpeningFragment,
71 children: Vec<HtmlElement>,
72 closing_fragment: HtmlClosingFragment,
73}
74
75#[allow(dead_code)]
76struct HtmlOpeningFragment {
77 opening_bracket_token: syn::Token![<],
78 closing_bracket_token: syn::Token![>],
79}
80
81#[allow(dead_code)]
82struct HtmlClosingFragment {
83 opening_bracket_token: syn::Token![<],
84 closing_slash_token: syn::Token![/],
85 closing_bracket_token: syn::Token![>],
86}
87
88#[allow(dead_code)]
89struct HtmlOpeningTag {
90 opening_bracket_token: syn::Token![<],
91 tag: syn::Ident,
92 generics: syn::Generics,
93 attributes: Vec<HtmlAttribute>,
94 self_closing_slash_token: Option<syn::Token![/]>,
95 closing_bracket_token: syn::Token![>],
96}
97
98#[allow(dead_code)]
99struct HtmlClosingTag {
100 opening_bracket_token: syn::Token![<],
101 closing_slash_token: syn::Token![/],
102 tag: syn::Ident,
103 closing_bracket_token: syn::Token![>],
104}
105
106#[allow(dead_code)]
107struct HtmlAttribute {
108 name: HtmlAttributeName,
109 eq_token: Option<syn::Token![=]>,
110 value: Option<HtmlAttributeValue>,
111}
112
113#[allow(dead_code)]
114enum HtmlAttributeName {
115 Block(syn::Block),
116 Ident(syn::Ident),
117 Shorthand {
118 brace_token: syn::token::Brace,
119 ident: syn::Ident,
120 },
121}
122
123#[allow(dead_code)]
124enum HtmlAttributeValue {
125 Block(syn::Block),
126 ExprArray(syn::ExprArray),
127 Lit(syn::Lit),
128}
129
130#[allow(dead_code)]
131struct HtmlElementFormat {
132 paren_token: syn::token::Paren,
133 args: syn::punctuated::Punctuated<syn::Expr, syn::Token![,]>,
134}