specificity
Advanced tools
Comparing version 0.4.1 to 1.0.0-beta
{ | ||
"name": "specificity", | ||
"version": "0.4.1", | ||
"version": "1.0.0-beta", | ||
"description": "Calculate the specificity of a CSS selector", | ||
@@ -22,17 +22,36 @@ "keywords": [ | ||
}, | ||
"main": "dist/specificity", | ||
"module": "dist/specificity.mjs", | ||
"bin": { | ||
"specificity": "./bin/specificity" | ||
"type": "module", | ||
"module": "./dist/esm/index.js", | ||
"main": "./dist/cjs/index.js", | ||
"types": "./dist/types/index.d.ts", | ||
"exports": { | ||
".": { | ||
"types": "./dist/types/index.d.ts", | ||
"import": "./dist/esm/index.js", | ||
"require": "./dist/cjs/index.js" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"scripts": { | ||
"prepare": "rollup --config", | ||
"test": "mocha test/test.js --require esm" | ||
"prebuild": "rm -rf ./dist", | ||
"build": "tsc -b ./tsconfig.json ./tsconfig.cjs.json && cp package-cjs.json dist/cjs/package.json", | ||
"test": "jest && node test/test-esm.mjs && node test/test-cjs.cjs" | ||
}, | ||
"devDependencies": { | ||
"esm": "^3.0.71", | ||
"mocha": "^5.2.0", | ||
"rollup": "^0.62.0" | ||
"@jest/globals": "^29.5.0", | ||
"@types/css-tree": "^2.3.1", | ||
"jest": "^29.5.0", | ||
"prettier": "^2.8.8", | ||
"ts-jest": "^29.1.0", | ||
"typescript": "^5.1.3" | ||
}, | ||
"types": "specificity.d.ts" | ||
"dependencies": { | ||
"css-tree": "^2.3.1" | ||
}, | ||
"files": [ | ||
"dist", | ||
"package.json", | ||
"README.md", | ||
"LICENSE" | ||
] | ||
} |
194
readme.md
# Specificity Calculator | ||
A JavaScript module for calculating and comparing the [specificity of CSS selectors](https://www.w3.org/TR/selectors-3/#specificity). The module is used on the [Specificity Calculator](https://specificity.keegan.st/) website. | ||
A JavaScript module for calculating and comparing the [specificity of CSS selectors](https://www.w3.org/TR/selectors-4/#specificity). The module is used on the [Specificity Calculator](https://specificity.keegan.st/) website. | ||
Specificity Calculator is built for CSS Selectors Level 3. Specificity Calculator isn’t a CSS validator. If you enter invalid selectors it will return incorrect results. For example, the [negation pseudo-class](https://www.w3.org/TR/selectors-3/#negation) may only take a simple selector as an argument. Using a psuedo-element or combinator as an argument for `:not()` is invalid CSS so Specificity Calculator will return incorrect results. | ||
Note that version 1 is a complete re-write with support for CSS Selectors Level 4, and has a different API than earlier versions. | ||
## Supported runtime environments | ||
## calculate(selector) | ||
The module is provided in two formats: an ECMAScript (ES) module in `dist/specificity.mjs`, and a Universal Module Definition (UMD) in `dist/specificity.js`. This enables support for the following runtime environments: | ||
### Parameters | ||
**Browser** | ||
- `selector`: `string` - should be a valid CSS selector | ||
* Directly loaded ES module | ||
* ES module in a precompiled script (using a bundler like Webpack or Rollup) | ||
* Global variable | ||
### Returns | ||
**Node.js** | ||
A `Specificity` object with a type of `Record<"A" | "B" | "C", number>`. | ||
* ES module | ||
* CommonJS module | ||
### Examples | ||
### Browser usage as a directly loaded ES module | ||
```html | ||
<script type="module"> | ||
import { calculate } from './specificity/dist/specificity.mjs'; | ||
calculate('ul#nav li.active a'); | ||
</script> | ||
``` | ||
### Browser usage as an ES module in a precompiled script | ||
Bundlers like [Webpack and Rollup](https://github.com/rollup/rollup/wiki/pkg.module) import from the `module` field in `package.json`, which is set to the ES module artefact, `dist/specificity.mjs`. | ||
```js | ||
import { calculate } from 'specificity'; | ||
calculate("#id"); | ||
{ | ||
A: 1, | ||
B: 0, | ||
C: 0 | ||
} | ||
calculate('ul#nav li.active a'); | ||
``` | ||
calculate(".classname"); | ||
{ | ||
A: 0, | ||
B: 1, | ||
C: 0 | ||
} | ||
### Browser usage as a global variable | ||
calculate("element"); | ||
{ | ||
A: 0, | ||
B: 0, | ||
C: 1 | ||
} | ||
The UMD artefact, `dist/specificity.js`, sets a global variable, `SPECIFICITY`. | ||
```html | ||
<script src="./specificity/dist/specificity.js"></script> | ||
<script> | ||
SPECIFICITY.calculate('ul#nav li.active a'); | ||
</script> | ||
``` | ||
### Node.js usage as an ES module | ||
The `main` field in `package.json` has an extensionless value, `dist/specificity`. This allows Node.js to use either the ES module, in `dist/specificity.mjs`, or the CommonJS module, in `dist/specificity.js`. | ||
When Node.js is run with the `--experimental-modules` [flag](https://nodejs.org/api/esm.html) or an [ES module loader](https://www.npmjs.com/package/esm), it will use the ES module artefact. | ||
```js | ||
import { calculate } from 'specificity'; | ||
calculate('ul#nav li.active a'); | ||
{ | ||
A: 1, | ||
B: 1, | ||
C: 3 | ||
} | ||
``` | ||
### Node.js usage as a CommonJS module | ||
## compare(a, b) | ||
Otherwise, Node.js will use the UMD artefact, which contains a CommonJS module definition. | ||
### Parameters | ||
```js | ||
const { calculate } = require('specificity'); | ||
- `a`: `Specificity` object with a type of `Record<"A" | "B" | "C", number>` | ||
- `b`: `Specificity` object with a type of `Record<"A" | "B" | "C", number>` | ||
calculate('ul#nav li.active a'); | ||
``` | ||
### Returns | ||
## Calculate function | ||
Returns a positive number if `a` has a higher specificity than `b` | ||
Returns a negative number if `a` has a lower specificity than `b` | ||
Returns `0` if `a` has the same specificity than `b` | ||
The `calculate` function returns an array containing a result object for each selector input. Each result object has the following properties: | ||
### Examples | ||
* `selector`: the input | ||
* `specificity`: the result as a string e.g. `0,1,0,0` | ||
* `specificityArray`: the result as an array of numbers e.g. `[0, 1, 0, 0]` | ||
* `parts`: array with details about each part of the selector that counts towards the specificity | ||
## Example | ||
```js | ||
calculate('ul#nav li.active a'); | ||
/* | ||
[ | ||
{ | ||
selector: 'ul#nav li.active a', | ||
specificity: '0,1,1,3', | ||
specificityArray: [0, 1, 1, 3], | ||
parts: [ | ||
{ selector: 'ul', type: 'c', index: 0, length: 2 }, | ||
{ selector: '#nav', type: 'a', index: 2, length: 4 }, | ||
{ selector: 'li', type: 'c', index: 5, length: 2 }, | ||
{ selector: '.active', type: 'b', index: 8, length: 7 }, | ||
{ selector: 'a', type: 'c', index: 13, length: 1 } | ||
] | ||
} | ||
"element", | ||
".classname", | ||
"#id", | ||
] | ||
*/ | ||
``` | ||
.map(calculate) | ||
.sort(compare); | ||
You can use comma separation to pass in multiple selectors: | ||
```js | ||
calculate('ul#nav li.active a, body.ie7 .col_3 h2 ~ h2'); | ||
/* | ||
[ | ||
{ | ||
selector: 'ul#nav li.active a', | ||
specificity: '0,1,1,3', | ||
... | ||
}, | ||
{ | ||
selector: 'body.ie7 .col_3 h2 ~ h2', | ||
specificity: '0,0,2,3', | ||
... | ||
} | ||
] | ||
*/ | ||
[ { A: 0, B: 0, C: 1 }, { A: 0, B: 1, C: 0 }, { A: 1, B: 0, C: 0 } ] | ||
``` | ||
## Comparing two selectors | ||
## compareDesc(a, b) | ||
Specificity Calculator also exports a `compare` function. This function accepts two CSS selectors or specificity arrays, `a` and `b`. | ||
* It returns `-1` if `a` has a lower specificity than `b` | ||
* It returns `1` if `a` has a higher specificity than `b` | ||
* It returns `0` if `a` has the same specificity than `b` | ||
```js | ||
compare('div', '.active'); // -1 | ||
compare('#main', 'div'); // 1 | ||
compare('span', 'div'); // 0 | ||
compare('span', [0, 0, 0, 1]); // 0 | ||
compare('#main > div', [0, 1, 0, 1]); // 0 | ||
``` | ||
## Ordering an array of selectors by specificity | ||
You can pass the `compare` function to `Array.prototype.sort` to sort an array of CSS selectors by specificity. | ||
```js | ||
import { compare } from 'specificity'; | ||
['#main', 'p', '.active'].sort(compare); // ['p', '.active', '#main'] | ||
``` | ||
## Command-line usage | ||
Run `npm install specificity` to install the module locally, or `npm install -g specificity` for global installation. Run `specificity` without arguments to learn about its usage: | ||
```bash | ||
$ specificity | ||
Usage: specificity <selector> | ||
Computes specificity of a CSS selector. | ||
``` | ||
Pass a selector as the first argument to get its specificity computed: | ||
```bash | ||
$ specificity "ul#nav li.active a" | ||
0,1,1,3 | ||
``` | ||
## Testing | ||
To install dependencies, run: `npm install` | ||
Then to test, run: `npm test` | ||
Same as `compare` but returns the opposite value, for use in sorting specificity objects with the highest specificity first. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28
Yes
34067
1
6
393
79
1
+ Addedcss-tree@^2.3.1
+ Addedcss-tree@2.3.1(transitive)
+ Addedmdn-data@2.0.30(transitive)
+ Addedsource-map-js@1.2.1(transitive)