UNPKG

@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
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 };