1#![doc = include_str!("../README.md")]
2
3use quote::format_ident;
4
5mod arguments;
6mod html;
7use server_fn_macro::server_macro_impl;
8mod template;
9
10#[proc_macro_attribute]
11pub fn html(
12 attr: proc_macro::TokenStream,
13 item: proc_macro::TokenStream,
14) -> proc_macro::TokenStream {
15 self::html::html(attr.into(), item.into())
16 .unwrap_or_else(syn::Error::into_compile_error)
17 .into()
18}
19
20#[proc_macro_attribute]
21pub fn template(
22 attr: proc_macro::TokenStream,
23 item: proc_macro::TokenStream,
24) -> proc_macro::TokenStream {
25 self::template::template(attr.into(), item.into())
26 .unwrap_or_else(syn::Error::into_compile_error)
27 .into()
28}
29
30#[proc_macro_attribute]
31pub fn server(
32 args: proc_macro::TokenStream,
33 s: proc_macro::TokenStream,
34) -> proc_macro::TokenStream {
35 match server_macro_impl(
36 args.into(),
37 s.into(),
38 Some(syn::parse_quote!(::server_fn)),
39 "/api/fn",
40 None,
41 None,
42 ) {
43 Err(e) => e.to_compile_error().into(),
44 Ok(s) => s.into(),
45 }
46}
47
48fn item_to_string(item: &syn::Item) -> String {
49 prettyplease::unparse(&syn::File {
50 shebang: None,
51 attrs: vec![],
52 items: vec![item.clone()],
53 })
54}
55
56fn is_path(path: &syn::Path, expected: &'static str) -> bool {
57 let syn::Path {
58 leading_colon: None,
59 segments,
60 } = path
61 else {
62 return false;
63 };
64 let Some(segment) = segments.last() else {
65 return false;
66 };
67 if segments.len() != 1 {
68 return false;
69 }
70 let syn::PathArguments::None = segment.arguments else {
71 return false;
72 };
73 return segment.ident == format_ident!("{}", expected);
74}