chore: pre0.1
This commit is contained in:
parent
c3f68d54e7
commit
be8ee7611d
13 changed files with 114 additions and 238 deletions
36
Cargo.toml
36
Cargo.toml
|
|
@ -1,5 +1,5 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "3"
|
||||||
members = [
|
members = [
|
||||||
"sabry_procmacro",
|
"sabry_procmacro",
|
||||||
"sabry_procmacro_impl",
|
"sabry_procmacro_impl",
|
||||||
|
|
@ -8,43 +8,42 @@ members = [
|
||||||
]
|
]
|
||||||
exclude = ["examples"]
|
exclude = ["examples"]
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "0.0.6"
|
||||||
|
edition = "2024"
|
||||||
|
rust-version = "1.88"
|
||||||
|
authors = ["Svyatoslav Pushkarev <yiffyrusdev@yandex.ru>"]
|
||||||
|
repository = "https://github.com/yiffyrusdev/sabry"
|
||||||
|
license = "MIT"
|
||||||
|
publish = true
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
## Workspace
|
## Workspace
|
||||||
sabry_intrnl = { path = "sabry_intrnl", version = "0.0.6" }
|
sabry_intrnl = { path = "sabry_intrnl", version = "0.0.6" }
|
||||||
sabry_procmacro = { path = "sabry_procmacro", version = "0.0.6" }
|
sabry_procmacro = { path = "sabry_procmacro", version = "0.0.6" }
|
||||||
sabry_procmacro_impl = { path = "sabry_procmacro_impl", version = "0.0.6" }
|
sabry_procmacro_impl = { path = "sabry_procmacro_impl", version = "0.0.6" }
|
||||||
sabry_build = { path = "sabry_build", version = "0.0.6" }
|
sabry_build = { path = "sabry_build", version = "0.0.6" }
|
||||||
#/
|
## CSS
|
||||||
lightningcss.version = "1.0.0-alpha.67"
|
lightningcss.version = "1.0.0-alpha.71"
|
||||||
lightningcss.default-features = false
|
lightningcss.default-features = false
|
||||||
grass.version = "^0.13"
|
grass.version = "^0.13"
|
||||||
grass.default-features = false
|
grass.default-features = false
|
||||||
raffia.version = "^0.11"
|
raffia.version = "^0.12"
|
||||||
#/
|
## Marshall
|
||||||
serde.version = "^1"
|
serde.version = "^1"
|
||||||
toml.version = "^0.9"
|
toml.version = "^1"
|
||||||
blake3.version = "^1"
|
|
||||||
base64.version = "^0.22"
|
base64.version = "^0.22"
|
||||||
regex.version = "^1"
|
regex.version = "^1"
|
||||||
#/
|
## Util
|
||||||
itertools.version = "^0.14"
|
itertools.version = "^0.14"
|
||||||
walkdir.version = "^2"
|
walkdir.version = "^2"
|
||||||
#/
|
## Codegen
|
||||||
cfg-if.version = "^1"
|
cfg-if.version = "^1"
|
||||||
thiserror.version = "^2"
|
thiserror.version = "^2"
|
||||||
proc-macro2.version = "^1"
|
proc-macro2.version = "^1"
|
||||||
quote.version = "^1"
|
quote.version = "^1"
|
||||||
syn.version = "^2"
|
syn.version = "^2"
|
||||||
|
|
||||||
[workspace.package]
|
|
||||||
version = "0.0.6"
|
|
||||||
edition = "2021"
|
|
||||||
rust-version = "1.88"
|
|
||||||
authors = ["Svyatoslav Pushkarev <yiffyrusdev@yandex.ru>"]
|
|
||||||
repository = "https://github.com/yiffyrusdev/sabry"
|
|
||||||
license = "MIT"
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "sabry"
|
name = "sabry"
|
||||||
description = "Syntactically Awesome But RustY - crate that brings SCSS/SASS into rust"
|
description = "Syntactically Awesome But RustY - crate that brings SCSS/SASS into rust"
|
||||||
|
|
@ -73,7 +72,6 @@ const-scoping = ["sabry_procmacro?/const-compile"]
|
||||||
procmacro = ["dep:sabry_procmacro"]
|
procmacro = ["dep:sabry_procmacro"]
|
||||||
build = ["dep:sabry_build"]
|
build = ["dep:sabry_build"]
|
||||||
net-files = ["sabry_build/net-files"]
|
net-files = ["sabry_build/net-files"]
|
||||||
nightly = ["sabry_procmacro?/nightly"]
|
|
||||||
internals = []
|
internals = []
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "define-styles"
|
name = "define-styles"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
rust-version = "1.88"
|
rust-version = "1.88"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,33 @@
|
||||||
name = "leptos-axum-sabry"
|
name = "leptos-axum-sabry"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
rust-version = "1.88"
|
rust-version = "1.88"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
leptos = { version = "^0.8" }
|
leptos.version = "^0.8"
|
||||||
leptos_axum = { version = "^0.8", optional = true }
|
leptos_axum.version = "^0.8"
|
||||||
leptos_meta = { version = "^0.8" }
|
leptos_axum.optional = true
|
||||||
leptos_router = { version = "^0.8" }
|
leptos_meta.version = "^0.8"
|
||||||
axum = { version = "0.8", optional = true }
|
leptos_router.version = "^0.8"
|
||||||
|
axum.version = "0.8"
|
||||||
|
axum.optional = true
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
|
tokio.version = "1"
|
||||||
tower = { version = "0.5", optional = true }
|
tokio.features = ["rt-multi-thread"]
|
||||||
tower-http = { version = "0.6", features = ["fs"], optional = true }
|
tokio.optional = true
|
||||||
wasm-bindgen = "=0.2.96"
|
tower.version = "0.5"
|
||||||
|
tower.optional = true
|
||||||
|
tower-http.version = "0.6"
|
||||||
|
tower-http.features = ["fs"]
|
||||||
|
tower-http.optional = true
|
||||||
|
wasm-bindgen = "=0.2.114"
|
||||||
thiserror = "^1"
|
thiserror = "^1"
|
||||||
tracing = { version = "0.1", optional = true }
|
tracing.version = "0.1"
|
||||||
|
tracing.optional = true
|
||||||
http = "^1"
|
http = "^1"
|
||||||
|
|
||||||
# sabry with sass
|
# sabry with sass
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@
|
||||||
name = "leptos-components"
|
name = "leptos-components"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
rust-version = "1.88"
|
rust-version = "1.88"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
leptos = { version = "^0.7" }
|
leptos.version = "^0.8"
|
||||||
leptos_meta = { version = "^0.7" }
|
leptos_meta.version = "^0.8"
|
||||||
leptos_router = { version = "^0.7" }
|
leptos_router.version = "^0.8"
|
||||||
|
|
||||||
sabry = { path = "../../", features = ["const-scoping"] }
|
sabry = { path = "../../", features = ["const-scoping"] }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "use-styles"
|
name = "use-styles"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
rust-version = "1.88"
|
rust-version = "1.88"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,10 @@ license.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn.workspace = true
|
syn.workspace = true
|
||||||
raffia.workspace = true
|
raffia.workspace = true
|
||||||
regex.workspace = true
|
|
||||||
regex.optional = true
|
|
||||||
grass.workspace = true
|
grass.workspace = true
|
||||||
grass.optional = true
|
grass.optional = true
|
||||||
lightningcss.workspace = true
|
lightningcss.workspace = true
|
||||||
lightningcss.optional = true
|
lightningcss.optional = true
|
||||||
blake3.workspace = true
|
|
||||||
blake3.optional = true
|
|
||||||
base64.workspace = true
|
base64.workspace = true
|
||||||
base64.optional = true
|
base64.optional = true
|
||||||
|
|
||||||
|
|
@ -29,7 +25,7 @@ toml.workspace = true
|
||||||
cfg-if.workspace = true
|
cfg-if.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
scope = ["dep:blake3", "dep:base64", "dep:regex"]
|
scope = ["dep:base64"]
|
||||||
compile = ["dep:lightningcss", "dep:grass"]
|
compile = ["dep:lightningcss", "dep:grass"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,20 @@ impl ScopeHash {
|
||||||
pub fn new(scope: &super::ArbitraryScope, config: &crate::config::SabryHashConfig) -> Self {
|
pub fn new(scope: &super::ArbitraryScope, config: &crate::config::SabryHashConfig) -> Self {
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use raffia::ast::InterpolableIdent;
|
use raffia::ast::InterpolableIdent;
|
||||||
|
use std::hash::Hasher;
|
||||||
|
|
||||||
use crate::scoper::apply_basic_rusty_member_gen_rules;
|
use crate::scoper::sanitize_css_member;
|
||||||
|
|
||||||
let mut hasher = blake3::Hasher::new();
|
let mut hasher = std::hash::DefaultHasher::new();
|
||||||
|
|
||||||
if config.use_scope_name {
|
if config.use_scope_name {
|
||||||
hasher.update(scope.name.to_string().as_bytes());
|
hasher.write(scope.name.to_string().as_bytes());
|
||||||
}
|
}
|
||||||
if config.use_code_text {
|
if config.use_code_text {
|
||||||
hasher.update(scope.adapter().source().as_bytes());
|
hasher.write(scope.adapter().source().as_bytes());
|
||||||
}
|
}
|
||||||
if config.use_code_size {
|
if config.use_code_size {
|
||||||
hasher.update(&scope.adapter().source().len().to_ne_bytes());
|
hasher.write(&scope.adapter().source().len().to_ne_bytes());
|
||||||
}
|
}
|
||||||
if config.use_item_names {
|
if config.use_item_names {
|
||||||
let classes = scope.adapter().class_selectors();
|
let classes = scope.adapter().class_selectors();
|
||||||
|
|
@ -38,22 +39,13 @@ impl ScopeHash {
|
||||||
.filter_map(|mbl| mbl.map(|l| l.raw))
|
.filter_map(|mbl| mbl.map(|l| l.raw))
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
hasher.update(merged_items.as_bytes());
|
hasher.write(merged_items.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = if config.size >= blake3::OUT_LEN {
|
let hash = hasher.finish().to_be_bytes();
|
||||||
blake3::OUT_LEN
|
|
||||||
} else {
|
|
||||||
config.size
|
|
||||||
};
|
|
||||||
|
|
||||||
let hash = hasher.finalize();
|
let hash = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(hash);
|
||||||
let hash = hash.as_bytes();
|
let hash = sanitize_css_member(&hash);
|
||||||
|
|
||||||
//? This isn't right. "size" is size of hash in symbols.
|
|
||||||
// naaah, its fine :D (Dan)
|
|
||||||
let hash = base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(&hash[..size]);
|
|
||||||
let hash = apply_basic_rusty_member_gen_rules(&hash);
|
|
||||||
|
|
||||||
Self(hash)
|
Self(hash)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ use std::fmt::Debug;
|
||||||
|
|
||||||
use hash::ScopeHash;
|
use hash::ScopeHash;
|
||||||
use raffia::{
|
use raffia::{
|
||||||
ast::{InterpolableIdent, TypeSelector},
|
|
||||||
Span, Spanned,
|
Span, Spanned,
|
||||||
|
ast::{InterpolableIdent, TypeSelector},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::syntax::{ostrta::OneSyntaxToRuleThemAll, StylesheetAdapter};
|
use crate::syntax::{StylesheetAdapter, ostrta::OneSyntaxToRuleThemAll};
|
||||||
|
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
|
|
||||||
|
|
@ -312,7 +312,7 @@ impl ScopedSelector {
|
||||||
#[cfg(feature = "scope")]
|
#[cfg(feature = "scope")]
|
||||||
pub fn gen_rusty_ident(&self) -> Option<syn::Ident> {
|
pub fn gen_rusty_ident(&self) -> Option<syn::Ident> {
|
||||||
let arb = &self.as_arbitrary().ident;
|
let arb = &self.as_arbitrary().ident;
|
||||||
let basic = apply_basic_rusty_member_gen_rules(arb);
|
let basic = sanitize_css_member(arb);
|
||||||
|
|
||||||
let ready = match self {
|
let ready = match self {
|
||||||
Self::Class(_) => Some(basic),
|
Self::Class(_) => Some(basic),
|
||||||
|
|
@ -376,34 +376,35 @@ impl ScopedSelector {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "scope")]
|
#[cfg(feature = "scope")]
|
||||||
pub fn apply_basic_rusty_member_gen_rules(source: &str) -> String {
|
pub fn sanitize_css_member(source: &str) -> String {
|
||||||
let omit_regex = regex::Regex::new(r"(^\-)|(\-$)|[^a-zA-Z0-9\-\_]")
|
let mut target = String::with_capacity(source.len());
|
||||||
.expect("BUG: can not build omition regex for rusty member generation");
|
|
||||||
|
|
||||||
// omit forbidden chars
|
|
||||||
let cleaned = omit_regex.replace_all(source, "").to_string();
|
|
||||||
|
|
||||||
// other not-so-obvious rules
|
|
||||||
let mut target = String::with_capacity(cleaned.len());
|
|
||||||
let mut next_uppercase: bool = false;
|
let mut next_uppercase: bool = false;
|
||||||
for (i, c) in cleaned.chars().enumerate() {
|
for (i, c) in source
|
||||||
|
.chars()
|
||||||
|
.filter(|c| c.is_alphanumeric() || *c == '-')
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
// first gidit is prepended with 'n'
|
// first gidit is prepended with 'n'
|
||||||
if i == 0 && c.is_numeric() {
|
if i == 0 && c.is_numeric() {
|
||||||
target.push('n');
|
target.push('n');
|
||||||
target.push(c);
|
target.push(c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// dash is omitted and next is uppercase if may be
|
|
||||||
|
// dash is omitted, replacing the next char with its uppercase
|
||||||
if c == '-' {
|
if c == '-' {
|
||||||
next_uppercase = true;
|
next_uppercase = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
target.push(if next_uppercase {
|
|
||||||
|
let char = if next_uppercase {
|
||||||
next_uppercase = false;
|
next_uppercase = false;
|
||||||
c.to_ascii_uppercase()
|
c.to_ascii_uppercase()
|
||||||
} else {
|
} else {
|
||||||
c
|
c
|
||||||
});
|
};
|
||||||
|
|
||||||
|
target.push(char);
|
||||||
}
|
}
|
||||||
target
|
target
|
||||||
}
|
}
|
||||||
|
|
@ -416,7 +417,7 @@ mod test {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::SabryHashConfig,
|
config::SabryHashConfig,
|
||||||
scoper::{hash::ScopeHash, HashedScope},
|
scoper::{HashedScope, hash::ScopeHash},
|
||||||
syntax::ostrta::OneSyntaxToRuleThemAll,
|
syntax::ostrta::OneSyntaxToRuleThemAll,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -424,20 +425,11 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn scope_hash_codegen() {
|
fn scope_hash_codegen() {
|
||||||
let code =
|
let code = ".cls1{color:red; &-dark{color: black;} #id1 {color:green;} div {color:blue;}} .cls3#id2{color: black;}";
|
||||||
".cls1{color:red; &-dark{color: black;} #id1 {color:green;} div {color:blue;}} .cls3#id2{color: black;}";
|
|
||||||
let hash = ScopeHash::test_init("F2kf8nMs".into());
|
let hash = ScopeHash::test_init("F2kf8nMs".into());
|
||||||
|
|
||||||
//cfg_if! {
|
|
||||||
//if #[cfg(feature = "lepty-scoping")]{
|
|
||||||
let expect_code = ".F2kf8nMs.cls1{color:red; &-dark{color: black;} #id1.F2kf8nMs {color:green;} div.F2kf8nMs {color:blue;}} .F2kf8nMs.cls3#id2.F2kf8nMs{color: black;}";
|
let expect_code = ".F2kf8nMs.cls1{color:red; &-dark{color: black;} #id1.F2kf8nMs {color:green;} div.F2kf8nMs {color:blue;}} .F2kf8nMs.cls3#id2.F2kf8nMs{color: black;}";
|
||||||
//} else {
|
|
||||||
// let expect_code = ".F2kf8nMs.cls1{color:red; &-dark{color: black;} #F2kf8nMs-id1 {color:green;} .F2kf8nMs div {color:blue;}} .F2kf8nMs.cls3#F2kf8nMs-id2{color: black;}";
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
// cfg_if! {
|
|
||||||
// if #[cfg(feature = "lepty-scoping")] {
|
|
||||||
let expect_selector_htmls = HashSet::from([
|
let expect_selector_htmls = HashSet::from([
|
||||||
"cls1".to_string(),
|
"cls1".to_string(),
|
||||||
"id1".to_string(),
|
"id1".to_string(),
|
||||||
|
|
@ -445,16 +437,6 @@ mod test {
|
||||||
"id2".to_string(),
|
"id2".to_string(),
|
||||||
"".to_string(), // comes from `div` which has no html hashed code, still want to check presense
|
"".to_string(), // comes from `div` which has no html hashed code, still want to check presense
|
||||||
]);
|
]);
|
||||||
// } else {
|
|
||||||
// let expect_selector_htmls = HashSet::from([
|
|
||||||
// "F2kf8nMs cls1".to_string(),
|
|
||||||
// "F2kf8nMs-id1".to_string(),
|
|
||||||
// "F2kf8nMs cls3".to_string(),
|
|
||||||
// "F2kf8nMs-id2".to_string(),
|
|
||||||
// "".to_string(), // comes from `div` which has no html hashed code, still want to check presense
|
|
||||||
// ]);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
let scope = ArbitraryScope::from_source(
|
let scope = ArbitraryScope::from_source(
|
||||||
OneSyntaxToRuleThemAll::Scss,
|
OneSyntaxToRuleThemAll::Scss,
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,8 @@ proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sabry_procmacro_impl.workspace = true
|
sabry_procmacro_impl.workspace = true
|
||||||
cfg-if.workspace = true
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
nightly = []
|
|
||||||
const-compile = ["sabry_procmacro_impl/const-compile"]
|
const-compile = ["sabry_procmacro_impl/const-compile"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![cfg_attr(feature = "nightly", feature(proc_macro_span))]
|
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use cfg_if::cfg_if;
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use sabry_procmacro_impl::impls::{
|
use sabry_procmacro_impl::impls::{
|
||||||
scssy::scssy_macro_impl, styly::styly_macro_impl, usey::usey_macro_impl,
|
scssy::scssy_macro_impl, styly::styly_macro_impl, usey::usey_macro_impl,
|
||||||
|
|
@ -38,17 +37,8 @@ use sabry_procmacro_impl::impls::{
|
||||||
///
|
///
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn scssy(input: TokenStream) -> TokenStream {
|
pub fn scssy(input: TokenStream) -> TokenStream {
|
||||||
cfg_if! {
|
let source_path =
|
||||||
if #[cfg(feature = "nightly")] {
|
PathBuf::from_str(&proc_macro::Span::call_site().file()).expect("Irrefutable result");
|
||||||
use proc_macro::Span;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
let source_path = Some(PathBuf::from_str(
|
|
||||||
&Span::call_site().file()).expect("&str to be Infallible converted into PathBuf")
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let source_path = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scssy_macro_impl(input.into(), source_path).into()
|
scssy_macro_impl(input.into(), source_path).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,18 +101,8 @@ pub fn scssy(input: TokenStream) -> TokenStream {
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn styly(input: TokenStream) -> TokenStream {
|
pub fn styly(input: TokenStream) -> TokenStream {
|
||||||
cfg_if! {
|
let source_path =
|
||||||
if #[cfg(feature = "nightly")] {
|
PathBuf::from_str(&proc_macro::Span::call_site().file()).expect("Irrefutable result");
|
||||||
use proc_macro::Span;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
let source_path = Some(PathBuf::from_str(
|
|
||||||
&Span::call_site().file()).expect("&str to be Infallible converted into PathBuf")
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let source_path = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
styly_macro_impl(input.into(), source_path).into()
|
styly_macro_impl(input.into(), source_path).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use std::{fmt::Debug, fs, path::PathBuf, str::FromStr};
|
use std::{fmt::Debug, fs, path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::{quote, ToTokens, TokenStreamExt};
|
use quote::{ToTokens, TokenStreamExt, quote};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use sabry_intrnl::syntax::ostrta::OneSyntaxToRuleThemAll;
|
use sabry_intrnl::syntax::ostrta::OneSyntaxToRuleThemAll;
|
||||||
use syn::{braced, parse::Parse, Ident, LitStr, Token};
|
use syn::{Ident, LitStr, Token, braced, parse::Parse};
|
||||||
|
|
||||||
pub mod scssy;
|
pub mod scssy;
|
||||||
pub mod styly;
|
pub mod styly;
|
||||||
|
|
@ -31,20 +31,15 @@ impl ArbitraryStyleBlock {
|
||||||
&self.code
|
&self.code
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_syn(
|
pub fn parse_syn(input: syn::parse::ParseStream, path_prefix: PathBuf) -> syn::Result<Self> {
|
||||||
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 (code, span) = if let Ok(path_tok) = input.parse::<LitStr>() {
|
||||||
let path = if let Some(prefix) = use_code_path_prefix {
|
let path = {
|
||||||
let p = path_tok.value();
|
let p = path_tok.value();
|
||||||
if let Some(pp) = p.strip_prefix("./") {
|
if let Some(pp) = p.strip_prefix("./") {
|
||||||
prefix.join(pp)
|
path_prefix.join(pp)
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from_str(&p).expect("Unable to convert path into PathBuf")
|
PathBuf::from_str(&p).unwrap() // infallible
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
PathBuf::from_str(&path_tok.value()).expect("Unable to convert path into PathBuf")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let fullpath = match path.canonicalize() {
|
let fullpath = match path.canonicalize() {
|
||||||
|
|
@ -52,8 +47,11 @@ impl ArbitraryStyleBlock {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
path_tok.span(),
|
path_tok.span(),
|
||||||
format!("Could not use path {path:?}: {:?}. If the path is relative and 'nightly' feature flag is set - this is likely false-positive", 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()
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -63,7 +61,7 @@ impl ArbitraryStyleBlock {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
path_tok.span(),
|
path_tok.span(),
|
||||||
format!("Could not read file at {fullpath:?}"),
|
format!("Could not read file at {fullpath:?}"),
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let code = String::from_utf8_lossy(&iofile).to_string();
|
let code = String::from_utf8_lossy(&iofile).to_string();
|
||||||
|
|
@ -79,7 +77,10 @@ impl ArbitraryStyleBlock {
|
||||||
let c = ident_regex.replace_all(&c, "\n").to_string();
|
let c = ident_regex.replace_all(&c, "\n").to_string();
|
||||||
(c, stream.span())
|
(c, stream.span())
|
||||||
} else {
|
} else {
|
||||||
return Err(syn::Error::new(s.span(), "Use \"\" within the braces to specify your SASS/SCSS. Unquoted style syntax is reserved for the future. Unquoted SCSS/SASS doesnt make sense though, as you won't benefit from it in rust file.\n\ntip: use `{\"style\"}` instead of `{style}`"));
|
return Err(syn::Error::new(
|
||||||
|
s.span(),
|
||||||
|
"Use \"\" within the braces to specify your SASS/SCSS. Unquoted style syntax is reserved for the future. Unquoted SCSS/SASS doesnt make sense though, as you won't benefit from it in rust file.\n\ntip: use `{\"style\"}` instead of `{style}`",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -87,12 +88,6 @@ impl 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)]
|
#[allow(clippy::to_string_trait_impl)]
|
||||||
impl ToString for ArbitraryStyleBlock {
|
impl ToString for ArbitraryStyleBlock {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
|
|
@ -148,56 +143,3 @@ impl Parse for ArbitraryStyleSyntax {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
#[test]
|
|
||||||
fn arbitrary_style_block_sass() {
|
|
||||||
use super::ArbitraryStyleBlock;
|
|
||||||
|
|
||||||
let code = "
|
|
||||||
#a
|
|
||||||
co: red
|
|
||||||
.sel
|
|
||||||
co: white
|
|
||||||
&-dark
|
|
||||||
& > div
|
|
||||||
co: blue";
|
|
||||||
let expect_code = "
|
|
||||||
#a
|
|
||||||
co: red
|
|
||||||
.sel
|
|
||||||
co: white
|
|
||||||
&-dark
|
|
||||||
& > div
|
|
||||||
co: blue";
|
|
||||||
let input = format!("{{\"{code}\"}}");
|
|
||||||
let block = syn::parse_str::<ArbitraryStyleBlock>(&input).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(expect_code, block.code);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn arbitrary_style_block_scss() {
|
|
||||||
use super::ArbitraryStyleBlock;
|
|
||||||
|
|
||||||
let code = "
|
|
||||||
#a {
|
|
||||||
c: r;
|
|
||||||
}
|
|
||||||
.b.c {
|
|
||||||
c: 'into';
|
|
||||||
}";
|
|
||||||
let expect_code = "
|
|
||||||
#a {
|
|
||||||
c: r;
|
|
||||||
}
|
|
||||||
.b.c {
|
|
||||||
c: 'into';
|
|
||||||
}";
|
|
||||||
let input = format!("{{\"{code}\"}}");
|
|
||||||
let block = syn::parse_str::<ArbitraryStyleBlock>(&input).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(expect_code, block.code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,7 @@ use std::path::PathBuf;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use sabry_intrnl::scoper::ArbitraryScope;
|
use sabry_intrnl::scoper::ArbitraryScope;
|
||||||
use syn::{
|
use syn::{Ident, parse::ParseStream};
|
||||||
parse::{Parse, ParseStream},
|
|
||||||
Ident,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
||||||
|
|
||||||
|
|
@ -16,7 +13,7 @@ use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
||||||
/// `$syntax`: sass/scss
|
/// `$syntax`: sass/scss
|
||||||
///
|
///
|
||||||
/// `$code`: intended to be valid based on $syntax
|
/// `$code`: intended to be valid based on $syntax
|
||||||
pub fn scssy_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> TokenStream {
|
pub fn scssy_macro_impl(input: TokenStream, source_path: PathBuf) -> TokenStream {
|
||||||
let MacroSyntax {
|
let MacroSyntax {
|
||||||
ident,
|
ident,
|
||||||
syntax,
|
syntax,
|
||||||
|
|
@ -36,7 +33,9 @@ pub fn scssy_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> Tok
|
||||||
}
|
}
|
||||||
|
|
||||||
let sourcesass = code.to_string();
|
let sourcesass = code.to_string();
|
||||||
let macro_doc = format!("Arbitrary {syntax:?} code declared with `scssy!`. Pretty usable in tandem with `usey!` and `buildy` at build time");
|
let macro_doc = format!(
|
||||||
|
"Arbitrary {syntax:?} code declared with `scssy!`. Pretty usable in tandem with `usey!` and `buildy` at build time"
|
||||||
|
);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #macro_doc]
|
#[doc = #macro_doc]
|
||||||
|
|
@ -55,17 +54,11 @@ pub struct MacroSyntax {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacroSyntax {
|
impl MacroSyntax {
|
||||||
pub fn parse_syn(
|
pub fn parse_syn(input: syn::parse::ParseStream, source_path: PathBuf) -> syn::Result<Self> {
|
||||||
input: syn::parse::ParseStream,
|
|
||||||
source_path: Option<PathBuf>,
|
|
||||||
) -> syn::Result<Self> {
|
|
||||||
let ident = input.parse::<Ident>()?;
|
let ident = input.parse::<Ident>()?;
|
||||||
let syntax = input.parse::<ArbitraryStyleSyntax>()?;
|
let syntax = input.parse::<ArbitraryStyleSyntax>()?;
|
||||||
|
|
||||||
let code = match source_path {
|
let code = ArbitraryStyleBlock::parse_syn(input, source_path)?;
|
||||||
Some(sp) => ArbitraryStyleBlock::parse_syn(input, Some(sp))?,
|
|
||||||
None => input.parse::<ArbitraryStyleBlock>()?,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
ident,
|
ident,
|
||||||
|
|
@ -75,11 +68,11 @@ impl MacroSyntax {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for MacroSyntax {
|
// impl Parse for MacroSyntax {
|
||||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
// fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||||
Self::parse_syn(input, None)
|
// Self::parse_syn(input, None)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {}
|
mod test {}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ use proc_macro2::{Span, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use sabry_intrnl::{
|
use sabry_intrnl::{
|
||||||
config::SabryConfig,
|
config::SabryConfig,
|
||||||
scoper::{apply_basic_rusty_member_gen_rules, ArbitraryScope, ScopedSelector},
|
scoper::{ArbitraryScope, ScopedSelector, sanitize_css_member},
|
||||||
};
|
};
|
||||||
use syn::{
|
use syn::{
|
||||||
parse::{Parse, ParseStream},
|
|
||||||
Ident, Token,
|
Ident, Token,
|
||||||
|
parse::{Parse, ParseStream},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
||||||
|
|
@ -32,7 +32,7 @@ use super::{ArbitraryStyleBlock, ArbitraryStyleSyntax};
|
||||||
///
|
///
|
||||||
/// The machine-readable output may also be forced by use `machine_readable: true` arg on `parse_macro_syntax` function
|
/// The machine-readable output may also be forced by use `machine_readable: true` arg on `parse_macro_syntax` function
|
||||||
/// without modifying tokenstream
|
/// without modifying tokenstream
|
||||||
pub fn styly_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> TokenStream {
|
pub fn styly_macro_impl(input: TokenStream, source_path: PathBuf) -> TokenStream {
|
||||||
let config = match SabryConfig::require() {
|
let config = match SabryConfig::require() {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -40,7 +40,7 @@ pub fn styly_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> Tok
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
format!("Could not read sabry configuration required by this macro: {e:?}",),
|
format!("Could not read sabry configuration required by this macro: {e:?}",),
|
||||||
)
|
)
|
||||||
.to_compile_error()
|
.to_compile_error();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let ms = match parse_macro_syntax(input, source_path) {
|
let ms = match parse_macro_syntax(input, source_path) {
|
||||||
|
|
@ -62,7 +62,7 @@ pub fn styly_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> Tok
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
format!("Could not generate scope: {e:?}"),
|
format!("Could not generate scope: {e:?}"),
|
||||||
)
|
)
|
||||||
.to_compile_error()
|
.to_compile_error();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ pub fn styly_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> Tok
|
||||||
})
|
})
|
||||||
.unique()
|
.unique()
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
let ident = apply_basic_rusty_member_gen_rules(&s);
|
let ident = sanitize_css_member(&s);
|
||||||
let fnident = syn::parse_str::<Ident>(format!("_{ident}").as_str())
|
let fnident = syn::parse_str::<Ident>(format!("_{ident}").as_str())
|
||||||
.expect("BUG: invalid ident for nesting selector formed");
|
.expect("BUG: invalid ident for nesting selector formed");
|
||||||
let formatstr = format!("{{c}}{}", &s);
|
let formatstr = format!("{{c}}{}", &s);
|
||||||
|
|
@ -223,7 +223,7 @@ pub fn styly_macro_impl(input: TokenStream, source_path: Option<PathBuf>) -> Tok
|
||||||
// reusable function, that does not return tokenstream for machine-processing at build time
|
// reusable function, that does not return tokenstream for machine-processing at build time
|
||||||
pub fn parse_macro_syntax(
|
pub fn parse_macro_syntax(
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
source_path: Option<PathBuf>,
|
source_path: PathBuf,
|
||||||
) -> Result<MacroSyntax, syn::Error> {
|
) -> Result<MacroSyntax, syn::Error> {
|
||||||
syn::parse::Parser::parse2(
|
syn::parse::Parser::parse2(
|
||||||
|input: ParseStream<'_>| MacroSyntax::parse_syn(input, source_path),
|
|input: ParseStream<'_>| MacroSyntax::parse_syn(input, source_path),
|
||||||
|
|
@ -263,18 +263,11 @@ pub struct MacroSyntax {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacroSyntax {
|
impl MacroSyntax {
|
||||||
pub fn parse_syn(
|
pub fn parse_syn(input: syn::parse::ParseStream, source_path: PathBuf) -> syn::Result<Self> {
|
||||||
input: syn::parse::ParseStream,
|
|
||||||
source_path: Option<PathBuf>,
|
|
||||||
) -> syn::Result<Self> {
|
|
||||||
let mut generator = input.parse::<ScopeGenerator>()?;
|
let mut generator = input.parse::<ScopeGenerator>()?;
|
||||||
let scope = input.parse::<Ident>()?;
|
let scope = input.parse::<Ident>()?;
|
||||||
let syntax = input.parse::<ArbitraryStyleSyntax>()?;
|
let syntax = input.parse::<ArbitraryStyleSyntax>()?;
|
||||||
let code = if source_path.is_some() {
|
let code = ArbitraryStyleBlock::parse_syn(input, source_path)?;
|
||||||
ArbitraryStyleBlock::parse_syn(input, source_path)
|
|
||||||
} else {
|
|
||||||
input.parse::<ArbitraryStyleBlock>()
|
|
||||||
}?;
|
|
||||||
|
|
||||||
if input.parse::<Token![#]>().is_ok() {
|
if input.parse::<Token![#]>().is_ok() {
|
||||||
generator = ScopeGenerator::MachineReadable
|
generator = ScopeGenerator::MachineReadable
|
||||||
|
|
@ -288,9 +281,3 @@ impl 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