refactor!: remove lepty-scoping feature and make its behaviour the default; deprecate scope members; bump MSRV; bump deps
This commit is contained in:
parent
c9ac3484d2
commit
6690ae1751
1 changed files with 284 additions and 374 deletions
178
README.md
178
README.md
|
|
@ -25,17 +25,6 @@ sabry::scssy!(tokens {"@mixin colored{color: red;}"});
|
|||
|
||||
<hr/>
|
||||
|
||||
Get the *(almost)* proper autocompletion for your scope from rust-analyzer
|
||||
|
||||
```rust
|
||||
sabry::styly!(scope {".cls1{} #id1{}"});
|
||||
/* autocompleted for you */
|
||||
scope::cls1;
|
||||
scope::theid1;
|
||||
```
|
||||
|
||||
<hr/>
|
||||
|
||||
Code your SASS in separate files to get proper syntax highlighting, or do sass-in-the-rust to keep things in one place
|
||||
|
||||
```rust
|
||||
|
|
@ -71,13 +60,23 @@ Keep things as private and modular as you wish
|
|||
|
||||
```rust
|
||||
sabry::styly!(pub cats "tests/assets/mixin-module.scss");
|
||||
sabry::styly!(dogs {"#howl {border: none;}"});
|
||||
sabry::styly!(dogs {".howl {border: none;}"});
|
||||
```
|
||||
```rust,ignore
|
||||
```html
|
||||
/// something like render function
|
||||
{
|
||||
<div class={cats::meow}>
|
||||
<ul id={dogs::thehowl}></ul>
|
||||
<div class={concatcp!("meow ", CATS)}>
|
||||
<ul class={concatcp!("howl ", DOGS)}></ul>
|
||||
</div>
|
||||
}
|
||||
```
|
||||
```html
|
||||
/// or even better with leptos
|
||||
view!{class=CATS
|
||||
<div class="meow">
|
||||
{move || view!{class=DOGS,
|
||||
<ul class="howl"></ul>
|
||||
}}
|
||||
</div>
|
||||
}
|
||||
```
|
||||
|
|
@ -122,7 +121,7 @@ The only need is the dependency
|
|||
#Cargo.toml
|
||||
|
||||
[dependencies]
|
||||
sabry = {version = "0.0.5"}
|
||||
sabry = {version = "0.0.6"}
|
||||
```
|
||||
And a proc-macro
|
||||
```rust
|
||||
|
|
@ -155,7 +154,7 @@ Depend on sabry
|
|||
# Cargo.toml
|
||||
|
||||
[dependencies]
|
||||
sabry = {version = "0.0.5"}
|
||||
sabry = {version = "0.0.6"}
|
||||
```
|
||||
And create a style scope wherever you want:
|
||||
```rust
|
||||
|
|
@ -173,18 +172,18 @@ styly!(styles {"
|
|||
color: white;
|
||||
}
|
||||
"});
|
||||
|
||||
/* Now you can use all scoped selectors: */
|
||||
let badges_scoped_class = styles::badges;
|
||||
let wolf_scoped_id = styles::thewolf;
|
||||
```
|
||||
|
||||
Every selector, if that does make sense, now available for you as a member of `styles` scope. In this example - `styles::badges`, `styles::thewolf` and `styles::_list()`. More about scoping and member names you can read [here](#styly-scopes).
|
||||
```html
|
||||
<ul class={concatcp!("badges ", STYLES)}>
|
||||
<li class={STYLES} id="wolf">
|
||||
"HOOOOWL!"
|
||||
</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
### Use styles earlier created in another crate
|
||||
|
||||
> **Tip** | If you use [leptos](https://github.com/leptos-rs/leptos) - check [this](#leptos-specials) section as well
|
||||
|
||||
The combination of previous two, with some additional work to do and some extra sugar to enjoy.
|
||||
|
||||
Sabry is needed as both dependency and build-dependency.
|
||||
|
|
@ -193,10 +192,10 @@ To be able to compile all styles sabry also needs the *build* feature flag:
|
|||
# Cargo.toml
|
||||
|
||||
[dependencies]
|
||||
sabry = {version = "0.0.5"}
|
||||
sabry = {version = "0.0.6"}
|
||||
|
||||
[build-dependencies]
|
||||
sabry = {version = "0.0.5", features = ["build"]}
|
||||
sabry = {version = "0.0.6", features = ["build"]}
|
||||
```
|
||||
> If you do use some non-default feature flags make sure to keep them in sync between sabry-dependency and sabry-build-dependency.
|
||||
|
||||
|
|
@ -318,81 +317,6 @@ So I'd say - do the const function back-propogation and let the consumer decide
|
|||
|
||||
</details>
|
||||
|
||||
### Leptos specials
|
||||
|
||||
With [leptos](https://github.com/leptos-rs/leptos) framework you can do the trick to apply some class to most of HtmlElements for the entire component/island:
|
||||
|
||||
```rust
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
fn component() -> impl IntoView {
|
||||
view! {class="cls1", /* <- here */
|
||||
<h1>"Head"</h1>
|
||||
<p>"text"</p>
|
||||
}
|
||||
}
|
||||
```
|
||||
... and have "cls1" on both `h1` and `p` auto-assigned. Isn't that cool?
|
||||
|
||||
So, if you're on leptos, and don't mind to take this approach, I'd highly recommend turning the *lepty-scoping* feature on:
|
||||
|
||||
```toml
|
||||
# Cargo.toml
|
||||
|
||||
[dependencies]
|
||||
sabry = {version = "0.0.5", features = ["lepty-scoping"]}
|
||||
|
||||
[build-dependencies]
|
||||
sabry = {version = "0.0.5", features = ["build", "lepty-scoping"]}
|
||||
```
|
||||
|
||||
```rust
|
||||
use leptos::prelude::*;
|
||||
use sabry::styly;
|
||||
|
||||
styly!(scope {"
|
||||
// assuming we have tokens!() macro generated by `scssy!`, which is handled by `buildy`
|
||||
@use 'tokens';
|
||||
h1 {
|
||||
@include tokens.sectionhead();
|
||||
img {
|
||||
@include tokens.sectionimg();
|
||||
}
|
||||
}
|
||||
.breadcumbs {
|
||||
@include tokens.badgelist();
|
||||
&__item {
|
||||
@include tokens.badge(secondary);
|
||||
}
|
||||
}
|
||||
"});
|
||||
|
||||
#[component]
|
||||
fn component() -> impl IntoView {
|
||||
view! {class=SCOPE,
|
||||
<h1>
|
||||
"Head"
|
||||
<img src="whatever"/>
|
||||
</h1>
|
||||
<ul class="breadcumbs">
|
||||
<li class="breadcumbs__item">
|
||||
"Home page"
|
||||
</li>
|
||||
</ul>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
That will perform *much* better:
|
||||
|
||||
- All scope members - like `scope::breadcumbs` - wont contain repeating scope hash, just the original class/id selector
|
||||
- So instead of scope members (which [aren't](https://github.com/yiffyrusdev/sabry/issues/2) autocompleted for sass-in-the-rust yet) you could just write bare selectors, as you do, for example, with svelte: `<li class="breadcumbs__item">`
|
||||
- You'll still have the rusty mod generated: its just the `scope::breadcumbs` is the `"breadcumbs"` without the hash
|
||||
- You will not encounter [the catch](#scoping) with nested tagname selectors
|
||||
|
||||
Also, this isn't really exclusive leptos-supporting feature. It just changes scoping behavour.
|
||||
|
||||
## Configuration
|
||||
|
||||
Sabry configuration lives in `[package.metadata.sabry]` table of the manifest file.
|
||||
|
|
@ -562,8 +486,8 @@ In general the scope does look like this:
|
|||
```rust,ignore
|
||||
const FOX: &str = "J9k_s9";
|
||||
mod fox {
|
||||
pub const fur: &str = "J9k_s9 fur";
|
||||
pub fn _dark(c: &str) -> String {format!("{c}-dark")}
|
||||
#[deprecated(since = "0.0.6", note = "will remove")]
|
||||
pub const fur: &str = "fur J9k_s9";
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -572,9 +496,6 @@ mod fox {
|
|||
Styly macro itself does not generate the scope. It is done in the `sabry_intrnl::scoper`. However, as a result, you will have the following:
|
||||
|
||||
- `const` with the UPPER_CASE name of the scope, which contains its hash
|
||||
- `mod` with exact scope name which is the scope you're going to use
|
||||
- for simple selectors, like `.fur` you will have a const members with hashed original selectors to use wherever you need a class/id/etc.
|
||||
- for parent-selectors like `&-dark` you will have a non-const function, which will create matching the selector from any other.
|
||||
|
||||
You can read more about scoping and hashing in the [scoping](#scoping) section.
|
||||
|
||||
|
|
@ -600,7 +521,6 @@ Which results in following:
|
|||
```rust,ignore
|
||||
const SCOPE: &str = /* scope hash */;
|
||||
const SCOPE_CSS: &str = /* compiled from src/assets/scope.scss */;
|
||||
mod scope {/* selector collection */}
|
||||
```
|
||||
|
||||
> **There is a catch** | with the `const` modifier macro must compile CSS at compile-time. That results in several game changers:
|
||||
|
|
@ -666,15 +586,15 @@ Exactly this kind of macros is produced by [`scssy!`](#style-definition-with-scs
|
|||
|
||||
### Scoping
|
||||
|
||||
Sabry handles scoping by restriction or mutation of existing selectors
|
||||
Sabry handles scoping by restriction of existing selectors
|
||||
with the hash. Hash is calculated for the entire scope by the [`styly!`](#scoping-with-styly) macro.
|
||||
|
||||
Currently the following types of selectors are scoped:
|
||||
|
||||
- class
|
||||
- id
|
||||
- tagname
|
||||
- SASS parent selectors (see below, there is a catch)
|
||||
- tagname (see below, there is a catch)
|
||||
|
||||
Sabry does not make difference between top-level and nested selectors,
|
||||
also selector complexity isn't taken into account: sabry simply walks through all compound selectors
|
||||
|
|
@ -683,40 +603,8 @@ and apply scoping for supported ones.
|
|||
Different selector types are scoped differently:
|
||||
|
||||
- class selectors are restricted with scope hash: `.class` -> `.HASH.class`
|
||||
- id selector are mutated with scope hash: `#id` -> `#id-HASH`
|
||||
- tagname selectors are changed into indirect descendance: `div` -> `.HASH div`
|
||||
|
||||
> **There is a catch** | currently tagname selectors are scoped with indirect descendancy
|
||||
> hash restriction. That means - if you do use tagnames in scoped stylesheets, you have to wrap your markdown
|
||||
> with `SCOPE` class generated by `styly!` macro.
|
||||
>
|
||||
> Also if there are nested tagname selectors - sabry won't take this into account and you'll
|
||||
> have to wrap them with `SCOPE` class as well
|
||||
>
|
||||
> **However** If you are able to apply some class to all html elements you have - like `view!{class=CLASS...}` with Leptos - you could use *lepty-scoping* feature flag for sabry and get rid of this catch! See more [here](#leptos-specials).
|
||||
|
||||
As for **SASS parent selectors**: they are currently handled in different way. Instead of
|
||||
walking up the syntax tree sabry just creates function member for the scope and leave the rest to grass:
|
||||
|
||||
```rust
|
||||
sabry::styly!(scope {"
|
||||
.cls1 {
|
||||
&-dark {}
|
||||
}
|
||||
"});
|
||||
```
|
||||
is something like
|
||||
```rust,ignore
|
||||
const SCOPE: &str = "Ut8CskJ";
|
||||
mod scope {
|
||||
pub const cls1: &str = "Ut8CskJ cls1";
|
||||
pub fn _dark(c: &str) -> String {format!("{c}-dark")}
|
||||
}
|
||||
```
|
||||
|
||||
So you still can get the scoped variant of `cls1-dark` class: `scope::_dark(scope::cls1)`.
|
||||
|
||||
This isn't very handy, also isn't strict enough, and is a high-priority subject to change. wip.
|
||||
- id selector are mutated with scope hash: `#id` -> `.HASH#id`
|
||||
- tagname selectors are changed into indirect descendance: `div` -> `div.HASH`
|
||||
|
||||
#### Scope member naming rules
|
||||
|
||||
|
|
@ -763,9 +651,9 @@ If you'd like to lend a paw - feel free to check the [WIP](#wip) section out, or
|
|||
|
||||
## MSRV
|
||||
|
||||
Sabry passes its own tests on 1.78 nightly/stable.
|
||||
Sabry passes its own tests on 1.88 nightly/stable.
|
||||
|
||||
Examples are on 1.82.
|
||||
Examples are on 1.88.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue