specificity
Advanced tools
Comparing version 0.1.6 to 0.2.0
{ | ||
"name": "specificity", | ||
"version": "0.1.6", | ||
"version": "0.2.0", | ||
"description": "Calculate the specificity of a CSS selector", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
# Specificity Calculator | ||
A JavaScript module for calculating the [specificity of CSS selectors](http://www.w3.org/TR/css3-selectors/#specificity). The module is used on the [Specificity Calculator](http://specificity.keegan.st/) website. | ||
A JavaScript module for calculating and comparing the [specificity of CSS selectors](http://www.w3.org/TR/css3-selectors/#specificity). The module is used on the [Specificity Calculator](http://specificity.keegan.st/) website. | ||
@@ -34,3 +34,4 @@ 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](http://www.w3.org/TR/css3-selectors/#negation) may only take a simple selector as an argument. Using a psuedo-element or combinator as an argument for `:not()` is invalid CSS3 so Specificity Calculator will return incorrect results. | ||
* `selector`: the input | ||
* `specificity`: the result e.g. `0,1,0,0` | ||
* `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 | ||
@@ -50,2 +51,3 @@ | ||
specificity: '0,1,1,3', | ||
specificityArray: [0, 1, 1, 3], | ||
parts: [ | ||
@@ -62,2 +64,24 @@ { selector: 'ul', type: 'c', index: 0, length: 2 }, | ||
## Comparing two selectors | ||
Specificity Calculator also exposes a `compare` function. This function accepts two CSS selectors, `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 | ||
SPECIFICITY.compare('div', '.active'); // -1 | ||
SPECIFICITY.compare('#main', 'div'); // 1 | ||
SPECIFICITY.compare('span', 'div'); // 0 | ||
``` | ||
## Ordering an array of selectors by specificity | ||
You can pass the `SPECIFICITY.compare` function to `Array.prototype.sort` to sort an array of CSS selectors by specificity. | ||
```js | ||
['#main', 'p', '.active'].sort(SPECIFICITY.compare); // ['p', '.active', '#main'] | ||
``` | ||
## Testing | ||
@@ -64,0 +88,0 @@ |
@@ -1,14 +0,7 @@ | ||
/** | ||
* Calculates the specificity of CSS selectors | ||
* http://www.w3.org/TR/css3-selectors/#specificity | ||
* | ||
* Returns an array of objects with the following properties: | ||
* - selector: the input | ||
* - specificity: e.g. 0,1,0,0 | ||
* - parts: array with details about each part of the selector that counts towards the specificity | ||
*/ | ||
var SPECIFICITY = (function() { | ||
var calculate, | ||
calculateSingle; | ||
calculateSingle, | ||
compare; | ||
// Calculate the specificity for a selector by dividing it into simple selectors and counting them | ||
calculate = function(input) { | ||
@@ -34,3 +27,12 @@ var selectors, | ||
// Calculate the specificity for a selector by dividing it into simple selectors and counting them | ||
/** | ||
* Calculates the specificity of CSS selectors | ||
* http://www.w3.org/TR/css3-selectors/#specificity | ||
* | ||
* Returns an object with the following properties: | ||
* - selector: the input | ||
* - specificity: e.g. 0,1,0,0 | ||
* - parts: array with details about each part of the selector that counts towards the specificity | ||
* - specificityArray: e.g. [0, 1, 0, 0] | ||
*/ | ||
calculateSingle = function(input) { | ||
@@ -160,2 +162,3 @@ var selector = input, | ||
specificity: '0,' + typeCount.a.toString() + ',' + typeCount.b.toString() + ',' + typeCount.c.toString(), | ||
specificityArray: [0, typeCount.a, typeCount.b, typeCount.c], | ||
parts: parts | ||
@@ -165,4 +168,39 @@ }; | ||
/** | ||
* Compares two CSS selectors for specificity | ||
* | ||
* - 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 | ||
*/ | ||
compare = function(a, b) { | ||
var aSpecificity, | ||
bSpecificity, | ||
i; | ||
if (a.indexOf(',') !== -1) { | ||
throw a + ' is not a valid CSS selector'; | ||
} | ||
if (b.indexOf(',') !== -1) { | ||
throw b + ' is not a valid CSS selector'; | ||
} | ||
aSpecificity = calculateSingle(a)['specificityArray']; | ||
bSpecificity = calculateSingle(b)['specificityArray']; | ||
for (i = 0; i < 4; i += 1) { | ||
if (aSpecificity[i] < bSpecificity[i]) { | ||
return -1; | ||
} else if (aSpecificity[i] > bSpecificity[i]) { | ||
return 1; | ||
} | ||
} | ||
return 0; | ||
}; | ||
return { | ||
calculate: calculate | ||
calculate: calculate, | ||
compare: compare | ||
}; | ||
@@ -174,2 +212,3 @@ }()); | ||
exports.calculate = SPECIFICITY.calculate; | ||
exports.compare = SPECIFICITY.compare; | ||
} |
var specificity = require('../'), | ||
assert = require('assert'), | ||
tests, | ||
testSelector; | ||
testSelector, | ||
comparisonTests, | ||
testCompare; | ||
@@ -64,8 +66,62 @@ tests = [ | ||
comparisonTests = [ | ||
{ a: 'div', b: 'span', expected: 0 }, | ||
{ a: '.active', b: ':focus', expected: 0 }, | ||
{ a: '#header', b: '#main', expected: 0 }, | ||
{ a: 'div', b: '.active', expected: -1 }, | ||
{ a: 'div', b: '#header', expected: -1 }, | ||
{ a: '.active', b: '#header', expected: -1 }, | ||
{ a: '.active', b: 'div', expected: 1 }, | ||
{ a: '#main', b: 'div', expected: 1 }, | ||
{ a: '#main', b: ':focus', expected: 1 }, | ||
{ a: 'div p', b: 'span a', expected: 0 }, | ||
{ a: '#main p .active', b: '#main span :focus', expected: 0 }, | ||
{ a: ':focus', b: 'span a', expected: 1 }, | ||
{ a: '#main', b: 'span a:hover', expected: 1 }, | ||
{ a: 'ul > li > a > span:before', b: '.active', expected: -1 }, | ||
{ a: 'a.active:hover', b: '#main', expected: -1 } | ||
]; | ||
testCompare = function(test) { | ||
it('compare("' + test.a + '", "' + test.b + '") should return ' + test.expected, function() { | ||
var result = specificity.compare(test.a, test.b); | ||
assert.equal(result, test.expected); | ||
}); | ||
}; | ||
describe('specificity', function() { | ||
var i, len, test; | ||
for (i = 0, len = tests.length; i < len; i += 1) { | ||
test = tests[i]; | ||
testSelector(test); | ||
} | ||
describe('calculate', function() { | ||
var i, len, test; | ||
for (i = 0, len = tests.length; i < len; i += 1) { | ||
test = tests[i]; | ||
testSelector(test); | ||
} | ||
}); | ||
describe('compare', function() { | ||
var i, len, test; | ||
for (i = 0, len = comparisonTests.length; i < len; i += 1) { | ||
test = comparisonTests[i]; | ||
testCompare(test); | ||
} | ||
}); | ||
describe('sorting with compare', function() { | ||
var a = 'div', | ||
b = 'p a', | ||
c = '.active', | ||
d = 'p.active', | ||
e = '.active:focus', | ||
f = '#main', | ||
original = [c, f, a, e, b, d], | ||
sorted = [a, b, c, d, e, f]; | ||
it('array.sort(specificity.compare) should sort the array by specificity', function() { | ||
var result = original.sort(specificity.compare); | ||
assert.equal(result.join('|'), sorted.join('|')); | ||
}); | ||
}); | ||
}); |
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
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
15515
293
89