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#[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
40fn 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 }
54 Ok(output)
55}