diff --git a/docs/metrics/readme.md b/docs/metrics/readme.md
index cbe7fad..5b3671e 100644
--- a/docs/metrics/readme.md
+++ b/docs/metrics/readme.md
@@ -12,6 +12,7 @@ Parker has a suite of metrics that are useful for measuring stylesheets. What fo
4. [Total Declarations](#total-declarations)
5. [Selectors Per Rule](#selectors-per-rule)
6. [Identifiers Per Selectors](#identifiers-per-selector)
+ 7. [Declarations Per Rule](#declarations-per-rule)
3. [Specificity](#specificity)
1. [Specificity Per Selector](#specificity-per-selector)
2. [Top Selector Specificity](#top-selector-specificity)
@@ -78,7 +79,7 @@ Measures the total number of rules. Each rule defines a specific behaviour of th
- __aggregate__: sum
- __format__: number
-
+
#### Total Selectors
Measures the total number of selectors. Each selector defines a group of elements affected by the design. Stylesheets with fewer selectors are simpler.
@@ -108,6 +109,7 @@ Measures the total number of property declarations. Each property declaration de
- __aggregate__: sum
- __format__: number
+
#### Selectors Per Rule
Measures the average number of selectors in every rule. Stylesheet rules can be applied to several groups of elements using multiple selectors, separated by a comma. Fewer selectors in a rule makes its properties specific to a smaller group of elements, and also makes a rule easier to read in text editors and developer tools.
@@ -117,6 +119,7 @@ Measures the average number of selectors in every rule. Stylesheet rules can be
- __aggregate__: sum
- __format__: number
+
#### Identifiers Per Selector
Measures the average number of identifiers in every selector. Selectors can be made more specific to combinations of elements by adding more identifiers to a selector. Fewer identifiers in a given selector reduces its dependency on certain DOM structures, allowing more changes to your HTML before being forced to change your CSS. Selectors with fewer identifiers are also more readable.
@@ -126,6 +129,16 @@ Measures the average number of identifiers in every selector. Selectors can be m
- __aggregate__: mean
- __format__: number
+
+#### Declarations Per Rule
+Measures the average number of declarations in every rule. Rules with fewer property declarations are simpler, and also makes rules easier to read in text editors and developer tools.
+
+- __id__: declarations-per-rule
+- __name__: Declarations Per Rule
+- __type__: rule
+- __aggregate__: mean
+- __format__: number
+
### Specificity
A rule can be overrided by another rule with a more specific selector. Complexity is added to stylesheets when multiple levels of cascading rules are used in stylesheets, because it becomes more difficult to predict which properties apply to a given element without keeping in mind other rules.
diff --git a/metrics/All.js b/metrics/All.js
index 06a995c..8d15702 100644
--- a/metrics/All.js
+++ b/metrics/All.js
@@ -15,6 +15,7 @@ module.exports = [
// Stylesheet Element Averages
require('./SelectorsPerRule.js'),
+ require('./DeclarationsPerRule.js'),
require('./IdentifiersPerSelector.js'),
// Specificity
diff --git a/metrics/DeclarationsPerRule.js b/metrics/DeclarationsPerRule.js
new file mode 100644
index 0000000..1d26764
--- /dev/null
+++ b/metrics/DeclarationsPerRule.js
@@ -0,0 +1,16 @@
+/*! Parker v0.0.0 - MIT license */
+
+'use strict';
+
+var CssRule = require( "../lib/CssRule.js" );
+
+module.exports = {
+ id: 'declarations-per-rule',
+ name: 'Declarations Per Rule',
+ type: 'rule',
+ aggregate: 'mean',
+ format: 'number',
+ measure: function (rule) {
+ return (new CssRule(rule)).getDeclarations().length;
+ }
+};
diff --git a/test/DeclarationsPerRule.js b/test/DeclarationsPerRule.js
new file mode 100644
index 0000000..9a7d1bf
--- /dev/null
+++ b/test/DeclarationsPerRule.js
@@ -0,0 +1,52 @@
+/*! Parker v0.0.0 - MIT license */
+
+var expect = require('chai').expect,
+ Parker = require('../lib/Parker.js'),
+ metric = require('../metrics/DeclarationsPerRule.js');
+
+
+describe('The declarations-per-rule metric', function () {
+ it('should provide a string identifier for the metric', function() {
+ expect(metric.id).to.be.a('string');
+ });
+
+ it('should provide a metric type', function() {
+ expect(metric.aggregate).to.match(/sum|mean/g);
+ });
+
+ it('should return 0 for an empty string', function () {
+ expect(metric.measure('')).to.equal(0);
+ });
+
+ it('should return 1 for the selector "body {color:blue;}"', function() {
+ expect(metric.measure('body {color:blue;}')).to.equal(1);
+ });
+
+ it('should return 2 for the selector "body section {color:blue;background:yellow;}"', function() {
+ expect(metric.measure('body section {color:blue;background:yellow;}')).to.equal(2);
+ });
+
+ it('should return 2 for the selector "body section {color:blue;background:yellow;} body article h3 {text-align:center;color:red;}"', function() {
+ var parker = new Parker([metric]),
+ report = parker.run('body section {color:blue;background:yellow;} body article h3 {text-align:center;color:red;}');
+
+ expect(report).to.have.property('declarations-per-rule');
+ expect(report['declarations-per-rule']).to.equal(2);
+ });
+
+ it('should return 1.5 for the selector "body section {color:blue;background:yellow;} body article h3 {text-align:center;}"', function() {
+ var parker = new Parker([metric]),
+ report = parker.run('body section {color:blue;background:yellow;} body article h3 {text-align:center;}');
+
+ expect(report).to.have.property('declarations-per-rule');
+ expect(report['declarations-per-rule']).to.equal(1.5);
+ });
+
+ it('should return 2 for the selector "body section {-webkit-something:blue;-moz-anything:yellow;} body article h3 {text-align:center;color:red;}"', function() {
+ var parker = new Parker([metric]),
+ report = parker.run('body section {-webkit-something:blue;-moz-anything:yellow;} body article h3 {text-align:center;color:red;}');
+
+ expect(report).to.have.property('declarations-per-rule');
+ expect(report['declarations-per-rule']).to.equal(2);
+ });
+});