An open API service indexing awesome lists of open source software.

https://github.com/trananhtung/specificity

Calculate the CSS specificity (a, b, c) of a selector — :is/:not/:has/:where aware. A Rust take on the specificity npm package. Zero deps, no_std.
https://github.com/trananhtung/specificity

cascade css no-std rust selector specificity

Last synced: 5 days ago
JSON representation

Calculate the CSS specificity (a, b, c) of a selector — :is/:not/:has/:where aware. A Rust take on the specificity npm package. Zero deps, no_std.

Awesome Lists containing this project

README

          

# specificity

[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)

[![Crates.io](https://img.shields.io/crates/v/specificity.svg)](https://crates.io/crates/specificity)
[![Documentation](https://docs.rs/specificity/badge.svg)](https://docs.rs/specificity)
[![CI](https://github.com/trananhtung/specificity/actions/workflows/ci.yml/badge.svg)](https://github.com/trananhtung/specificity/actions/workflows/ci.yml)
[![License](https://img.shields.io/crates/l/specificity.svg)](#license)

**Calculate the CSS specificity `(a, b, c)` of a selector** — `a` for ID selectors,
`b` for classes/attributes/pseudo-classes, `c` for type selectors/pseudo-elements.
Modern selectors are handled per the
[spec](https://www.w3.org/TR/selectors-4/#specificity-rules). The Rust counterpart of
the [`specificity`](https://www.npmjs.com/package/specificity) npm package. Zero
dependencies and `#![no_std]`.

```rust
use specificity::{specificity, Specificity};

assert_eq!(specificity("#id .cls a"), Specificity::new(1, 1, 1));
assert_eq!(specificity(":is(.a, #b)"), Specificity::new(1, 0, 0)); // max of the args
assert_eq!(specificity(":where(.a)"), Specificity::new(0, 0, 0)); // contributes nothing

// Specificity is `Ord`, so selectors compare directly.
assert!(specificity("#id") > specificity(".a.b.c"));
```

## Why specificity?

CSS linters, cascade-analysis tools, devtools, and CSS-in-JS engines all need to
know how strongly a selector matches. The rules are small but full of corners
(`:is`/`:not`/`:has` take the most specific argument, `:where` is free, `::part`
ignores its argument, namespaces and escapes don't fool the counter). Rust had this
only buried inside full CSS engines; this is the focused, dependency-free piece.

```toml
[dependencies]
specificity = "0.1"
```

## API

| Item | Purpose |
| --- | --- |
| `specificity(selector)` | The `Specificity` of a single complex selector (max of a list) |
| `specificity_list(list)` | One `Specificity` per comma-separated selector |
| `Specificity { a, b, c }` | The components; implements `Ord` (a, then b, then c) and `Display` (`"a,b,c"`) |

## Behavior

- `a` = ID selectors; `b` = classes, attribute selectors, pseudo-classes;
`c` = type selectors and pseudo-elements. The universal `*` and combinators add
nothing.
- `:is()`, `:not()`, `:has()` (and `:matches()`/`:-*-any()`) contribute the
specificity of their **most specific** argument; `:where()` contributes nothing.
- `:nth-child()`/`:nth-last-child()` are pseudo-classes; an `… of S` argument adds
the most specific selector in `S`.
- Pseudo-elements (`::before`, `::part(x)`, the legacy single-colon `:before`, …)
count as `c`, and their functional arguments are ignored.
- Namespace prefixes (`svg|a`, `*|div`) and CSS escapes (`.foo\.bar`) are parsed
correctly, and CSS `/* … */` comments are ignored.

## Differences from the npm package

Where keeganstreet `specificity` diverges from the CSS spec, this crate follows the
spec: `:matches()` / `:-*-any()` are treated as aliases of `:is()` (most specific
argument, not a plain pseudo-class), and a namespaced universal such as `*|*`
contributes nothing. CSS Modules' `:global()` / `:local()` are supported, taking
their argument's specificity.

## Contributors ✨

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome — code, docs, bug reports, ideas, reviews! See the [emoji key](https://allcontributors.org/docs/en/emoji-key) for how each contribution is recognized, and open a PR or issue to get involved.

Thanks goes to these wonderful people:



Tung Tran
Tung Tran

💻 🚧

## License

Licensed under either of [Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) at
your option.