diff --git a/front/src/css/rule.css b/front/src/css/rule.css index b66c470..2a2dce0 100644 --- a/front/src/css/rule.css +++ b/front/src/css/rule.css @@ -148,3 +148,45 @@ font-style: italic; font-weight: normal; } +.colorPalette { + width: 30em; + border: 2px solid #000; + text-align: left; + /* Checkerboard background */ + background-color: #ddd; + background-image: linear-gradient(45deg, #aaaaaa 25%, transparent 25%, transparent 75%, #aaaaaa 75%, #aaaaaa), linear-gradient(45deg, #aaaaaa 25%, transparent 25%, transparent 75%, #aaaaaa 75%, #aaaaaa); + background-size: 1em 1em; + background-position: 0 0, 0.5em 0.5em; +} +.colorPalette > div { + display: inline-block; + height: 2em; + position: relative; +} +.colorPalette > div div { + display: none; + position: absolute; + left: 100%; + top: 100%; + background: #FFF; + padding: 0.5em; + border: 2px solid #f1c40f; + border-radius: 0.5em; + white-space: nowrap; + z-index: 3; + font-weight: bold; +} +.colorPalette > div:hover div { + display: block; +} +.colorPalette > div:hover:after { + content: " "; + position: absolute; + background-color: inherit; + left: -0.2em; + top: -0.2em; + width: 100%; + height: 100%; + z-index: 2; + border: 0.2em solid #f1c40f; +} diff --git a/front/src/less/rule.less b/front/src/less/rule.less index ccf862a..ce68297 100644 --- a/front/src/less/rule.less +++ b/front/src/less/rule.less @@ -168,4 +168,52 @@ font-weight: normal; } } +} + +.colorPalette { + width: 30em; + border: 2px solid #000; + text-align: left; + + /* Checkerboard background */ + background-color: #ddd; + background-image: linear-gradient(45deg, #AAA 25%, transparent 25%, transparent 75%, #AAA 75%, #AAA), linear-gradient(45deg, #AAA 25%, transparent 25%, transparent 75%, #AAA 75%, #AAA); + background-size:1em 1em; + background-position:0 0, 0.5em 0.5em; + + > div { + display: inline-block; + height: 2em; + position: relative; + + div { + display: none; + position: absolute; + left: 100%; + top: 100%; + background: #FFF; + padding: 0.5em; + border: 2px solid #f1c40f; + border-radius: 0.5em; + white-space: nowrap; + z-index: 3; + font-weight: bold; + } + + &:hover div { + display: block; + } + + &:hover:after { + content: " "; + position: absolute; + background-color: inherit; + left: -0.2em; + top: -0.2em; + width: 100%; + height: 100%; + z-index: 2; + border: 0.2em solid #f1c40f; + } + } } \ No newline at end of file diff --git a/front/src/views/rule.html b/front/src/views/rule.html index ab7d250..e954f73 100644 --- a/front/src/views/rule.html +++ b/front/src/views/rule.html @@ -143,6 +143,13 @@ +
+

This is the color palette, sized by total occurrences:

+
+
{{offender.color}} ({{offender.occurrences}} times)
+
+
+ diff --git a/lib/metadata/policies.js b/lib/metadata/policies.js index ac11d83..92b99e0 100644 --- a/lib/metadata/policies.js +++ b/lib/metadata/policies.js @@ -410,6 +410,52 @@ var policies = { }; } }, + "cssColors": { + "tool": "phantomas", + "label": "Different colors", + "message": "

This is the number of different colors defined in CSS.

Your CSS project will be easier to maintain if you keep a small color set.

", + "isOkThreshold": 30, + "isBadThreshold": 150, + "isAbnormalThreshold": 300, + "hasOffenders": true, + "offendersTransformFn": function(offenders, ruleObject) { + var deduplicatedObj = {}; + + offenders.map(function(offender) { + var parts = /^([^ ]*) \((\d+) times\)$/.exec(offender); + + if (!parts) { + debug('cssColors offenders transform function error with "%s"', offender); + return; + } + + var color = parts[1]; + var count = parseInt(parts[2], 10); + + deduplicatedObj[color] = (deduplicatedObj[color] || 0) + count; + }); + + var deduplicatedTable = []; + for (var color in deduplicatedObj) { + deduplicatedTable.push({ + color: color, + occurrences: deduplicatedObj[color] + }); + } + + deduplicatedTable.sort(function(a, b) { + return b.occurrences - a.occurrences; + }); + + // Override rules.value + ruleObject.value = deduplicatedTable.length; + + return { + count: deduplicatedTable.length, + palette: deduplicatedTable + }; + } + }, "cssImports": { "tool": "phantomas", "label": "Uses of @import", diff --git a/lib/metadata/scoreProfileGeneric.json b/lib/metadata/scoreProfileGeneric.json index 8a3b2d3..044db52 100644 --- a/lib/metadata/scoreProfileGeneric.json +++ b/lib/metadata/scoreProfileGeneric.json @@ -46,7 +46,8 @@ "policies": { "cssRules": 2, "cssComplexSelectors": 2, - "cssComplexSelectorsByAttribute": 1.5 + "cssComplexSelectorsByAttribute": 1.5, + "cssColors": 0.5 } }, "badCSS": { diff --git a/lib/rulesChecker.js b/lib/rulesChecker.js index b82b7d7..bc570a7 100644 --- a/lib/rulesChecker.js +++ b/lib/rulesChecker.js @@ -65,7 +65,7 @@ var RulesChecker = function() { if (policy.offendersTransformFn) { try { - offendersObj = policy.offendersTransformFn(offenders); + offendersObj = policy.offendersTransformFn(offenders, rule); } catch(err) { debug('Error while transforming offenders for %s', metricName); debug(err); diff --git a/test/core/customPoliciesTest.js b/test/core/customPoliciesTest.js index 302b1c4..abfb601 100644 --- a/test/core/customPoliciesTest.js +++ b/test/core/customPoliciesTest.js @@ -404,20 +404,20 @@ describe('rulesChecker', function() { results.should.deep.equals({}); - // If jQueryDifferentVersions is 0 + // If jQueryVersionsLoaded is 0 results = rulesChecker.check({ "toolsResults": { "phantomas": { "metrics": { "jQueryVersion": "1.6.0", - "jQueryDifferentVersions": 0 + "jQueryVersionsLoaded": 0 } } } }, policies); results.should.not.have.a.property('jQueryVersion'); - results.should.have.a.property('jQueryDifferentVersions'); - results.jQueryDifferentVersions.should.have.a.property('score').that.equals(100); + results.should.have.a.property('jQueryVersionsLoaded'); + results.jQueryVersionsLoaded.should.have.a.property('score').that.equals(100); // If there are more than 1 jQuery version @@ -426,15 +426,15 @@ describe('rulesChecker', function() { "phantomas": { "metrics": { "jQueryVersion": "1.6.0", - "jQueryDifferentVersions": 2 + "jQueryVersionsLoaded": 2 } } } }, policies); results.should.not.have.a.property('jQueryVersion'); - results.should.have.a.property('jQueryDifferentVersions'); - results.jQueryDifferentVersions.should.have.a.property('score').that.equals(0); - results.jQueryDifferentVersions.should.have.a.property('abnormal').that.equals(true); + results.should.have.a.property('jQueryVersionsLoaded'); + results.jQueryVersionsLoaded.should.have.a.property('score').that.equals(0); + results.jQueryVersionsLoaded.should.have.a.property('abnormal').that.equals(true); });