@projectwallace/css-analyzer 5.0.0-alpha.1 → 5.0.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.
Files changed (48) hide show
  1. package/dist/analyzer.cjs +1 -1
  2. package/dist/analyzer.cjs.map +1 -1
  3. package/dist/analyzer.modern.js +2 -0
  4. package/dist/analyzer.modern.js.map +1 -0
  5. package/dist/analyzer.module.js +1 -1
  6. package/dist/analyzer.module.js.map +1 -1
  7. package/dist/analyzer.umd.js +1 -1
  8. package/dist/analyzer.umd.js.map +1 -1
  9. package/package.json +10 -10
  10. package/dist/analyzer.js +0 -2
  11. package/dist/analyzer.js.map +0 -1
  12. package/src/aggregate-collection.js +0 -113
  13. package/src/aggregate-collection.test.js +0 -47
  14. package/src/atrules/atrules.js +0 -76
  15. package/src/atrules/atrules.test.js +0 -289
  16. package/src/context-collection.js +0 -36
  17. package/src/countable-collection.js +0 -46
  18. package/src/declarations/declarations.js +0 -46
  19. package/src/declarations/declarations.test.js +0 -113
  20. package/src/index.js +0 -259
  21. package/src/index.test.js +0 -60
  22. package/src/properties/properties.js +0 -48
  23. package/src/properties/properties.test.js +0 -138
  24. package/src/rules/rules.js +0 -57
  25. package/src/rules/rules.test.js +0 -247
  26. package/src/selectors/complexity.test.js +0 -123
  27. package/src/selectors/selectors.js +0 -122
  28. package/src/selectors/selectors.test.js +0 -189
  29. package/src/selectors/specificity.js +0 -201
  30. package/src/selectors/specificity.test.js +0 -247
  31. package/src/smoke.test.js +0 -39
  32. package/src/stylesheet/stylesheet.test.js +0 -88
  33. package/src/values/animations.js +0 -53
  34. package/src/values/animations.test.js +0 -154
  35. package/src/values/box-shadows.test.js +0 -82
  36. package/src/values/colors.js +0 -192
  37. package/src/values/colors.test.js +0 -804
  38. package/src/values/font-families.js +0 -98
  39. package/src/values/font-families.test.js +0 -119
  40. package/src/values/font-sizes.js +0 -92
  41. package/src/values/font-sizes.test.js +0 -120
  42. package/src/values/text-shadows.test.js +0 -93
  43. package/src/values/units.test.js +0 -72
  44. package/src/values/values.js +0 -30
  45. package/src/values/vendor-prefix.js +0 -45
  46. package/src/values/vendor-prefix.test.js +0 -64
  47. package/src/values/z-index.test.js +0 -54
  48. package/src/vendor-prefix.js +0 -16
@@ -1,289 +0,0 @@
1
- import { suite } from 'uvu'
2
- import * as assert from 'uvu/assert'
3
- import { analyze } from '../index.js'
4
-
5
- const AtRules = suite('at-rules')
6
-
7
- AtRules('finds @font-face', () => {
8
- const fixture = `
9
- @font-face {
10
- font-family: Arial;
11
- src: url("https://url-to-arial.woff");
12
- }
13
-
14
- @font-face {
15
- font-display: swap;
16
- font-family: Test;
17
- font-stretch: condensed;
18
- font-style: italic;
19
- font-weight: 700;
20
- font-variant: no-common-ligatures proportional-nums;
21
- font-feature-settings: "liga" 0;
22
- font-variation-settings: "xhgt" 0.7;
23
- src: local("Input Mono");
24
- unicode-range: U+0025-00FF;
25
- }
26
-
27
- @font-face {
28
- font-family: 'Input Mono';
29
- src: local('Input Mono') url("https://url-to-input-mono.woff");
30
- }
31
-
32
- @font-face {
33
- font-family: MyHelvetica;
34
- src: local("Helvetica Neue Bold"), local("HelveticaNeue-Bold"), url(MgOpenModernaBold.ttf);
35
- font-weight: bold;
36
- }
37
-
38
- /* Duplicate @font-face in Media Query */
39
- @media (min-width: 1000px) {
40
- @font-face {
41
- font-family: 'Input Mono';
42
- src: local('Input Mono') url("https://url-to-input-mono.woff");
43
- }
44
- }`
45
- const actual = analyze(fixture).atrules.fontface
46
- const expected = {
47
- total: 5,
48
- totalUnique: 5,
49
- unique: [
50
- {
51
- "font-family": "Arial",
52
- "src": "url(\"https://url-to-arial.woff\")"
53
- },
54
- {
55
- "font-display": `swap`,
56
- "font-family": `Test`,
57
- "font-stretch": `condensed`,
58
- "font-style": `italic`,
59
- "font-weight": `700`,
60
- "font-variant": `no-common-ligatures proportional-nums`,
61
- "font-feature-settings": `"liga" 0`,
62
- "font-variation-settings": `"xhgt" 0.7`,
63
- "src": `local("Input Mono")`,
64
- "unicode-range": `U+0025-00FF`,
65
- },
66
- {
67
- "font-family": "'Input Mono'",
68
- "src": "local('Input Mono') url(\"https://url-to-input-mono.woff\")"
69
- },
70
- {
71
- 'font-family': 'MyHelvetica',
72
- 'src': 'local("Helvetica Neue Bold"), local("HelveticaNeue-Bold"), url(MgOpenModernaBold.ttf)',
73
- 'font-weight': 'bold',
74
- },
75
- {
76
- "font-family": "'Input Mono'",
77
- "src": "local('Input Mono') url(\"https://url-to-input-mono.woff\")"
78
- }
79
- ],
80
- uniquenessRatio: 1
81
- }
82
-
83
- assert.equal(actual, expected)
84
- })
85
-
86
- AtRules('finds @imports', () => {
87
- const fixture = `
88
- @import "https://example.com/without-url";
89
- @import url("https://example.com/with-url");
90
- @import url("https://example.com/with-media-query") screen and (min-width: 33em);
91
- @import url("https://example.com/with-multiple-media-queries") screen, projection;
92
- `
93
- const actual = analyze(fixture).atrules.import
94
- const expected = {
95
- total: 4,
96
- totalUnique: 4,
97
- unique: {
98
- '"https://example.com/without-url"': 1,
99
- 'url("https://example.com/with-url")': 1,
100
- 'url("https://example.com/with-media-query") screen and (min-width: 33em)': 1,
101
- 'url("https://example.com/with-multiple-media-queries") screen, projection': 1,
102
- },
103
- uniquenessRatio: 4 / 4
104
- }
105
-
106
- assert.equal(actual, expected)
107
- })
108
-
109
- AtRules('finds @charsets', () => {
110
- const fixture = `
111
- @charset "UTF-8";
112
- @charset "UTF-16";
113
- `
114
- const actual = analyze(fixture).atrules.charset
115
- const expected = {
116
- total: 2,
117
- totalUnique: 2,
118
- unique: {
119
- '"UTF-8"': 1,
120
- '"UTF-16"': 1,
121
- },
122
- uniquenessRatio: 2 / 2
123
- }
124
-
125
- assert.equal(actual, expected)
126
- })
127
-
128
- AtRules('finds @supports', () => {
129
- const fixture = `
130
- @supports (filter: blur(5px)) {}
131
- @supports (display: table-cell) and (display: list-item) {}
132
- @supports (-webkit-appearance: none) {}
133
-
134
- @media (min-width: 0) {
135
- @supports (-webkit-appearance: none) {}
136
- }
137
- `
138
- const actual = analyze(fixture).atrules.supports
139
- const expected = {
140
- total: 4,
141
- totalUnique: 3,
142
- unique: {
143
- '(filter: blur(5px))': 1,
144
- '(display: table-cell) and (display: list-item)': 1,
145
- '(-webkit-appearance: none)': 2,
146
- },
147
- uniquenessRatio: 3 / 4
148
- }
149
-
150
- assert.equal(actual, expected)
151
- })
152
-
153
- AtRules('finds @media', () => {
154
- const fixture = `
155
- @media screen {}
156
- @media screen and (min-width: 33em) {}
157
- @media (min-width: 20px) {}
158
- @media (max-width: 200px) {}
159
- @media screen or print {}
160
- @media \\0 all {}
161
-
162
- @supports (-webkit-appearance: none) {
163
- @media (min-width: 0) {}
164
- }
165
- `
166
- const actual = analyze(fixture).atrules.media
167
- const expected = {
168
- total: 7,
169
- totalUnique: 7,
170
- unique: {
171
- 'screen': 1,
172
- 'screen and (min-width: 33em)': 1,
173
- '(min-width: 20px)': 1,
174
- '(max-width: 200px)': 1,
175
- 'screen or print': 1,
176
- '\\0 all': 1,
177
- '(min-width: 0)': 1,
178
- },
179
- uniquenessRatio: 7 / 7
180
- }
181
-
182
- assert.equal(actual, expected)
183
- })
184
-
185
- AtRules('analyzes @keyframes', () => {
186
- const fixture = `
187
- @keyframes one {}
188
- @keyframes one {}
189
- @keyframes TWO {}
190
-
191
- /* Prefixes */
192
- @-webkit-keyframes animation {}
193
- @-moz-keyframes animation {}
194
- @-o-keyframes animation {}
195
- `
196
- const actual = analyze(fixture).atrules.keyframes
197
- const expected = {
198
- total: 6,
199
- totalUnique: 5,
200
- unique: {
201
- '@keyframes one': 2,
202
- '@keyframes TWO': 1,
203
- '@-webkit-keyframes animation': 1,
204
- '@-moz-keyframes animation': 1,
205
- '@-o-keyframes animation': 1,
206
- },
207
- uniquenessRatio: 5 / 6,
208
- prefixed: {
209
- total: 3,
210
- totalUnique: 3,
211
- unique: {
212
- '@-webkit-keyframes animation': 1,
213
- '@-moz-keyframes animation': 1,
214
- '@-o-keyframes animation': 1,
215
- },
216
- uniquenessRatio: 3 / 3,
217
- ratio: 3 / 6
218
- }
219
- }
220
-
221
- assert.equal(actual, expected)
222
- })
223
-
224
- AtRules('analyzes container queries', () => {
225
- // Fixture contains examples from the spec.
226
- // https://drafts.csswg.org/css-contain-3/
227
- const fixture = `
228
- /* Example 2 */
229
- @container (inline-size > 45em) {
230
- .media-object {
231
- grid-template: 'img content' auto / auto 1fr;
232
- }
233
- }
234
-
235
- /* Example 3 */
236
- @container (width > 40em) {
237
- h2 { font-size: 1.5em; }
238
- }
239
-
240
- /* Example 4 */
241
- @container (--cards) {
242
- article {
243
- border: thin solid silver;
244
- border-radius: 0.5em;
245
- padding: 1em;
246
- }
247
- }
248
-
249
- /* Example 5 */
250
- @container page-layout (block-size > 12em) {
251
- .card { margin-block: 2em; }
252
- }
253
-
254
- @container component-library (inline-size > 30em) {
255
- .card { margin-inline: 2em; }
256
- }
257
-
258
- /* Example 8 */
259
- @container card (inline-size > 30em) and (--responsive = true) {
260
- /* styles */
261
- }
262
-
263
- /* Example 11 */
264
- @container type(inline-size) {
265
- /* only applies when an inline-size container is available */
266
- h2 { font-size: calc(1.2em + 1cqi); }
267
- }
268
- `
269
- const result = analyze(fixture)
270
- const actual = result.atrules.container
271
- const expected = {
272
- total: 7,
273
- totalUnique: 7,
274
- unique: {
275
- '(inline-size > 45em)': 1,
276
- '(width > 40em)': 1,
277
- '(--cards)': 1,
278
- 'page-layout (block-size > 12em)': 1,
279
- 'component-library (inline-size > 30em)': 1,
280
- 'card (inline-size > 30em) and (--responsive = true)': 1,
281
- 'type(inline-size)': 1,
282
- },
283
- uniquenessRatio: 7 / 7
284
- }
285
-
286
- assert.equal(actual, expected)
287
- })
288
-
289
- AtRules.run()
@@ -1,36 +0,0 @@
1
- import { CountableCollection } from './countable-collection.js'
2
-
3
- class ContextCollection {
4
- constructor() {
5
- this.list = new CountableCollection()
6
- this.contexts = {}
7
- this.contextCount = 0
8
- }
9
-
10
- push(item, context) {
11
- this.list.push(item)
12
-
13
- if (!this.contexts[context]) {
14
- this.contexts[context] = new CountableCollection()
15
- this.contextCount++
16
- }
17
-
18
- this.contexts[context].push(item)
19
- }
20
-
21
- count() {
22
- const itemsPerContext = {}
23
-
24
- for (let context in this.contexts) {
25
- itemsPerContext[context] = this.contexts[context].count()
26
- }
27
-
28
- return Object.assign(this.list.count(), {
29
- itemsPerContext
30
- })
31
- }
32
- }
33
-
34
- export {
35
- ContextCollection
36
- }
@@ -1,46 +0,0 @@
1
- class CountableCollection {
2
- constructor(initial) {
3
- this.items = {}
4
- this.total = 0
5
- this.totalUnique = 0
6
-
7
- if (initial) {
8
- for (let index = 0; index < initial.length; index++) {
9
- this.push(initial[index])
10
- }
11
- }
12
- }
13
-
14
- /**
15
- *
16
- * @param {string} item
17
- */
18
- push(item) {
19
- this.total++
20
-
21
- if (this.items[item]) {
22
- this.items[item]++
23
- return
24
- }
25
-
26
- this.items[item] = 1
27
- this.totalUnique++
28
- }
29
-
30
- size() {
31
- return this.total
32
- }
33
-
34
- count() {
35
- return {
36
- total: this.total,
37
- totalUnique: this.totalUnique,
38
- unique: this.items,
39
- uniquenessRatio: this.total === 0 ? 0 : this.totalUnique / this.total,
40
- }
41
- }
42
- }
43
-
44
- export {
45
- CountableCollection
46
- }
@@ -1,46 +0,0 @@
1
- const analyzeDeclarations = ({ stringifyNode, declarations }) => {
2
- const total = declarations.length
3
- const cache = Object.create(null)
4
- let importants = 0
5
- let totalUnique = 0
6
- let totalInKeyframes = 0
7
-
8
- for (let i = 0; i < total; i++) {
9
- const declaration = declarations[i]
10
-
11
- if (declaration.important === true) {
12
- importants++
13
-
14
- if (declaration.inKeyframe) {
15
- totalInKeyframes++
16
- }
17
- }
18
-
19
- const stringified = stringifyNode(declaration)
20
-
21
- if (!cache[stringified]) {
22
- cache[stringified] = 1
23
- totalUnique++
24
- }
25
- }
26
-
27
- return {
28
- total,
29
- unique: {
30
- total: totalUnique,
31
- ratio: total === 0 ? 0 : totalUnique / total,
32
- },
33
- importants: {
34
- total: importants,
35
- ratio: total === 0 ? 0 : importants / total,
36
- inKeyframes: {
37
- total: totalInKeyframes,
38
- ratio: importants === 0 ? 0 : totalInKeyframes / importants,
39
- },
40
- },
41
- }
42
- }
43
-
44
- export {
45
- analyzeDeclarations
46
- }
@@ -1,113 +0,0 @@
1
- import { suite } from 'uvu'
2
- import * as assert from 'uvu/assert'
3
- import { analyze } from '../index.js'
4
-
5
- const Declarations = suite('Declarations')
6
-
7
- Declarations('should be counted', () => {
8
- const fixture = `
9
- rule {
10
- color: green;
11
- color: orange !important;
12
- }
13
-
14
- rule2 {
15
- color: green; /* not unique */
16
- }
17
-
18
- @media print {
19
- @media (min-width: 1000px) {
20
- @supports (display: grid) {
21
- @keyframes test {
22
- from {
23
- opacity: 1;
24
- }
25
- to {
26
- opacity: 0;
27
- }
28
- }
29
-
30
- another-rule {
31
- color: purple;
32
- }
33
- }
34
- }
35
- }
36
- `
37
- const actual = analyze(fixture).declarations
38
-
39
- assert.is(actual.total, 6)
40
- assert.is(actual.unique.total, 5)
41
- assert.is(actual.unique.ratio, 5 / 6)
42
- })
43
-
44
- Declarations('should count !importants', () => {
45
- const fixture = `
46
- some {
47
- color: red;
48
- color: red: !important;
49
- }
50
-
51
- @media (min-width: 0) {
52
- nested {
53
- color: darkred;
54
- color: darkred !important;
55
- }
56
- }
57
-
58
- @supports (color: rebeccapurple) {
59
- nested-too {
60
- color: rebeccapurple;
61
- color: rebeccapurple !important;
62
- }
63
- }
64
-
65
- @media print {
66
- @media (max-width: 0) {
67
- @page {
68
- color: black;
69
- color: black !important;
70
- }
71
- }
72
- }
73
- `
74
- const actual = analyze(fixture).declarations.importants
75
- const expected = {
76
- total: 4,
77
- ratio: 0.5,
78
- inKeyframes: {
79
- total: 0,
80
- ratio: 0
81
- }
82
- }
83
-
84
- assert.equal(actual, expected)
85
- })
86
-
87
- /**
88
- * @see https://drafts.csswg.org/css-animations-1/#keyframes
89
- * @see https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes#!important_in_a_keyframe
90
- */
91
- Declarations('should calculate !importants within @keyframes', () => {
92
- const fixture = `
93
- test1 {
94
- color: green !important;
95
- }
96
-
97
- @keyframes myTest {
98
- from {
99
- opacity: 1 !important;
100
- }
101
- }
102
- `
103
- const result = analyze(fixture)
104
- const actual = result.declarations.importants
105
-
106
- assert.is(actual.total, 2)
107
- assert.equal(actual.inKeyframes, {
108
- total: 1,
109
- ratio: 1 / 2
110
- })
111
- })
112
-
113
- Declarations.run()