@projectwallace/css-code-quality 0.3.2 → 1.0.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/css-code-quality.cjs.map +1 -1
- package/dist/css-code-quality.modern.js.map +1 -1
- package/dist/css-code-quality.module.js.map +1 -1
- package/dist/css-code-quality.umd.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/package.json +4 -2
- package/readme.md +72 -3
- package/src/complexity.test.js +6 -6
- package/src/core.js +1 -0
- package/src/index.js +1 -0
- package/src/index.test.js +371 -0
- package/src/maintainability.test.js +8 -8
- package/src/performance.test.js +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-code-quality.cjs","sources":["../src/performance.js","../src/maintainability.js","../src/complexity.js","../src/core.js","../src/index.js"],"sourcesContent":["export const guards = [\n\n // Should not contain @import rules\n result => ({\n id: 'Imports',\n score: result.atrules.import.total * 10,\n value: result.atrules.import.total,\n actuals: Object.keys(result.atrules.import.unique),\n }),\n\n // Should not contain empty rules\n result => ({\n id: 'EmptyRules',\n score: result.rules.empty.total,\n value: result.rules.empty.total,\n }),\n\n // Too many selectors appear multiple times\n result => {\n const outcome = {\n id: 'SelectorDuplications',\n score: 0,\n value: 1 - result.selectors.uniquenessRatio,\n }\n\n if (result.selectors.uniquenessRatio < 0.66) {\n outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)\n }\n\n return outcome\n },\n\n // Too many declarations appear multiple times\n result => {\n const outcome = {\n id: 'DeclarationDuplications',\n score: 0,\n value: 1 - result.declarations.unique.ratio,\n }\n\n if (result.declarations.unique.ratio < 0.66) {\n outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)\n }\n\n return outcome\n },\n\n // The total amount of CSS should not be too high\n result => ({\n id: 'CssSize',\n score: result.stylesheet.size > 200_000 ? 5 : 0,\n value: result.stylesheet.size,\n }),\n\n // Should not contain (too much) comments\n // Deduct 1 point for every 250 bytes\n result => {\n const { comments } = result.stylesheet\n return {\n id: 'TooMuchComments',\n score: Math.min(10, Math.floor(comments.size / 250)),\n value: comments.size,\n }\n },\n\n // Should not contain too much embedded content\n // Deduct 1 point for every 250 bytes\n result => {\n const { size } = result.stylesheet.embeddedContent\n return {\n id: 'TooMuchEmbeddedContent',\n score: Math.min(20, Math.floor(size.total / 250)),\n value: size.total,\n actuals: Object.keys(result.stylesheet.embeddedContent.unique),\n }\n },\n]\n","export const guards = [\n\n // Source Lines of Code should be low'\n result => {\n const outcome = {\n id: 'SourceLinesOfCode',\n score: 0,\n value: result.stylesheet.sourceLinesOfCode,\n }\n\n if (result.stylesheet.sourceLinesOfCode > 10000) {\n // deduct 1 point per 1000 lines of code over 10,000\n const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Selectors per RuleSet should be low\n result => {\n const ALLOWED_SELECTORS_PER_RULESET = 2\n const actual = result.rules.selectors.mean\n\n const outcome = {\n id: 'AverageSelectorsPerRule',\n score: 0,\n value: actual,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 5 points per selector over 2\n if (actual > ALLOWED_SELECTORS_PER_RULESET) {\n const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Declarations per RuleSet should be low\n result => {\n const ALLOWED_DECLARATIONS_PER_RULESET = 5\n\n const outcome = {\n id: 'AverageDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mean,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 5 points per declaration over 5\n if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {\n const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Max number of Selectors per Rule should be low\n result => {\n const MAX_SELECTORS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.max,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 0.5 points per selectors over 10\n if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {\n const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)\n outcome.score = Math.min(score, 15)\n }\n\n return outcome\n },\n\n // Max number of Declarations per Rule should be low\n result => {\n const MAX_DECLARATIONS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.max,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 0.5 points per declarations over 10\n if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {\n const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Selectors per RuleSet should not differ too much from the most common amount of\n // Selectors per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.selectors.items\n .filter(item => item > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.mode,\n actuals: result.rules.selectors.items,\n }\n\n // if more than 10% of RuleSets has more Selectors than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Declarations per RuleSet should not differ too much from the most common amount of\n // Declarations per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length\n\n const outcome = {\n id: 'MoreThanMostCommonDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mode,\n actuals: result.rules.declarations.items,\n }\n\n // if more than 10% of RuleSets has more Declarations than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n]\n","import { compareSpecificity } from '@projectwallace/css-analyzer'\n\nexport const guards = [\n\n // Complexity per Selector should not differ too much from the most common Complexity\n result => {\n const mode = result.selectors.complexity.mode\n const selectorsAboveMode = result.selectors.complexity.items\n .filter(c => c > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorComplexity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.complexity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Specificity per Selector should not differ too much from the most common Specificity\n result => {\n const mode = result.selectors.specificity.mode\n const selectorsAboveMode = result.selectors.specificity.items\n .filter(c => compareSpecificity(c, mode) < 0)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorSpecificity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.specificity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Maximum Selector Complexity should be low\n result => {\n const MAX_SELECTOR_COMPLEXITY = 5\n const actual = result.selectors.complexity.max\n\n const outcome = {\n id: 'MaxSelectorComplexity',\n score: 0,\n value: result.selectors.complexity.max,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 0.5 points per complexity over 5, up to 5 points\n if (actual > MAX_SELECTOR_COMPLEXITY) {\n const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)\n outcome.score = Math.min(5, score)\n }\n\n return outcome\n },\n\n // Average Selector Complexity should be low\n result => {\n const ALLOWED_COMPLEXITY = 2\n const actual = result.selectors.complexity.mean\n\n const outcome = {\n id: 'AverageSelectorComplexity',\n score: 0,\n value: actual,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 2 points per selector over 2\n if (actual > ALLOWED_COMPLEXITY) {\n const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.selectors.id.ratio\n const outcome = {\n id: 'IdSelectorRatio',\n score: 0,\n value: actual,\n actuals: Object.keys(result.selectors.id.unique)\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.declarations.importants.ratio\n const outcome = {\n id: 'ImportantRatio',\n score: 0,\n value: actual,\n actuals: result.declarations.importants.total,\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n]\n","import { guards as performanceGuards } from './performance.js'\nimport { guards as maintainabilityGuards } from './maintainability.js'\nimport { guards as complexityGuards } from './complexity.js'\n\nfunction calculateScore({ result, guards }) {\n\tlet score = 100\n\tlet violations = []\n\tlet passes = []\n\n\tfor (const guard of guards) {\n\t\t/** @type {{score: number, value: number, id: string}} */\n\t\tconst outcome = guard(result)\n\n\t\tif (outcome.score > 0) {\n\t\t\tscore -= outcome.score\n\t\t\tviolations.push(outcome)\n\t\t} else {\n\t\t\tpasses.push(outcome)\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.max(score, 0),\n\t\tviolations,\n\t\tpasses,\n\t}\n}\n\nexport function calculate(analysis) {\n\tconst performance = calculateScore({ result: analysis, guards: performanceGuards })\n\tconst maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })\n\tconst complexity = calculateScore({ result: analysis, guards: complexityGuards })\n\n\treturn {\n\t\t/** @deprecated */\n\t\tscore: 0,\n\t\tviolations: performance.violations\n\t\t\t.concat(maintainability.violations)\n\t\t\t.concat(complexity.violations),\n\t\tpasses: performance.passes\n\t\t\t.concat(maintainability.passes)\n\t\t\t.concat(complexity.passes),\n\t\tperformance,\n\t\tmaintainability,\n\t\tcomplexity,\n\t}\n}\n","import { analyze } from '@projectwallace/css-analyzer'\nimport { calculate as calculateFromAnalysis } from './core.js'\n\nexport function calculate(css) {\n\tconst analysis = analyze(css)\n\treturn calculateFromAnalysis(analysis)\n}\n"],"names":["guards","result","id","score","atrules","total","value","actuals","Object","keys","unique","rules","empty","outcome","selectors","uniquenessRatio","Math","floor","declarations","ratio","stylesheet","size","comments","min","embeddedContent","sourceLinesOfCode","actual","mean","items","max","ceil","mode","rulesHavingMoreThanMode","filter","item","length","complexity","selectorsAboveMode","c","specificity","compareSpecificity","importants","calculateScore","violations","passes","guard","push","css","performance","analysis","analyze","performanceGuards","maintainability","maintainabilityGuards","complexityGuards","concat"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"css-code-quality.cjs","sources":["../src/performance.js","../src/maintainability.js","../src/complexity.js","../src/core.js","../src/index.js"],"sourcesContent":["export const guards = [\n\n // Should not contain @import rules\n result => ({\n id: 'Imports',\n score: result.atrules.import.total * 10,\n value: result.atrules.import.total,\n actuals: Object.keys(result.atrules.import.unique),\n }),\n\n // Should not contain empty rules\n result => ({\n id: 'EmptyRules',\n score: result.rules.empty.total,\n value: result.rules.empty.total,\n }),\n\n // Too many selectors appear multiple times\n result => {\n const outcome = {\n id: 'SelectorDuplications',\n score: 0,\n value: 1 - result.selectors.uniquenessRatio,\n }\n\n if (result.selectors.uniquenessRatio < 0.66) {\n outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)\n }\n\n return outcome\n },\n\n // Too many declarations appear multiple times\n result => {\n const outcome = {\n id: 'DeclarationDuplications',\n score: 0,\n value: 1 - result.declarations.unique.ratio,\n }\n\n if (result.declarations.unique.ratio < 0.66) {\n outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)\n }\n\n return outcome\n },\n\n // The total amount of CSS should not be too high\n result => ({\n id: 'CssSize',\n score: result.stylesheet.size > 200_000 ? 5 : 0,\n value: result.stylesheet.size,\n }),\n\n // Should not contain (too much) comments\n // Deduct 1 point for every 250 bytes\n result => {\n const { comments } = result.stylesheet\n return {\n id: 'TooMuchComments',\n score: Math.min(10, Math.floor(comments.size / 250)),\n value: comments.size,\n }\n },\n\n // Should not contain too much embedded content\n // Deduct 1 point for every 250 bytes\n result => {\n const { size } = result.stylesheet.embeddedContent\n return {\n id: 'TooMuchEmbeddedContent',\n score: Math.min(20, Math.floor(size.total / 250)),\n value: size.total,\n actuals: Object.keys(result.stylesheet.embeddedContent.unique),\n }\n },\n]\n","export const guards = [\n\n // Source Lines of Code should be low'\n result => {\n const outcome = {\n id: 'SourceLinesOfCode',\n score: 0,\n value: result.stylesheet.sourceLinesOfCode,\n }\n\n if (result.stylesheet.sourceLinesOfCode > 10000) {\n // deduct 1 point per 1000 lines of code over 10,000\n const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Selectors per RuleSet should be low\n result => {\n const ALLOWED_SELECTORS_PER_RULESET = 2\n const actual = result.rules.selectors.mean\n\n const outcome = {\n id: 'AverageSelectorsPerRule',\n score: 0,\n value: actual,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 5 points per selector over 2\n if (actual > ALLOWED_SELECTORS_PER_RULESET) {\n const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Declarations per RuleSet should be low\n result => {\n const ALLOWED_DECLARATIONS_PER_RULESET = 5\n\n const outcome = {\n id: 'AverageDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mean,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 5 points per declaration over 5\n if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {\n const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Max number of Selectors per Rule should be low\n result => {\n const MAX_SELECTORS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.max,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 0.5 points per selectors over 10\n if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {\n const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)\n outcome.score = Math.min(score, 15)\n }\n\n return outcome\n },\n\n // Max number of Declarations per Rule should be low\n result => {\n const MAX_DECLARATIONS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.max,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 0.5 points per declarations over 10\n if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {\n const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Selectors per RuleSet should not differ too much from the most common amount of\n // Selectors per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.selectors.items\n .filter(item => item > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.mode,\n actuals: result.rules.selectors.items,\n }\n\n // if more than 10% of RuleSets has more Selectors than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Declarations per RuleSet should not differ too much from the most common amount of\n // Declarations per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length\n\n const outcome = {\n id: 'MoreThanMostCommonDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mode,\n actuals: result.rules.declarations.items,\n }\n\n // if more than 10% of RuleSets has more Declarations than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n]\n","import { compareSpecificity } from '@projectwallace/css-analyzer'\n\nexport const guards = [\n\n // Complexity per Selector should not differ too much from the most common Complexity\n result => {\n const mode = result.selectors.complexity.mode\n const selectorsAboveMode = result.selectors.complexity.items\n .filter(c => c > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorComplexity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.complexity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Specificity per Selector should not differ too much from the most common Specificity\n result => {\n const mode = result.selectors.specificity.mode\n const selectorsAboveMode = result.selectors.specificity.items\n .filter(c => compareSpecificity(c, mode) < 0)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorSpecificity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.specificity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Maximum Selector Complexity should be low\n result => {\n const MAX_SELECTOR_COMPLEXITY = 5\n const actual = result.selectors.complexity.max\n\n const outcome = {\n id: 'MaxSelectorComplexity',\n score: 0,\n value: result.selectors.complexity.max,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 0.5 points per complexity over 5, up to 5 points\n if (actual > MAX_SELECTOR_COMPLEXITY) {\n const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)\n outcome.score = Math.min(5, score)\n }\n\n return outcome\n },\n\n // Average Selector Complexity should be low\n result => {\n const ALLOWED_COMPLEXITY = 2\n const actual = result.selectors.complexity.mean\n\n const outcome = {\n id: 'AverageSelectorComplexity',\n score: 0,\n value: actual,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 2 points per selector over 2\n if (actual > ALLOWED_COMPLEXITY) {\n const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.selectors.id.ratio\n const outcome = {\n id: 'IdSelectorRatio',\n score: 0,\n value: actual,\n actuals: Object.keys(result.selectors.id.unique)\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.declarations.importants.ratio\n const outcome = {\n id: 'ImportantRatio',\n score: 0,\n value: actual,\n actuals: result.declarations.importants.total,\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n]\n","import { guards as performanceGuards } from './performance.js'\nimport { guards as maintainabilityGuards } from './maintainability.js'\nimport { guards as complexityGuards } from './complexity.js'\n\nfunction calculateScore({ result, guards }) {\n\tlet score = 100\n\tlet violations = []\n\tlet passes = []\n\n\tfor (const guard of guards) {\n\t\t/** @type {{score: number, value: number, id: string}} */\n\t\tconst outcome = guard(result)\n\n\t\tif (outcome.score > 0) {\n\t\t\tscore -= outcome.score\n\t\t\tviolations.push(outcome)\n\t\t} else {\n\t\t\tpasses.push(outcome)\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.max(score, 0),\n\t\tviolations,\n\t\tpasses,\n\t}\n}\n\n/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} analysis */\nexport function calculate(analysis) {\n\tconst performance = calculateScore({ result: analysis, guards: performanceGuards })\n\tconst maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })\n\tconst complexity = calculateScore({ result: analysis, guards: complexityGuards })\n\n\treturn {\n\t\t/** @deprecated */\n\t\tscore: 0,\n\t\tviolations: performance.violations\n\t\t\t.concat(maintainability.violations)\n\t\t\t.concat(complexity.violations),\n\t\tpasses: performance.passes\n\t\t\t.concat(maintainability.passes)\n\t\t\t.concat(complexity.passes),\n\t\tperformance,\n\t\tmaintainability,\n\t\tcomplexity,\n\t}\n}\n","import { analyze } from '@projectwallace/css-analyzer'\nimport { calculate as calculateFromAnalysis } from './core.js'\n\n/** @param {string} css */\nexport function calculate(css) {\n\tconst analysis = analyze(css)\n\treturn calculateFromAnalysis(analysis)\n}\n"],"names":["guards","result","id","score","atrules","total","value","actuals","Object","keys","unique","rules","empty","outcome","selectors","uniquenessRatio","Math","floor","declarations","ratio","stylesheet","size","comments","min","embeddedContent","sourceLinesOfCode","actual","mean","items","max","ceil","mode","rulesHavingMoreThanMode","filter","item","length","complexity","selectorsAboveMode","c","specificity","compareSpecificity","importants","calculateScore","_ref","_step","violations","passes","_iterator","_createForOfIteratorHelperLoose","done","guard","push","css","performance","analysis","analyze","performanceGuards","maintainability","maintainabilityGuards","complexityGuards","concat"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-code-quality.modern.js","sources":["../src/performance.js","../src/maintainability.js","../src/complexity.js","../src/core.js","../src/index.js"],"sourcesContent":["export const guards = [\n\n // Should not contain @import rules\n result => ({\n id: 'Imports',\n score: result.atrules.import.total * 10,\n value: result.atrules.import.total,\n actuals: Object.keys(result.atrules.import.unique),\n }),\n\n // Should not contain empty rules\n result => ({\n id: 'EmptyRules',\n score: result.rules.empty.total,\n value: result.rules.empty.total,\n }),\n\n // Too many selectors appear multiple times\n result => {\n const outcome = {\n id: 'SelectorDuplications',\n score: 0,\n value: 1 - result.selectors.uniquenessRatio,\n }\n\n if (result.selectors.uniquenessRatio < 0.66) {\n outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)\n }\n\n return outcome\n },\n\n // Too many declarations appear multiple times\n result => {\n const outcome = {\n id: 'DeclarationDuplications',\n score: 0,\n value: 1 - result.declarations.unique.ratio,\n }\n\n if (result.declarations.unique.ratio < 0.66) {\n outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)\n }\n\n return outcome\n },\n\n // The total amount of CSS should not be too high\n result => ({\n id: 'CssSize',\n score: result.stylesheet.size > 200_000 ? 5 : 0,\n value: result.stylesheet.size,\n }),\n\n // Should not contain (too much) comments\n // Deduct 1 point for every 250 bytes\n result => {\n const { comments } = result.stylesheet\n return {\n id: 'TooMuchComments',\n score: Math.min(10, Math.floor(comments.size / 250)),\n value: comments.size,\n }\n },\n\n // Should not contain too much embedded content\n // Deduct 1 point for every 250 bytes\n result => {\n const { size } = result.stylesheet.embeddedContent\n return {\n id: 'TooMuchEmbeddedContent',\n score: Math.min(20, Math.floor(size.total / 250)),\n value: size.total,\n actuals: Object.keys(result.stylesheet.embeddedContent.unique),\n }\n },\n]\n","export const guards = [\n\n // Source Lines of Code should be low'\n result => {\n const outcome = {\n id: 'SourceLinesOfCode',\n score: 0,\n value: result.stylesheet.sourceLinesOfCode,\n }\n\n if (result.stylesheet.sourceLinesOfCode > 10000) {\n // deduct 1 point per 1000 lines of code over 10,000\n const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Selectors per RuleSet should be low\n result => {\n const ALLOWED_SELECTORS_PER_RULESET = 2\n const actual = result.rules.selectors.mean\n\n const outcome = {\n id: 'AverageSelectorsPerRule',\n score: 0,\n value: actual,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 5 points per selector over 2\n if (actual > ALLOWED_SELECTORS_PER_RULESET) {\n const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Declarations per RuleSet should be low\n result => {\n const ALLOWED_DECLARATIONS_PER_RULESET = 5\n\n const outcome = {\n id: 'AverageDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mean,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 5 points per declaration over 5\n if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {\n const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Max number of Selectors per Rule should be low\n result => {\n const MAX_SELECTORS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.max,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 0.5 points per selectors over 10\n if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {\n const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)\n outcome.score = Math.min(score, 15)\n }\n\n return outcome\n },\n\n // Max number of Declarations per Rule should be low\n result => {\n const MAX_DECLARATIONS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.max,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 0.5 points per declarations over 10\n if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {\n const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Selectors per RuleSet should not differ too much from the most common amount of\n // Selectors per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.selectors.items\n .filter(item => item > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.mode,\n actuals: result.rules.selectors.items,\n }\n\n // if more than 10% of RuleSets has more Selectors than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Declarations per RuleSet should not differ too much from the most common amount of\n // Declarations per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length\n\n const outcome = {\n id: 'MoreThanMostCommonDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mode,\n actuals: result.rules.declarations.items,\n }\n\n // if more than 10% of RuleSets has more Declarations than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n]\n","import { compareSpecificity } from '@projectwallace/css-analyzer'\n\nexport const guards = [\n\n // Complexity per Selector should not differ too much from the most common Complexity\n result => {\n const mode = result.selectors.complexity.mode\n const selectorsAboveMode = result.selectors.complexity.items\n .filter(c => c > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorComplexity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.complexity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Specificity per Selector should not differ too much from the most common Specificity\n result => {\n const mode = result.selectors.specificity.mode\n const selectorsAboveMode = result.selectors.specificity.items\n .filter(c => compareSpecificity(c, mode) < 0)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorSpecificity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.specificity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Maximum Selector Complexity should be low\n result => {\n const MAX_SELECTOR_COMPLEXITY = 5\n const actual = result.selectors.complexity.max\n\n const outcome = {\n id: 'MaxSelectorComplexity',\n score: 0,\n value: result.selectors.complexity.max,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 0.5 points per complexity over 5, up to 5 points\n if (actual > MAX_SELECTOR_COMPLEXITY) {\n const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)\n outcome.score = Math.min(5, score)\n }\n\n return outcome\n },\n\n // Average Selector Complexity should be low\n result => {\n const ALLOWED_COMPLEXITY = 2\n const actual = result.selectors.complexity.mean\n\n const outcome = {\n id: 'AverageSelectorComplexity',\n score: 0,\n value: actual,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 2 points per selector over 2\n if (actual > ALLOWED_COMPLEXITY) {\n const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.selectors.id.ratio\n const outcome = {\n id: 'IdSelectorRatio',\n score: 0,\n value: actual,\n actuals: Object.keys(result.selectors.id.unique)\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.declarations.importants.ratio\n const outcome = {\n id: 'ImportantRatio',\n score: 0,\n value: actual,\n actuals: result.declarations.importants.total,\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n]\n","import { guards as performanceGuards } from './performance.js'\nimport { guards as maintainabilityGuards } from './maintainability.js'\nimport { guards as complexityGuards } from './complexity.js'\n\nfunction calculateScore({ result, guards }) {\n\tlet score = 100\n\tlet violations = []\n\tlet passes = []\n\n\tfor (const guard of guards) {\n\t\t/** @type {{score: number, value: number, id: string}} */\n\t\tconst outcome = guard(result)\n\n\t\tif (outcome.score > 0) {\n\t\t\tscore -= outcome.score\n\t\t\tviolations.push(outcome)\n\t\t} else {\n\t\t\tpasses.push(outcome)\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.max(score, 0),\n\t\tviolations,\n\t\tpasses,\n\t}\n}\n\nexport function calculate(analysis) {\n\tconst performance = calculateScore({ result: analysis, guards: performanceGuards })\n\tconst maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })\n\tconst complexity = calculateScore({ result: analysis, guards: complexityGuards })\n\n\treturn {\n\t\t/** @deprecated */\n\t\tscore: 0,\n\t\tviolations: performance.violations\n\t\t\t.concat(maintainability.violations)\n\t\t\t.concat(complexity.violations),\n\t\tpasses: performance.passes\n\t\t\t.concat(maintainability.passes)\n\t\t\t.concat(complexity.passes),\n\t\tperformance,\n\t\tmaintainability,\n\t\tcomplexity,\n\t}\n}\n","import { analyze } from '@projectwallace/css-analyzer'\nimport { calculate as calculateFromAnalysis } from './core.js'\n\nexport function calculate(css) {\n\tconst analysis = analyze(css)\n\treturn calculateFromAnalysis(analysis)\n}\n"],"names":["guards","result","id","score","atrules","import","total","value","actuals","Object","keys","unique","rules","empty","outcome","selectors","uniquenessRatio","Math","floor","declarations","ratio","stylesheet","size","comments","min","embeddedContent","sourceLinesOfCode","actual","mean","items","max","ceil","mode","rulesHavingMoreThanMode","filter","item","length","complexity","selectorsAboveMode","c","specificity","compareSpecificity","importants","calculateScore","violations","passes","guard","push","calculate","css","analysis","performance","performanceGuards","maintainability","maintainabilityGuards","complexityGuards","concat","calculateFromAnalysis","analyze"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"css-code-quality.modern.js","sources":["../src/performance.js","../src/maintainability.js","../src/complexity.js","../src/core.js","../src/index.js"],"sourcesContent":["export const guards = [\n\n // Should not contain @import rules\n result => ({\n id: 'Imports',\n score: result.atrules.import.total * 10,\n value: result.atrules.import.total,\n actuals: Object.keys(result.atrules.import.unique),\n }),\n\n // Should not contain empty rules\n result => ({\n id: 'EmptyRules',\n score: result.rules.empty.total,\n value: result.rules.empty.total,\n }),\n\n // Too many selectors appear multiple times\n result => {\n const outcome = {\n id: 'SelectorDuplications',\n score: 0,\n value: 1 - result.selectors.uniquenessRatio,\n }\n\n if (result.selectors.uniquenessRatio < 0.66) {\n outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)\n }\n\n return outcome\n },\n\n // Too many declarations appear multiple times\n result => {\n const outcome = {\n id: 'DeclarationDuplications',\n score: 0,\n value: 1 - result.declarations.unique.ratio,\n }\n\n if (result.declarations.unique.ratio < 0.66) {\n outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)\n }\n\n return outcome\n },\n\n // The total amount of CSS should not be too high\n result => ({\n id: 'CssSize',\n score: result.stylesheet.size > 200_000 ? 5 : 0,\n value: result.stylesheet.size,\n }),\n\n // Should not contain (too much) comments\n // Deduct 1 point for every 250 bytes\n result => {\n const { comments } = result.stylesheet\n return {\n id: 'TooMuchComments',\n score: Math.min(10, Math.floor(comments.size / 250)),\n value: comments.size,\n }\n },\n\n // Should not contain too much embedded content\n // Deduct 1 point for every 250 bytes\n result => {\n const { size } = result.stylesheet.embeddedContent\n return {\n id: 'TooMuchEmbeddedContent',\n score: Math.min(20, Math.floor(size.total / 250)),\n value: size.total,\n actuals: Object.keys(result.stylesheet.embeddedContent.unique),\n }\n },\n]\n","export const guards = [\n\n // Source Lines of Code should be low'\n result => {\n const outcome = {\n id: 'SourceLinesOfCode',\n score: 0,\n value: result.stylesheet.sourceLinesOfCode,\n }\n\n if (result.stylesheet.sourceLinesOfCode > 10000) {\n // deduct 1 point per 1000 lines of code over 10,000\n const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Selectors per RuleSet should be low\n result => {\n const ALLOWED_SELECTORS_PER_RULESET = 2\n const actual = result.rules.selectors.mean\n\n const outcome = {\n id: 'AverageSelectorsPerRule',\n score: 0,\n value: actual,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 5 points per selector over 2\n if (actual > ALLOWED_SELECTORS_PER_RULESET) {\n const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Declarations per RuleSet should be low\n result => {\n const ALLOWED_DECLARATIONS_PER_RULESET = 5\n\n const outcome = {\n id: 'AverageDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mean,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 5 points per declaration over 5\n if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {\n const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Max number of Selectors per Rule should be low\n result => {\n const MAX_SELECTORS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.max,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 0.5 points per selectors over 10\n if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {\n const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)\n outcome.score = Math.min(score, 15)\n }\n\n return outcome\n },\n\n // Max number of Declarations per Rule should be low\n result => {\n const MAX_DECLARATIONS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.max,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 0.5 points per declarations over 10\n if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {\n const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Selectors per RuleSet should not differ too much from the most common amount of\n // Selectors per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.selectors.items\n .filter(item => item > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.mode,\n actuals: result.rules.selectors.items,\n }\n\n // if more than 10% of RuleSets has more Selectors than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Declarations per RuleSet should not differ too much from the most common amount of\n // Declarations per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length\n\n const outcome = {\n id: 'MoreThanMostCommonDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mode,\n actuals: result.rules.declarations.items,\n }\n\n // if more than 10% of RuleSets has more Declarations than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n]\n","import { compareSpecificity } from '@projectwallace/css-analyzer'\n\nexport const guards = [\n\n // Complexity per Selector should not differ too much from the most common Complexity\n result => {\n const mode = result.selectors.complexity.mode\n const selectorsAboveMode = result.selectors.complexity.items\n .filter(c => c > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorComplexity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.complexity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Specificity per Selector should not differ too much from the most common Specificity\n result => {\n const mode = result.selectors.specificity.mode\n const selectorsAboveMode = result.selectors.specificity.items\n .filter(c => compareSpecificity(c, mode) < 0)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorSpecificity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.specificity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Maximum Selector Complexity should be low\n result => {\n const MAX_SELECTOR_COMPLEXITY = 5\n const actual = result.selectors.complexity.max\n\n const outcome = {\n id: 'MaxSelectorComplexity',\n score: 0,\n value: result.selectors.complexity.max,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 0.5 points per complexity over 5, up to 5 points\n if (actual > MAX_SELECTOR_COMPLEXITY) {\n const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)\n outcome.score = Math.min(5, score)\n }\n\n return outcome\n },\n\n // Average Selector Complexity should be low\n result => {\n const ALLOWED_COMPLEXITY = 2\n const actual = result.selectors.complexity.mean\n\n const outcome = {\n id: 'AverageSelectorComplexity',\n score: 0,\n value: actual,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 2 points per selector over 2\n if (actual > ALLOWED_COMPLEXITY) {\n const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.selectors.id.ratio\n const outcome = {\n id: 'IdSelectorRatio',\n score: 0,\n value: actual,\n actuals: Object.keys(result.selectors.id.unique)\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.declarations.importants.ratio\n const outcome = {\n id: 'ImportantRatio',\n score: 0,\n value: actual,\n actuals: result.declarations.importants.total,\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n]\n","import { guards as performanceGuards } from './performance.js'\nimport { guards as maintainabilityGuards } from './maintainability.js'\nimport { guards as complexityGuards } from './complexity.js'\n\nfunction calculateScore({ result, guards }) {\n\tlet score = 100\n\tlet violations = []\n\tlet passes = []\n\n\tfor (const guard of guards) {\n\t\t/** @type {{score: number, value: number, id: string}} */\n\t\tconst outcome = guard(result)\n\n\t\tif (outcome.score > 0) {\n\t\t\tscore -= outcome.score\n\t\t\tviolations.push(outcome)\n\t\t} else {\n\t\t\tpasses.push(outcome)\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.max(score, 0),\n\t\tviolations,\n\t\tpasses,\n\t}\n}\n\n/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} analysis */\nexport function calculate(analysis) {\n\tconst performance = calculateScore({ result: analysis, guards: performanceGuards })\n\tconst maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })\n\tconst complexity = calculateScore({ result: analysis, guards: complexityGuards })\n\n\treturn {\n\t\t/** @deprecated */\n\t\tscore: 0,\n\t\tviolations: performance.violations\n\t\t\t.concat(maintainability.violations)\n\t\t\t.concat(complexity.violations),\n\t\tpasses: performance.passes\n\t\t\t.concat(maintainability.passes)\n\t\t\t.concat(complexity.passes),\n\t\tperformance,\n\t\tmaintainability,\n\t\tcomplexity,\n\t}\n}\n","import { analyze } from '@projectwallace/css-analyzer'\nimport { calculate as calculateFromAnalysis } from './core.js'\n\n/** @param {string} css */\nexport function calculate(css) {\n\tconst analysis = analyze(css)\n\treturn calculateFromAnalysis(analysis)\n}\n"],"names":["guards","result","id","score","atrules","import","total","value","actuals","Object","keys","unique","rules","empty","outcome","selectors","uniquenessRatio","Math","floor","declarations","ratio","stylesheet","size","comments","min","embeddedContent","sourceLinesOfCode","actual","mean","items","max","ceil","mode","rulesHavingMoreThanMode","filter","item","length","complexity","selectorsAboveMode","c","specificity","compareSpecificity","importants","calculateScore","violations","passes","guard","push","calculate","css","analysis","performance","performanceGuards","maintainability","maintainabilityGuards","complexityGuards","concat","calculateFromAnalysis","analyze"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-code-quality.module.js","sources":["../src/performance.js","../src/maintainability.js","../src/complexity.js","../src/core.js","../src/index.js"],"sourcesContent":["export const guards = [\n\n // Should not contain @import rules\n result => ({\n id: 'Imports',\n score: result.atrules.import.total * 10,\n value: result.atrules.import.total,\n actuals: Object.keys(result.atrules.import.unique),\n }),\n\n // Should not contain empty rules\n result => ({\n id: 'EmptyRules',\n score: result.rules.empty.total,\n value: result.rules.empty.total,\n }),\n\n // Too many selectors appear multiple times\n result => {\n const outcome = {\n id: 'SelectorDuplications',\n score: 0,\n value: 1 - result.selectors.uniquenessRatio,\n }\n\n if (result.selectors.uniquenessRatio < 0.66) {\n outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)\n }\n\n return outcome\n },\n\n // Too many declarations appear multiple times\n result => {\n const outcome = {\n id: 'DeclarationDuplications',\n score: 0,\n value: 1 - result.declarations.unique.ratio,\n }\n\n if (result.declarations.unique.ratio < 0.66) {\n outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)\n }\n\n return outcome\n },\n\n // The total amount of CSS should not be too high\n result => ({\n id: 'CssSize',\n score: result.stylesheet.size > 200_000 ? 5 : 0,\n value: result.stylesheet.size,\n }),\n\n // Should not contain (too much) comments\n // Deduct 1 point for every 250 bytes\n result => {\n const { comments } = result.stylesheet\n return {\n id: 'TooMuchComments',\n score: Math.min(10, Math.floor(comments.size / 250)),\n value: comments.size,\n }\n },\n\n // Should not contain too much embedded content\n // Deduct 1 point for every 250 bytes\n result => {\n const { size } = result.stylesheet.embeddedContent\n return {\n id: 'TooMuchEmbeddedContent',\n score: Math.min(20, Math.floor(size.total / 250)),\n value: size.total,\n actuals: Object.keys(result.stylesheet.embeddedContent.unique),\n }\n },\n]\n","export const guards = [\n\n // Source Lines of Code should be low'\n result => {\n const outcome = {\n id: 'SourceLinesOfCode',\n score: 0,\n value: result.stylesheet.sourceLinesOfCode,\n }\n\n if (result.stylesheet.sourceLinesOfCode > 10000) {\n // deduct 1 point per 1000 lines of code over 10,000\n const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Selectors per RuleSet should be low\n result => {\n const ALLOWED_SELECTORS_PER_RULESET = 2\n const actual = result.rules.selectors.mean\n\n const outcome = {\n id: 'AverageSelectorsPerRule',\n score: 0,\n value: actual,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 5 points per selector over 2\n if (actual > ALLOWED_SELECTORS_PER_RULESET) {\n const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Declarations per RuleSet should be low\n result => {\n const ALLOWED_DECLARATIONS_PER_RULESET = 5\n\n const outcome = {\n id: 'AverageDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mean,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 5 points per declaration over 5\n if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {\n const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Max number of Selectors per Rule should be low\n result => {\n const MAX_SELECTORS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.max,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 0.5 points per selectors over 10\n if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {\n const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)\n outcome.score = Math.min(score, 15)\n }\n\n return outcome\n },\n\n // Max number of Declarations per Rule should be low\n result => {\n const MAX_DECLARATIONS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.max,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 0.5 points per declarations over 10\n if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {\n const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Selectors per RuleSet should not differ too much from the most common amount of\n // Selectors per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.selectors.items\n .filter(item => item > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.mode,\n actuals: result.rules.selectors.items,\n }\n\n // if more than 10% of RuleSets has more Selectors than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Declarations per RuleSet should not differ too much from the most common amount of\n // Declarations per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length\n\n const outcome = {\n id: 'MoreThanMostCommonDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mode,\n actuals: result.rules.declarations.items,\n }\n\n // if more than 10% of RuleSets has more Declarations than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n]\n","import { compareSpecificity } from '@projectwallace/css-analyzer'\n\nexport const guards = [\n\n // Complexity per Selector should not differ too much from the most common Complexity\n result => {\n const mode = result.selectors.complexity.mode\n const selectorsAboveMode = result.selectors.complexity.items\n .filter(c => c > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorComplexity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.complexity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Specificity per Selector should not differ too much from the most common Specificity\n result => {\n const mode = result.selectors.specificity.mode\n const selectorsAboveMode = result.selectors.specificity.items\n .filter(c => compareSpecificity(c, mode) < 0)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorSpecificity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.specificity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Maximum Selector Complexity should be low\n result => {\n const MAX_SELECTOR_COMPLEXITY = 5\n const actual = result.selectors.complexity.max\n\n const outcome = {\n id: 'MaxSelectorComplexity',\n score: 0,\n value: result.selectors.complexity.max,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 0.5 points per complexity over 5, up to 5 points\n if (actual > MAX_SELECTOR_COMPLEXITY) {\n const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)\n outcome.score = Math.min(5, score)\n }\n\n return outcome\n },\n\n // Average Selector Complexity should be low\n result => {\n const ALLOWED_COMPLEXITY = 2\n const actual = result.selectors.complexity.mean\n\n const outcome = {\n id: 'AverageSelectorComplexity',\n score: 0,\n value: actual,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 2 points per selector over 2\n if (actual > ALLOWED_COMPLEXITY) {\n const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.selectors.id.ratio\n const outcome = {\n id: 'IdSelectorRatio',\n score: 0,\n value: actual,\n actuals: Object.keys(result.selectors.id.unique)\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.declarations.importants.ratio\n const outcome = {\n id: 'ImportantRatio',\n score: 0,\n value: actual,\n actuals: result.declarations.importants.total,\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n]\n","import { guards as performanceGuards } from './performance.js'\nimport { guards as maintainabilityGuards } from './maintainability.js'\nimport { guards as complexityGuards } from './complexity.js'\n\nfunction calculateScore({ result, guards }) {\n\tlet score = 100\n\tlet violations = []\n\tlet passes = []\n\n\tfor (const guard of guards) {\n\t\t/** @type {{score: number, value: number, id: string}} */\n\t\tconst outcome = guard(result)\n\n\t\tif (outcome.score > 0) {\n\t\t\tscore -= outcome.score\n\t\t\tviolations.push(outcome)\n\t\t} else {\n\t\t\tpasses.push(outcome)\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.max(score, 0),\n\t\tviolations,\n\t\tpasses,\n\t}\n}\n\nexport function calculate(analysis) {\n\tconst performance = calculateScore({ result: analysis, guards: performanceGuards })\n\tconst maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })\n\tconst complexity = calculateScore({ result: analysis, guards: complexityGuards })\n\n\treturn {\n\t\t/** @deprecated */\n\t\tscore: 0,\n\t\tviolations: performance.violations\n\t\t\t.concat(maintainability.violations)\n\t\t\t.concat(complexity.violations),\n\t\tpasses: performance.passes\n\t\t\t.concat(maintainability.passes)\n\t\t\t.concat(complexity.passes),\n\t\tperformance,\n\t\tmaintainability,\n\t\tcomplexity,\n\t}\n}\n","import { analyze } from '@projectwallace/css-analyzer'\nimport { calculate as calculateFromAnalysis } from './core.js'\n\nexport function calculate(css) {\n\tconst analysis = analyze(css)\n\treturn calculateFromAnalysis(analysis)\n}\n"],"names":["guards","result","id","score","atrules","total","value","actuals","Object","keys","unique","rules","empty","outcome","selectors","uniquenessRatio","Math","floor","declarations","ratio","stylesheet","size","comments","min","embeddedContent","sourceLinesOfCode","actual","mean","items","max","ceil","mode","rulesHavingMoreThanMode","filter","item","length","complexity","selectorsAboveMode","c","specificity","compareSpecificity","importants","calculateScore","violations","passes","guard","push","calculate","css","performance","analysis","analyze","performanceGuards","maintainability","maintainabilityGuards","complexityGuards","concat"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"css-code-quality.module.js","sources":["../src/performance.js","../src/maintainability.js","../src/complexity.js","../src/core.js","../src/index.js"],"sourcesContent":["export const guards = [\n\n // Should not contain @import rules\n result => ({\n id: 'Imports',\n score: result.atrules.import.total * 10,\n value: result.atrules.import.total,\n actuals: Object.keys(result.atrules.import.unique),\n }),\n\n // Should not contain empty rules\n result => ({\n id: 'EmptyRules',\n score: result.rules.empty.total,\n value: result.rules.empty.total,\n }),\n\n // Too many selectors appear multiple times\n result => {\n const outcome = {\n id: 'SelectorDuplications',\n score: 0,\n value: 1 - result.selectors.uniquenessRatio,\n }\n\n if (result.selectors.uniquenessRatio < 0.66) {\n outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)\n }\n\n return outcome\n },\n\n // Too many declarations appear multiple times\n result => {\n const outcome = {\n id: 'DeclarationDuplications',\n score: 0,\n value: 1 - result.declarations.unique.ratio,\n }\n\n if (result.declarations.unique.ratio < 0.66) {\n outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)\n }\n\n return outcome\n },\n\n // The total amount of CSS should not be too high\n result => ({\n id: 'CssSize',\n score: result.stylesheet.size > 200_000 ? 5 : 0,\n value: result.stylesheet.size,\n }),\n\n // Should not contain (too much) comments\n // Deduct 1 point for every 250 bytes\n result => {\n const { comments } = result.stylesheet\n return {\n id: 'TooMuchComments',\n score: Math.min(10, Math.floor(comments.size / 250)),\n value: comments.size,\n }\n },\n\n // Should not contain too much embedded content\n // Deduct 1 point for every 250 bytes\n result => {\n const { size } = result.stylesheet.embeddedContent\n return {\n id: 'TooMuchEmbeddedContent',\n score: Math.min(20, Math.floor(size.total / 250)),\n value: size.total,\n actuals: Object.keys(result.stylesheet.embeddedContent.unique),\n }\n },\n]\n","export const guards = [\n\n // Source Lines of Code should be low'\n result => {\n const outcome = {\n id: 'SourceLinesOfCode',\n score: 0,\n value: result.stylesheet.sourceLinesOfCode,\n }\n\n if (result.stylesheet.sourceLinesOfCode > 10000) {\n // deduct 1 point per 1000 lines of code over 10,000\n const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Selectors per RuleSet should be low\n result => {\n const ALLOWED_SELECTORS_PER_RULESET = 2\n const actual = result.rules.selectors.mean\n\n const outcome = {\n id: 'AverageSelectorsPerRule',\n score: 0,\n value: actual,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 5 points per selector over 2\n if (actual > ALLOWED_SELECTORS_PER_RULESET) {\n const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Declarations per RuleSet should be low\n result => {\n const ALLOWED_DECLARATIONS_PER_RULESET = 5\n\n const outcome = {\n id: 'AverageDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mean,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 5 points per declaration over 5\n if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {\n const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Max number of Selectors per Rule should be low\n result => {\n const MAX_SELECTORS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.max,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 0.5 points per selectors over 10\n if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {\n const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)\n outcome.score = Math.min(score, 15)\n }\n\n return outcome\n },\n\n // Max number of Declarations per Rule should be low\n result => {\n const MAX_DECLARATIONS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.max,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 0.5 points per declarations over 10\n if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {\n const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Selectors per RuleSet should not differ too much from the most common amount of\n // Selectors per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.selectors.items\n .filter(item => item > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.mode,\n actuals: result.rules.selectors.items,\n }\n\n // if more than 10% of RuleSets has more Selectors than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Declarations per RuleSet should not differ too much from the most common amount of\n // Declarations per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length\n\n const outcome = {\n id: 'MoreThanMostCommonDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mode,\n actuals: result.rules.declarations.items,\n }\n\n // if more than 10% of RuleSets has more Declarations than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n]\n","import { compareSpecificity } from '@projectwallace/css-analyzer'\n\nexport const guards = [\n\n // Complexity per Selector should not differ too much from the most common Complexity\n result => {\n const mode = result.selectors.complexity.mode\n const selectorsAboveMode = result.selectors.complexity.items\n .filter(c => c > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorComplexity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.complexity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Specificity per Selector should not differ too much from the most common Specificity\n result => {\n const mode = result.selectors.specificity.mode\n const selectorsAboveMode = result.selectors.specificity.items\n .filter(c => compareSpecificity(c, mode) < 0)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorSpecificity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.specificity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Maximum Selector Complexity should be low\n result => {\n const MAX_SELECTOR_COMPLEXITY = 5\n const actual = result.selectors.complexity.max\n\n const outcome = {\n id: 'MaxSelectorComplexity',\n score: 0,\n value: result.selectors.complexity.max,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 0.5 points per complexity over 5, up to 5 points\n if (actual > MAX_SELECTOR_COMPLEXITY) {\n const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)\n outcome.score = Math.min(5, score)\n }\n\n return outcome\n },\n\n // Average Selector Complexity should be low\n result => {\n const ALLOWED_COMPLEXITY = 2\n const actual = result.selectors.complexity.mean\n\n const outcome = {\n id: 'AverageSelectorComplexity',\n score: 0,\n value: actual,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 2 points per selector over 2\n if (actual > ALLOWED_COMPLEXITY) {\n const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.selectors.id.ratio\n const outcome = {\n id: 'IdSelectorRatio',\n score: 0,\n value: actual,\n actuals: Object.keys(result.selectors.id.unique)\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.declarations.importants.ratio\n const outcome = {\n id: 'ImportantRatio',\n score: 0,\n value: actual,\n actuals: result.declarations.importants.total,\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n]\n","import { guards as performanceGuards } from './performance.js'\nimport { guards as maintainabilityGuards } from './maintainability.js'\nimport { guards as complexityGuards } from './complexity.js'\n\nfunction calculateScore({ result, guards }) {\n\tlet score = 100\n\tlet violations = []\n\tlet passes = []\n\n\tfor (const guard of guards) {\n\t\t/** @type {{score: number, value: number, id: string}} */\n\t\tconst outcome = guard(result)\n\n\t\tif (outcome.score > 0) {\n\t\t\tscore -= outcome.score\n\t\t\tviolations.push(outcome)\n\t\t} else {\n\t\t\tpasses.push(outcome)\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.max(score, 0),\n\t\tviolations,\n\t\tpasses,\n\t}\n}\n\n/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} analysis */\nexport function calculate(analysis) {\n\tconst performance = calculateScore({ result: analysis, guards: performanceGuards })\n\tconst maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })\n\tconst complexity = calculateScore({ result: analysis, guards: complexityGuards })\n\n\treturn {\n\t\t/** @deprecated */\n\t\tscore: 0,\n\t\tviolations: performance.violations\n\t\t\t.concat(maintainability.violations)\n\t\t\t.concat(complexity.violations),\n\t\tpasses: performance.passes\n\t\t\t.concat(maintainability.passes)\n\t\t\t.concat(complexity.passes),\n\t\tperformance,\n\t\tmaintainability,\n\t\tcomplexity,\n\t}\n}\n","import { analyze } from '@projectwallace/css-analyzer'\nimport { calculate as calculateFromAnalysis } from './core.js'\n\n/** @param {string} css */\nexport function calculate(css) {\n\tconst analysis = analyze(css)\n\treturn calculateFromAnalysis(analysis)\n}\n"],"names":["guards","result","id","score","atrules","total","value","actuals","Object","keys","unique","rules","empty","outcome","selectors","uniquenessRatio","Math","floor","declarations","ratio","stylesheet","size","comments","min","embeddedContent","sourceLinesOfCode","actual","mean","items","max","ceil","mode","rulesHavingMoreThanMode","filter","item","length","complexity","selectorsAboveMode","c","specificity","compareSpecificity","importants","calculateScore","_ref","_step","violations","passes","_iterator","_createForOfIteratorHelperLoose","done","guard","push","calculate","css","performance","analysis","analyze","performanceGuards","maintainability","maintainabilityGuards","complexityGuards","concat"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-code-quality.umd.js","sources":["../src/performance.js","../src/maintainability.js","../src/complexity.js","../src/core.js","../src/index.js"],"sourcesContent":["export const guards = [\n\n // Should not contain @import rules\n result => ({\n id: 'Imports',\n score: result.atrules.import.total * 10,\n value: result.atrules.import.total,\n actuals: Object.keys(result.atrules.import.unique),\n }),\n\n // Should not contain empty rules\n result => ({\n id: 'EmptyRules',\n score: result.rules.empty.total,\n value: result.rules.empty.total,\n }),\n\n // Too many selectors appear multiple times\n result => {\n const outcome = {\n id: 'SelectorDuplications',\n score: 0,\n value: 1 - result.selectors.uniquenessRatio,\n }\n\n if (result.selectors.uniquenessRatio < 0.66) {\n outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)\n }\n\n return outcome\n },\n\n // Too many declarations appear multiple times\n result => {\n const outcome = {\n id: 'DeclarationDuplications',\n score: 0,\n value: 1 - result.declarations.unique.ratio,\n }\n\n if (result.declarations.unique.ratio < 0.66) {\n outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)\n }\n\n return outcome\n },\n\n // The total amount of CSS should not be too high\n result => ({\n id: 'CssSize',\n score: result.stylesheet.size > 200_000 ? 5 : 0,\n value: result.stylesheet.size,\n }),\n\n // Should not contain (too much) comments\n // Deduct 1 point for every 250 bytes\n result => {\n const { comments } = result.stylesheet\n return {\n id: 'TooMuchComments',\n score: Math.min(10, Math.floor(comments.size / 250)),\n value: comments.size,\n }\n },\n\n // Should not contain too much embedded content\n // Deduct 1 point for every 250 bytes\n result => {\n const { size } = result.stylesheet.embeddedContent\n return {\n id: 'TooMuchEmbeddedContent',\n score: Math.min(20, Math.floor(size.total / 250)),\n value: size.total,\n actuals: Object.keys(result.stylesheet.embeddedContent.unique),\n }\n },\n]\n","export const guards = [\n\n // Source Lines of Code should be low'\n result => {\n const outcome = {\n id: 'SourceLinesOfCode',\n score: 0,\n value: result.stylesheet.sourceLinesOfCode,\n }\n\n if (result.stylesheet.sourceLinesOfCode > 10000) {\n // deduct 1 point per 1000 lines of code over 10,000\n const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Selectors per RuleSet should be low\n result => {\n const ALLOWED_SELECTORS_PER_RULESET = 2\n const actual = result.rules.selectors.mean\n\n const outcome = {\n id: 'AverageSelectorsPerRule',\n score: 0,\n value: actual,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 5 points per selector over 2\n if (actual > ALLOWED_SELECTORS_PER_RULESET) {\n const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Declarations per RuleSet should be low\n result => {\n const ALLOWED_DECLARATIONS_PER_RULESET = 5\n\n const outcome = {\n id: 'AverageDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mean,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 5 points per declaration over 5\n if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {\n const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Max number of Selectors per Rule should be low\n result => {\n const MAX_SELECTORS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.max,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 0.5 points per selectors over 10\n if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {\n const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)\n outcome.score = Math.min(score, 15)\n }\n\n return outcome\n },\n\n // Max number of Declarations per Rule should be low\n result => {\n const MAX_DECLARATIONS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.max,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 0.5 points per declarations over 10\n if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {\n const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Selectors per RuleSet should not differ too much from the most common amount of\n // Selectors per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.selectors.items\n .filter(item => item > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.mode,\n actuals: result.rules.selectors.items,\n }\n\n // if more than 10% of RuleSets has more Selectors than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Declarations per RuleSet should not differ too much from the most common amount of\n // Declarations per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length\n\n const outcome = {\n id: 'MoreThanMostCommonDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mode,\n actuals: result.rules.declarations.items,\n }\n\n // if more than 10% of RuleSets has more Declarations than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n]\n","import { compareSpecificity } from '@projectwallace/css-analyzer'\n\nexport const guards = [\n\n // Complexity per Selector should not differ too much from the most common Complexity\n result => {\n const mode = result.selectors.complexity.mode\n const selectorsAboveMode = result.selectors.complexity.items\n .filter(c => c > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorComplexity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.complexity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Specificity per Selector should not differ too much from the most common Specificity\n result => {\n const mode = result.selectors.specificity.mode\n const selectorsAboveMode = result.selectors.specificity.items\n .filter(c => compareSpecificity(c, mode) < 0)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorSpecificity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.specificity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Maximum Selector Complexity should be low\n result => {\n const MAX_SELECTOR_COMPLEXITY = 5\n const actual = result.selectors.complexity.max\n\n const outcome = {\n id: 'MaxSelectorComplexity',\n score: 0,\n value: result.selectors.complexity.max,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 0.5 points per complexity over 5, up to 5 points\n if (actual > MAX_SELECTOR_COMPLEXITY) {\n const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)\n outcome.score = Math.min(5, score)\n }\n\n return outcome\n },\n\n // Average Selector Complexity should be low\n result => {\n const ALLOWED_COMPLEXITY = 2\n const actual = result.selectors.complexity.mean\n\n const outcome = {\n id: 'AverageSelectorComplexity',\n score: 0,\n value: actual,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 2 points per selector over 2\n if (actual > ALLOWED_COMPLEXITY) {\n const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.selectors.id.ratio\n const outcome = {\n id: 'IdSelectorRatio',\n score: 0,\n value: actual,\n actuals: Object.keys(result.selectors.id.unique)\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.declarations.importants.ratio\n const outcome = {\n id: 'ImportantRatio',\n score: 0,\n value: actual,\n actuals: result.declarations.importants.total,\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n]\n","import { guards as performanceGuards } from './performance.js'\nimport { guards as maintainabilityGuards } from './maintainability.js'\nimport { guards as complexityGuards } from './complexity.js'\n\nfunction calculateScore({ result, guards }) {\n\tlet score = 100\n\tlet violations = []\n\tlet passes = []\n\n\tfor (const guard of guards) {\n\t\t/** @type {{score: number, value: number, id: string}} */\n\t\tconst outcome = guard(result)\n\n\t\tif (outcome.score > 0) {\n\t\t\tscore -= outcome.score\n\t\t\tviolations.push(outcome)\n\t\t} else {\n\t\t\tpasses.push(outcome)\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.max(score, 0),\n\t\tviolations,\n\t\tpasses,\n\t}\n}\n\nexport function calculate(analysis) {\n\tconst performance = calculateScore({ result: analysis, guards: performanceGuards })\n\tconst maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })\n\tconst complexity = calculateScore({ result: analysis, guards: complexityGuards })\n\n\treturn {\n\t\t/** @deprecated */\n\t\tscore: 0,\n\t\tviolations: performance.violations\n\t\t\t.concat(maintainability.violations)\n\t\t\t.concat(complexity.violations),\n\t\tpasses: performance.passes\n\t\t\t.concat(maintainability.passes)\n\t\t\t.concat(complexity.passes),\n\t\tperformance,\n\t\tmaintainability,\n\t\tcomplexity,\n\t}\n}\n","import { analyze } from '@projectwallace/css-analyzer'\nimport { calculate as calculateFromAnalysis } from './core.js'\n\nexport function calculate(css) {\n\tconst analysis = analyze(css)\n\treturn calculateFromAnalysis(analysis)\n}\n"],"names":["guards","result","id","score","atrules","total","value","actuals","Object","keys","unique","rules","empty","outcome","selectors","uniquenessRatio","Math","floor","declarations","ratio","stylesheet","size","comments","min","embeddedContent","sourceLinesOfCode","actual","mean","items","max","ceil","mode","rulesHavingMoreThanMode","filter","item","length","complexity","selectorsAboveMode","c","specificity","compareSpecificity","importants","calculateScore","violations","passes","guard","push","css","performance","analysis","analyze","performanceGuards","maintainability","maintainabilityGuards","complexityGuards","concat"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"css-code-quality.umd.js","sources":["../src/performance.js","../src/maintainability.js","../src/complexity.js","../src/core.js","../src/index.js"],"sourcesContent":["export const guards = [\n\n // Should not contain @import rules\n result => ({\n id: 'Imports',\n score: result.atrules.import.total * 10,\n value: result.atrules.import.total,\n actuals: Object.keys(result.atrules.import.unique),\n }),\n\n // Should not contain empty rules\n result => ({\n id: 'EmptyRules',\n score: result.rules.empty.total,\n value: result.rules.empty.total,\n }),\n\n // Too many selectors appear multiple times\n result => {\n const outcome = {\n id: 'SelectorDuplications',\n score: 0,\n value: 1 - result.selectors.uniquenessRatio,\n }\n\n if (result.selectors.uniquenessRatio < 0.66) {\n outcome.score = Math.floor((1 - result.selectors.uniquenessRatio) * 10)\n }\n\n return outcome\n },\n\n // Too many declarations appear multiple times\n result => {\n const outcome = {\n id: 'DeclarationDuplications',\n score: 0,\n value: 1 - result.declarations.unique.ratio,\n }\n\n if (result.declarations.unique.ratio < 0.66) {\n outcome.score = Math.floor((1 - result.declarations.unique.ratio) * 10)\n }\n\n return outcome\n },\n\n // The total amount of CSS should not be too high\n result => ({\n id: 'CssSize',\n score: result.stylesheet.size > 200_000 ? 5 : 0,\n value: result.stylesheet.size,\n }),\n\n // Should not contain (too much) comments\n // Deduct 1 point for every 250 bytes\n result => {\n const { comments } = result.stylesheet\n return {\n id: 'TooMuchComments',\n score: Math.min(10, Math.floor(comments.size / 250)),\n value: comments.size,\n }\n },\n\n // Should not contain too much embedded content\n // Deduct 1 point for every 250 bytes\n result => {\n const { size } = result.stylesheet.embeddedContent\n return {\n id: 'TooMuchEmbeddedContent',\n score: Math.min(20, Math.floor(size.total / 250)),\n value: size.total,\n actuals: Object.keys(result.stylesheet.embeddedContent.unique),\n }\n },\n]\n","export const guards = [\n\n // Source Lines of Code should be low'\n result => {\n const outcome = {\n id: 'SourceLinesOfCode',\n score: 0,\n value: result.stylesheet.sourceLinesOfCode,\n }\n\n if (result.stylesheet.sourceLinesOfCode > 10000) {\n // deduct 1 point per 1000 lines of code over 10,000\n const score = Math.floor((result.stylesheet.sourceLinesOfCode - 10000) / 1000)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Selectors per RuleSet should be low\n result => {\n const ALLOWED_SELECTORS_PER_RULESET = 2\n const actual = result.rules.selectors.mean\n\n const outcome = {\n id: 'AverageSelectorsPerRule',\n score: 0,\n value: actual,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 5 points per selector over 2\n if (actual > ALLOWED_SELECTORS_PER_RULESET) {\n const score = Math.floor((actual - ALLOWED_SELECTORS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Average count of Declarations per RuleSet should be low\n result => {\n const ALLOWED_DECLARATIONS_PER_RULESET = 5\n\n const outcome = {\n id: 'AverageDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mean,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 5 points per declaration over 5\n if (result.rules.declarations.mean > ALLOWED_DECLARATIONS_PER_RULESET) {\n const score = Math.floor((result.rules.declarations.mean - ALLOWED_DECLARATIONS_PER_RULESET) * 5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Max number of Selectors per Rule should be low\n result => {\n const MAX_SELECTORS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.max,\n actuals: result.rules.selectors.items,\n }\n\n // Deduct 0.5 points per selectors over 10\n if (result.rules.selectors.max > MAX_SELECTORS_PER_RULESET) {\n const score = Math.ceil((result.rules.selectors.max - MAX_SELECTORS_PER_RULESET) * 0.5)\n outcome.score = Math.min(score, 15)\n }\n\n return outcome\n },\n\n // Max number of Declarations per Rule should be low\n result => {\n const MAX_DECLARATIONS_PER_RULESET = 10\n\n const outcome = {\n id: 'MaxDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.max,\n actuals: result.rules.declarations.items,\n }\n\n // Deduct 0.5 points per declarations over 10\n if (result.rules.declarations.max > MAX_DECLARATIONS_PER_RULESET) {\n const score = Math.ceil((result.rules.declarations.max - MAX_DECLARATIONS_PER_RULESET) * 0.5)\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Selectors per RuleSet should not differ too much from the most common amount of\n // Selectors per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.selectors.items\n .filter(item => item > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorsPerRule',\n score: 0,\n value: result.rules.selectors.mode,\n actuals: result.rules.selectors.items,\n }\n\n // if more than 10% of RuleSets has more Selectors than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n\n // Number of Declarations per RuleSet should not differ too much from the most common amount of\n // Declarations per RuleSet\n result => {\n const mode = result.rules.selectors.mode\n const rulesHavingMoreThanMode = result.rules.declarations.items.filter(item => item > mode).length\n\n const outcome = {\n id: 'MoreThanMostCommonDeclarationsPerRule',\n score: 0,\n value: result.rules.declarations.mode,\n actuals: result.rules.declarations.items,\n }\n\n // if more than 10% of RuleSets has more Declarations than most common:\n if (rulesHavingMoreThanMode > result.rules.total * 0.1) {\n // then deduct 0.01 for ever applicable RuleSet\n const score = Math.floor(rulesHavingMoreThanMode * 0.01)\n // with a maximum of 10 points\n outcome.score = Math.min(15, score)\n }\n\n return outcome\n },\n]\n","import { compareSpecificity } from '@projectwallace/css-analyzer'\n\nexport const guards = [\n\n // Complexity per Selector should not differ too much from the most common Complexity\n result => {\n const mode = result.selectors.complexity.mode\n const selectorsAboveMode = result.selectors.complexity.items\n .filter(c => c > mode)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorComplexity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.complexity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Specificity per Selector should not differ too much from the most common Specificity\n result => {\n const mode = result.selectors.specificity.mode\n const selectorsAboveMode = result.selectors.specificity.items\n .filter(c => compareSpecificity(c, mode) < 0)\n .length\n\n const outcome = {\n id: 'MoreThanMostCommonSelectorSpecificity',\n score: 0,\n value: result.selectors.total === 0 ? 0 : selectorsAboveMode / result.selectors.total,\n actuals: result.selectors.specificity.items,\n }\n\n if (selectorsAboveMode > result.selectors.total * 0.1) {\n const score = Math.floor(selectorsAboveMode * 0.01)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n // Maximum Selector Complexity should be low\n result => {\n const MAX_SELECTOR_COMPLEXITY = 5\n const actual = result.selectors.complexity.max\n\n const outcome = {\n id: 'MaxSelectorComplexity',\n score: 0,\n value: result.selectors.complexity.max,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 0.5 points per complexity over 5, up to 5 points\n if (actual > MAX_SELECTOR_COMPLEXITY) {\n const score = Math.ceil((actual - MAX_SELECTOR_COMPLEXITY) * 0.5)\n outcome.score = Math.min(5, score)\n }\n\n return outcome\n },\n\n // Average Selector Complexity should be low\n result => {\n const ALLOWED_COMPLEXITY = 2\n const actual = result.selectors.complexity.mean\n\n const outcome = {\n id: 'AverageSelectorComplexity',\n score: 0,\n value: actual,\n actuals: result.selectors.complexity.items,\n }\n\n // Deduct 2 points per selector over 2\n if (actual > ALLOWED_COMPLEXITY) {\n const score = Math.ceil((actual - ALLOWED_COMPLEXITY) * 2)\n outcome.score = Math.min(10, score)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.selectors.id.ratio\n const outcome = {\n id: 'IdSelectorRatio',\n score: 0,\n value: actual,\n actuals: Object.keys(result.selectors.id.unique)\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n\n result => {\n const ALLOWED = 0.01\n const actual = result.declarations.importants.ratio\n const outcome = {\n id: 'ImportantRatio',\n score: 0,\n value: actual,\n actuals: result.declarations.importants.total,\n }\n\n if (actual > ALLOWED) {\n const score = Math.floor((actual - ALLOWED) * 10)\n outcome.score = Math.min(score, 5)\n }\n\n return outcome\n },\n]\n","import { guards as performanceGuards } from './performance.js'\nimport { guards as maintainabilityGuards } from './maintainability.js'\nimport { guards as complexityGuards } from './complexity.js'\n\nfunction calculateScore({ result, guards }) {\n\tlet score = 100\n\tlet violations = []\n\tlet passes = []\n\n\tfor (const guard of guards) {\n\t\t/** @type {{score: number, value: number, id: string}} */\n\t\tconst outcome = guard(result)\n\n\t\tif (outcome.score > 0) {\n\t\t\tscore -= outcome.score\n\t\t\tviolations.push(outcome)\n\t\t} else {\n\t\t\tpasses.push(outcome)\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.max(score, 0),\n\t\tviolations,\n\t\tpasses,\n\t}\n}\n\n/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} analysis */\nexport function calculate(analysis) {\n\tconst performance = calculateScore({ result: analysis, guards: performanceGuards })\n\tconst maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })\n\tconst complexity = calculateScore({ result: analysis, guards: complexityGuards })\n\n\treturn {\n\t\t/** @deprecated */\n\t\tscore: 0,\n\t\tviolations: performance.violations\n\t\t\t.concat(maintainability.violations)\n\t\t\t.concat(complexity.violations),\n\t\tpasses: performance.passes\n\t\t\t.concat(maintainability.passes)\n\t\t\t.concat(complexity.passes),\n\t\tperformance,\n\t\tmaintainability,\n\t\tcomplexity,\n\t}\n}\n","import { analyze } from '@projectwallace/css-analyzer'\nimport { calculate as calculateFromAnalysis } from './core.js'\n\n/** @param {string} css */\nexport function calculate(css) {\n\tconst analysis = analyze(css)\n\treturn calculateFromAnalysis(analysis)\n}\n"],"names":["guards","result","id","score","atrules","total","value","actuals","Object","keys","unique","rules","empty","outcome","selectors","uniquenessRatio","Math","floor","declarations","ratio","stylesheet","size","comments","min","embeddedContent","sourceLinesOfCode","actual","mean","items","max","ceil","mode","rulesHavingMoreThanMode","filter","item","length","complexity","selectorsAboveMode","c","specificity","compareSpecificity","importants","calculateScore","_ref","_step","violations","passes","_iterator","_createForOfIteratorHelperLoose","done","guard","push","css","performance","analysis","analyze","performanceGuards","maintainability","maintainabilityGuards","complexityGuards","concat"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"repository": "git@github.com:projectwallace/css-code-quality.git",
|
|
6
6
|
"author": {
|
|
7
7
|
"email": "bart@projectwallace.com",
|
|
@@ -37,13 +37,15 @@
|
|
|
37
37
|
"types": "./dist/index.d.ts",
|
|
38
38
|
"scripts": {
|
|
39
39
|
"test": "uvu",
|
|
40
|
+
"lint": "oxlint",
|
|
40
41
|
"build": "microbundle"
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
|
-
"@projectwallace/css-analyzer": "^5.
|
|
44
|
+
"@projectwallace/css-analyzer": "^5.14.0"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"microbundle": "^0.15.1",
|
|
48
|
+
"oxlint": "^0.2.13",
|
|
47
49
|
"uvu": "^0.5.6"
|
|
48
50
|
}
|
|
49
51
|
}
|
package/readme.md
CHANGED
|
@@ -22,8 +22,77 @@
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
-
This package analyzes your CSS on a high level and comes up with a score, divided
|
|
25
|
+
This package analyzes your CSS on a high level and comes up with a score, divided into three areas:
|
|
26
26
|
|
|
27
27
|
- **Maintainability**: how difficult is it for someone looking at the CSS from a high level to find the exact spot to fix a bug?
|
|
28
|
-
- **Complexity**: how difficult is it for someone to make a change and
|
|
29
|
-
- **Performance**: How likely is the CSS to have a negative impact on performance, based on high-level metrics? (Not including using hardware accelerated transforms and the like, because other tools are more
|
|
28
|
+
- **Complexity**: how difficult is it for someone to make a change and be confident that they can make that change without side effects?
|
|
29
|
+
- **Performance**: How likely is the CSS to have a negative impact on performance, based on high-level metrics? (Not including using hardware accelerated transforms and the like, because other tools are more suited for that.)
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install @projectwallace/css-code-quality
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
import { calculate } from "@projectwallace/css-code-quality";
|
|
41
|
+
|
|
42
|
+
let css = `my_css { /* ... */ }`;
|
|
43
|
+
let result = calculate(css);
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
The result shape looks something like this:
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
"violations": [ ],
|
|
50
|
+
"passes": [ ],
|
|
51
|
+
"performance": {
|
|
52
|
+
"score": 90,
|
|
53
|
+
"violations": [ ],
|
|
54
|
+
"passes": [ ]
|
|
55
|
+
},
|
|
56
|
+
"maintainability": {
|
|
57
|
+
"score": 100,
|
|
58
|
+
"violations": [ ],
|
|
59
|
+
"passes": [ ]
|
|
60
|
+
},
|
|
61
|
+
"complexity": {
|
|
62
|
+
"score": 97,
|
|
63
|
+
"violations": [ ],
|
|
64
|
+
"passes": [ ]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Each `passes` or `violations` array contains an object that looks like this:
|
|
69
|
+
|
|
70
|
+
{
|
|
71
|
+
"id": "EmptyRules",
|
|
72
|
+
"score": 0,
|
|
73
|
+
"value": 0
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "AverageSelectorsPerRule",
|
|
77
|
+
"score": 0,
|
|
78
|
+
"value": 1.5,
|
|
79
|
+
"actuals": [
|
|
80
|
+
2,
|
|
81
|
+
1
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
etc. etc.
|
|
86
|
+
|
|
87
|
+
*/
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Related projects
|
|
91
|
+
|
|
92
|
+
- [CSS Analyzer](https://github.com/projectwallace/css-analyzer) -
|
|
93
|
+
A CSS Analyzer that goes through your CSS to find all kinds of relevant statistics.
|
|
94
|
+
- [Wallace CLI](https://github.com/projectwallace/wallace-cli) - CLI tool for
|
|
95
|
+
@projectwallace/css-analyzer
|
|
96
|
+
- [Constyble](https://github.com/projectwallace/constyble) - CSS Complexity linter
|
|
97
|
+
- [Color Sorter](https://github.com/projectwallace/color-sorter) - Sort CSS colors
|
|
98
|
+
by hue, saturation, lightness and opacity
|
package/src/complexity.test.js
CHANGED
|
@@ -6,13 +6,13 @@ const Complexity = suite('Complexity')
|
|
|
6
6
|
|
|
7
7
|
Complexity('should deduct points for a lot of Selectors more complex than most common Complexity', () => {
|
|
8
8
|
const fixture = `
|
|
9
|
-
${
|
|
9
|
+
${Array.from({ length: 1000 })
|
|
10
10
|
.fill('')
|
|
11
11
|
.map(_ => `selector { }`)
|
|
12
12
|
.join('')
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
${
|
|
15
|
+
${Array.from({ length: 500 })
|
|
16
16
|
.fill('')
|
|
17
17
|
.map(_ => `:where(selector) { }`)
|
|
18
18
|
.join('')
|
|
@@ -25,7 +25,7 @@ Complexity('should deduct points for a lot of Selectors more complex than most c
|
|
|
25
25
|
id: 'MoreThanMostCommonSelectorComplexity',
|
|
26
26
|
score: 5,
|
|
27
27
|
value: 1 / 3,
|
|
28
|
-
actuals: (
|
|
28
|
+
actuals: (Array.from({ length: 1000 }).fill(1)).concat(Array.from({ length: 500 }).fill(2)),
|
|
29
29
|
}
|
|
30
30
|
])
|
|
31
31
|
assert.is(actual.complexity.score, 95)
|
|
@@ -33,13 +33,13 @@ Complexity('should deduct points for a lot of Selectors more complex than most c
|
|
|
33
33
|
|
|
34
34
|
Complexity('should deduct points for a lot of Selectors more complex than most common Specificity', () => {
|
|
35
35
|
const fixture = `
|
|
36
|
-
${
|
|
36
|
+
${Array.from({ length: 500 })
|
|
37
37
|
.fill('')
|
|
38
38
|
.map(_ => `selector1 { }`)
|
|
39
39
|
.join('')
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
${
|
|
42
|
+
${Array.from({ length: 200 })
|
|
43
43
|
.fill('')
|
|
44
44
|
.map(_ => `.selector { }`)
|
|
45
45
|
.join('')
|
|
@@ -52,7 +52,7 @@ Complexity('should deduct points for a lot of Selectors more complex than most c
|
|
|
52
52
|
id: 'MoreThanMostCommonSelectorSpecificity',
|
|
53
53
|
score: 2,
|
|
54
54
|
value: 200 / 700,
|
|
55
|
-
actuals: (
|
|
55
|
+
actuals: (Array.from({ length: 500 }).fill([0, 0, 1])).concat(Array.from({ length: 200 }).fill([0, 1, 0])),
|
|
56
56
|
}
|
|
57
57
|
])
|
|
58
58
|
assert.is(actual.complexity.score, 98)
|
package/src/core.js
CHANGED
|
@@ -26,6 +26,7 @@ function calculateScore({ result, guards }) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/** @param {ReturnType<import('@projectwallace/css-analyzer').analyze>} analysis */
|
|
29
30
|
export function calculate(analysis) {
|
|
30
31
|
const performance = calculateScore({ result: analysis, guards: performanceGuards })
|
|
31
32
|
const maintainability = calculateScore({ result: analysis, guards: maintainabilityGuards })
|
package/src/index.js
CHANGED
package/src/index.test.js
CHANGED
|
@@ -9,6 +9,377 @@ Index('exposes a calculcate function', () => {
|
|
|
9
9
|
assert.is(typeof calculate, 'function')
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
+
Index('smoke test', () => {
|
|
13
|
+
let css = `
|
|
14
|
+
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
|
|
15
|
+
|
|
16
|
+
.my_test,
|
|
17
|
+
.my_extra_test {
|
|
18
|
+
color: red;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#my_test {
|
|
22
|
+
color: green;
|
|
23
|
+
}
|
|
24
|
+
`
|
|
25
|
+
let result = calculate(css)
|
|
26
|
+
assert.equal(result, {
|
|
27
|
+
"score": 0,
|
|
28
|
+
"violations": [
|
|
29
|
+
{
|
|
30
|
+
"id": "Imports",
|
|
31
|
+
"score": 10,
|
|
32
|
+
"value": 1,
|
|
33
|
+
"actuals": [
|
|
34
|
+
"url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap')"
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "IdSelectorRatio",
|
|
39
|
+
"score": 3,
|
|
40
|
+
"value": 0.3333333333333333,
|
|
41
|
+
"actuals": [
|
|
42
|
+
"#my_test"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"passes": [
|
|
47
|
+
{
|
|
48
|
+
"id": "EmptyRules",
|
|
49
|
+
"score": 0,
|
|
50
|
+
"value": 0
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "SelectorDuplications",
|
|
54
|
+
"score": 0,
|
|
55
|
+
"value": 0
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"id": "DeclarationDuplications",
|
|
59
|
+
"score": 0,
|
|
60
|
+
"value": 0
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "CssSize",
|
|
64
|
+
"score": 0,
|
|
65
|
+
"value": 180
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "TooMuchComments",
|
|
69
|
+
"score": 0,
|
|
70
|
+
"value": 0
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "TooMuchEmbeddedContent",
|
|
74
|
+
"score": 0,
|
|
75
|
+
"value": 0,
|
|
76
|
+
"actuals": []
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "SourceLinesOfCode",
|
|
80
|
+
"score": 0,
|
|
81
|
+
"value": 6
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "AverageSelectorsPerRule",
|
|
85
|
+
"score": 0,
|
|
86
|
+
"value": 1.5,
|
|
87
|
+
"actuals": [
|
|
88
|
+
2,
|
|
89
|
+
1
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "AverageDeclarationsPerRule",
|
|
94
|
+
"score": 0,
|
|
95
|
+
"value": 1,
|
|
96
|
+
"actuals": [
|
|
97
|
+
1,
|
|
98
|
+
1
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "MaxSelectorsPerRule",
|
|
103
|
+
"score": 0,
|
|
104
|
+
"value": 2,
|
|
105
|
+
"actuals": [
|
|
106
|
+
2,
|
|
107
|
+
1
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "MaxDeclarationsPerRule",
|
|
112
|
+
"score": 0,
|
|
113
|
+
"value": 1,
|
|
114
|
+
"actuals": [
|
|
115
|
+
1,
|
|
116
|
+
1
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"id": "MoreThanMostCommonSelectorsPerRule",
|
|
121
|
+
"score": 0,
|
|
122
|
+
"value": 1.5,
|
|
123
|
+
"actuals": [
|
|
124
|
+
2,
|
|
125
|
+
1
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"id": "MoreThanMostCommonDeclarationsPerRule",
|
|
130
|
+
"score": 0,
|
|
131
|
+
"value": 1,
|
|
132
|
+
"actuals": [
|
|
133
|
+
1,
|
|
134
|
+
1
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"id": "MoreThanMostCommonSelectorComplexity",
|
|
139
|
+
"score": 0,
|
|
140
|
+
"value": 0,
|
|
141
|
+
"actuals": [
|
|
142
|
+
1,
|
|
143
|
+
1,
|
|
144
|
+
1
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"id": "MoreThanMostCommonSelectorSpecificity",
|
|
149
|
+
"score": 0,
|
|
150
|
+
"value": 0.3333333333333333,
|
|
151
|
+
"actuals": [
|
|
152
|
+
[
|
|
153
|
+
0,
|
|
154
|
+
1,
|
|
155
|
+
0
|
|
156
|
+
],
|
|
157
|
+
[
|
|
158
|
+
0,
|
|
159
|
+
1,
|
|
160
|
+
0
|
|
161
|
+
],
|
|
162
|
+
[
|
|
163
|
+
1,
|
|
164
|
+
0,
|
|
165
|
+
0
|
|
166
|
+
]
|
|
167
|
+
]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"id": "MaxSelectorComplexity",
|
|
171
|
+
"score": 0,
|
|
172
|
+
"value": 1,
|
|
173
|
+
"actuals": [
|
|
174
|
+
1,
|
|
175
|
+
1,
|
|
176
|
+
1
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"id": "AverageSelectorComplexity",
|
|
181
|
+
"score": 0,
|
|
182
|
+
"value": 1,
|
|
183
|
+
"actuals": [
|
|
184
|
+
1,
|
|
185
|
+
1,
|
|
186
|
+
1
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "ImportantRatio",
|
|
191
|
+
"score": 0,
|
|
192
|
+
"value": 0,
|
|
193
|
+
"actuals": 0
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
"performance": {
|
|
197
|
+
"score": 90,
|
|
198
|
+
"violations": [
|
|
199
|
+
{
|
|
200
|
+
"id": "Imports",
|
|
201
|
+
"score": 10,
|
|
202
|
+
"value": 1,
|
|
203
|
+
"actuals": [
|
|
204
|
+
"url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap')"
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
],
|
|
208
|
+
"passes": [
|
|
209
|
+
{
|
|
210
|
+
"id": "EmptyRules",
|
|
211
|
+
"score": 0,
|
|
212
|
+
"value": 0
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"id": "SelectorDuplications",
|
|
216
|
+
"score": 0,
|
|
217
|
+
"value": 0
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"id": "DeclarationDuplications",
|
|
221
|
+
"score": 0,
|
|
222
|
+
"value": 0
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"id": "CssSize",
|
|
226
|
+
"score": 0,
|
|
227
|
+
"value": 180
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"id": "TooMuchComments",
|
|
231
|
+
"score": 0,
|
|
232
|
+
"value": 0
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"id": "TooMuchEmbeddedContent",
|
|
236
|
+
"score": 0,
|
|
237
|
+
"value": 0,
|
|
238
|
+
"actuals": []
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
"maintainability": {
|
|
243
|
+
"score": 100,
|
|
244
|
+
"violations": [],
|
|
245
|
+
"passes": [
|
|
246
|
+
{
|
|
247
|
+
"id": "SourceLinesOfCode",
|
|
248
|
+
"score": 0,
|
|
249
|
+
"value": 6
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"id": "AverageSelectorsPerRule",
|
|
253
|
+
"score": 0,
|
|
254
|
+
"value": 1.5,
|
|
255
|
+
"actuals": [
|
|
256
|
+
2,
|
|
257
|
+
1
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"id": "AverageDeclarationsPerRule",
|
|
262
|
+
"score": 0,
|
|
263
|
+
"value": 1,
|
|
264
|
+
"actuals": [
|
|
265
|
+
1,
|
|
266
|
+
1
|
|
267
|
+
]
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"id": "MaxSelectorsPerRule",
|
|
271
|
+
"score": 0,
|
|
272
|
+
"value": 2,
|
|
273
|
+
"actuals": [
|
|
274
|
+
2,
|
|
275
|
+
1
|
|
276
|
+
]
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"id": "MaxDeclarationsPerRule",
|
|
280
|
+
"score": 0,
|
|
281
|
+
"value": 1,
|
|
282
|
+
"actuals": [
|
|
283
|
+
1,
|
|
284
|
+
1
|
|
285
|
+
]
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"id": "MoreThanMostCommonSelectorsPerRule",
|
|
289
|
+
"score": 0,
|
|
290
|
+
"value": 1.5,
|
|
291
|
+
"actuals": [
|
|
292
|
+
2,
|
|
293
|
+
1
|
|
294
|
+
]
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"id": "MoreThanMostCommonDeclarationsPerRule",
|
|
298
|
+
"score": 0,
|
|
299
|
+
"value": 1,
|
|
300
|
+
"actuals": [
|
|
301
|
+
1,
|
|
302
|
+
1
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
},
|
|
307
|
+
"complexity": {
|
|
308
|
+
"score": 97,
|
|
309
|
+
"violations": [
|
|
310
|
+
{
|
|
311
|
+
"id": "IdSelectorRatio",
|
|
312
|
+
"score": 3,
|
|
313
|
+
"value": 0.3333333333333333,
|
|
314
|
+
"actuals": [
|
|
315
|
+
"#my_test"
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
],
|
|
319
|
+
"passes": [
|
|
320
|
+
{
|
|
321
|
+
"id": "MoreThanMostCommonSelectorComplexity",
|
|
322
|
+
"score": 0,
|
|
323
|
+
"value": 0,
|
|
324
|
+
"actuals": [
|
|
325
|
+
1,
|
|
326
|
+
1,
|
|
327
|
+
1
|
|
328
|
+
]
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"id": "MoreThanMostCommonSelectorSpecificity",
|
|
332
|
+
"score": 0,
|
|
333
|
+
"value": 0.3333333333333333,
|
|
334
|
+
"actuals": [
|
|
335
|
+
[
|
|
336
|
+
0,
|
|
337
|
+
1,
|
|
338
|
+
0
|
|
339
|
+
],
|
|
340
|
+
[
|
|
341
|
+
0,
|
|
342
|
+
1,
|
|
343
|
+
0
|
|
344
|
+
],
|
|
345
|
+
[
|
|
346
|
+
1,
|
|
347
|
+
0,
|
|
348
|
+
0
|
|
349
|
+
]
|
|
350
|
+
]
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"id": "MaxSelectorComplexity",
|
|
354
|
+
"score": 0,
|
|
355
|
+
"value": 1,
|
|
356
|
+
"actuals": [
|
|
357
|
+
1,
|
|
358
|
+
1,
|
|
359
|
+
1
|
|
360
|
+
]
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"id": "AverageSelectorComplexity",
|
|
364
|
+
"score": 0,
|
|
365
|
+
"value": 1,
|
|
366
|
+
"actuals": [
|
|
367
|
+
1,
|
|
368
|
+
1,
|
|
369
|
+
1
|
|
370
|
+
]
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"id": "ImportantRatio",
|
|
374
|
+
"score": 0,
|
|
375
|
+
"value": 0,
|
|
376
|
+
"actuals": 0
|
|
377
|
+
}
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
})
|
|
381
|
+
})
|
|
382
|
+
|
|
12
383
|
Index.run()
|
|
13
384
|
|
|
14
385
|
const Package = suite('NPM Package')
|
|
@@ -11,7 +11,7 @@ Maintainability('does not deduct points for 1 SLoC', () => {
|
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
Maintainability('deducts points for having lots of SLoC', () => {
|
|
14
|
-
const fixture =
|
|
14
|
+
const fixture = Array.from({ length: 10_000 })
|
|
15
15
|
.fill('')
|
|
16
16
|
.map((_, index) => `selector-${index} { opacity: 0.${index}}`)
|
|
17
17
|
.join('')
|
|
@@ -109,7 +109,7 @@ Maintainability('deducts points for having too many Declarations in a single Rul
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
selector2 {
|
|
112
|
-
${
|
|
112
|
+
${Array.from({ length: 23 })
|
|
113
113
|
.fill('')
|
|
114
114
|
.map(i => `z-index: ${i};`)
|
|
115
115
|
.join('')
|
|
@@ -136,13 +136,13 @@ Maintainability('deducts points for having too many Declarations in a single Rul
|
|
|
136
136
|
|
|
137
137
|
Maintainability('deducts points for having RuleSets with more Selectors than what is most common', () => {
|
|
138
138
|
const fixture = `
|
|
139
|
-
${
|
|
139
|
+
${Array.from({ length: 1000 })
|
|
140
140
|
.fill('')
|
|
141
141
|
.map(index => `selector-${index} {}`)
|
|
142
142
|
.join('')
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
${
|
|
145
|
+
${Array.from({ length: 500 })
|
|
146
146
|
.fill('')
|
|
147
147
|
.map(index => `selector-${index}a, selector-${index}-b {}`)
|
|
148
148
|
.join('')
|
|
@@ -155,7 +155,7 @@ Maintainability('deducts points for having RuleSets with more Selectors than wha
|
|
|
155
155
|
id: 'MoreThanMostCommonSelectorsPerRule',
|
|
156
156
|
score: 5,
|
|
157
157
|
value: 1,
|
|
158
|
-
actuals: (
|
|
158
|
+
actuals: (Array.from({ length: 1000 }).fill(1)).concat(Array.from({ length: 500 }).fill(2)),
|
|
159
159
|
},
|
|
160
160
|
])
|
|
161
161
|
assert.is(actual.maintainability.score, 95)
|
|
@@ -163,13 +163,13 @@ Maintainability('deducts points for having RuleSets with more Selectors than wha
|
|
|
163
163
|
|
|
164
164
|
Maintainability('deducts points for having RuleSets with more Selectors than what is most common', () => {
|
|
165
165
|
const fixture = `
|
|
166
|
-
${
|
|
166
|
+
${Array.from({ length: 1000 })
|
|
167
167
|
.fill('')
|
|
168
168
|
.map(index => `selector-${index}a { z-index: ${index}; }`)
|
|
169
169
|
.join('')
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
${
|
|
172
|
+
${Array.from({ length: 500 })
|
|
173
173
|
.fill('')
|
|
174
174
|
.map(index => `selector-${index}b { z-index: ${index}; content: "${index}" }`)
|
|
175
175
|
.join('')
|
|
@@ -182,7 +182,7 @@ Maintainability('deducts points for having RuleSets with more Selectors than wha
|
|
|
182
182
|
id: 'MoreThanMostCommonDeclarationsPerRule',
|
|
183
183
|
score: 5,
|
|
184
184
|
value: 1,
|
|
185
|
-
actuals: (
|
|
185
|
+
actuals: (Array.from({ length: 1000 }).fill(1)).concat(Array.from({ length: 500 }).fill(2)),
|
|
186
186
|
},
|
|
187
187
|
])
|
|
188
188
|
assert.is(actual.maintainability.score, 95)
|
package/src/performance.test.js
CHANGED
|
@@ -140,7 +140,7 @@ Performance('does not deduct points for small stylesheets', () => {
|
|
|
140
140
|
})
|
|
141
141
|
|
|
142
142
|
Performance('deducts points for large stylesheets', () => {
|
|
143
|
-
const fixture =
|
|
143
|
+
const fixture = Array.from({ length: 10_000 })
|
|
144
144
|
.fill('')
|
|
145
145
|
.map((_, index) => `selector-${index} { opacity: 0.${index}}`)
|
|
146
146
|
.join('')
|
|
@@ -150,7 +150,7 @@ Performance('deducts points for large stylesheets', () => {
|
|
|
150
150
|
})
|
|
151
151
|
|
|
152
152
|
Performance('deducts points for having comments', () => {
|
|
153
|
-
const fixture =
|
|
153
|
+
const fixture = Array.from({ length: 100 })
|
|
154
154
|
.fill('/* a comment to take up some space */')
|
|
155
155
|
.map((comment, index) => `${comment} selector-${index} { opacity: 0.${index} }`)
|
|
156
156
|
.join('')
|
|
@@ -170,7 +170,7 @@ Performance('deducts points for having embedded content', () => {
|
|
|
170
170
|
function generateEmbed(index) {
|
|
171
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
172
|
}
|
|
173
|
-
const fixture =
|
|
173
|
+
const fixture = Array.from({ length: 100 })
|
|
174
174
|
.fill('')
|
|
175
175
|
.map((_, index) => `
|
|
176
176
|
selector-${index} {
|
|
@@ -186,7 +186,7 @@ Performance('deducts points for having embedded content', () => {
|
|
|
186
186
|
id: 'TooMuchEmbeddedContent',
|
|
187
187
|
score: 20,
|
|
188
188
|
value: 45990,
|
|
189
|
-
actuals:
|
|
189
|
+
actuals: Array.from({ length: 100 }).fill('').map((_, index) => generateEmbed(index)),
|
|
190
190
|
},
|
|
191
191
|
])
|
|
192
192
|
})
|