analyze-css
Advanced tools
Comparing version 0.1.0 to 0.2.0
@@ -57,3 +57,3 @@ #!/usr/bin/env node | ||
if (err) { | ||
console.error(err); | ||
console.error(err.toString()); | ||
process.exit(255); | ||
@@ -75,2 +75,1 @@ } | ||
}); | ||
@@ -85,3 +85,4 @@ /** | ||
initRules: function() { | ||
var re = /\.js$/, | ||
var debug = require('debug')('analyze-css:rules'), | ||
re = /\.js$/, | ||
rules = []; | ||
@@ -115,2 +116,4 @@ | ||
parseCss: function(css) { | ||
var debug = require('debug')('analyze-css:parser'); | ||
debug('Going to parse %s kB of CSS', (css.length / 1024).toFixed(2)); | ||
@@ -122,6 +125,8 @@ | ||
catch(ex) { | ||
debug('CSS parsing failed: %s', ex.toString()); | ||
var errMsg = 'CSS parsing failed: ' + ex.toString(); | ||
debug(errMsg); | ||
debug('Offending line: ' + css.split('\n')[ex.line-1]); | ||
return ex.toString(); | ||
return new Error(errMsg); | ||
} | ||
@@ -213,2 +218,4 @@ | ||
this.emit('report'); | ||
debug('Completed in %d ms', Date.now() - then); | ||
@@ -215,0 +222,0 @@ return true; |
@@ -6,3 +6,3 @@ /** | ||
*/ | ||
var debug = require('debug')('runner'), | ||
var debug = require('debug')('analyze-css:runner'), | ||
readFileSync = require('fs').readFileSync, | ||
@@ -19,3 +19,3 @@ resolve = require('path').resolve, | ||
function request(url, callback) { | ||
var debug = require('debug')('http'), | ||
var debug = require('debug')('analyze-css:http'), | ||
isHttps = url.indexOf('https://') === 0, | ||
@@ -35,2 +35,3 @@ client = require(isHttps ? 'https' : 'http'); | ||
debug('HTTP %d', resp.statusCode); | ||
debug('Headers: %j', resp.headers); | ||
callback(null, resp, out); | ||
@@ -68,3 +69,3 @@ }); | ||
if (err || resp.statusCode !== 200) { | ||
err = err || new Error('HTTP ' + resp.statusCode); | ||
err = new Error('HTTP request failed: ' + (err ? err.toString() : 'received HTTP ' + resp.statusCode)); | ||
@@ -71,0 +72,0 @@ debug(err); |
{ | ||
"name": "analyze-css", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"author": "Maciej Brencz <maciej.brencz@gmail.com> (https://github.com/macbre)", | ||
@@ -22,8 +22,11 @@ "description": "CSS selectors complexity and performance analyzer", | ||
"dependencies": { | ||
"css-parse": "1.5", | ||
"css-parse": "~1.6.0", | ||
"debug": "0.7.x", | ||
"fast-stats": "0.0.x", | ||
"optimist": "0.6.x", | ||
"slick": "1.0" | ||
"slick": "1.0", | ||
"specificity": "~0.1.3" | ||
}, | ||
"devDependencies": { | ||
"autoprefixer": "~0.8.20131213", | ||
"jshint": ">=2.1.11", | ||
@@ -35,3 +38,3 @@ "mocha": "~1.16.0" | ||
"scripts": { | ||
"test": "mocha -R spec", | ||
"test": "mocha -R dot", | ||
"lint": "jshint --verbose bin/ lib/ rules/ test/" | ||
@@ -38,0 +41,0 @@ }, |
@@ -6,2 +6,3 @@ analyze-css | ||
[![Build Status](https://api.travis-ci.org/macbre/analyze-css.png)](http://travis-ci.org/macbre/analyze-css) | ||
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/macbre/analyze-css/trend.png)](https://bitdeli.com/free "Bitdeli Badge") | ||
@@ -12,3 +13,3 @@ CSS selectors complexity and performance analyzer. analyze-css is built as a set of rules bound to events fired by CSS parser. Each rule can generate metrics and add "offenders" with more detailed information (see Usage section for an example). | ||
analyze-css comes as a "binary" for command-line and as CommonJS module. | ||
analyze-css comes as a "binary" for command-line and as CommonJS module. Run the following to install them globally: | ||
@@ -23,8 +24,4 @@ ``` | ||
``` | ||
npm install -g analyze-css | ||
``` | ||
You can use analyze-css "binary" to analyze local CSS files or remote CSS assets: | ||
This will install analyze-css "binary" globally. Now you can use it to analyze local CSS files or remote CSS assets: | ||
``` | ||
@@ -44,3 +41,3 @@ analyze-css --file examples/elecena.css | ||
console.error(err); | ||
console.log(results); | ||
console.log(results); // example? see below | ||
}); | ||
@@ -56,9 +53,18 @@ | ||
"metrics": { | ||
"base64Length": 9308, | ||
"comments": 1, | ||
"commentsLength": 68, | ||
"complexSelectors": 32, | ||
"duplicatedSelectors": 7, | ||
"emptyRules": 0, | ||
"oldIEFixes": 51, | ||
"importants": 3, | ||
"oldPropertyPrefixes": 65, | ||
"qualifiedSelectors": 28, | ||
"specificityIdAvg": 0.05, | ||
"specificityIdTotal": 35, | ||
"specificityClassAvg": 1.25, | ||
"specificityClassTotal": 872, | ||
"specificityTagAvg": 0.78, | ||
"specificityTagTotal": 548, | ||
"selectorsByAttribute": 93, | ||
@@ -69,2 +75,3 @@ "selectorsByClass": 568, | ||
"selectorsByTag": 519, | ||
"universalSelectors": 4, | ||
"length": 51665, | ||
@@ -85,18 +92,28 @@ "rules": 422, | ||
* comments: number of comments in CSS source | ||
* commentsLength: length of comments content in CSS source | ||
* complexSelectors: number of complex selectors (consisting of more than three expressions, e.g. ``header ul li .foo``) | ||
* emptyRules: number of rules with no properties (e.g. ``.foo { }``) | ||
* oldIEFixes: number of fixes for old versions of Internet Explorer (e.g. ``* html .foo {}`` and ``.foo { *zoom: 1 }``, [read](http://blogs.msdn.com/b/ie/archive/2005/09/02/460115.aspx) [more](http://www.impressivewebs.com/ie7-ie8-css-hacks/)) | ||
* importants: number of properties with value forced by ``!important`` | ||
* qualifiedSelectors: number of [qualified selectors](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Writing_efficient_CSS) (e.g. ``header#nav``, ``.foo#bar``, ``h1.title``) | ||
* selectorsByAttribute: number of selectors by attribute (e.g. ``.foo[value=bar]``) | ||
* selectorsByClass: number of selectors by class | ||
* selectorsById: number of selectors by ID | ||
* selectorsByPseudo: number of pseudo-selectors (e,g. ``:hover``) | ||
* selectorsByTag: number of selectors by tag name | ||
* length: length of CSS source (in bytes) | ||
* rules: number of rules (e.g. ``.foo, .bar { color: red }`` is counted as one rule) | ||
* selectors: number of selectors (e.g. ``.foo, .bar { color: red }`` is counted as two selectors - ``.foo`` and ``.bar``) | ||
* declarations: number of declarations (e.g. ``.foo, .bar { color: red }`` is counted as one declaration - ``color: red``) | ||
* **base64Length**: total length of base64-encoded data in CSS source (will warn about base64-encoded data bigger than 4 kB) | ||
* **comments**: number of comments in CSS source | ||
* **commentsLength**: length of comments content in CSS source | ||
* **complexSelectors**: number of complex selectors (consisting of more than three expressions, e.g. ``header ul li .foo``) | ||
* **duplicatedSelectors**: number of CSS selectors defined more than once in CSS source | ||
* **emptyRules**: number of rules with no properties (e.g. ``.foo { }``) | ||
* **oldIEFixes**: number of fixes for old versions of Internet Explorer (e.g. ``* html .foo {}`` and ``.foo { *zoom: 1 }``, [read](http://blogs.msdn.com/b/ie/archive/2005/09/02/460115.aspx) [more](http://www.impressivewebs.com/ie7-ie8-css-hacks/)) | ||
* **importants**: number of properties with value forced by ``!important`` | ||
* **oldPropertyPrefixes**: number of properties with no longer needed vendor prefix, powered by data provided by [autoprefixer](https://github.com/ai/autoprefixer) (e.g. ``--moz-border-radius``) | ||
* **qualifiedSelectors**: number of [qualified selectors](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Writing_efficient_CSS) (e.g. ``header#nav``, ``.foo#bar``, ``h1.title``) | ||
* **specificityIdAvg**: average [specificity](http://css-tricks.com/specifics-on-css-specificity/) for ID | ||
* **specificityIdTotal**: total [specificity](http://css-tricks.com/specifics-on-css-specificity/) for ID | ||
* **specificityClassAvg**: average [specificity](http://css-tricks.com/specifics-on-css-specificity/) for class, pseudo-class or attribute | ||
* **specificityClassTotal**: total [specificity](http://css-tricks.com/specifics-on-css-specificity/) for class, pseudo-class or attribute | ||
* **specificityTagAvg**: average [specificity](http://css-tricks.com/specifics-on-css-specificity/) for element | ||
* **specificityTagTotal**: total [specificity](http://css-tricks.com/specifics-on-css-specificity/) for element | ||
* **selectorsByAttribute**: number of selectors by attribute (e.g. ``.foo[value=bar]``) | ||
* **selectorsByClass**: number of selectors by class | ||
* **selectorsById**: number of selectors by ID | ||
* **selectorsByPseudo**: number of pseudo-selectors (e,g. ``:hover``) | ||
* **selectorsByTag**: number of selectors by tag name | ||
* **universalSelectors**: number of selectors trying to match every element (e.g. ``.foo > *``) | ||
* **length**: length of CSS source (in bytes) | ||
* **rules**: number of rules (e.g. ``.foo, .bar { color: red }`` is counted as one rule) | ||
* **selectors**: number of selectors (e.g. ``.foo, .bar { color: red }`` is counted as two selectors - ``.foo`` and ``.bar``) | ||
* **declarations**: number of declarations (e.g. ``.foo, .bar { color: red }`` is counted as one declaration - ``color: red``) | ||
@@ -109,1 +126,15 @@ ## Read more | ||
* [CSS specificity](http://css-tricks.com/specifics-on-css-specificity/) | ||
## Dev hints | ||
Running tests and linting the code: | ||
``` | ||
npm test && npm run-script lint | ||
``` | ||
Turning on debug mode (i.e. verbose logging to stderr via [debug module](https://npmjs.org/package/debug)): | ||
``` | ||
DEBUG=analyze-css* analyze-css ... | ||
``` |
@@ -5,3 +5,7 @@ function rule(analyzer) { | ||
analyzer.on('rule', function(rule) { | ||
if (rule.declarations.length === 0) { | ||
var properties = rule.declarations.filter(function(item) { | ||
return item.type === 'declaration'; | ||
}); | ||
if (properties.length === 0) { | ||
analyzer.incrMetric('emptyRules'); | ||
@@ -8,0 +12,0 @@ analyzer.addOffender('emptyRules', rule.selectors.join(', ')); |
@@ -9,2 +9,10 @@ var analyzer = require('../'), | ||
{ | ||
css: '.foo { background-image: url(data:image/gif;base64,R0lGODlhAQABAIABAAAAAP///yH5BAEAAAEALAAAAAABAAEAQAICTAEAOw%3D%3D) }', // blank 1x1 gif | ||
metrics: { | ||
base64Length: 64 | ||
} | ||
}, | ||
// comments | ||
{ | ||
css: '.foo { color: red } /* test */', | ||
@@ -32,2 +40,40 @@ metrics: { | ||
// duplicated selectors | ||
{ | ||
css: '.foo { } .bar { }', | ||
metrics: { | ||
duplicatedSelectors: 0 | ||
} | ||
}, | ||
{ | ||
css: '.foo, #bar { } .foo { }', | ||
metrics: { | ||
duplicatedSelectors: 0 | ||
} | ||
}, | ||
{ | ||
css: '.foo { } .foo { }', | ||
metrics: { | ||
duplicatedSelectors: 1 | ||
} | ||
}, | ||
{ | ||
css: '.foo { } .bar .foo { } .foo { }', | ||
metrics: { | ||
duplicatedSelectors: 1 | ||
} | ||
}, | ||
{ | ||
css: '.foo { } .foo { } .foo { }', | ||
metrics: { | ||
duplicatedSelectors: 1 | ||
} | ||
}, | ||
{ | ||
css: '.foo { } .bar { } .foo { } .bar { } #foo { } .bar { }', | ||
metrics: { | ||
duplicatedSelectors: 2 | ||
} | ||
}, | ||
// empty rules | ||
@@ -40,3 +86,16 @@ { | ||
}, | ||
{ | ||
css: '.foo { /* a comment */ }', | ||
metrics: { | ||
emptyRules: 1 | ||
} | ||
}, | ||
{ | ||
css: '.foo { color:red /* a comment */ }', | ||
metrics: { | ||
emptyRules: 0 | ||
} | ||
}, | ||
// IE fixes | ||
@@ -72,2 +131,16 @@ { | ||
// outdated vendor prefixes | ||
{ | ||
css: '.foo { -moz-border-radius: 2px }', | ||
metrics: { | ||
oldPropertyPrefixes: 1 | ||
} | ||
}, | ||
{ | ||
css: '.foo { -webkit-animation: none }', | ||
metrics: { | ||
oldPropertyPrefixes: 0 | ||
} | ||
}, | ||
// qualified selectors | ||
@@ -99,2 +172,47 @@ { | ||
// specificty | ||
{ | ||
css: '#foo {}', | ||
metrics: { | ||
specificityIdAvg: 1, | ||
specificityIdTotal: 1 | ||
} | ||
}, | ||
{ | ||
css: '.foo {}', | ||
metrics: { | ||
specificityClassAvg: 1, | ||
specificityClassTotal: 1 | ||
} | ||
}, | ||
{ | ||
css: 'a {}', | ||
metrics: { | ||
specificityTagAvg: 1, | ||
specificityTagTotal: 1 | ||
} | ||
}, | ||
{ | ||
css: '.search-result figure.image:hover > .price {}', | ||
metrics: { | ||
specificityIdAvg: 0, | ||
specificityIdTotal: 0, | ||
specificityClassAvg: 4, | ||
specificityClassTotal: 4, | ||
specificityTagAvg: 1, | ||
specificityTagTotal: 1 | ||
} | ||
}, | ||
{ | ||
css: '.search-result figure.image:hover > .price {} #slideshow > form input[type="text"] {}', | ||
metrics: { | ||
specificityIdAvg: 0.5, | ||
specificityIdTotal: 1, | ||
specificityClassAvg: 2.5, | ||
specificityClassTotal: 5, | ||
specificityTagAvg: 1.5, | ||
specificityTagTotal: 3 | ||
} | ||
}, | ||
// stats | ||
@@ -154,2 +272,58 @@ { | ||
} | ||
}, | ||
// universal selectors | ||
{ | ||
css: '* html .ui-autocomplete {}', | ||
metrics: { | ||
universalSelectors: 0 | ||
} | ||
}, | ||
{ | ||
css: 'input[type="..."] {}', | ||
metrics: { | ||
universalSelectors: 0 | ||
} | ||
}, | ||
{ | ||
css: '.foo[type="..."] {}', | ||
metrics: { | ||
universalSelectors: 0 | ||
} | ||
}, | ||
{ | ||
css: '#id[type="..."] {}', | ||
metrics: { | ||
universalSelectors: 0 | ||
} | ||
}, | ||
{ | ||
css: '[type="..."] {}', | ||
metrics: { | ||
universalSelectors: 1 | ||
} | ||
}, | ||
{ | ||
css: 'ul :hover {}', | ||
metrics: { | ||
universalSelectors: 1 | ||
} | ||
}, | ||
{ | ||
css: '.foo > * {}', | ||
metrics: { | ||
universalSelectors: 1 | ||
} | ||
}, | ||
{ | ||
css: 'table.wikitable>*>tr>th {}', | ||
metrics: { | ||
universalSelectors: 1 | ||
} | ||
}, | ||
{ | ||
css: '.foo * li {}', | ||
metrics: { | ||
universalSelectors: 1 | ||
} | ||
} | ||
@@ -166,3 +340,3 @@ ]; | ||
Object.keys(expectedMetrics).forEach(function(metric) { | ||
assert.equal(expectedMetrics[metric], actualMetrics[metric], metric + ' should equal ' + expectedMetrics[metric] + ' (was ' + actualMetrics[metric] + ')'); | ||
assert.strictEqual(expectedMetrics[metric], actualMetrics[metric], metric + ' should equal ' + expectedMetrics[metric] + ' (got ' + actualMetrics[metric] + ')'); | ||
}); | ||
@@ -169,0 +343,0 @@ |
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
127613
27
2630
133
6
3
5
1
+ Addedfast-stats@0.0.x
+ Addedspecificity@~0.1.3
+ Addedcss-parse@1.6.0(transitive)
+ Addedfast-stats@0.0.7(transitive)
+ Addedspecificity@0.1.6(transitive)
- Removedcss-parse@1.5.3(transitive)
Updatedcss-parse@~1.6.0