fhtml_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3
4mod ast;
5mod fmt;
6mod lower_ast;
7mod parse;
8
9pub(crate) struct FormatArgsInput {
10    pub template: String,
11    pub values: Vec<ast::LitValue>,
12}
13
14/// A low level macro for creating an [`fmt::Arguments`] with formatted HTML.
15///
16/// See [`std::format_args!`] for more information.
17///
18/// [`fmt::Arguments`]: https://doc.rust-lang.org/stable/std/fmt/struct.Arguments.html
19/// [`std::format_args!`]: https://doc.rust-lang.org/stable/std/macro.format_args.html
20#[proc_macro]
21pub fn format_args(input: TokenStream) -> TokenStream {
22    let input = syn::parse_macro_input!(input as FormatArgsInput);
23
24    let template = input.template;
25    let values = input.values;
26
27    let output = quote! {
28        ::std::format_args!(#template, #(#values),*)
29    };
30
31    output.into()
32}
33
34/// Creates an [`fmt::Arguments`] with a newline (`<br>`) appended.
35///
36/// See [`std::format_args_nl!`] for more information.
37///
38/// [`std::format_args_nl!`]: https://doc.rust-lang.org/stable/std/macro.format_args_nl.html
39#[proc_macro]
40pub fn format_args_nl(input: TokenStream) -> TokenStream {
41    let input = syn::parse_macro_input!(input as FormatArgsInput);
42
43    let template_with_nl = format!("{}<br>", input.template);
44    let values = input.values;
45
46    let output = quote! {
47        ::std::format_args!(#template_with_nl, #(#values),*)
48    };
49
50    output.into()
51}
52
53pub(crate) struct ConcatInput {
54    pub segments: Vec<proc_macro2::TokenStream>,
55}
56
57/// Creates a &'static str with formatted HTML.
58///
59/// Only supports certain literals as values.
60/// See [`std::concat!`] for more information.
61///
62/// [`std::concat!`]: https://doc.rust-lang.org/stable/std/macro.concat.html
63#[proc_macro]
64pub fn concat(input: TokenStream) -> TokenStream {
65    let input = syn::parse_macro_input!(input as ConcatInput);
66    let segments = input.segments;
67
68    let output = quote! {
69        ::std::concat!(#(#segments),*)
70    };
71
72    output.into()
73}