feat: relative style paths & component crate example

This commit is contained in:
Yiffy Dev 2024-11-16 22:32:38 +05:00
commit 17fa4ab197
No known key found for this signature in database
GPG key ID: FB83DFEAFB3F4709
4 changed files with 376 additions and 89 deletions

View file

@ -18,6 +18,7 @@ raffia = {version = "^0.9"}
regex = {version = "^1.11"}
[features]
nightly = []
[package.metadata.docs.rs]
all-features = true

View file

@ -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 {

View file

@ -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 {}

View file

@ -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)
}
}