feat: relative style paths & component crate example
This commit is contained in:
parent
fd751082b5
commit
336852a74d
4 changed files with 376 additions and 89 deletions
|
|
@ -18,6 +18,7 @@ raffia = {version = "^0.9"}
|
|||
regex = {version = "^1.11"}
|
||||
|
||||
[features]
|
||||
nightly = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
|
|
|||
|
|
@ -30,28 +30,29 @@ impl ArbitraryStyleBlock {
|
|||
pub fn code(&self) -> &str {
|
||||
&self.code
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for ArbitraryStyleBlock {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
pub fn parse_syn(
|
||||
input: syn::parse::ParseStream,
|
||||
use_code_path_prefix: Option<PathBuf>,
|
||||
) -> syn::Result<Self> {
|
||||
let (code, span) = if let Ok(path_tok) = input.parse::<LitStr>() {
|
||||
let path = path_tok.value();
|
||||
|
||||
let path = match PathBuf::from_str(&path) {
|
||||
Ok(p) => p,
|
||||
Err(_) => {
|
||||
return Err(syn::Error::new(
|
||||
path_tok.span(),
|
||||
format!("Could not read {} as a path: Infallible", path),
|
||||
))
|
||||
let path = if let Some(prefix) = use_code_path_prefix {
|
||||
let p = path_tok.value();
|
||||
if let Some(pp) = p.strip_prefix("./") {
|
||||
prefix.join(pp)
|
||||
} else {
|
||||
PathBuf::from_str(&p).expect("Unable to convert path into PathBuf")
|
||||
}
|
||||
} else {
|
||||
PathBuf::from_str(&path_tok.value()).expect("Unable to convert path into PathBuf")
|
||||
};
|
||||
|
||||
let fullpath = match path.canonicalize() {
|
||||
Ok(cp) => cp,
|
||||
Err(e) => {
|
||||
return Err(syn::Error::new(
|
||||
path_tok.span(),
|
||||
format!("Could not use path {path:?}: {:?}", e.kind()),
|
||||
format!("Could not use path {path:?}: {:?}. If the path is relative and 'nightly' feature flag is set - this is likely false-positive", e.kind()),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
|
@ -86,6 +87,12 @@ impl Parse for ArbitraryStyleBlock {
|
|||
}
|
||||
}
|
||||
|
||||
impl Parse for ArbitraryStyleBlock {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
Self::parse_syn(input, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::to_string_trait_impl)]
|
||||
impl ToString for ArbitraryStyleBlock {
|
||||
fn to_string(&self) -> String {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use sabry_intrnl::scoper::ArbitraryScope;
|
||||
use syn::{parse::Parse, Ident};
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
Ident,
|
||||
};
|
||||
|
||||
use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
||||
|
||||
|
|
@ -11,31 +16,34 @@ use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
|||
/// `$syntax`: sass/scss
|
||||
///
|
||||
/// `$code`: intended to be valid based on $syntax
|
||||
pub fn scssy_macro_impl(input: TokenStream) -> TokenStream {
|
||||
pub fn scssy_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> TokenStream {
|
||||
let MacroSyntax {
|
||||
ident,
|
||||
syntax: mode,
|
||||
syntax,
|
||||
code,
|
||||
} = match syn::parse2::<MacroSyntax>(input) {
|
||||
} = match syn::parse::Parser::parse2(
|
||||
|input: ParseStream<'_>| MacroSyntax::parse_syn(input, source_path),
|
||||
input,
|
||||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => return e.to_compile_error(),
|
||||
};
|
||||
|
||||
// quick raffia syntax check
|
||||
match ArbitraryScope::from_source(mode.0, ident.clone(), &code.code) {
|
||||
match ArbitraryScope::from_source(syntax.0, ident.clone(), &code.code) {
|
||||
Ok(_) => {}
|
||||
Err(e) => return syn::Error::new(code.span, format!("{e:?}")).into_compile_error(),
|
||||
}
|
||||
|
||||
let sourcesass = code.to_string();
|
||||
let macro_doc = format!("Arbitrary {:?} code declared with `scssy!`. Pretty usable in tandem with `usey!` and `magic()` at build time", mode);
|
||||
let macro_doc = format!("Arbitrary {:?} code declared with `scssy!`. Pretty usable in tandem with `usey!` and `buildy` at build time", syntax);
|
||||
|
||||
quote! {
|
||||
#[doc = #macro_doc]
|
||||
#[macro_export]
|
||||
macro_rules! #ident {
|
||||
() => {#sourcesass};
|
||||
(syntax) => {#mode};
|
||||
(syntax) => {#syntax};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,19 +54,32 @@ pub struct MacroSyntax {
|
|||
code: ArbitraryStyleBlock,
|
||||
}
|
||||
|
||||
impl Parse for MacroSyntax {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
impl MacroSyntax {
|
||||
pub fn parse_syn(
|
||||
input: syn::parse::ParseStream,
|
||||
source_path: Option<PathBuf>,
|
||||
) -> syn::Result<Self> {
|
||||
let ident = input.parse::<Ident>()?;
|
||||
let mode = input.parse::<ArbitraryStyleSyntax>()?;
|
||||
let code = input.parse::<ArbitraryStyleBlock>()?;
|
||||
let syntax = input.parse::<ArbitraryStyleSyntax>()?;
|
||||
|
||||
let code = match source_path {
|
||||
Some(sp) => ArbitraryStyleBlock::parse_syn(input, Some(sp))?,
|
||||
None => input.parse::<ArbitraryStyleBlock>()?,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
ident,
|
||||
syntax: mode,
|
||||
syntax,
|
||||
code,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for MacroSyntax {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
Self::parse_syn(input, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use sabry_intrnl::{
|
||||
|
|
@ -5,7 +7,10 @@ use sabry_intrnl::{
|
|||
config::SabryConfig,
|
||||
scoper::{apply_basic_rusty_member_gen_rules, ArbitraryScope, ScopedSelector},
|
||||
};
|
||||
use syn::{parse::Parse, Ident, Token};
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
Ident, Token,
|
||||
};
|
||||
|
||||
use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
||||
|
||||
|
|
@ -26,7 +31,7 @@ use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
|||
///
|
||||
/// The machine-readable output may also be forced by use `machine_readable: true` arg on `parse_macro_syntax` function
|
||||
/// without modifying tokenstream
|
||||
pub fn styly_macro_impl(input: TokenStream) -> TokenStream {
|
||||
pub fn styly_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> TokenStream {
|
||||
let config = match SabryConfig::require() {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
|
|
@ -40,7 +45,7 @@ pub fn styly_macro_impl(input: TokenStream) -> TokenStream {
|
|||
.to_compile_error()
|
||||
}
|
||||
};
|
||||
let ms = match parse_macro_syntax(input) {
|
||||
let ms = match parse_macro_syntax(input, source_path) {
|
||||
Ok(ms) => ms,
|
||||
Err(e) => return e.to_compile_error(),
|
||||
};
|
||||
|
|
@ -180,8 +185,14 @@ pub fn styly_macro_impl(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
// reusable function, that does not return tokenstream for machine-processing at build time
|
||||
pub fn parse_macro_syntax(input: TokenStream) -> Result<MacroSyntax, syn::Error> {
|
||||
syn::parse2::<MacroSyntax>(input)
|
||||
pub fn parse_macro_syntax(
|
||||
input: TokenStream,
|
||||
source_path: Option<PathBuf>,
|
||||
) -> Result<MacroSyntax, syn::Error> {
|
||||
syn::parse::Parser::parse2(
|
||||
|input: ParseStream<'_>| MacroSyntax::parse_syn(input, source_path),
|
||||
input,
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -215,12 +226,19 @@ pub struct MacroSyntax {
|
|||
pub code: ArbitraryStyleBlock,
|
||||
}
|
||||
|
||||
impl Parse for MacroSyntax {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
impl MacroSyntax {
|
||||
pub fn parse_syn(
|
||||
input: syn::parse::ParseStream,
|
||||
source_path: Option<PathBuf>,
|
||||
) -> syn::Result<Self> {
|
||||
let mut generator = input.parse::<ScopeGenerator>()?;
|
||||
let scope = input.parse::<Ident>()?;
|
||||
let syntax = input.parse::<ArbitraryStyleSyntax>()?;
|
||||
let code = input.parse::<ArbitraryStyleBlock>()?;
|
||||
let code = if source_path.is_some() {
|
||||
ArbitraryStyleBlock::parse_syn(input, source_path)
|
||||
} else {
|
||||
input.parse::<ArbitraryStyleBlock>()
|
||||
}?;
|
||||
|
||||
if input.parse::<Token![#]>().is_ok() {
|
||||
generator = ScopeGenerator::MachineReadable
|
||||
|
|
@ -234,3 +252,9 @@ impl Parse for MacroSyntax {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for MacroSyntax {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
Self::parse_syn(input, None)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue