@projectwallace/css-code-quality 1.0.3 → 3.0.0-alpha.0

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/core.d.ts CHANGED
@@ -1,56 +1,92 @@
1
- /**
2
- * @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} analysis
3
- */
1
+ /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} analysis */
4
2
  export function calculate(analysis: ReturnType<typeof import('@projectwallace/css-analyzer').analyze>): {
5
- /** @deprecated */
6
- score: number;
7
- violations: {
3
+ violations: ({
8
4
  id: string;
9
5
  score: number;
10
6
  value: number;
11
- }[];
12
- passes: {
7
+ } | {
8
+ id: string;
9
+ score: number;
10
+ value: number | undefined;
11
+ actuals: number[];
12
+ })[];
13
+ passes: ({
13
14
  id: string;
14
15
  score: number;
15
16
  value: number;
16
- }[];
17
+ } | {
18
+ id: string;
19
+ score: number;
20
+ value: number | undefined;
21
+ actuals: number[];
22
+ })[];
17
23
  performance: {
18
24
  score: number;
19
- violations: {
25
+ violations: ({
20
26
  id: string;
21
27
  score: number;
22
28
  value: number;
23
- }[];
24
- passes: {
29
+ } | {
30
+ id: string;
31
+ score: number;
32
+ value: number | undefined;
33
+ actuals: number[];
34
+ })[];
35
+ passes: ({
25
36
  id: string;
26
37
  score: number;
27
38
  value: number;
28
- }[];
39
+ } | {
40
+ id: string;
41
+ score: number;
42
+ value: number | undefined;
43
+ actuals: number[];
44
+ })[];
29
45
  };
30
46
  maintainability: {
31
47
  score: number;
32
- violations: {
48
+ violations: ({
33
49
  id: string;
34
50
  score: number;
35
51
  value: number;
36
- }[];
37
- passes: {
52
+ } | {
53
+ id: string;
54
+ score: number;
55
+ value: number | undefined;
56
+ actuals: number[];
57
+ })[];
58
+ passes: ({
38
59
  id: string;
39
60
  score: number;
40
61
  value: number;
41
- }[];
62
+ } | {
63
+ id: string;
64
+ score: number;
65
+ value: number | undefined;
66
+ actuals: number[];
67
+ })[];
42
68
  };
43
69
  complexity: {
44
70
  score: number;
45
- violations: {
71
+ violations: ({
46
72
  id: string;
47
73
  score: number;
48
74
  value: number;
49
- }[];
50
- passes: {
75
+ } | {
76
+ id: string;
77
+ score: number;
78
+ value: number | undefined;
79
+ actuals: number[];
80
+ })[];
81
+ passes: ({
51
82
  id: string;
52
83
  score: number;
53
84
  value: number;
54
- }[];
85
+ } | {
86
+ id: string;
87
+ score: number;
88
+ value: number | undefined;
89
+ actuals: number[];
90
+ })[];
55
91
  };
56
92
  };
@@ -1,5 +1,5 @@
1
- import { compareSpecificity as i, analyze as l } from "@projectwallace/css-analyzer";
2
- const m = [
1
+ import { compareSpecificity as i } from "@projectwallace/css-analyzer";
2
+ const l = [
3
3
  // Should not contain @import rules
4
4
  /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
5
5
  (e) => ({
@@ -31,9 +31,9 @@ const m = [
31
31
  const s = {
32
32
  id: "DeclarationDuplications",
33
33
  score: 0,
34
- value: 1 - e.declarations.unique.ratio
34
+ value: 1 - e.declarations.uniquenessRatio
35
35
  };
36
- return e.declarations.unique.ratio < 0.66 && (s.score = Math.floor((1 - e.declarations.unique.ratio) * 10)), s;
36
+ return e.declarations.uniquenessRatio < 0.66 && (s.score = Math.floor((1 - e.declarations.uniquenessRatio) * 10)), s;
37
37
  },
38
38
  // The total amount of CSS should not be too high
39
39
  /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
@@ -61,11 +61,10 @@ const m = [
61
61
  return {
62
62
  id: "TooMuchEmbeddedContent",
63
63
  score: Math.min(20, Math.floor(s.total / 250)),
64
- value: s.total,
65
- actuals: Object.keys(e.stylesheet.embeddedContent.unique)
64
+ value: s.total
66
65
  };
67
66
  }
68
- ], u = [
67
+ ], m = [
69
68
  // Source Lines of Code should be low
70
69
  /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
71
70
  (e) => {
@@ -113,32 +112,33 @@ const m = [
113
112
  // Max number of Selectors per Rule should be low
114
113
  /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
115
114
  (e) => {
116
- const o = {
115
+ let o = e.rules.selectors.max || 0;
116
+ const t = {
117
117
  id: "MaxSelectorsPerRule",
118
118
  score: 0,
119
- value: e.rules.selectors.max,
119
+ value: o,
120
120
  actuals: e.rules.selectors.items
121
121
  };
122
- if (e.rules.selectors.max > 10) {
123
- const t = Math.ceil((e.rules.selectors.max - 10) * 0.5);
124
- o.score = Math.min(t, 15);
122
+ if (o > 10) {
123
+ const c = Math.ceil((o - 10) * 0.5);
124
+ t.score = Math.min(c, 15);
125
125
  }
126
- return o;
126
+ return t;
127
127
  },
128
128
  // Max number of Declarations per Rule should be low
129
129
  /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
130
130
  (e) => {
131
- const o = {
131
+ const o = e.rules.declarations.max || 0, t = {
132
132
  id: "MaxDeclarationsPerRule",
133
133
  score: 0,
134
- value: e.rules.declarations.max,
134
+ value: o,
135
135
  actuals: e.rules.declarations.items
136
136
  };
137
- if (e.rules.declarations.max > 10) {
138
- const t = Math.ceil((e.rules.declarations.max - 10) * 0.5);
139
- o.score = Math.min(15, t);
137
+ if (o > 10) {
138
+ const c = Math.ceil((o - 10) * 0.5);
139
+ t.score = Math.min(15, c);
140
140
  }
141
- return o;
141
+ return t;
142
142
  },
143
143
  // Number of Selectors per RuleSet should not differ too much from the most common amount of
144
144
  // Selectors per RuleSet
@@ -172,7 +172,7 @@ const m = [
172
172
  }
173
173
  return t;
174
174
  }
175
- ], E = [
175
+ ], u = [
176
176
  // Complexity per Selector should not differ too much from the most common Complexity
177
177
  /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
178
178
  (e) => {
@@ -191,22 +191,22 @@ const m = [
191
191
  // Specificity per Selector should not differ too much from the most common Specificity
192
192
  /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
193
193
  (e) => {
194
- const s = e.selectors.specificity.mode, o = e.selectors.specificity.items.filter((c) => i(c, s) < 0).length, t = {
194
+ const s = e.selectors.specificity.mode, t = e.selectors.specificity.items.filter((a) => i(a, s) < 0).length, c = {
195
195
  id: "MoreThanMostCommonSelectorSpecificity",
196
196
  score: 0,
197
- value: e.selectors.total === 0 ? 0 : o / e.selectors.total,
197
+ value: e.selectors.total === 0 ? 0 : t / e.selectors.total,
198
198
  actuals: e.selectors.specificity.items
199
199
  };
200
- if (o > e.selectors.total * 0.1) {
201
- const c = Math.floor(o * 0.01);
202
- t.score = Math.min(10, c);
200
+ if (t > e.selectors.total * 0.1) {
201
+ const a = Math.floor(t * 0.01);
202
+ c.score = Math.min(10, a);
203
203
  }
204
- return t;
204
+ return c;
205
205
  },
206
206
  // Maximum Selector Complexity should be low
207
207
  /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
208
208
  (e) => {
209
- const o = e.selectors.complexity.max, t = {
209
+ const o = e.selectors.complexity.max || 0, t = {
210
210
  id: "MaxSelectorComplexity",
211
211
  score: 0,
212
212
  value: e.selectors.complexity.max,
@@ -262,11 +262,11 @@ const m = [
262
262
  return t;
263
263
  }
264
264
  ];
265
- function r(e, s) {
265
+ function n(e, s) {
266
266
  let o = 100, t = [], c = [];
267
- for (const n of s) {
268
- const a = n(e);
269
- a.score > 0 ? (o -= a.score, t.push(a)) : c.push(a);
267
+ for (const a of s) {
268
+ const r = a(e);
269
+ r.score > 0 ? (o -= r.score, t.push(r)) : c.push(r);
270
270
  }
271
271
  return {
272
272
  score: Math.max(o, 0),
@@ -274,11 +274,9 @@ function r(e, s) {
274
274
  passes: c
275
275
  };
276
276
  }
277
- function d(e) {
278
- const s = r(e, m), o = r(e, u), t = r(e, E);
277
+ function L(e) {
278
+ const s = n(e, l), o = n(e, m), t = n(e, u);
279
279
  return {
280
- /** @deprecated */
281
- score: 0,
282
280
  violations: s.violations.concat(o.violations).concat(t.violations),
283
281
  passes: s.passes.concat(o.passes).concat(t.passes),
284
282
  performance: s,
@@ -286,10 +284,6 @@ function d(e) {
286
284
  complexity: t
287
285
  };
288
286
  }
289
- function M(e) {
290
- const s = l(e);
291
- return d(s);
292
- }
293
287
  export {
294
- M as calculate
288
+ L as calculate
295
289
  };
package/dist/index.d.ts CHANGED
@@ -2,54 +2,93 @@
2
2
  * @param {string} css
3
3
  */
4
4
  export function calculate(css: string): {
5
- score: number;
6
- violations: {
5
+ violations: ({
7
6
  id: string;
8
7
  score: number;
9
8
  value: number;
10
- }[];
11
- passes: {
9
+ } | {
10
+ id: string;
11
+ score: number;
12
+ value: number | undefined;
13
+ actuals: number[];
14
+ })[];
15
+ passes: ({
12
16
  id: string;
13
17
  score: number;
14
18
  value: number;
15
- }[];
19
+ } | {
20
+ id: string;
21
+ score: number;
22
+ value: number | undefined;
23
+ actuals: number[];
24
+ })[];
16
25
  performance: {
17
26
  score: number;
18
- violations: {
27
+ violations: ({
19
28
  id: string;
20
29
  score: number;
21
30
  value: number;
22
- }[];
23
- passes: {
31
+ } | {
32
+ id: string;
33
+ score: number;
34
+ value: number | undefined;
35
+ actuals: number[];
36
+ })[];
37
+ passes: ({
24
38
  id: string;
25
39
  score: number;
26
40
  value: number;
27
- }[];
41
+ } | {
42
+ id: string;
43
+ score: number;
44
+ value: number | undefined;
45
+ actuals: number[];
46
+ })[];
28
47
  };
29
48
  maintainability: {
30
49
  score: number;
31
- violations: {
50
+ violations: ({
32
51
  id: string;
33
52
  score: number;
34
53
  value: number;
35
- }[];
36
- passes: {
54
+ } | {
55
+ id: string;
56
+ score: number;
57
+ value: number | undefined;
58
+ actuals: number[];
59
+ })[];
60
+ passes: ({
37
61
  id: string;
38
62
  score: number;
39
63
  value: number;
40
- }[];
64
+ } | {
65
+ id: string;
66
+ score: number;
67
+ value: number | undefined;
68
+ actuals: number[];
69
+ })[];
41
70
  };
42
71
  complexity: {
43
72
  score: number;
44
- violations: {
73
+ violations: ({
45
74
  id: string;
46
75
  score: number;
47
76
  value: number;
48
- }[];
49
- passes: {
77
+ } | {
78
+ id: string;
79
+ score: number;
80
+ value: number | undefined;
81
+ actuals: number[];
82
+ })[];
83
+ passes: ({
50
84
  id: string;
51
85
  score: number;
52
86
  value: number;
53
- }[];
87
+ } | {
88
+ id: string;
89
+ score: number;
90
+ value: number | undefined;
91
+ actuals: number[];
92
+ })[];
54
93
  };
55
94
  };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { analyze as c } from "@projectwallace/css-analyzer";
2
+ import { calculate as l } from "./core.js";
3
+ function e(a) {
4
+ const t = c(a);
5
+ return l(t);
6
+ }
7
+ export {
8
+ e as calculate
9
+ };
package/package.json CHANGED
@@ -1,10 +1,10 @@
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": "1.0.3",
4
+ "version": "3.0.0-alpha.0",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "git@github.com:projectwallace/css-code-quality.git"
7
+ "url": "git+https://github.com:projectwallace/css-code-quality.git"
8
8
  },
9
9
  "homepage": "https://github.com/projectwallace/css-code-quality",
10
10
  "issues": "https://github.com/projectwallace/css-code-quality/issues",
@@ -23,40 +23,37 @@
23
23
  "maintainability",
24
24
  "score"
25
25
  ],
26
- "files": [
27
- "dist",
28
- "src",
29
- "!src/**/*.test.js"
30
- ],
26
+ "engines": {
27
+ "node": ">=16.0.0"
28
+ },
31
29
  "type": "module",
32
- "source": "src/index.js",
33
- "main": "./dist/css-code-quality.umd.cjs",
34
- "module": "./dist/css-code-quality.js",
35
- "unpkg": "./dist/css-code-quality.umd.cjs",
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
36
32
  "exports": {
37
33
  ".": {
38
34
  "types": "./dist/index.d.ts",
39
- "import": "./dist/css-code-quality.js",
40
- "require": "./dist/css-code-quality.umd.cjs"
35
+ "import": "./dist/index.js"
41
36
  },
42
37
  "./core": {
43
38
  "types": "./dist/core.d.ts",
44
- "import": "./src/core.js"
39
+ "import": "./dist/core.js"
45
40
  }
46
41
  },
47
- "types": "./dist/index.d.ts",
42
+ "files": [
43
+ "dist"
44
+ ],
48
45
  "scripts": {
49
46
  "test": "uvu",
50
47
  "build": "vite build",
51
48
  "check": "tsc --noEmit"
52
49
  },
53
50
  "dependencies": {
54
- "@projectwallace/css-analyzer": "^5.14.0"
51
+ "@projectwallace/css-analyzer": "^6.0.0"
55
52
  },
56
53
  "devDependencies": {
57
- "typescript": "^5.4.5",
54
+ "typescript": "^5.7.3",
58
55
  "uvu": "^0.5.6",
59
- "vite": "^5.2.12",
60
- "vite-plugin-dts": "^3.9.1"
56
+ "vite": "^6.2.0",
57
+ "vite-plugin-dts": "^4.5.0"
61
58
  }
62
59
  }
@@ -1 +0,0 @@
1
- (function(a,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("@projectwallace/css-analyzer")):typeof define=="function"&&define.amd?define(["exports","@projectwallace/css-analyzer"],r):(a=typeof globalThis<"u"?globalThis:a||self,r(a.cssCodeQuality={},a.cssAnalyzer))})(this,function(a,r){"use strict";const l=[e=>({id:"Imports",score:e.atrules.import.total*10,value:e.atrules.import.total,actuals:Object.keys(e.atrules.import.unique)}),e=>({id:"EmptyRules",score:e.rules.empty.total,value:e.rules.empty.total}),e=>{const s={id:"SelectorDuplications",score:0,value:1-e.selectors.uniquenessRatio};return e.selectors.uniquenessRatio<.66&&(s.score=Math.floor((1-e.selectors.uniquenessRatio)*10)),s},e=>{const s={id:"DeclarationDuplications",score:0,value:1-e.declarations.unique.ratio};return e.declarations.unique.ratio<.66&&(s.score=Math.floor((1-e.declarations.unique.ratio)*10)),s},e=>({id:"CssSize",score:e.stylesheet.size>2e5?5:0,value:e.stylesheet.size}),e=>{const{comments:s}=e.stylesheet;return{id:"TooMuchComments",score:Math.min(10,Math.floor(s.size/250)),value:s.size}},e=>{const{size:s}=e.stylesheet.embeddedContent;return{id:"TooMuchEmbeddedContent",score:Math.min(20,Math.floor(s.total/250)),value:s.total,actuals:Object.keys(e.stylesheet.embeddedContent.unique)}}],u=[e=>{const s={id:"SourceLinesOfCode",score:0,value:e.stylesheet.sourceLinesOfCode};if(e.stylesheet.sourceLinesOfCode>1e4){const o=Math.floor((e.stylesheet.sourceLinesOfCode-1e4)/1e3);s.score=Math.min(15,o)}return s},e=>{const o=e.rules.selectors.mean,t={id:"AverageSelectorsPerRule",score:0,value:o,actuals:e.rules.selectors.items};if(o>2){const c=Math.floor((o-2)*5);t.score=Math.min(15,c)}return t},e=>{const o={id:"AverageDeclarationsPerRule",score:0,value:e.rules.declarations.mean,actuals:e.rules.declarations.items};if(e.rules.declarations.mean>5){const t=Math.floor((e.rules.declarations.mean-5)*5);o.score=Math.min(15,t)}return o},e=>{const o={id:"MaxSelectorsPerRule",score:0,value:e.rules.selectors.max,actuals:e.rules.selectors.items};if(e.rules.selectors.max>10){const t=Math.ceil((e.rules.selectors.max-10)*.5);o.score=Math.min(t,15)}return o},e=>{const o={id:"MaxDeclarationsPerRule",score:0,value:e.rules.declarations.max,actuals:e.rules.declarations.items};if(e.rules.declarations.max>10){const t=Math.ceil((e.rules.declarations.max-10)*.5);o.score=Math.min(15,t)}return o},e=>{const s=e.rules.selectors.mode,o=e.rules.selectors.items.filter(c=>c>s).length,t={id:"MoreThanMostCommonSelectorsPerRule",score:0,value:e.rules.selectors.mode,actuals:e.rules.selectors.items};if(o>e.rules.total*.1){const c=Math.floor(o*.01);t.score=Math.min(15,c)}return t},e=>{const s=e.rules.selectors.mode,o=e.rules.declarations.items.filter(c=>c>s).length,t={id:"MoreThanMostCommonDeclarationsPerRule",score:0,value:e.rules.declarations.mode,actuals:e.rules.declarations.items};if(o>e.rules.total*.1){const c=Math.floor(o*.01);t.score=Math.min(15,c)}return t}],m=[e=>{const s=e.selectors.complexity.mode,o=e.selectors.complexity.items.filter(c=>c>s).length,t={id:"MoreThanMostCommonSelectorComplexity",score:0,value:e.selectors.total===0?0:o/e.selectors.total,actuals:e.selectors.complexity.items};if(o>e.selectors.total*.1){const c=Math.floor(o*.01);t.score=Math.min(10,c)}return t},e=>{const s=e.selectors.specificity.mode,o=e.selectors.specificity.items.filter(c=>r.compareSpecificity(c,s)<0).length,t={id:"MoreThanMostCommonSelectorSpecificity",score:0,value:e.selectors.total===0?0:o/e.selectors.total,actuals:e.selectors.specificity.items};if(o>e.selectors.total*.1){const c=Math.floor(o*.01);t.score=Math.min(10,c)}return t},e=>{const o=e.selectors.complexity.max,t={id:"MaxSelectorComplexity",score:0,value:e.selectors.complexity.max,actuals:e.selectors.complexity.items};if(o>5){const c=Math.ceil((o-5)*.5);t.score=Math.min(5,c)}return t},e=>{const o=e.selectors.complexity.mean,t={id:"AverageSelectorComplexity",score:0,value:o,actuals:e.selectors.complexity.items};if(o>2){const c=Math.ceil((o-2)*2);t.score=Math.min(10,c)}return t},e=>{const o=e.selectors.id.ratio,t={id:"IdSelectorRatio",score:0,value:o,actuals:Object.keys(e.selectors.id.unique)};if(o>.01){const c=Math.floor((o-.01)*10);t.score=Math.min(c,5)}return t},e=>{const o=e.declarations.importants.ratio,t={id:"ImportantRatio",score:0,value:o,actuals:e.declarations.importants.total};if(o>.01){const c=Math.floor((o-.01)*10);t.score=Math.min(c,5)}return t}];function i(e,s){let o=100,t=[],c=[];for(const M of s){const n=M(e);n.score>0?(o-=n.score,t.push(n)):c.push(n)}return{score:Math.max(o,0),violations:t,passes:c}}function E(e){const s=i(e,l),o=i(e,u),t=i(e,m);return{score:0,violations:s.violations.concat(o.violations).concat(t.violations),passes:s.passes.concat(o.passes).concat(t.passes),performance:s,maintainability:o,complexity:t}}function d(e){const s=r.analyze(e);return E(s)}a.calculate=d,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
package/src/complexity.js DELETED
@@ -1,132 +0,0 @@
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
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
7
- result => {
8
- const mode = result.selectors.complexity.mode
9
- const selectorsAboveMode = result.selectors.complexity.items
10
- .filter(c => c > mode)
11
- .length
12
-
13
- const outcome = {
14
- id: 'MoreThanMostCommonSelectorComplexity',
15
- score: 0,
16
- value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,
17
- actuals: result.selectors.complexity.items,
18
- }
19
-
20
- if (selectorsAboveMode > result.selectors.total * 0.1) {
21
- const score = Math.floor(selectorsAboveMode * 0.01)
22
- outcome.score = Math.min(10, score)
23
- }
24
-
25
- return outcome
26
- },
27
-
28
- // Specificity per Selector should not differ too much from the most common Specificity
29
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
30
- result => {
31
- const mode = result.selectors.specificity.mode
32
- const selectorsAboveMode = result.selectors.specificity.items
33
- .filter(c => compareSpecificity(c, mode) < 0)
34
- .length
35
-
36
- const outcome = {
37
- id: 'MoreThanMostCommonSelectorSpecificity',
38
- score: 0,
39
- value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,
40
- actuals: result.selectors.specificity.items,
41
- }
42
-
43
- if (selectorsAboveMode > result.selectors.total * 0.1) {
44
- const score = Math.floor(selectorsAboveMode * 0.01)
45
- outcome.score = Math.min(10, score)
46
- }
47
-
48
- return outcome
49
- },
50
-
51
- // Maximum Selector Complexity should be low
52
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
53
- result => {
54
- const MAX_SELECTOR_COMPLEXITY = 5
55
- const actual = result.selectors.complexity.max
56
-
57
- const outcome = {
58
- id: 'MaxSelectorComplexity',
59
- score: 0,
60
- value: result.selectors.complexity.max,
61
- actuals: result.selectors.complexity.items,
62
- }
63
-
64
- // Deduct 0.5 points per complexity over 5, up to 5 points
65
- if (actual > MAX_SELECTOR_COMPLEXITY) {
66
- const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)
67
- outcome.score = Math.min(5, score)
68
- }
69
-
70
- return outcome
71
- },
72
-
73
- // Average Selector Complexity should be low
74
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
75
- result => {
76
- const ALLOWED_COMPLEXITY = 2
77
- const actual = result.selectors.complexity.mean
78
-
79
- const outcome = {
80
- id: 'AverageSelectorComplexity',
81
- score: 0,
82
- value: actual,
83
- actuals: result.selectors.complexity.items,
84
- }
85
-
86
- // Deduct 2 points per selector over 2
87
- if (actual > ALLOWED_COMPLEXITY) {
88
- const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)
89
- outcome.score = Math.min(10, score)
90
- }
91
-
92
- return outcome
93
- },
94
-
95
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
96
- result => {
97
- const ALLOWED = 0.01
98
- const actual = result.selectors.id.ratio
99
- const outcome = {
100
- id: 'IdSelectorRatio',
101
- score: 0,
102
- value: actual,
103
- actuals: Object.keys(result.selectors.id.unique)
104
- }
105
-
106
- if (actual > ALLOWED) {
107
- const score = Math.floor((actual - ALLOWED) * 10)
108
- outcome.score = Math.min(score, 5)
109
- }
110
-
111
- return outcome
112
- },
113
-
114
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
115
- result => {
116
- const ALLOWED = 0.01
117
- const actual = result.declarations.importants.ratio
118
- const outcome = {
119
- id: 'ImportantRatio',
120
- score: 0,
121
- value: actual,
122
- actuals: result.declarations.importants.total,
123
- }
124
-
125
- if (actual > ALLOWED) {
126
- const score = Math.floor((actual - ALLOWED) * 10)
127
- outcome.score = Math.min(score, 5)
128
- }
129
-
130
- return outcome
131
- },
132
- ]
package/src/core.js DELETED
@@ -1,53 +0,0 @@
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
- /**
6
- * @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result
7
- * @param {performanceGuards | maintainabilityGuards | complexityGuards} guards
8
- */
9
- function calculateScore(result, guards) {
10
- let score = 100
11
- let violations = []
12
- let passes = []
13
-
14
- for (const guard of guards) {
15
- const outcome = guard(result)
16
-
17
- if (outcome.score > 0) {
18
- score -= outcome.score
19
- violations.push(outcome)
20
- } else {
21
- passes.push(outcome)
22
- }
23
- }
24
-
25
- return {
26
- score: Math.max(score, 0),
27
- violations,
28
- passes,
29
- }
30
- }
31
-
32
- /**
33
- * @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} analysis
34
- */
35
- export function calculate(analysis) {
36
- const performance = calculateScore(analysis, performanceGuards)
37
- const maintainability = calculateScore(analysis, maintainabilityGuards)
38
- const complexity = calculateScore(analysis, complexityGuards)
39
-
40
- return {
41
- /** @deprecated */
42
- score: 0,
43
- violations: performance.violations
44
- .concat(maintainability.violations)
45
- .concat(complexity.violations),
46
- passes: performance.passes
47
- .concat(maintainability.passes)
48
- .concat(complexity.passes),
49
- performance,
50
- maintainability,
51
- complexity,
52
- }
53
- }
package/src/index.js DELETED
@@ -1,10 +0,0 @@
1
- import { analyze } from '@projectwallace/css-analyzer'
2
- import { calculate as calculateFromAnalysis } from './core.js'
3
-
4
- /**
5
- * @param {string} css
6
- */
7
- export function calculate(css) {
8
- const analysis = analyze(css)
9
- return calculateFromAnalysis(analysis)
10
- }
@@ -1,157 +0,0 @@
1
- export const guards = [
2
-
3
- // Source Lines of Code should be low
4
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
5
- result => {
6
- const outcome = {
7
- id: 'SourceLinesOfCode',
8
- score: 0,
9
- value: result.stylesheet.sourceLinesOfCode,
10
- }
11
-
12
- if (result.stylesheet.sourceLinesOfCode > 10000) {
13
- // deduct 1 point per 1000 lines of code over 10,000
14
- const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)
15
- outcome.score = Math.min(15, score)
16
- }
17
-
18
- return outcome
19
- },
20
-
21
- // Average count of Selectors per RuleSet should be low
22
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
23
- result => {
24
- const ALLOWED_SELECTORS_PER_RULESET = 2
25
- const actual = result.rules.selectors.mean
26
-
27
- const outcome = {
28
- id: 'AverageSelectorsPerRule',
29
- score: 0,
30
- value: actual,
31
- actuals: result.rules.selectors.items,
32
- }
33
-
34
- // Deduct 5 points per selector over 2
35
- if (actual > ALLOWED_SELECTORS_PER_RULESET) {
36
- const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)
37
- outcome.score = Math.min(15, score)
38
- }
39
-
40
- return outcome
41
- },
42
-
43
- // Average count of Declarations per RuleSet should be low
44
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
45
- result => {
46
- const ALLOWED_DECLARATIONS_PER_RULESET = 5
47
-
48
- const outcome = {
49
- id: 'AverageDeclarationsPerRule',
50
- score: 0,
51
- value: result.rules.declarations.mean,
52
- actuals: result.rules.declarations.items,
53
- }
54
-
55
- // Deduct 5 points per declaration over 5
56
- if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {
57
- const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)
58
- outcome.score = Math.min(15, score)
59
- }
60
-
61
- return outcome
62
- },
63
-
64
- // Max number of Selectors per Rule should be low
65
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
66
- result => {
67
- const MAX_SELECTORS_PER_RULESET = 10
68
-
69
- const outcome = {
70
- id: 'MaxSelectorsPerRule',
71
- score: 0,
72
- value: result.rules.selectors.max,
73
- actuals: result.rules.selectors.items,
74
- }
75
-
76
- // Deduct 0.5 points per selectors over 10
77
- if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {
78
- const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)
79
- outcome.score = Math.min(score, 15)
80
- }
81
-
82
- return outcome
83
- },
84
-
85
- // Max number of Declarations per Rule should be low
86
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
87
- result => {
88
- const MAX_DECLARATIONS_PER_RULESET = 10
89
-
90
- const outcome = {
91
- id: 'MaxDeclarationsPerRule',
92
- score: 0,
93
- value: result.rules.declarations.max,
94
- actuals: result.rules.declarations.items,
95
- }
96
-
97
- // Deduct 0.5 points per declarations over 10
98
- if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {
99
- const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)
100
- outcome.score = Math.min(15, score)
101
- }
102
-
103
- return outcome
104
- },
105
-
106
- // Number of Selectors per RuleSet should not differ too much from the most common amount of
107
- // Selectors per RuleSet
108
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
109
- result => {
110
- const mode = result.rules.selectors.mode
111
- const rulesHavingMoreThanMode = result.rules.selectors.items
112
- .filter(item => item > mode)
113
- .length
114
-
115
- const outcome = {
116
- id: 'MoreThanMostCommonSelectorsPerRule',
117
- score: 0,
118
- value: result.rules.selectors.mode,
119
- actuals: result.rules.selectors.items,
120
- }
121
-
122
- // if more than 10% of RuleSets has more Selectors than most common:
123
- if (rulesHavingMoreThanMode > result.rules.total * 0.1) {
124
- // then deduct 0.01 for ever applicable RuleSet
125
- const score = Math.floor(rulesHavingMoreThanMode * 0.01)
126
- // with a maximum of 10 points
127
- outcome.score = Math.min(15, score)
128
- }
129
-
130
- return outcome
131
- },
132
-
133
- // Number of Declarations per RuleSet should not differ too much from the most common amount of
134
- // Declarations per RuleSet
135
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
136
- result => {
137
- const mode = result.rules.selectors.mode
138
- const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length
139
-
140
- const outcome = {
141
- id: 'MoreThanMostCommonDeclarationsPerRule',
142
- score: 0,
143
- value: result.rules.declarations.mode,
144
- actuals: result.rules.declarations.items,
145
- }
146
-
147
- // if more than 10% of RuleSets has more Declarations than most common:
148
- if (rulesHavingMoreThanMode > result.rules.total * 0.1) {
149
- // then deduct 0.01 for ever applicable RuleSet
150
- const score = Math.floor(rulesHavingMoreThanMode * 0.01)
151
- // with a maximum of 10 points
152
- outcome.score = Math.min(15, score)
153
- }
154
-
155
- return outcome
156
- },
157
- ]
@@ -1,84 +0,0 @@
1
- export const guards = [
2
-
3
- // Should not contain @import rules
4
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
5
- result => ({
6
- id: 'Imports',
7
- score: result.atrules.import.total * 10,
8
- value: result.atrules.import.total,
9
- actuals: Object.keys(result.atrules.import.unique),
10
- }),
11
-
12
- // Should not contain empty rules
13
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
14
- result => ({
15
- id: 'EmptyRules',
16
- score: result.rules.empty.total,
17
- value: result.rules.empty.total,
18
- }),
19
-
20
- // Too many selectors appear multiple times
21
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
22
- result => {
23
- const outcome = {
24
- id: 'SelectorDuplications',
25
- score: 0,
26
- value: 1 - result.selectors.uniquenessRatio,
27
- }
28
-
29
- if (result.selectors.uniquenessRatio < 0.66) {
30
- outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)
31
- }
32
-
33
- return outcome
34
- },
35
-
36
- // Too many declarations appear multiple times
37
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
38
- result => {
39
- const outcome = {
40
- id: 'DeclarationDuplications',
41
- score: 0,
42
- value: 1 - result.declarations.unique.ratio,
43
- }
44
-
45
- if (result.declarations.unique.ratio < 0.66) {
46
- outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)
47
- }
48
-
49
- return outcome
50
- },
51
-
52
- // The total amount of CSS should not be too high
53
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
54
- result => ({
55
- id: 'CssSize',
56
- score: result.stylesheet.size > 200_000 ? 5 : 0,
57
- value: result.stylesheet.size,
58
- }),
59
-
60
- // Should not contain (too much) comments
61
- // Deduct 1 point for every 250 bytes
62
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
63
- result => {
64
- const { comments } = result.stylesheet
65
- return {
66
- id: 'TooMuchComments',
67
- score: Math.min(10, Math.floor(comments.size / 250)),
68
- value: comments.size,
69
- }
70
- },
71
-
72
- // Should not contain too much embedded content
73
- // Deduct 1 point for every 250 bytes
74
- /** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
75
- result => {
76
- const { size } = result.stylesheet.embeddedContent
77
- return {
78
- id: 'TooMuchEmbeddedContent',
79
- score: Math.min(20, Math.floor(size.total / 250)),
80
- value: size.total,
81
- actuals: Object.keys(result.stylesheet.embeddedContent.unique),
82
- }
83
- },
84
- ]