@projectwallace/css-code-quality 0.2.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css-code-quality.cjs +1 -1
- package/dist/css-code-quality.cjs.map +1 -1
- package/dist/css-code-quality.modern.js +1 -1
- package/dist/css-code-quality.modern.js.map +1 -1
- package/dist/css-code-quality.module.js +1 -1
- package/dist/css-code-quality.module.js.map +1 -1
- package/dist/css-code-quality.umd.js +1 -1
- package/dist/css-code-quality.umd.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/package.json +13 -7
- package/src/complexity.js +126 -0
- package/src/complexity.test.js +126 -0
- package/src/core.js +47 -0
- package/src/core.test.js +11 -0
- package/src/index.js +7 -0
- package/src/index.test.js +20 -0
- package/src/maintainability.js +150 -0
- package/src/maintainability.test.js +191 -0
- package/src/performance.js +77 -0
- package/src/performance.test.js +194 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@projectwallace/css-code-quality",
|
|
3
3
|
"description": "Calculate the Code Quality score of your CSS based on a range of different quality guards",
|
|
4
|
-
"version": "0.2
|
|
4
|
+
"version": "0.3.2",
|
|
5
5
|
"repository": "git@github.com:projectwallace/css-code-quality.git",
|
|
6
6
|
"author": {
|
|
7
7
|
"email": "bart@projectwallace.com",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"maintainability"
|
|
18
18
|
],
|
|
19
19
|
"files": [
|
|
20
|
-
"dist"
|
|
20
|
+
"dist",
|
|
21
|
+
"src"
|
|
21
22
|
],
|
|
22
23
|
"type": "module",
|
|
23
24
|
"source": "src/index.js",
|
|
@@ -25,8 +26,13 @@
|
|
|
25
26
|
"module": "./dist/css-code-quality.module.js",
|
|
26
27
|
"unpkg": "./dist/css-code-quality.umd.js",
|
|
27
28
|
"exports": {
|
|
28
|
-
"
|
|
29
|
-
|
|
29
|
+
".": {
|
|
30
|
+
"import": "./dist/css-code-quality.modern.js",
|
|
31
|
+
"require": "./dist/css-code-quality.cjs"
|
|
32
|
+
},
|
|
33
|
+
"./core": {
|
|
34
|
+
"import": "./src/core.js"
|
|
35
|
+
}
|
|
30
36
|
},
|
|
31
37
|
"types": "./dist/index.d.ts",
|
|
32
38
|
"scripts": {
|
|
@@ -34,10 +40,10 @@
|
|
|
34
40
|
"build": "microbundle"
|
|
35
41
|
},
|
|
36
42
|
"dependencies": {
|
|
37
|
-
"@projectwallace/css-analyzer": "^5.
|
|
43
|
+
"@projectwallace/css-analyzer": "^5.7.1"
|
|
38
44
|
},
|
|
39
45
|
"devDependencies": {
|
|
40
|
-
"microbundle": "^0.15.
|
|
41
|
-
"uvu": "^0.5.
|
|
46
|
+
"microbundle": "^0.15.1",
|
|
47
|
+
"uvu": "^0.5.6"
|
|
42
48
|
}
|
|
43
49
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { compareSpecificity } from '@projectwallace/css-analyzer'
|
|
2
|
+
|
|
3
|
+
export const guards = [
|
|
4
|
+
|
|
5
|
+
// Complexity per Selector should not differ too much from the most common Complexity
|
|
6
|
+
result => {
|
|
7
|
+
const mode = result.selectors.complexity.mode
|
|
8
|
+
const selectorsAboveMode = result.selectors.complexity.items
|
|
9
|
+
.filter(c => c > mode)
|
|
10
|
+
.length
|
|
11
|
+
|
|
12
|
+
const outcome = {
|
|
13
|
+
id: 'MoreThanMostCommonSelectorComplexity',
|
|
14
|
+
score: 0,
|
|
15
|
+
value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,
|
|
16
|
+
actuals: result.selectors.complexity.items,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (selectorsAboveMode > result.selectors.total * 0.1) {
|
|
20
|
+
const score = Math.floor(selectorsAboveMode * 0.01)
|
|
21
|
+
outcome.score = Math.min(10, score)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return outcome
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
// Specificity per Selector should not differ too much from the most common Specificity
|
|
28
|
+
result => {
|
|
29
|
+
const mode = result.selectors.specificity.mode
|
|
30
|
+
const selectorsAboveMode = result.selectors.specificity.items
|
|
31
|
+
.filter(c => compareSpecificity(c, mode) < 0)
|
|
32
|
+
.length
|
|
33
|
+
|
|
34
|
+
const outcome = {
|
|
35
|
+
id: 'MoreThanMostCommonSelectorSpecificity',
|
|
36
|
+
score: 0,
|
|
37
|
+
value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,
|
|
38
|
+
actuals: result.selectors.specificity.items,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (selectorsAboveMode > result.selectors.total * 0.1) {
|
|
42
|
+
const score = Math.floor(selectorsAboveMode * 0.01)
|
|
43
|
+
outcome.score = Math.min(10, score)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return outcome
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// Maximum Selector Complexity should be low
|
|
50
|
+
result => {
|
|
51
|
+
const MAX_SELECTOR_COMPLEXITY = 5
|
|
52
|
+
const actual = result.selectors.complexity.max
|
|
53
|
+
|
|
54
|
+
const outcome = {
|
|
55
|
+
id: 'MaxSelectorComplexity',
|
|
56
|
+
score: 0,
|
|
57
|
+
value: result.selectors.complexity.max,
|
|
58
|
+
actuals: result.selectors.complexity.items,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Deduct 0.5 points per complexity over 5, up to 5 points
|
|
62
|
+
if (actual > MAX_SELECTOR_COMPLEXITY) {
|
|
63
|
+
const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)
|
|
64
|
+
outcome.score = Math.min(5, score)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return outcome
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// Average Selector Complexity should be low
|
|
71
|
+
result => {
|
|
72
|
+
const ALLOWED_COMPLEXITY = 2
|
|
73
|
+
const actual = result.selectors.complexity.mean
|
|
74
|
+
|
|
75
|
+
const outcome = {
|
|
76
|
+
id: 'AverageSelectorComplexity',
|
|
77
|
+
score: 0,
|
|
78
|
+
value: actual,
|
|
79
|
+
actuals: result.selectors.complexity.items,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Deduct 2 points per selector over 2
|
|
83
|
+
if (actual > ALLOWED_COMPLEXITY) {
|
|
84
|
+
const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)
|
|
85
|
+
outcome.score = Math.min(10, score)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return outcome
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
result => {
|
|
92
|
+
const ALLOWED = 0.01
|
|
93
|
+
const actual = result.selectors.id.ratio
|
|
94
|
+
const outcome = {
|
|
95
|
+
id: 'IdSelectorRatio',
|
|
96
|
+
score: 0,
|
|
97
|
+
value: actual,
|
|
98
|
+
actuals: Object.keys(result.selectors.id.unique)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (actual > ALLOWED) {
|
|
102
|
+
const score = Math.floor((actual - ALLOWED) * 10)
|
|
103
|
+
outcome.score = Math.min(score, 5)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return outcome
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
result => {
|
|
110
|
+
const ALLOWED = 0.01
|
|
111
|
+
const actual = result.declarations.importants.ratio
|
|
112
|
+
const outcome = {
|
|
113
|
+
id: 'ImportantRatio',
|
|
114
|
+
score: 0,
|
|
115
|
+
value: actual,
|
|
116
|
+
actuals: result.declarations.importants.total,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (actual > ALLOWED) {
|
|
120
|
+
const score = Math.floor((actual - ALLOWED) * 10)
|
|
121
|
+
outcome.score = Math.min(score, 5)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return outcome
|
|
125
|
+
},
|
|
126
|
+
]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as assert from 'uvu/assert'
|
|
2
|
+
import { suite } from 'uvu'
|
|
3
|
+
import { calculate } from './index.js'
|
|
4
|
+
|
|
5
|
+
const Complexity = suite('Complexity')
|
|
6
|
+
|
|
7
|
+
Complexity('should deduct points for a lot of Selectors more complex than most common Complexity', () => {
|
|
8
|
+
const fixture = `
|
|
9
|
+
${new Array(1000)
|
|
10
|
+
.fill('')
|
|
11
|
+
.map(_ => `selector { }`)
|
|
12
|
+
.join('')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
${new Array(500)
|
|
16
|
+
.fill('')
|
|
17
|
+
.map(_ => `:where(selector) { }`)
|
|
18
|
+
.join('')
|
|
19
|
+
}
|
|
20
|
+
`
|
|
21
|
+
const actual = calculate(fixture)
|
|
22
|
+
|
|
23
|
+
assert.equal(actual.complexity.violations, [
|
|
24
|
+
{
|
|
25
|
+
id: 'MoreThanMostCommonSelectorComplexity',
|
|
26
|
+
score: 5,
|
|
27
|
+
value: 1 / 3,
|
|
28
|
+
actuals: (new Array(1000).fill(1)).concat(new Array(500).fill(2)),
|
|
29
|
+
}
|
|
30
|
+
])
|
|
31
|
+
assert.is(actual.complexity.score, 95)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
Complexity('should deduct points for a lot of Selectors more complex than most common Specificity', () => {
|
|
35
|
+
const fixture = `
|
|
36
|
+
${new Array(500)
|
|
37
|
+
.fill('')
|
|
38
|
+
.map(_ => `selector1 { }`)
|
|
39
|
+
.join('')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
${new Array(200)
|
|
43
|
+
.fill('')
|
|
44
|
+
.map(_ => `.selector { }`)
|
|
45
|
+
.join('')
|
|
46
|
+
}
|
|
47
|
+
`
|
|
48
|
+
const actual = calculate(fixture)
|
|
49
|
+
|
|
50
|
+
assert.equal(actual.complexity.violations, [
|
|
51
|
+
{
|
|
52
|
+
id: 'MoreThanMostCommonSelectorSpecificity',
|
|
53
|
+
score: 2,
|
|
54
|
+
value: 200 / 700,
|
|
55
|
+
actuals: (new Array(500).fill([0, 0, 1])).concat(new Array(200).fill([0, 1, 0])),
|
|
56
|
+
}
|
|
57
|
+
])
|
|
58
|
+
assert.is(actual.complexity.score, 98)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
Complexity('deducts points for selectors with high complexity', () => {
|
|
62
|
+
const fixture = `
|
|
63
|
+
a b c d e f {}
|
|
64
|
+
`
|
|
65
|
+
const actual = calculate(fixture)
|
|
66
|
+
|
|
67
|
+
assert.equal(actual.complexity.violations, [
|
|
68
|
+
{
|
|
69
|
+
id: 'MaxSelectorComplexity',
|
|
70
|
+
score: 3,
|
|
71
|
+
value: 11,
|
|
72
|
+
actuals: [11],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: 'AverageSelectorComplexity',
|
|
76
|
+
score: 10,
|
|
77
|
+
value: 11,
|
|
78
|
+
actuals: [11],
|
|
79
|
+
}
|
|
80
|
+
])
|
|
81
|
+
assert.is(actual.complexity.score, 87)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
Complexity('deducts points for having a high ratio of ID selectors', () => {
|
|
85
|
+
const fixture = `
|
|
86
|
+
a {}
|
|
87
|
+
b {}
|
|
88
|
+
c {}
|
|
89
|
+
#a {}
|
|
90
|
+
`
|
|
91
|
+
const actual = calculate(fixture)
|
|
92
|
+
|
|
93
|
+
assert.equal(actual.complexity.violations, [
|
|
94
|
+
{
|
|
95
|
+
id: 'IdSelectorRatio',
|
|
96
|
+
score: 2,
|
|
97
|
+
value: 0.25,
|
|
98
|
+
actuals: ['#a'],
|
|
99
|
+
}
|
|
100
|
+
])
|
|
101
|
+
assert.is(actual.complexity.score, 98)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
Complexity('deducts points for having a high ratio !importants', () => {
|
|
105
|
+
const fixture = `
|
|
106
|
+
selector {
|
|
107
|
+
a: b;
|
|
108
|
+
c: d;
|
|
109
|
+
e: f;
|
|
110
|
+
g: h !important;
|
|
111
|
+
}
|
|
112
|
+
`
|
|
113
|
+
const actual = calculate(fixture)
|
|
114
|
+
|
|
115
|
+
assert.equal(actual.complexity.violations, [
|
|
116
|
+
{
|
|
117
|
+
id: 'ImportantRatio',
|
|
118
|
+
score: 2,
|
|
119
|
+
value: 0.25,
|
|
120
|
+
actuals: 1,
|
|
121
|
+
}
|
|
122
|
+
])
|
|
123
|
+
assert.is(actual.complexity.score, 98)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
Complexity.run()
|
package/src/core.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { guards as performanceGuards } from './performance.js'
|
|
2
|
+
import { guards as maintainabilityGuards } from './maintainability.js'
|
|
3
|
+
import { guards as complexityGuards } from './complexity.js'
|
|
4
|
+
|
|
5
|
+
function calculateScore({ result, guards }) {
|
|
6
|
+
let score = 100
|
|
7
|
+
let violations = []
|
|
8
|
+
let passes = []
|
|
9
|
+
|
|
10
|
+
for (const guard of guards) {
|
|
11
|
+
/** @type {{score: number, value: number, id: string}} */
|
|
12
|
+
const outcome = guard(result)
|
|
13
|
+
|
|
14
|
+
if (outcome.score > 0) {
|
|
15
|
+
score -= outcome.score
|
|
16
|
+
violations.push(outcome)
|
|
17
|
+
} else {
|
|
18
|
+
passes.push(outcome)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
score: Math.max(score, 0),
|
|
24
|
+
violations,
|
|
25
|
+
passes,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function calculate(analysis) {
|
|
30
|
+
const performance = calculateScore({ result: analysis, guards: performanceGuards })
|
|
31
|
+
const maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })
|
|
32
|
+
const complexity = calculateScore({ result: analysis, guards: complexityGuards })
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
/** @deprecated */
|
|
36
|
+
score: 0,
|
|
37
|
+
violations: performance.violations
|
|
38
|
+
.concat(maintainability.violations)
|
|
39
|
+
.concat(complexity.violations),
|
|
40
|
+
passes: performance.passes
|
|
41
|
+
.concat(maintainability.passes)
|
|
42
|
+
.concat(complexity.passes),
|
|
43
|
+
performance,
|
|
44
|
+
maintainability,
|
|
45
|
+
complexity,
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/core.test.js
ADDED
package/src/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as assert from 'uvu/assert'
|
|
2
|
+
import { suite } from 'uvu'
|
|
3
|
+
import { calculate } from './index.js'
|
|
4
|
+
import { calculate as pkgCalculate } from '../dist/css-code-quality.modern.js'
|
|
5
|
+
|
|
6
|
+
const Index = suite('Index')
|
|
7
|
+
|
|
8
|
+
Index('exposes a calculcate function', () => {
|
|
9
|
+
assert.is(typeof calculate, 'function')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
Index.run()
|
|
13
|
+
|
|
14
|
+
const Package = suite('NPM Package')
|
|
15
|
+
|
|
16
|
+
Package('exposes a calculate function', () => {
|
|
17
|
+
assert.is(typeof pkgCalculate, 'function')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
Package.run()
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
export const guards = [
|
|
2
|
+
|
|
3
|
+
// Source Lines of Code should be low'
|
|
4
|
+
result => {
|
|
5
|
+
const outcome = {
|
|
6
|
+
id: 'SourceLinesOfCode',
|
|
7
|
+
score: 0,
|
|
8
|
+
value: result.stylesheet.sourceLinesOfCode,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (result.stylesheet.sourceLinesOfCode > 10000) {
|
|
12
|
+
// deduct 1 point per 1000 lines of code over 10,000
|
|
13
|
+
const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)
|
|
14
|
+
outcome.score = Math.min(15, score)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return outcome
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
// Average count of Selectors per RuleSet should be low
|
|
21
|
+
result => {
|
|
22
|
+
const ALLOWED_SELECTORS_PER_RULESET = 2
|
|
23
|
+
const actual = result.rules.selectors.mean
|
|
24
|
+
|
|
25
|
+
const outcome = {
|
|
26
|
+
id: 'AverageSelectorsPerRule',
|
|
27
|
+
score: 0,
|
|
28
|
+
value: actual,
|
|
29
|
+
actuals: result.rules.selectors.items,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Deduct 5 points per selector over 2
|
|
33
|
+
if (actual > ALLOWED_SELECTORS_PER_RULESET) {
|
|
34
|
+
const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)
|
|
35
|
+
outcome.score = Math.min(15, score)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return outcome
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
// Average count of Declarations per RuleSet should be low
|
|
42
|
+
result => {
|
|
43
|
+
const ALLOWED_DECLARATIONS_PER_RULESET = 5
|
|
44
|
+
|
|
45
|
+
const outcome = {
|
|
46
|
+
id: 'AverageDeclarationsPerRule',
|
|
47
|
+
score: 0,
|
|
48
|
+
value: result.rules.declarations.mean,
|
|
49
|
+
actuals: result.rules.declarations.items,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Deduct 5 points per declaration over 5
|
|
53
|
+
if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {
|
|
54
|
+
const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)
|
|
55
|
+
outcome.score = Math.min(15, score)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return outcome
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// Max number of Selectors per Rule should be low
|
|
62
|
+
result => {
|
|
63
|
+
const MAX_SELECTORS_PER_RULESET = 10
|
|
64
|
+
|
|
65
|
+
const outcome = {
|
|
66
|
+
id: 'MaxSelectorsPerRule',
|
|
67
|
+
score: 0,
|
|
68
|
+
value: result.rules.selectors.max,
|
|
69
|
+
actuals: result.rules.selectors.items,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Deduct 0.5 points per selectors over 10
|
|
73
|
+
if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {
|
|
74
|
+
const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)
|
|
75
|
+
outcome.score = Math.min(score, 15)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return outcome
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
// Max number of Declarations per Rule should be low
|
|
82
|
+
result => {
|
|
83
|
+
const MAX_DECLARATIONS_PER_RULESET = 10
|
|
84
|
+
|
|
85
|
+
const outcome = {
|
|
86
|
+
id: 'MaxDeclarationsPerRule',
|
|
87
|
+
score: 0,
|
|
88
|
+
value: result.rules.declarations.max,
|
|
89
|
+
actuals: result.rules.declarations.items,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Deduct 0.5 points per declarations over 10
|
|
93
|
+
if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {
|
|
94
|
+
const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)
|
|
95
|
+
outcome.score = Math.min(15, score)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return outcome
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
// Number of Selectors per RuleSet should not differ too much from the most common amount of
|
|
102
|
+
// Selectors per RuleSet
|
|
103
|
+
result => {
|
|
104
|
+
const mode = result.rules.selectors.mode
|
|
105
|
+
const rulesHavingMoreThanMode = result.rules.selectors.items
|
|
106
|
+
.filter(item => item > mode)
|
|
107
|
+
.length
|
|
108
|
+
|
|
109
|
+
const outcome = {
|
|
110
|
+
id: 'MoreThanMostCommonSelectorsPerRule',
|
|
111
|
+
score: 0,
|
|
112
|
+
value: result.rules.selectors.mode,
|
|
113
|
+
actuals: result.rules.selectors.items,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// if more than 10% of RuleSets has more Selectors than most common:
|
|
117
|
+
if (rulesHavingMoreThanMode > result.rules.total * 0.1) {
|
|
118
|
+
// then deduct 0.01 for ever applicable RuleSet
|
|
119
|
+
const score = Math.floor(rulesHavingMoreThanMode * 0.01)
|
|
120
|
+
// with a maximum of 10 points
|
|
121
|
+
outcome.score = Math.min(15, score)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return outcome
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
// Number of Declarations per RuleSet should not differ too much from the most common amount of
|
|
128
|
+
// Declarations per RuleSet
|
|
129
|
+
result => {
|
|
130
|
+
const mode = result.rules.selectors.mode
|
|
131
|
+
const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length
|
|
132
|
+
|
|
133
|
+
const outcome = {
|
|
134
|
+
id: 'MoreThanMostCommonDeclarationsPerRule',
|
|
135
|
+
score: 0,
|
|
136
|
+
value: result.rules.declarations.mode,
|
|
137
|
+
actuals: result.rules.declarations.items,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// if more than 10% of RuleSets has more Declarations than most common:
|
|
141
|
+
if (rulesHavingMoreThanMode > result.rules.total * 0.1) {
|
|
142
|
+
// then deduct 0.01 for ever applicable RuleSet
|
|
143
|
+
const score = Math.floor(rulesHavingMoreThanMode * 0.01)
|
|
144
|
+
// with a maximum of 10 points
|
|
145
|
+
outcome.score = Math.min(15, score)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return outcome
|
|
149
|
+
},
|
|
150
|
+
]
|