Skip to content
This repository has been archived by the owner on Jan 27, 2019. It is now read-only.

Commit

Permalink
Merge pull request #42 from cssstats/v2
Browse files Browse the repository at this point in the history
V2
  • Loading branch information
jxnblk committed Aug 5, 2015
2 parents fef4673 + e9d8a43 commit 151a60e
Show file tree
Hide file tree
Showing 31 changed files with 4,802 additions and 57,585 deletions.
1 change: 1 addition & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@


// Personal styling preferences.
"asi" : true,
"newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
"noempty" : true, // Prohibit use of empty blocks.
"nomen" : true, // Prohibit use of initial or trailing underbars in names.
Expand Down
251 changes: 208 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
# CSS Statistics
# cssstats
Parses stylesheets and returns an object with statistics

Used in http://cssstats.com
This is the core module used in http://cssstats.com

## Installation

```sh
npm install --save cssstats
npm install cssstats
```

## Usage

### Node

```js
var fs = require('fs');
var cssstats = require('csstats');
var fs = require('fs')
var cssstats = require('csstats')

var css = fs.readFileSync('./styles.css', 'utf8');
var obj = cssstats(css);
var css = fs.readFileSync('./styles.css', 'utf8')
var stats = cssstats(css)
```

Instead of a CSS string, you can also pass the [PostCSS AST](https://github.com/postcss/postcss):
### PostCSS Plugin

```js
var fs = require('fs');
var postcss = require('postcss');
var cssstats = require('csstats');
CSS Stats can be used as a [PostCSS](https://github.com/postcss/postcss) plugin.
The stats will be added to PostCSS's messages array.

var css = fs.readFileSync('./styles.css', 'utf8');
var ast = postcss.parse(css);
var obj = cssstats(ast);
```js
var fs = require('fs')
var postcss = require('postcss')
var cssstats = require('csstats')

var css = fs.readFileSync('./styles.css', 'utf8')
postcss()
.use(cssstats())
.process(css)
.then(function (result) {
result.messages.forEach(function (message) {
console.log(message)
})
})
```

### Using the CLI
#### CLI

```sh
npm i -g cssstats
Expand All @@ -45,41 +56,195 @@ cat some-css-file.css | cssstats
getcss google.com | cssstats
```

#### Options

Options may be passed as a second argument.

```js
var stats = cssstats(css, { mediaQueries: false })
```

- `safe` (boolean, default: `true`) - enables [PostCSS safe mode](https://github.com/postcss/postcss#safe-mode) for parsing CSS with syntax errors
- `mediaQueries` (boolean, default `true`) - determines whether or not to generate stats for each media query block
- `importantDeclarations` (boolean, default `false`) - include an array of declarations with `!important`

The following options add the results of helper methods to the returned object. This is helpful when using `JSON.stringify()`.

- `specificityGraph` (boolean, deault `false`)
- `sortedSpecificityGraph` (boolean, deault `false`)
- `repeatedSelectors` (boolean, deault `false`)
- `propertyResets` (boolean, deault `false`)
- `vendorPrefixedProperties` (boolean, deault `false`)

### Returned Object

__`size`:__ The size of the file in bytes
```js
// Example
{
size: n,
gzipSize: n,
rules: {
total: n,
size: {
graph: [n],
max: n,
average: n
}
},
selectors: {
total: n,
id: n,
class: n,
type: n,
pseudoClass: n,
psuedoElement: n,
values: [str],
specificity: {
max: n
average: n
},
getSpecificityGraph(),
getRepeatedValues(),
getSortedSpecificity()
},
declarations: {
total: n,
important: n,
properties:
prop: [str]
},
getPropertyResets(),
getUniquePropertyCount(),
getPropertyValueCount(),
getVendorPrefixed(),
getAllFontSizes(),
getAllFontFamilies(),
},
mediaQueries: {
total: n,
unique: n,
values: [str],
contents: [
{
value: str,
rules: {
total: n,
size: {
graph: [n],
max: n,
average: n
}
},
selectors: {
total: n,
id: n,
class: n,
type: n,
pseudoClass: n,
pseudoElement: n,
values: [str],
specificity: {
max: n,
average: n
}
},
declarations: {
total: n,
important: n,
vendorPrefix: n,
properties: {
prop: [str]
}
}
}
]
}
}
```

#### `size` number
The size of the file in bytes

#### `gzipSize` number
The size of the stylesheet gzipped in bytes

__`gzipSize`:__ The size of the stylesheet gzipped in bytes
#### `rules` object

__`selectors`:__ An array of selectors sorted by source order with the selector string, specificity score, and parts array
- `total` number - total number of rules
- `size` object
- `size.graph` array - ruleset sizes (number of declarations per rule) in source order
- `size.max` number - maximum ruleset size
- `size.average` number - average ruleset size

__`declarations`:__ An object of declarations.
- `declarations.all`: An array of declaration objects from PostCSS.
- `declarations.byProperty`: An object with keys for each property found in the stylesheet.
- `declarations.unique`: An object with keys for each unique property/value found in the stylesheet.
- `declarations.byMedia`: An object with keys for each media query found in the stylesheet.
- `declarations.propertyResetDeclarations`: An object with keys for each property with a value of `0` found in the stylesheet. (Actually only margins and paddings are counted)
- `declarations.importantCount`: The number of declarations with values that contain `!important`
- `declarations.vendorPrefixCount`: The number of declaration properties that have vendor prefixes.
- `declarations.displayNoneCount`: The number of `display: none;` declarations.
- `declarations.uniqueDeclarationsCount`: The number of unique declarations.
#### `selectors` object

__`rules`:__ Flattened array of rules from PostCSS.
- `total` number - total number of selectors
- `type` number - total number of type selectors
- `class` number - total number of class selectors
- `id` number - total number of id selectors
- `pseudoClass` number - total number of pseudo class selectors
- `pseudoElement` number - total number of pseudo element selectors
- `values` array - array of strings for all selectors
- `specificity` object
- `specificity.max` number - maximum specificity as a base 10 number
- `specificity.average` number - average specificity as a base 10 number
- `getSpecificityGraph()` function - returns an array of numbers for each selector’s specificity as a base 10 number
- `getRepeatedValues()` function - returns an array of strings of repeated selectors
- `getSortedSpecificity()` function - returns an array of selectors with base 10 specificity score, sorted from highest to lowest

__`aggregates`:__ Aggregate data for the entire stylesheet.
- `selectors` - total number of selectors
- `declarations` - total number of declarations
- `properties` - an array of properties used in the stylesheet
- `mediaQueries` - an array of media query strings used in the stylesheet
- `idSelectors` - total number of selectors containing an id
- `classSelectors` - total number of selectors containing a class
- `pseudoElementSelectors` - total number of selectors containing an pseudo element
- `pseudoClassSelectors` - total number of selectors containing a pseudo class
- `repeatedSelectors` - array of selectors that were declared more than once
#### `declarations` object

For every unique property found in the stylesheet, `aggregates` also includes these values:
- `[property].total` - total number of [property] declarations
- `[property].unique` - number of unique [property] declarations
- `total` number - total number of declarations
- `properties` object - object with each unique property and an array of that property’s values
- `getPropertyResets()` function - returns an object with the number of times margin or padding is reset for each property
- `getUniquePropertyCount(property)` function - returns the number of unique values for the given property
- `getPropertyValueCount(property, value)` function - returns the number of times a declaration occurs for the given property and value
- `getVendorPrefixed()` function - returns an array of declarations with vendor prefixed properties
- `getAllFontSizes()` function - returns an array of font sizes from both `font-size` and `font` shorthand declarations
- `getAllFontFamilies()` function - returns an array of font families from both `font-family` and `font` shorthand declarations
- `important` array (optional) - `!important` declaration objects with `property` and `value`

#### `mediaQueries` object

- `total` number - total number of media queries
- `unique` number - total unique media queries
- `values` array - array of values for each media query
- `contents` array - array of media query blocks with full stats object for each


See the `/test/results` folder for example JSON results.

### Usage examples

```js
var cssstats = require('cssstats')
var stats = cssstats(css)
```

#### Generate a [specificity graph](http://csswizardry.com/2014/10/the-specificity-graph/)

```js
var specificityGraph = stats.selectors.getSpecificityGraph()
```

#### Sort selectors by highest specificity

```js
var sortedSelectors = stats.selectors.getSortedSpecificity()
```

#### Get total number of unique colors

```js
var uniqueColorsCount = stats.declarations.getUniquePropertyCount('color')
```

#### `display: none` count

```js
var displayNoneCount = stats.declarations.getPropertyValueCount('display', 'none')
```


MIT License

38 changes: 19 additions & 19 deletions bin/cssstats.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
#!/usr/bin/env node

var program = require('commander');
var cssstats = require('..');
var fs = require('fs');
var stdin = require('stdin');
var program = require('commander')
var cssstats = require('..')
var fs = require('fs')
var stdin = require('stdin')

var version = '1.6.0'

console.log('CSS Statistics CLI (' + version + ')');
console.log('CSS Statistics CLI (' + version + ')')

program
.version(version);
.version(version)

program
.command('file [file]')
.description('read a local css file')
.action(function(file) {
.action(function (file) {
if (!file) {
console.log('Please specify a CSS file');
return;
console.log('Please specify a CSS file')
return
}

try {
var css = fs.readFileSync(file, 'utf8');
console.log(JSON.stringify(cssstats(css), null, 2));
var css = fs.readFileSync(file, 'utf8')
console.log(JSON.stringify(cssstats(css), null, 2))
} catch (e) {
console.log('CSS Statistics encountered an error reading ' + file);
console.log(e);
console.log('CSS Statistics encountered an error reading ' + file)
console.log(e)
}
});
})

program.parse(process.argv);
program.parse(process.argv)

if (!program.args.length) {
console.log('Input some CSS\n^C to cancel\n^D when complete');
console.log('Input some CSS\n^C to cancel\n^D when complete')

stdin(function(css) {
stdin(function (css) {
if (css) {
console.log(JSON.stringify(cssstats(css), null, 2));
console.log(JSON.stringify(cssstats(css), null, 2))
}
});
})
}
Loading

0 comments on commit 151a60e

Please sign in to comment.