@projectwallace/css-code-quality 0.2.1 → 0.3.1

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.
@@ -0,0 +1,77 @@
1
+ export const guards = [
2
+
3
+ // Should not contain @import rules
4
+ result => ({
5
+ id: 'Imports',
6
+ score: result.atrules.import.total * 10,
7
+ value: result.atrules.import.total,
8
+ actuals: Object.keys(result.atrules.import.unique),
9
+ }),
10
+
11
+ // Should not contain empty rules
12
+ result => ({
13
+ id: 'EmptyRules',
14
+ score: result.rules.empty.total,
15
+ value: result.rules.empty.total,
16
+ }),
17
+
18
+ // Too many selectors appear multiple times
19
+ result => {
20
+ const outcome = {
21
+ id: 'SelectorDuplications',
22
+ score: 0,
23
+ value: 1 - result.selectors.uniquenessRatio,
24
+ }
25
+
26
+ if (result.selectors.uniquenessRatio < 0.66) {
27
+ outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)
28
+ }
29
+
30
+ return outcome
31
+ },
32
+
33
+ // Too many declarations appear multiple times
34
+ result => {
35
+ const outcome = {
36
+ id: 'DeclarationDuplications',
37
+ score: 0,
38
+ value: 1 - result.declarations.unique.ratio,
39
+ }
40
+
41
+ if (result.declarations.unique.ratio < 0.66) {
42
+ outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)
43
+ }
44
+
45
+ return outcome
46
+ },
47
+
48
+ // The total amount of CSS should not be too high
49
+ result => ({
50
+ id: 'CssSize',
51
+ score: result.stylesheet.size > 200_000 ? 5 : 0,
52
+ value: result.stylesheet.size,
53
+ }),
54
+
55
+ // Should not contain (too much) comments
56
+ // Deduct 1 point for every 250 bytes
57
+ result => {
58
+ const { comments } = result.stylesheet
59
+ return {
60
+ id: 'TooMuchComments',
61
+ score: Math.min(10, Math.floor(comments.size / 250)),
62
+ value: comments.size,
63
+ }
64
+ },
65
+
66
+ // Should not contain too much embedded content
67
+ // Deduct 1 point for every 250 bytes
68
+ result => {
69
+ const { size } = result.stylesheet.embeddedContent
70
+ return {
71
+ id: 'TooMuchEmbeddedContent',
72
+ score: Math.min(20, Math.floor(size.total / 250)),
73
+ value: size.total,
74
+ actuals: Object.keys(result.stylesheet.embeddedContent.unique),
75
+ }
76
+ },
77
+ ]
@@ -0,0 +1,194 @@
1
+ import { suite } from 'uvu'
2
+ import * as assert from 'uvu/assert'
3
+ import { calculate } from './index.js'
4
+
5
+ const Performance = suite('Performance')
6
+
7
+ Performance('does not deduct points for not having @import', () => {
8
+ const actual = calculate(`
9
+ test { color: green; }
10
+ `)
11
+ assert.is(actual.performance.score, 100)
12
+ assert.is(actual.performance.violations.length, 0)
13
+ })
14
+
15
+ Performance('deducts points for having a single @import', () => {
16
+ const actual = calculate(`
17
+ @import url('some-url');
18
+ test { color: green; }
19
+ `)
20
+ assert.is(actual.performance.score, 90)
21
+ assert.equal(actual.performance.violations, [
22
+ {
23
+ id: 'Imports',
24
+ value: 1,
25
+ score: 10,
26
+ actuals: [`url('some-url')`],
27
+ },
28
+ ])
29
+ })
30
+
31
+ Performance('deducts points for having multiple @imports', () => {
32
+ const actual = calculate(`
33
+ @import url('some-url');
34
+ @import url('another-url');
35
+ test { color: green; }
36
+ `)
37
+ assert.is(actual.performance.score, 80)
38
+ assert.equal(actual.performance.violations, [
39
+ {
40
+ id: 'Imports',
41
+ value: 2,
42
+ score: 20,
43
+ actuals: [`url('some-url')`, `url('another-url')`],
44
+ },
45
+ ])
46
+ })
47
+
48
+ Performance('does not deduct points for not having empty rules', () => {
49
+ const actual = calculate(`test { color: green; }`)
50
+ assert.is(actual.performance.score, 100)
51
+ assert.is(actual.performance.violations.length, 0)
52
+ })
53
+
54
+ Performance('deducts points for having a single empty rule', () => {
55
+ const actual = calculate(`
56
+ test-empty {}
57
+ test { color: green; }
58
+ `)
59
+ assert.is(actual.performance.score, 99)
60
+ assert.equal(actual.performance.violations, [
61
+ {
62
+ id: 'EmptyRules',
63
+ score: 1,
64
+ value: 1,
65
+ }
66
+ ])
67
+ })
68
+
69
+ Performance('deducts points for having multiple empty rules', () => {
70
+ const actual = calculate(`
71
+ test-empty1 {}
72
+ test-empty2 {}
73
+ test { color: green; }
74
+ `)
75
+ assert.is(actual.performance.score, 98)
76
+ assert.equal(actual.performance.violations, [
77
+ {
78
+ id: 'EmptyRules',
79
+ score: 2,
80
+ value: 2,
81
+ },
82
+ ])
83
+ })
84
+
85
+ Performance('does not deduct points for having unique selectors', () => {
86
+ const actual = calculate(`
87
+ test1 { color: green; }
88
+ test2 { color: red; }
89
+ `)
90
+ assert.is(actual.performance.score, 100)
91
+ })
92
+
93
+ Performance('deducts points for having low selector uniqueness', () => {
94
+ const actual = calculate(`
95
+ test1 { color: green; }
96
+ test1 { color: red; }
97
+ test2 { color: magenta; }
98
+ test2 { color: blue; }
99
+ `)
100
+ assert.is(actual.performance.score, 95)
101
+ assert.equal(actual.performance.violations, [
102
+ {
103
+ id: 'SelectorDuplications',
104
+ score: 5,
105
+ value: 2 / 4
106
+ },
107
+ ])
108
+ })
109
+
110
+ Performance('does not deduct points for having unique declarations', () => {
111
+ const actual = calculate(`
112
+ test1 { color: green; }
113
+ test2 { color: red; }
114
+ `)
115
+ assert.is(actual.performance.score, 100)
116
+ })
117
+
118
+ Performance('deducts points for having low declaration uniqueness', () => {
119
+ const actual = calculate(`
120
+ test1 { color: green; }
121
+ test2 { color: green; }
122
+ test3 { color: red; }
123
+ test4 { color: red; }
124
+ `)
125
+ assert.is(actual.performance.score, 95)
126
+ assert.equal(actual.performance.violations, [
127
+ {
128
+ id: 'DeclarationDuplications',
129
+ score: 5,
130
+ value: 2 / 4
131
+ }
132
+ ])
133
+ })
134
+
135
+ Performance('does not deduct points for small stylesheets', () => {
136
+ const actual = calculate(`
137
+ test { color: green; }
138
+ `);
139
+ assert.is(actual.performance.score, 100)
140
+ })
141
+
142
+ Performance('deducts points for large stylesheets', () => {
143
+ const fixture = new Array(10_000)
144
+ .fill('')
145
+ .map((_, index) => `selector-${index} { opacity: 0.${index}}`)
146
+ .join('')
147
+ const actual = calculate(fixture)
148
+
149
+ assert.is(actual.performance.score, 95)
150
+ })
151
+
152
+ Performance('deducts points for having comments', () => {
153
+ const fixture = new Array(100)
154
+ .fill('/* a comment to take up some space */')
155
+ .map((comment, index) => `${comment} selector-${index} { opacity: 0.${index} }`)
156
+ .join('')
157
+ const actual = calculate(fixture)
158
+
159
+ assert.is(actual.performance.score, 90)
160
+ assert.equal(actual.performance.violations, [
161
+ {
162
+ id: 'TooMuchComments',
163
+ score: 10,
164
+ value: 3300,
165
+ },
166
+ ])
167
+ })
168
+
169
+ Performance('deducts points for having embedded content', () => {
170
+ function generateEmbed(index) {
171
+ return `data:image/svg+xml,%3Csvg%20id%3D%22Layer_${index}%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20195.6%20107.8%22%3E%3Cpath%20fill%3D%22%23B5B5B5%22%20class%3D%22st0%22%20d%3D%22M97.8%20107.8c-2.6%200-5.1-1-7.1-2.9L2.9%2017.1C-1%2013.2-1%206.8%202.9%202.9%206.8-1%2013.2-1%2017.1%202.9l80.7%2080.7%2080.7-80.7c3.9-3.9%2010.2-3.9%2014.1%200%203.9%203.9%203.9%2010.2%200%2014.1l-87.8%2087.8c-1.9%202-4.4%203-7%203z%22%2F%3E%3C%2Fsvg%3E`
172
+ }
173
+ const fixture = new Array(100)
174
+ .fill('')
175
+ .map((_, index) => `
176
+ selector-${index} {
177
+ background: url(${generateEmbed(index)});
178
+ }
179
+ `)
180
+ .join('')
181
+ const actual = calculate(fixture)
182
+
183
+ assert.is(actual.performance.score, 80)
184
+ assert.equal(actual.performance.violations, [
185
+ {
186
+ id: 'TooMuchEmbeddedContent',
187
+ score: 20,
188
+ value: 45990,
189
+ actuals: new Array(100).fill('').map((_, index) => generateEmbed(index)),
190
+ },
191
+ ])
192
+ })
193
+
194
+ Performance.run()