rcss_macro/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro2::Span;
3
4use quote::quote_spanned;
5use rcss_core::CssOutput;
6
7mod fallback_ide;
8mod helpers;
9use helpers::CssOutputGenerateExt;
10
11/// Generate CSS scope object based on css.
12/// Don't use this macro directly, use rcss crate instead, since bundler will ignore macro that used directly.
13#[proc_macro]
14pub fn css(tokens: TokenStream) -> TokenStream {
15    let output = if Span::call_site().source_text().is_some() {
16        match css_inner() {
17            Ok(output) => output,
18            Err(e) => {
19                let msg = format!("{}", e);
20                return quote_spanned! {Span::call_site()=>
21                    compile_error!(#msg)
22                }
23                .into();
24            }
25        }
26    } else {
27        fallback_ide::parse(tokens.into())
28    };
29
30    output.generate().into()
31}
32#[derive(thiserror::Error, Debug)]
33enum MacroError {
34    #[error("Failed to parse css: {0}")]
35    ParseError(#[from] rcss_core::Error),
36    #[error("No valid source code available for this macro call.")]
37    NoSourceAvailable,
38}
39
40/// Return None if macro input is invalid.
41/// Or if source_text is not found.
42fn css_inner() -> Result<CssOutput, MacroError> {
43    let Some(text) = Span::call_site().source_text() else {
44        return Err(MacroError::NoSourceAvailable);
45    };
46    let Some(text) = helpers::macro_input(&text) else {
47        return Err(MacroError::NoSourceAvailable);
48    };
49    let mut output = rcss_core::CssProcessor::process_style(&text)?;
50    if cfg!(disable_styles) {
51        output.clear_styles();
52        // panic!("Styles was disabled.")
53    }
54    Ok(output)
55}