1#![feature(proc_macro_span)]
2
3#[macro_use]
4extern crate pest_derive;
5#[macro_use]
6extern crate proc_macro_error;
7
8mod bind;
9mod component;
10mod css_parser;
11mod get_target_dir;
12mod html_parser;
13mod include_static;
14mod js_expression;
15mod jsjson;
16mod main_wrap;
17mod store;
18mod trace_tailwind;
19mod utils;
20mod wasm_path;
21
22use proc_macro::{Span, TokenStream};
23use quote::quote;
24
25use crate::{
26 bind::{bind_inner, bind_rc_inner, bind_spawn_inner},
27 component::component_inner,
28 css_parser::generate_css_string,
29 html_parser::{dom_element_inner, dom_inner},
30 include_static::include_static_inner,
31 js_expression::js_expression,
32 main_wrap::main_wrap,
33 store::store_inner,
34 trace_tailwind::trace_tailwind,
35};
36
37#[proc_macro]
38#[proc_macro_error]
39pub fn dom(input: TokenStream) -> TokenStream {
40 dom_inner(input)
41}
42
43#[proc_macro]
44#[proc_macro_error]
45pub fn dom_element(input: TokenStream) -> TokenStream {
46 dom_element_inner(input)
47}
48
49#[proc_macro]
50#[proc_macro_error]
51pub fn dom_debug(input: TokenStream) -> TokenStream {
52 let stream = dom_inner(input);
53 emit_warning!("debug: {:?}", stream);
54 stream
55}
56
57#[proc_macro]
58#[proc_macro_error]
59pub fn css_block(input: TokenStream) -> TokenStream {
60 let (css_str, _, refs) = generate_css_string(input);
61 let result = quote! {{
62 #refs
63 #css_str
64 }};
65 result.into()
66}
67
68#[proc_macro]
69#[proc_macro_error]
70pub fn css(input: TokenStream) -> TokenStream {
71 let (css_str, is_dynamic, refs) = generate_css_string(input);
72
73 let result = if is_dynamic {
74 quote! {{
75 #refs
76 vertigo::Css::string(#css_str)
77 }}
78 } else {
79 quote! {
80 vertigo::Css::str(#css_str)
81 }
82 };
83 result.into()
84}
85
86#[proc_macro_derive(AutoJsJson, attributes(js_json))]
87#[proc_macro_error]
88pub fn auto_js_json(input: TokenStream) -> TokenStream {
89 let ast = syn::parse(input).unwrap();
90
91 match jsjson::impl_js_json_derive(&ast) {
92 Ok(result) => result,
93 Err(message) => {
94 emit_error!(Span::call_site(), "{}", message);
95 let empty = "";
96 quote! { #empty }.into()
97 }
98 }
99}
100
101#[proc_macro]
102#[proc_macro_error]
103pub fn tw(input: TokenStream) -> TokenStream {
104 trace_tailwind(input)
105}
106
107#[proc_macro]
108#[proc_macro_error]
109pub fn include_static(input: TokenStream) -> TokenStream {
110 include_static_inner(input)
111}
112
113#[proc_macro]
114#[proc_macro_error]
115pub fn bind(input: TokenStream) -> TokenStream {
116 convert_to_tokens(bind_inner(input))
117}
118
119#[proc_macro]
120#[proc_macro_error]
121pub fn bind_spawn(input: TokenStream) -> TokenStream {
122 convert_to_tokens(bind_spawn_inner(input))
123}
124
125#[proc_macro]
126#[proc_macro_error]
127pub fn bind_rc(input: TokenStream) -> TokenStream {
128 convert_to_tokens(bind_rc_inner(input))
129}
130
131#[proc_macro_attribute]
132#[proc_macro_error]
133pub fn main(_attr: TokenStream, input: TokenStream) -> TokenStream {
134 main_wrap(input)
135}
136
137#[proc_macro_attribute]
138#[proc_macro_error]
139pub fn component(attrs: TokenStream, input: TokenStream) -> TokenStream {
140 component_inner(attrs, input)
141}
142
143#[proc_macro]
144#[proc_macro_error]
145pub fn js_inner(input: TokenStream) -> TokenStream {
146 js_expression(input)
147}
148
149fn convert_to_tokens(input: Result<TokenStream, String>) -> TokenStream {
150 match input {
151 Ok(body) => body,
152 Err(message) => {
153 emit_error!(Span::call_site(), "{}", message);
154 let empty = "";
155 quote! { #empty }.into()
156 }
157 }
158}
159
160#[proc_macro_attribute]
161pub fn store(attr: TokenStream, item: TokenStream) -> TokenStream {
162 store_inner(attr.into(), item.into()).into()
163}