diff --git a/README.md b/README.md index 59ca70d..a434c5c 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ At first, I'll show how this crate "tastes". With SABRY, its in your power to: Write arbitrary SASS/SCSS code and ship it *as a crate* however you please: with modules, with feature flags, etc. Say "bye" to manual copying, cli-tools and consts. -```rust,ignore -sassy!(tokens {@mixin colored{color: red;}}); +```rust +sabry::sassy!(tokens {"@mixin colored{color: red;}"}); ``` @@ -38,9 +38,9 @@ sassy!(tokens {@mixin colored{color: red;}}); Code your SASS in separate files to get proper syntax highlighting, or do sass-in-the-rust to keep things in one place -```rust,ignore -styly!(component {.btn {color: green;}}); -styly!(extras "src/components/extras.scss"); +```rust +sabry::styly!(component {".btn {color: green;}"}); +sabry::styly!(extras "tests/assets/mixins.scss"); ``` @@ -68,11 +68,11 @@ tgk_brandstyle = {version = "0.0.1", features = ["utils"]} `@use` your style-crates in sass code *naturally* -```rust,ignore -styly!(breadbadge { +```rust +sabry::styly!(breadbadge {" @use 'tokens'; .scope {@include tokens.badge(primary);} -}) +"}); ``` @@ -85,10 +85,11 @@ styly!(breadbadge { Keep things as private and modular as you wish +```rust +sabry::styly!(pub cats "tests/assets/mixins.scss"); +sabry::styly!(dogs {"#howl {border: none;}"}); +``` ```rust,ignore -styly!(pub cats "src/sections/cats/style.scss"); -styly!(dogs {#howl {border: none;}}) - /// something like render function {
@@ -107,9 +108,9 @@ styly!(dogs {#howl {border: none;}}) Compile all the sweet SASS/SCSS into the optimized CSS bundle, ship it in CSS shunks or even include the compiled style into the binary -```rust,ignore -styly!(cssbundle {.c1 {color: white;}}) -styly!(const binary {.c2 {color: black;}}) +```rust +sabry::styly!(cssbundle {".c1 {color: white;}"}); +sabry::styly!(const binary {".c2 {color: black;}"}); ``` @@ -127,8 +128,7 @@ Sabry will gladly: - prepare ready CSS bundle and put it wherever you wish - include CSS into the build artifact - if you really want it -Also, just about everything is pub-available in this crate - Sabry is ready for experiments. - +Also, just about everything is pub-available in this crate (with *internals* feature flag) - Sabry is ready for experiments. ## Usage @@ -153,7 +153,7 @@ And a proc-macro use sabry::sassy; sassy!(mixins "tests/assets/mixins.scss"); -sassy!(styles { +sassy!(styles {" $primary-color: black; @mixin colored($col: primary) { @if $col == primary { @@ -162,8 +162,10 @@ sassy!(styles { color: $col; } } -}); +"}); ``` +*\* Unlike most of other crates that do sass-in-the-rust, sabry currently does not allow unquoted sass/scss. You still have to write it in a string-quotes. Unquoted sass/scss is reserved for the future, where we shall introduce variable injection.* + Now you can build and see two ready for export macros: `mixins!` and `styles!`. These are usefull on their own, as invocation of `mixins!()` or `styles!()` - both shall give you the code literal. @@ -183,7 +185,7 @@ And create a style scope wherever you want: // breadbadgelist.rs use sabry::styly; -styly!(const styles { +styly!(const styles {" .badges { display: flex; &__list { @@ -193,7 +195,7 @@ styly!(const styles { #wolf { color: white; } -}); +"}); /* Now you can use all scoped selectors: */ let badges_scoped_class = styles::badges; @@ -242,9 +244,9 @@ Now lets get back to the code and use the mixin defined in another crate: // breadbadgelist.rs use sabry::styly; -styly!(styles { - // "mixins" is available beacuse we did call mixins!() macro in the example below - @use "mixins"; +styly!(styles {" + // 'mixins' is available beacuse we did call mixins!() macro in the example below + @use 'mixins'; .badges { display: flex; &__list { @@ -254,7 +256,7 @@ styly!(styles { #wolf { @include mixins.colored(white); } -}); +"}); ``` So the `mixins!` macro we just passed to the `usey!` macro inside of `buildy` function call is now accessible with simple and natural `@use "mixins"` SASS rule! @@ -291,9 +293,9 @@ sabry = {version = "0.0.1", features = ["build", "lepty-scoping"]} use leptos::prelude::*; use sabry::styly; -styly!(scope { +styly!(scope {" // assuming we have tokens!() macro generated by `sassy!`, which is handled by `buildy` - @use "tokens"; + @use 'tokens'; h1 { @include tokens.sectionhead(); img { @@ -306,7 +308,7 @@ styly!(scope { @include tokens.badge(secondary); } } -}); +"}); #[component] fn component() -> impl IntoView { @@ -441,17 +443,17 @@ Examples: ```rust use sabry::sassy; -sassy!(module1 {$primary-color: red;}); +sassy!(module1 {"$primary-color: red;"}); sassy!(module2 "tests/assets/mixins.scss"); sassy!(module3:sass "tests/assets/mixins.sass"); // works, but there are catches. -sassy!(module4:sass { +sassy!(module4:sass {" =colored($col: primary) @if $col == primary color: white @else color: red -}); +"}); ``` You may omit the syntax specifier - sabry uses SCSS as the default one. @@ -477,14 +479,14 @@ Examples ```rust use sabry::styly; -styly!(private_fox {.fur {color: red; &-dark {color: black;}}}); -styly!(pub public_fox {.fur {color: red; &-dark {color: black;}}}); -styly!(pub const pub_compiletime_fox:sass { +styly!(private_fox {".fur {color: red; &-dark {color: black;}}"}); +styly!(pub public_fox {".fur {color: red; &-dark {color: black;}}"}); +styly!(pub const pub_compiletime_fox:sass {" .fur color: red &-dark color: black -}); +"}); ``` Every of those calls will produce the styling scope as a module. Differences are explained right below. @@ -522,7 +524,7 @@ As you've seen above, scope doe not contain any style code by itself. That's the However you could still compile styles into the artifact by simply adding the `const` to the macro call: -```rust,ignore +```rust sabry::styly!(const scope "tests/assets/mixins.scss"); ``` Which results in following: @@ -613,11 +615,11 @@ As for **SASS parent selectors**: they are currently handled in different way. I walking up the syntax tree sabry just creates function member for the scope and leave the rest to grass: ```rust -sabry::styly!(scope { +sabry::styly!(scope {" .cls1 { &-dark {} } -}); +"}); ``` is something like ```rust,ignore @@ -648,10 +650,20 @@ Not any valid CSS selector is a valid rust identifier. In general this section s *(sorted by my own priority)*, "dones" are excluded -- [ ] Somehow achieve the autocompletion for scopes. The problem is explained in details [here](https://github.com/yiffyrusdev/sabry/issues/2) +- [x] Somehow achieve the autocompletion for scopes. The problem is explained in details [here](https://github.com/yiffyrusdev/sabry/issues/2) + - [ ] some weird unrelated stuff I can see in autocompletion - [ ] Crates of styled components - currently the only way to create them seems to be const styly. - [ ] CSS support - [ ] Currently the crate causes "dependency inheritance" infection. We cant get rid of it, however should be doable to at least get rid of flag inheritance +- [ ] Use sass-in-rust without quoted styles for variable injection: + ```rust, ignore + let myvar = "content"; + styly!(scope { + .c::after { + content: somehow(myvar); + } + }) + ``` - [ ] There are some strange parsing errors, seems like a bug, however very hard to reproduce. Have to investigate. Maybe do more tests. - [ ] Experience with cargo-leptos is fine, and we do use it, however its a bit "raughy". Need to do something about it. diff --git a/examples/define-styles/Cargo.lock b/examples/define-styles/Cargo.lock index ce5f0bc..5c7cbf1 100644 --- a/examples/define-styles/Cargo.lock +++ b/examples/define-styles/Cargo.lock @@ -994,7 +994,7 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "sabry" -version = "0.0.1-alpha.1" +version = "0.0.1-alpha.2" dependencies = [ "sabry_intrnl", "sabry_procmacro", @@ -1002,10 +1002,11 @@ dependencies = [ [[package]] name = "sabry_intrnl" -version = "0.0.1-alpha.1" +version = "0.0.1-alpha.2" dependencies = [ "base64", "blake3", + "cfg-if", "const_format", "grass", "lightningcss", @@ -1021,14 +1022,14 @@ dependencies = [ [[package]] name = "sabry_procmacro" -version = "0.0.1-alpha.1" +version = "0.0.1-alpha.2" dependencies = [ "sabry_procmacro_impl", ] [[package]] name = "sabry_procmacro_impl" -version = "0.0.1-alpha.1" +version = "0.0.1-alpha.2" dependencies = [ "proc-macro2", "quote", diff --git a/examples/define-styles/src/lib.rs b/examples/define-styles/src/lib.rs index d53f80c..9850a64 100644 --- a/examples/define-styles/src/lib.rs +++ b/examples/define-styles/src/lib.rs @@ -2,7 +2,7 @@ use sabry::sassy; sassy!(style "src/style.scss"); -sassy!(utils { +sassy!(utils {" @mixin flex($direction, $align, $justify, $gap: .5rem) { display: flex; list-style: none; @@ -29,9 +29,9 @@ sassy!(utils { justify-content: $justify; } } -}); +"}); -sassy!(theme { +sassy!(theme {" $thm-surface-primary: #2b2a29; $thm-surface-secondary: #6C6C6C; $thm-surface-tertiary: #4C4C4C; @@ -75,10 +75,10 @@ sassy!(theme { color: $thm-text-accent; } } -}); +"}); -sassy!(tokens { - @use "theme"; +sassy!(tokens {" + @use 'theme'; @mixin clickable($style: accent, $scale: 1.2, $clickscale: 0.9){ @if $style == accent{ @@ -103,4 +103,4 @@ sassy!(tokens { transform: scale($clickscale); } } -}); +"}); diff --git a/examples/leptos-axum/src/routes/home.rs b/examples/leptos-axum/src/routes/home.rs index b79682d..c8b8d4b 100644 --- a/examples/leptos-axum/src/routes/home.rs +++ b/examples/leptos-axum/src/routes/home.rs @@ -1,10 +1,10 @@ use leptos::prelude::*; use sabry::styly; -styly!(style { - @use "tokens"; - @use "utils"; - @use "theme"; +styly!(style {" + @use 'tokens'; + @use 'utils'; + @use 'theme'; h2 { margin-bottom: 1rem; @@ -35,7 +35,7 @@ styly!(style { text-transform: uppercase; } -}); +"}); /// Renders the home page of your application. #[component] diff --git a/examples/use-styles/build.rs b/examples/use-styles/build.rs index 88a9998..d8b254f 100644 --- a/examples/use-styles/build.rs +++ b/examples/use-styles/build.rs @@ -3,11 +3,11 @@ use sabry::{sassy, usey}; // This module will have the same name as define_styles_example::utils // and sabry is configured to merge them -sassy!(utils { +sassy!(utils {" @mixin nonclickable(){ display: none; } -}); +"}); fn main(){ /* Declare modules to use with sabry */ diff --git a/examples/use-styles/src/main.rs b/examples/use-styles/src/main.rs index 0f69f52..cb9bd46 100644 --- a/examples/use-styles/src/main.rs +++ b/examples/use-styles/src/main.rs @@ -1,7 +1,10 @@ use sabry::styly; -styly!(pub const bundlemod { - @use "tokens"; +// Sabry now (0.0.1-alpha.3) disallows unquoted styles +// you won't benefit from unqouted styles though, as you won't get syntax highlighting +// Also, unqouted styles are reserved for future +styly!(pub const bundlemod {" + @use 'tokens'; .someth { @include tokens.clickable; background-color: black; @@ -9,7 +12,9 @@ styly!(pub const bundlemod { background-color: white; } } -}); +"}); + +styly!(pub filemod:sass "src/main.sass"); fn main(){ println!("someth class codemod styles: {}", bundlemod::someth); diff --git a/sabry_intrnl/src/scoper/mod.rs b/sabry_intrnl/src/scoper/mod.rs index 659fc7f..b519cff 100644 --- a/sabry_intrnl/src/scoper/mod.rs +++ b/sabry_intrnl/src/scoper/mod.rs @@ -215,7 +215,7 @@ impl HashedSelector { /// /// Not every hashed selector is presentable for HTML-ish use: like `div`, in that case /// returns [None] - pub fn make_hashed_html(value: &ScopedSelector, hash: &ScopeHash) -> Option { + pub fn make_hashed_html(value: &ScopedSelector, _hash: &ScopeHash) -> Option { match value { // Class scoping is done with class composition ScopedSelector::Class(a) => { @@ -223,7 +223,7 @@ impl HashedSelector { if #[cfg(feature = "lepty-scoping")] { Some(a.ident.to_string()) } else { - Some(format!("{} {}", hash.as_str(), a.ident)) + Some(format!("{} {}", _hash.as_str(), a.ident)) } } } @@ -234,7 +234,7 @@ impl HashedSelector { if #[cfg(feature = "lepty-scoping")] { Some(a.ident.to_string()) } else { - Some(format!("{}-{}", hash.as_str(), a.ident)) + Some(format!("{}-{}", _hash.as_str(), a.ident)) } } } diff --git a/sabry_procmacro_impl/src/impls/mod.rs b/sabry_procmacro_impl/src/impls/mod.rs index f86a7ae..faa10df 100644 --- a/sabry_procmacro_impl/src/impls/mod.rs +++ b/sabry_procmacro_impl/src/impls/mod.rs @@ -2,8 +2,9 @@ use std::{fmt::Debug, fs, path::PathBuf, str::FromStr}; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; +use regex::Regex; use sabry_intrnl::compiler::CompilerSyntax; -use syn::{braced, parse::Parse, spanned::Spanned, Ident, LitStr, Token}; +use syn::{braced, parse::Parse, Ident, LitStr, Token}; pub mod sassy; pub mod styly; @@ -68,21 +69,17 @@ impl Parse for ArbitraryStyleBlock { (code, path_tok.span()) } else { - // Does not work on stable! - // We're on nightly though - // So what? - // Then is works. - let _s; - braced!(_s in input); - let stream = _s.parse::()?; - - let c = match stream.span().source_text() { - Some(stx) => stx, - // TODO: rust-analyzer does fall into this even if all is fine - None => "".to_string(), //return Err(syn::Error::new(stream.span(), "Source code expected")), - }; - - (c, stream.span()) + let s; + braced!(s in input); + if let Ok(stream) = s.parse::() { + let c = stream.value(); + // shift the entire code for the first line ident + let ident_regex = Regex::new(r"\n\s{4}").expect("BUG: base ident regex at sabry_procmacro_impl/src/impls/mod.rs:: impl Parse for ArbitraryStyleBlock"); + let c = ident_regex.replace_all(&c, "\n").to_string(); + (c, stream.span()) + } 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}`")); + } }; Ok(Self { code, span }) @@ -137,9 +134,9 @@ impl Parse for ArbitraryStyleSyntax { _ => Err(syn::Error::new( ident.span(), format!( - "Available syntax are `sass` (WIP) and `scss`, each of them requires feature flag. Omit to use default {:?} syntax", - Self::default() - ), + "Available syntax are `sass` and `scss`, omit to use default {:?} syntax", + Self::default() + ), )), } } @@ -176,31 +173,49 @@ mod test { fn arbitrary_style_block_sass() { use super::ArbitraryStyleBlock; - let code = "#a - co:d - .sel - di: pi - .sel,div > sel - f: \"into\""; - let braced_code = format!("{{{code}}}"); - let block = syn::parse_str::(&braced_code).unwrap(); + 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::(&input).unwrap(); - assert_eq!(code, block.code); + 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 braced_code = format!("{{{code}}}"); - let block = syn::parse_str::(&braced_code).unwrap(); + 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::(&input).unwrap(); - assert_eq!(code, block.code) + assert_eq!(expect_code, block.code) } } diff --git a/src/lib.rs b/src/lib.rs index 92fcb93..4cc9d27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ pub use sabry_build::buildmagic::buildy; #[cfg(feature = "procmacro")] pub use sabry_procmacro::*; - // reexports #[cfg_attr(docsrs, doc(cfg(all(feature = "build", feature = "internals"))))] #[cfg(all(feature = "build", feature = "internals"))]