@projectwallace/css-code-quality
Version:
Calculate the Code Quality score of your CSS based on a range of different quality guards
290 lines (289 loc) • 9.18 kB
JavaScript
import { compareSpecificity as i } from "@projectwallace/css-analyzer";
const l = [
// Should not contain @import rules
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => ({
id: "Imports",
score: e.atrules.import.total * 10,
value: e.atrules.import.total,
actuals: Object.keys(e.atrules.import.unique)
}),
// Should not contain empty rules
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => ({
id: "EmptyRules",
score: e.rules.empty.total,
value: e.rules.empty.total
}),
// Too many selectors appear multiple times
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const s = {
id: "SelectorDuplications",
score: 0,
value: 1 - e.selectors.uniquenessRatio
};
return e.selectors.uniquenessRatio < 0.66 && (s.score = Math.floor((1 - e.selectors.uniquenessRatio) * 10)), s;
},
// Too many declarations appear multiple times
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const s = {
id: "DeclarationDuplications",
score: 0,
value: 1 - e.declarations.uniquenessRatio
};
return e.declarations.uniquenessRatio < 0.66 && (s.score = Math.floor((1 - e.declarations.uniquenessRatio) * 10)), s;
},
// The total amount of CSS should not be too high
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => ({
id: "CssSize",
score: e.stylesheet.size > 2e5 ? 5 : 0,
value: e.stylesheet.size
}),
// Should not contain (too much) comments
// Deduct 1 point for every 250 bytes
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const { comments: s } = e.stylesheet;
return {
id: "TooMuchComments",
score: Math.min(10, Math.floor(s.size / 250)),
value: s.size
};
},
// Should not contain too much embedded content
// Deduct 1 point for every 250 bytes
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const { size: s } = e.stylesheet.embeddedContent;
return {
id: "TooMuchEmbeddedContent",
score: Math.min(20, Math.floor(s.total / 250)),
value: s.total
};
}
], m = [
// Source Lines of Code should be low
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(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;
},
// Average count of Selectors per RuleSet should be low
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(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;
},
// Average count of Declarations per RuleSet should be low
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(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;
},
// Max number of Selectors per Rule should be low
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
let o = e.rules.selectors.max || 0;
const t = {
id: "MaxSelectorsPerRule",
score: 0,
value: o,
actuals: e.rules.selectors.items
};
if (o > 10) {
const c = Math.ceil((o - 10) * 0.5);
t.score = Math.min(c, 15);
}
return t;
},
// Max number of Declarations per Rule should be low
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const o = e.rules.declarations.max || 0, t = {
id: "MaxDeclarationsPerRule",
score: 0,
value: o,
actuals: e.rules.declarations.items
};
if (o > 10) {
const c = Math.ceil((o - 10) * 0.5);
t.score = Math.min(15, c);
}
return t;
},
// Number of Selectors per RuleSet should not differ too much from the most common amount of
// Selectors per RuleSet
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(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 * 0.1) {
const c = Math.floor(o * 0.01);
t.score = Math.min(15, c);
}
return t;
},
// Number of Declarations per RuleSet should not differ too much from the most common amount of
// Declarations per RuleSet
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(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 * 0.1) {
const c = Math.floor(o * 0.01);
t.score = Math.min(15, c);
}
return t;
}
], u = [
// Complexity per Selector should not differ too much from the most common Complexity
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(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 * 0.1) {
const c = Math.floor(o * 0.01);
t.score = Math.min(10, c);
}
return t;
},
// Specificity per Selector should not differ too much from the most common Specificity
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const s = e.selectors.specificity.mode, t = e.selectors.specificity.items.filter((a) => i(a, s) < 0).length, c = {
id: "MoreThanMostCommonSelectorSpecificity",
score: 0,
value: e.selectors.total === 0 ? 0 : t / e.selectors.total,
actuals: e.selectors.specificity.items
};
if (t > e.selectors.total * 0.1) {
const a = Math.floor(t * 0.01);
c.score = Math.min(10, a);
}
return c;
},
// Maximum Selector Complexity should be low
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const o = e.selectors.complexity.max || 0, t = {
id: "MaxSelectorComplexity",
score: 0,
value: e.selectors.complexity.max,
actuals: e.selectors.complexity.items
};
if (o > 5) {
const c = Math.ceil((o - 5) * 0.5);
t.score = Math.min(5, c);
}
return t;
},
// Average Selector Complexity should be low
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(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;
},
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const o = e.selectors.id.ratio, t = {
id: "IdSelectorRatio",
score: 0,
value: o,
actuals: Object.keys(e.selectors.id.unique)
};
if (o > 0.01) {
const c = Math.floor((o - 0.01) * 10);
t.score = Math.min(c, 5);
}
return t;
},
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} result */
(e) => {
const o = e.declarations.importants.ratio, t = {
id: "ImportantRatio",
score: 0,
value: o,
actuals: e.declarations.importants.total
};
if (o > 0.01) {
const c = Math.floor((o - 0.01) * 10);
t.score = Math.min(c, 5);
}
return t;
}
];
function n(e, s) {
let o = 100, t = [], c = [];
for (const a of s) {
const r = a(e);
r.score > 0 ? (o -= r.score, t.push(r)) : c.push(r);
}
return {
score: Math.max(o, 0),
violations: t,
passes: c
};
}
function L(e) {
const s = n(e, l), o = n(e, m), t = n(e, u);
return {
violations: s.violations.concat(o.violations).concat(t.violations),
passes: s.passes.concat(o.passes).concat(t.passes),
performance: s,
maintainability: o,
complexity: t
};
}
export {
L as calculate
};