@projectwallace/css-analyzer 5.2.1 → 5.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.umd.js","sources":["../src/string-utils.js","../src/selectors/specificity.js","../src/values/colors.js","../src/countable-collection.js","../src/values/font-families.js","../src/values/font-sizes.js","../src/values/values.js","../src/values/animations.js","../src/vendor-prefix.js","../src/values/vendor-prefix.js","../src/atrules/atrules.js","../src/context-collection.js","../src/aggregate-collection.js","../src/properties/property-utils.js","../src/index.js","../src/rules/rules.js"],"sourcesContent":["/**\n * Case-insensitive compare two character codes\n * @param {string} charA\n * @param {string} charB\n * @see https://github.com/csstree/csstree/blob/41f276e8862d8223eeaa01a3d113ab70bb13d2d9/lib/tokenizer/utils.js#L22\n */\nfunction compareChar(referenceCode, testCode) {\n // if uppercase\n if (testCode >= 0x0041 && testCode <= 0x005A) {\n // shifting the 6th bit makes a letter lowercase\n testCode = testCode | 32\n }\n return referenceCode === testCode\n}\n\n/**\n * Case-insensitive string-comparison\n * @param {string} base\n * @param {string} test\n * @returns {boolean} true if the two strings are the same, false otherwise\n */\nexport function strEquals(base, test) {\n if (base.length !== test.length) return false\n\n for (let i = 0; i < base.length; i++) {\n if (compareChar(base.charCodeAt(i), test.charCodeAt(i)) === false) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Case-insensitive testing whether a string ends with a given substring\n * @param {string} base e.g. '-webkit-transform'\n * @param {string} cmp e.g. 'transform'\n * @returns {boolean} true if `test` ends with `base`, false otherwise\n */\nexport function endsWith(base, test) {\n const offset = test.length - base.length\n\n if (offset < 0) {\n return false\n }\n\n for (let i = test.length - 1; i >= offset; i--) {\n if (compareChar(base.charCodeAt(i - offset), test.charCodeAt(i)) === false) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Case-insensitive testing whether a string starts with a given substring\n * @param {string} base\n * @param {test} test\n * @returns {boolean} true if `test` starts with `base`, false otherwise\n */\nexport function startsWith(base, test) {\n if (test.length < base.length) return false\n\n for (let i = 0; i < base.length; i++) {\n if (compareChar(base.charCodeAt(i), test.charCodeAt(i)) === false) {\n return false\n }\n }\n\n return true\n}\n","import walk from 'css-tree/walker'\nimport { startsWith } from '../string-utils.js'\n\n/**\n * Compare specificity A to Specificity B\n * @param {[number,number,number]} a - Specificity A\n * @param {[number,number,number]} b - Specificity B\n * @returns {number} sortIndex - 0 when a==b, 1 when a<b, -1 when a>b\n */\nfunction compareSpecificity(a, b) {\n if (a[0] === b[0]) {\n if (a[1] === b[1]) {\n return b[2] - a[2]\n }\n\n return b[1] - a[1]\n }\n\n return b[0] - a[0]\n}\n\n/**\n *\n * @param {import('css-tree').SelectorList} selectorListAst\n * @returns {Selector} topSpecificitySelector\n */\nfunction selectorListSpecificities(selectorListAst) {\n const childSelectors = []\n walk(selectorListAst, {\n visit: 'Selector',\n enter(node) {\n childSelectors.push(analyzeSpecificity(node))\n }\n })\n\n return childSelectors.sort((a, b) => compareSpecificity(a.specificity, b.specificity))\n}\n\n/**\n * Get the Specificity for the AST of a Selector Node\n * @param {import('css-tree').Selector} ast - AST Node for a Selector\n * @return {Object}\n * @property {[number,number,number]} specificity\n * @property {number} complexity\n * @property {Boolean} isId\n * @property {Boolean} isA11y\n */\nconst analyzeSpecificity = (node) => {\n let A = 0\n let B = 0\n let C = 0\n let complexity = 0\n let isA11y = false\n\n walk(node, function (selector) {\n switch (selector.type) {\n case 'IdSelector': {\n A++\n complexity++\n break\n }\n case 'ClassSelector': {\n B++\n complexity++\n break\n }\n case 'AttributeSelector': {\n B++\n complexity++\n\n // Add 1 for [attr=value] (or any variation using *= $= ^= |= )\n if (Boolean(selector.value)) {\n complexity++\n }\n\n isA11y = selector.name.name === 'role' || startsWith('aria-', selector.name.name)\n break\n }\n case 'PseudoElementSelector':\n case 'TypeSelector': {\n complexity++\n\n // 42 === '*'.charCodeAt(0)\n if (selector.name.charCodeAt(0) === 42 && selector.name.length === 1) {\n break\n }\n\n C++\n break\n }\n case 'PseudoClassSelector': {\n switch (selector.name) {\n case 'before':\n case 'after':\n case 'first-letter':\n case 'first-line': {\n C++\n complexity++\n return this.skip\n }\n\n // The specificity of an :is(), :not(), or :has() pseudo-class is\n // replaced by the specificity of the most specific complex\n // selector in its selector list argument.\n case 'where':\n case 'is':\n case 'has':\n case 'matches':\n case '-webkit-any':\n case '-moz-any':\n case 'not':\n case 'nth-child':\n case 'nth-last-child': {\n // The specificity of an :nth-child() or :nth-last-child() selector\n // is the specificity of the pseudo class itself (counting as one\n // pseudo-class selector) plus the specificity of the most\n // specific complex selector in its selector list argument (if any).\n if (selector.name === 'nth-child' || selector.name === 'nth-last-child') {\n // +1 for the pseudo class itself\n B++\n }\n\n const selectorList = selectorListSpecificities(selector)\n\n // Bail out for empty/non-existent :nth-child() params\n if (selectorList.length === 0) return\n\n // The specificity of a :where() pseudo-class is replaced by zero,\n // but it does count towards complexity.\n if (selector.name !== 'where') {\n const [topA, topB, topC] = selectorList[0].specificity\n A += topA\n B += topB\n C += topC\n }\n\n for (let i = 0; i < selectorList.length; i++) {\n const listItem = selectorList[i]\n if (listItem.isA11y) {\n isA11y = true\n }\n complexity += listItem.complexity\n }\n\n complexity++\n return this.skip\n }\n\n default: {\n // Regular pseudo classes have specificity [0,1,0]\n complexity++\n B++\n return this.skip\n }\n }\n }\n case 'Combinator': {\n complexity++\n break\n }\n }\n })\n\n return {\n /** @type {[number,number,number]} */\n specificity: [A, B, C],\n complexity,\n isId: A > 0,\n isA11y\n }\n}\n\nexport {\n analyzeSpecificity,\n compareSpecificity,\n}","export const colorNames = {\n // CSS Named Colors\n // Spec: https://drafts.csswg.org/css-color/#named-colors\n aliceblue: 1,\n antiquewhite: 1,\n aqua: 1,\n aquamarine: 1,\n azure: 1,\n beige: 1,\n bisque: 1,\n black: 1,\n blanchedalmond: 1,\n blue: 1,\n blueviolet: 1,\n brown: 1,\n burlywood: 1,\n cadetblue: 1,\n chartreuse: 1,\n chocolate: 1,\n coral: 1,\n cornflowerblue: 1,\n cornsilk: 1,\n crimson: 1,\n cyan: 1,\n darkblue: 1,\n darkcyan: 1,\n darkgoldenrod: 1,\n darkgray: 1,\n darkgreen: 1,\n darkgrey: 1,\n darkkhaki: 1,\n darkmagenta: 1,\n darkolivegreen: 1,\n darkorange: 1,\n darkorchid: 1,\n darkred: 1,\n darksalmon: 1,\n darkseagreen: 1,\n darkslateblue: 1,\n darkslategray: 1,\n darkslategrey: 1,\n darkturquoise: 1,\n darkviolet: 1,\n deeppink: 1,\n deepskyblue: 1,\n dimgray: 1,\n dimgrey: 1,\n dodgerblue: 1,\n firebrick: 1,\n floralwhite: 1,\n forestgreen: 1,\n fuchsia: 1,\n gainsboro: 1,\n ghostwhite: 1,\n gold: 1,\n goldenrod: 1,\n gray: 1,\n green: 1,\n greenyellow: 1,\n grey: 1,\n honeydew: 1,\n hotpink: 1,\n indianred: 1,\n indigo: 1,\n ivory: 1,\n khaki: 1,\n lavender: 1,\n lavenderblush: 1,\n lawngreen: 1,\n lemonchiffon: 1,\n lightblue: 1,\n lightcoral: 1,\n lightcyan: 1,\n lightgoldenrodyellow: 1,\n lightgray: 1,\n lightgreen: 1,\n lightgrey: 1,\n lightpink: 1,\n lightsalmon: 1,\n lightseagreen: 1,\n lightskyblue: 1,\n lightslategray: 1,\n lightslategrey: 1,\n lightsteelblue: 1,\n lightyellow: 1,\n lime: 1,\n limegreen: 1,\n linen: 1,\n magenta: 1,\n maroon: 1,\n mediumaquamarine: 1,\n mediumblue: 1,\n mediumorchid: 1,\n mediumpurple: 1,\n mediumseagreen: 1,\n mediumslateblue: 1,\n mediumspringgreen: 1,\n mediumturquoise: 1,\n mediumvioletred: 1,\n midnightblue: 1,\n mintcream: 1,\n mistyrose: 1,\n moccasin: 1,\n navajowhite: 1,\n navy: 1,\n oldlace: 1,\n olive: 1,\n olivedrab: 1,\n orange: 1,\n orangered: 1,\n orchid: 1,\n palegoldenrod: 1,\n palegreen: 1,\n paleturquoise: 1,\n palevioletred: 1,\n papayawhip: 1,\n peachpuff: 1,\n peru: 1,\n pink: 1,\n plum: 1,\n powderblue: 1,\n purple: 1,\n rebeccapurple: 1,\n red: 1,\n rosybrown: 1,\n royalblue: 1,\n saddlebrown: 1,\n salmon: 1,\n sandybrown: 1,\n seagreen: 1,\n seashell: 1,\n sienna: 1,\n silver: 1,\n skyblue: 1,\n slateblue: 1,\n slategray: 1,\n slategrey: 1,\n snow: 1,\n springgreen: 1,\n steelblue: 1,\n tan: 1,\n teal: 1,\n thistle: 1,\n tomato: 1,\n turquoise: 1,\n violet: 1,\n wheat: 1,\n white: 1,\n whitesmoke: 1,\n yellow: 1,\n yellowgreen: 1,\n\n // CSS System Colors\n // Spec: https://drafts.csswg.org/css-color/#css-system-colors\n canvas: 1,\n canvastext: 1,\n linktext: 1,\n visitedtext: 1,\n activetext: 1,\n buttonface: 1,\n buttontext: 1,\n buttonborder: 1,\n field: 1,\n fieldtext: 1,\n highlight: 1,\n highlighttext: 1,\n selecteditem: 1,\n selecteditemtext: 1,\n mark: 1,\n marktext: 1,\n graytext: 1,\n\n // TODO: Deprecated CSS System colors\n // Spec: https://drafts.csswg.org/css-color/#deprecated-system-colors\n}\n\nexport const colorFunctions = {\n rgb: 1,\n rgba: 1,\n hsl: 1,\n hsla: 1,\n hwb: 1,\n lab: 1,\n lch: 1,\n oklab: 1,\n oklch: 1,\n color: 1,\n}\n","class CountableCollection {\n /**\n * @param {string[]} initial\n */\n constructor(initial) {\n /** @type [index: string]: string */\n this.items = {}\n /** @type number */\n this.total = 0\n /** @type number */\n this.totalUnique = 0\n\n if (initial) {\n for (let index = 0; index < initial.length; index++) {\n this.push(initial[index])\n }\n }\n }\n\n /**\n * Push an item to the end of this collection\n * @param {string} item\n * @returns {void}\n */\n push(item) {\n this.total++\n\n if (this.items[item]) {\n this.items[item]++\n return\n }\n\n this.items[item] = 1\n this.totalUnique++\n }\n\n /**\n * Get the size of this collection\n * @returns {number} the size of this collection\n */\n size() {\n return this.total\n }\n\n /**\n * Get the counts of this collection, like total, uniques, etc.\n */\n count() {\n return {\n total: this.total,\n totalUnique: this.totalUnique,\n unique: this.items,\n uniquenessRatio: this.total === 0 ? 0 : this.totalUnique / this.total,\n }\n }\n}\n\nexport {\n CountableCollection\n}","import walk from 'css-tree/walker'\nimport { CountableCollection } from '../countable-collection.js'\n\nconst systemKeywords = {\n // Global CSS keywords\n 'inherit': 1,\n 'initial': 1,\n 'unset': 1,\n 'revert': 1,\n\n // System font keywords\n 'caption': 1,\n 'icon': 1,\n 'menu': 1,\n 'message-box': 1,\n 'small-caption': 1,\n 'status-bar': 1,\n}\n\nconst keywordDisallowList = {\n // font-weight, font-stretch, font-style\n 'normal': 1,\n\n // font-size keywords\n 'xx-small': 1,\n 'x-small': 1,\n 'small': 1,\n 'medium': 1,\n 'large': 1,\n 'x-large': 1,\n 'xx-large': 1,\n 'larger': 1,\n 'smaller': 1,\n\n // font-weight keywords\n 'bold': 1,\n 'bolder': 1,\n 'lighter': 1,\n\n // font-stretch keywords\n 'ultra-condensed': 1,\n 'extra-condensed': 1,\n 'condensed': 1,\n 'semi-condensed': 1,\n 'semi-expanded': 1,\n 'expanded': 1,\n 'extra-expanded': 1,\n 'ultra-expanded': 1,\n\n // font-style keywords\n 'italic': 1,\n 'oblique': 1,\n}\n\nconst COMMA = 44 // ','.charCodeAt(0) === 44\n\nconst analyzeFontFamilies = ({ fontValues, fontFamilyValues, stringifyNode }) => {\n const all = new CountableCollection(fontFamilyValues)\n\n for (let index = 0; index < fontValues.length; index++) {\n const value = fontValues[index]\n\n // Avoid tree traversal as soon as possible\n const firstChild = value.children.first\n\n if (firstChild.type === 'Identifier' && systemKeywords[firstChild.name]) {\n continue\n }\n\n let parts = ''\n\n walk(value, {\n reverse: true,\n enter: function (fontNode) {\n if (fontNode.type === 'String') {\n const loc = fontNode.loc.start\n // Stringify the first character to get the correct quote character\n const quote = stringifyNode({\n loc: {\n start: {\n line: loc.line,\n column: loc.column\n },\n end: {\n line: loc.line,\n column: loc.column + 1\n }\n }\n })\n return parts = quote + fontNode.value + quote + parts\n }\n if (fontNode.type === 'Operator' && fontNode.value.charCodeAt(0) === COMMA) {\n return parts = fontNode.value + parts\n }\n if (fontNode.type === 'Identifier') {\n if (keywordDisallowList[fontNode.name]) {\n return this.skip\n }\n return parts = fontNode.name + parts\n }\n }\n })\n\n all.push(parts)\n }\n\n return all.count()\n}\n\nexport {\n analyzeFontFamilies\n}","import walk from 'css-tree/walker'\nimport { CountableCollection } from '../countable-collection.js'\n\nconst sizeKeywords = {\n 'xx-small': 1,\n 'x-small': 1,\n 'small': 1,\n 'medium': 1,\n 'large': 1,\n 'x-large': 1,\n 'xx-large': 1,\n 'larger': 1,\n 'smaller': 1,\n}\n\nconst keywords = {\n // Global CSS keywords\n 'inherit': 1,\n 'initial': 1,\n 'unset': 1,\n 'revert': 1,\n\n // System font keywords\n 'caption': 1,\n 'icon': 1,\n 'menu': 1,\n 'message-box': 1,\n 'small-caption': 1,\n 'status-bar': 1,\n}\n\nconst ZERO = 48 // '0'.charCodeAt(0) === 48\nconst SLASH = 47 // '/'.charCodeAt(0) === 47\n\nconst analyzeFontSizes = ({ stringifyNode, fontSizeValues, fontValues }) => {\n const all = new CountableCollection(fontSizeValues)\n\n for (let index = 0; index < fontValues.length; index++) {\n const fontNode = fontValues[index];\n // Try to eliminate a keyword before we continue\n const firstChild = fontNode.children.first\n\n if (firstChild.type === 'Identifier' && keywords[firstChild.name]) {\n continue\n }\n\n let operator = false\n let size\n\n walk(fontNode, function (fontNode) {\n switch (fontNode.type) {\n case 'Number': {\n // Special case for `font: 0/0 a`\n if (fontNode.value.charCodeAt(0) === ZERO) {\n size = '0'\n return this.break\n }\n }\n case 'Operator': {\n if (fontNode.value.charCodeAt(0) === SLASH) {\n operator = true\n }\n break\n }\n case 'Dimension': {\n if (!operator) {\n size = stringifyNode(fontNode)\n return this.break\n }\n }\n case 'Identifier': {\n if (sizeKeywords[fontNode.name]) {\n size = fontNode.name\n return this.break\n }\n }\n }\n })\n\n if (size) {\n all.push(size)\n }\n }\n\n return all.count()\n}\n\nexport {\n analyzeFontSizes\n}","import { CountableCollection } from '../countable-collection.js'\n\nconst keywords = {\n 'auto': 1,\n 'inherit': 1,\n 'initial': 1,\n 'unset': 1,\n 'revert': 1,\n 'none': 1, // for `text-shadow` and `box-shadow`\n}\n\nconst analyzeValues = ({ values, stringifyNode }) => {\n const all = new CountableCollection()\n\n for (let i = 0; i < values.length; i++) {\n const node = values[i]\n const firstChild = node.children.first\n\n if (!firstChild) continue\n if (firstChild.type === 'Identifier' && keywords[firstChild.name]) continue\n\n all.push(stringifyNode(node))\n }\n\n return all.count()\n}\n\nexport {\n analyzeValues\n}","import { CountableCollection } from '../countable-collection.js'\n\nconst timingKeywords = {\n 'linear': 1,\n 'ease': 1,\n 'ease-in': 1,\n 'ease-out': 1,\n 'ease-in-out': 1,\n 'step-start': 1,\n 'step-end': 1,\n}\n\nconst analyzeAnimations = ({ animations, durations, timingFunctions, stringifyNode }) => {\n const allDurations = new CountableCollection(durations)\n const allTimingFunctions = new CountableCollection(timingFunctions)\n\n for (let index = 0; index < animations.length; index++) {\n // Flag to know if we've grabbed the first Duration\n // yet (the first Dimension in a shorthand)\n let durationFound = false\n\n animations[index].forEach(child => {\n // Right after a ',' we start over again\n if (child.type === 'Operator') {\n return durationFound = false\n }\n if (child.type === 'Dimension' && durationFound === false) {\n durationFound = true\n return allDurations.push(stringifyNode(child))\n }\n if (child.type === 'Identifier' && timingKeywords[child.name]) {\n return allTimingFunctions.push(stringifyNode(child))\n }\n if (child.type === 'Function'\n && (\n child.name === 'cubic-bezier' || child.name === 'steps'\n )\n ) {\n return allTimingFunctions.push(stringifyNode(child))\n }\n })\n }\n\n return {\n durations: allDurations.count(),\n timingFunctions: allTimingFunctions.count(),\n }\n}\n\nexport {\n analyzeAnimations\n}","const HYPHENMINUS = 45; // '-'.charCodeAt()\n\n/**\n * @param {string} keyword\n * @returns {boolean}\n */\nfunction hasVendorPrefix(keyword) {\n if (keyword.charCodeAt(0) === HYPHENMINUS && keyword.charCodeAt(1) !== HYPHENMINUS) {\n // String must have a 2nd occurrence of '-', at least at position 3 (offset=2)\n if (keyword.indexOf('-', 2) !== -1) {\n return true\n }\n }\n\n return false\n}\n\nexport {\n hasVendorPrefix\n}","import { CountableCollection } from '../countable-collection.js'\nimport { hasVendorPrefix } from '../vendor-prefix.js'\n\nfunction isAstVendorPrefixed(children) {\n children = children.toArray()\n\n for (let index = 0; index < children.length; index++) {\n const child = children[index];\n\n if (child.type === 'Identifier' && child.name.length >= 3) {\n if (hasVendorPrefix(child.name)) {\n return true\n }\n }\n\n if (child.type === 'Function') {\n if (hasVendorPrefix(child.name)) {\n return true\n }\n\n if (child.children && isAstVendorPrefixed(child.children)) {\n return true\n }\n }\n }\n return false\n}\n\nconst analyzeVendorPrefixes = ({ values, stringifyNode }) => {\n const all = new CountableCollection()\n\n for (let i = 0; i < values.length; i++) {\n /** @type {import('css-tree').Value} */\n const value = values[i]\n\n if (value.children && isAstVendorPrefixed(value.children)) {\n all.push(stringifyNode(value))\n }\n }\n\n return all.count()\n}\n\nexport {\n analyzeVendorPrefixes\n}","import { CountableCollection } from '../countable-collection.js'\nimport { hasVendorPrefix } from '../vendor-prefix.js'\nimport { endsWith } from '../string-utils.js'\n\nconst analyzeAtRules = ({ atrules, stringifyNode }) => {\n /** @type {{[index: string]: string}[]} */\n const fontfaces = []\n const layers = new CountableCollection()\n const imports = new CountableCollection()\n const medias = new CountableCollection()\n const charsets = new CountableCollection()\n const supports = new CountableCollection()\n const keyframes = new CountableCollection()\n const prefixedKeyframes = new CountableCollection()\n const containers = new CountableCollection()\n\n const machine = {\n 'font-face': (node) => {\n /** @type {[index: string]: string} */\n const descriptors = {}\n\n node.block.children.forEach(\n /** @param {import('css-tree').Declaration} descriptor */\n descriptor => (descriptors[descriptor.property] = stringifyNode(descriptor.value))\n )\n\n fontfaces.push(descriptors)\n },\n 'media': node => medias.push(node.prelude),\n 'supports': node => supports.push(node.prelude),\n 'keyframes': node => keyframes.push(`@${node.name} ${node.prelude}`),\n 'import': node => imports.push(node.prelude),\n 'charset': node => charsets.push(node.prelude),\n 'container': node => containers.push(node.prelude),\n 'layer': node => {\n node.prelude.trim()\n .split(',')\n .map(name => name.trim())\n .forEach(name => layers.push(name))\n },\n }\n\n for (let i = 0; i < atrules.length; i++) {\n /** @type {import('css-tree').Atrule} */\n const node = atrules[i]\n const atRuleName = node.name\n const action = machine[atRuleName]\n if (action) {\n action(node)\n continue\n }\n\n if (endsWith('keyframes', atRuleName)) {\n const name = `@${atRuleName} ${node.prelude}`\n keyframes.push(name)\n\n if (hasVendorPrefix(atRuleName)) {\n prefixedKeyframes.push(name)\n }\n continue\n }\n }\n\n return {\n fontface: {\n total: fontfaces.length,\n totalUnique: fontfaces.length,\n unique: fontfaces,\n uniquenessRatio: fontfaces.length === 0 ? 0 : 1\n },\n import: imports.count(),\n media: medias.count(),\n charset: charsets.count(),\n supports: supports.count(),\n keyframes: {\n ...keyframes.count(),\n prefixed: {\n ...prefixedKeyframes.count(),\n ratio: keyframes.size() === 0 ? 0 : prefixedKeyframes.size() / keyframes.size()\n }\n },\n container: containers.count(),\n layer: layers.count(),\n }\n}\n\nexport {\n analyzeAtRules\n}","import { CountableCollection } from './countable-collection.js'\n\nclass ContextCollection {\n constructor() {\n this.list = new CountableCollection()\n /** @type {[index; string]: CountableCollection} */\n this.contexts = {}\n }\n\n /**\n * Add an item to this list's context\n * @param {string} item Item to push\n * @param {string} context Context to push Item to\n */\n push(item, context) {\n this.list.push(item)\n\n if (!this.contexts[context]) {\n this.contexts[context] = new CountableCollection()\n }\n\n this.contexts[context].push(item)\n }\n\n count() {\n /** @type {[index: string]: string} */\n const itemsPerContext = {}\n\n for (let context in this.contexts) {\n itemsPerContext[context] = this.contexts[context].count()\n }\n\n return Object.assign(this.list.count(), {\n itemsPerContext\n })\n }\n}\n\nexport {\n ContextCollection\n}","/**\n * Find the mode (most occurring value) in an array of Numbers\n * Takes the mean/average of multiple values if multiple values occur the same amount of times.\n *\n * @see https://github.com/angus-c/just/blob/684af9ca0c7808bc78543ec89379b1fdfce502b1/packages/array-mode/index.js\n * @param {Array} arr - Array to find the mode value for\n * @returns {Number} mode - The `mode` value of `arr`\n */\nfunction Mode(arr) {\n const frequencies = Object.create(null)\n let maxOccurrences = -1\n let maxOccurenceCount = 0\n let sum = 0\n\n for (let i = 0; i < arr.length; i++) {\n const element = arr[i]\n const updatedCount = (frequencies[element] || 0) + 1\n frequencies[element] = updatedCount\n\n if (updatedCount > maxOccurrences) {\n maxOccurrences = updatedCount\n maxOccurenceCount = 0\n sum = 0\n }\n\n if (updatedCount >= maxOccurrences) {\n maxOccurenceCount++\n sum += element\n }\n }\n\n return sum / maxOccurenceCount\n}\n\n/**\n * Find the middle number in an Array of Numbers\n * Returns the average of 2 numbers if the Array length is an even number\n * @see https://github.com/angus-c/just/blob/684af9ca0c7808bc78543ec89379b1fdfce502b1/packages/array-median/index.js\n * @param {Array} arr - A sorted Array\n * @returns {Number} - The array's Median\n */\nfunction Median(arr) {\n const middle = arr.length / 2\n const lowerMiddleRank = Math.floor(middle)\n\n if (middle !== lowerMiddleRank) {\n return arr[lowerMiddleRank]\n }\n return (arr[lowerMiddleRank] + arr[lowerMiddleRank - 1]) / 2\n}\n\nclass AggregateCollection {\n constructor() {\n /** @type number[] */\n this.items = []\n }\n\n /**\n * Add a new Integer at the end of this AggregateCollection\n * @param {number} item - The item to add\n */\n add(item) {\n this.items.push(item)\n }\n\n aggregate() {\n if (this.items.length === 0) {\n return {\n min: 0,\n max: 0,\n mean: 0,\n mode: 0,\n median: 0,\n range: 0,\n sum: 0,\n }\n }\n\n /** @type Number[] */\n const sorted = this.items.slice().sort((a, b) => a - b)\n const min = sorted[0]\n const max = sorted[sorted.length - 1]\n\n const sum = this.items.reduce((total, num) => (total += num))\n const mode = Mode(this.items)\n const median = Median(sorted)\n\n return {\n min,\n max,\n mean: sum / this.items.length,\n mode,\n median,\n range: max - min,\n sum,\n }\n }\n\n /**\n * @returns {number[]} All items in this collection\n */\n toArray() {\n return this.items\n }\n}\n\nexport {\n AggregateCollection\n}","import { hasVendorPrefix } from '../vendor-prefix.js'\nimport { endsWith } from '../string-utils.js'\n\n/**\n * @param {string} property\n * @see https://github.com/csstree/csstree/blob/master/lib/utils/names.js#L69\n */\nexport function isHack(property) {\n if (isCustom(property) || hasVendorPrefix(property)) return false\n\n let code = property.charCodeAt(0)\n\n return code === 47 // /\n || code === 95 // _\n || code === 43 // +\n || code === 42 // *\n || code === 38 // &\n || code === 36 // $\n || code === 35 // #\n}\n\nexport function isCustom(property) {\n if (property.length < 3) return false\n // 45 === '-'.charCodeAt(0)\n return property.charCodeAt(0) === 45 && property.charCodeAt(1) === 45\n}\n\nexport function isProperty(basename, property) {\n if (isCustom(property)) return false\n return endsWith(basename, property)\n}","import parse from 'css-tree/parser'\nimport walk from 'css-tree/walker'\nimport { analyzeRule } from './rules/rules.js'\nimport { analyzeSpecificity, compareSpecificity } from './selectors/specificity.js'\nimport { colorFunctions, colorNames } from './values/colors.js'\nimport { analyzeFontFamilies } from './values/font-families.js'\nimport { analyzeFontSizes } from './values/font-sizes.js'\nimport { analyzeValues } from './values/values.js'\nimport { analyzeAnimations } from './values/animations.js'\nimport { analyzeVendorPrefixes } from './values/vendor-prefix.js'\nimport { analyzeAtRules } from './atrules/atrules.js'\nimport { ContextCollection } from './context-collection.js'\nimport { CountableCollection } from './countable-collection.js'\nimport { AggregateCollection } from './aggregate-collection.js'\nimport { strEquals, startsWith, endsWith } from './string-utils.js'\nimport { hasVendorPrefix } from './vendor-prefix.js'\nimport { isCustom, isHack, isProperty } from './properties/property-utils.js'\n\n/**\n * Analyze CSS\n * @param {string} css\n */\nconst analyze = (css) => {\n const start = new Date()\n\n // We need all lines later on when we need to stringify the AST again\n // e.g. for Selectors\n const lines = css.split(/\\r?\\n/)\n\n /**\n * Recreate the authored CSS from a CSSTree node\n * @param {import('css-tree').CssNode} node - Node from CSSTree AST to stringify\n * @returns {string} str - The stringified node\n */\n function stringifyNode(node) {\n const start = node.loc.start\n const end = node.loc.end\n const lineCount = end.line - start.line\n\n // Single-line nodes\n if (lineCount === 0) {\n return lines[start.line - 1].substring(start.column - 1, end.column - 1)\n }\n\n // Multi-line nodes\n let value = ''\n\n for (let i = start.line; i <= end.line; i++) {\n const line = lines[i - 1]\n // First line\n if (i === start.line) {\n value += line.substring(start.column - 1) + '\\n'\n continue\n }\n // Last line\n if (i === end.line) {\n value += line.substring(0, end.column - 1)\n continue\n }\n // All lines in between first and last\n value += line + '\\n'\n }\n\n return value\n }\n\n const startParse = new Date()\n let totalComments = 0\n let commentsSize = 0\n\n const ast = parse(css, {\n parseAtrulePrelude: false,\n parseCustomProperty: true, // To find font-families, colors, etc.\n positions: true, // So we can use stringifyNode()\n onComment: function (comment) {\n totalComments++\n commentsSize += comment.length\n },\n })\n\n const startAnalysis = new Date()\n const embeds = new CountableCollection()\n const atrules = []\n\n let totalRules = 0\n let emptyRules = 0\n const selectorsPerRule = new AggregateCollection()\n const declarationsPerRule = new AggregateCollection()\n\n const keyframeSelectors = new CountableCollection()\n const declarationsCache = Object.create(null)\n let totalDeclarations = 0\n let importantDeclarations = 0\n let importantsInKeyframes = 0\n\n const properties = new CountableCollection()\n const propertyHacks = new CountableCollection()\n const propertyVendorPrefixes = new CountableCollection()\n const customProperties = new CountableCollection()\n\n const values = []\n const zindex = []\n const textShadows = []\n const boxShadows = []\n const fontValues = []\n const fontFamilyValues = []\n const fontSizeValues = []\n const animations = []\n const timingFunctions = []\n const durations = []\n const colors = new ContextCollection()\n const units = new ContextCollection()\n\n // SELECTORS\n /** @type number */\n const selectorCounts = Object.create(null)\n /** @type [number,number,number] */\n let maxSpecificity\n /** @type [number,number,number] */\n let minSpecificity\n let specificityA = new AggregateCollection()\n let specificityB = new AggregateCollection()\n let specificityC = new AggregateCollection()\n const complexityAggregator = new AggregateCollection()\n /** @type [number,number,number][] */\n const specificities = []\n /** @type number[] */\n const complexities = []\n const ids = new CountableCollection()\n const a11y = new CountableCollection()\n\n walk(ast, function (node) {\n switch (node.type) {\n case 'Atrule': {\n atrules.push({\n name: node.name,\n prelude: node.prelude && node.prelude.value,\n block: strEquals('font-face', node.name) && node.block,\n })\n break\n }\n case 'Rule': {\n const [numSelectors, numDeclarations] = analyzeRule(node)\n\n totalRules++\n\n if (numDeclarations === 0) {\n emptyRules++\n }\n\n selectorsPerRule.add(numSelectors)\n declarationsPerRule.add(numDeclarations)\n break\n }\n case 'Selector': {\n const selector = stringifyNode(node)\n\n if (this.atrule && endsWith('keyframes', this.atrule.name)) {\n keyframeSelectors.push(selector)\n return this.skip\n }\n\n const { specificity, complexity, isId, isA11y } = analyzeSpecificity(node)\n\n if (isId) {\n ids.push(selector)\n }\n\n if (isA11y) {\n a11y.push(selector)\n }\n\n if (selectorCounts[selector]) {\n selectorCounts[selector]++\n } else {\n selectorCounts[selector] = 1\n }\n\n complexityAggregator.add(complexity)\n\n if (maxSpecificity === undefined) {\n maxSpecificity = specificity\n }\n\n if (minSpecificity === undefined) {\n minSpecificity = specificity\n }\n\n specificityA.add(specificity[0])\n specificityB.add(specificity[1])\n specificityC.add(specificity[2])\n\n if (minSpecificity !== undefined && compareSpecificity(minSpecificity, specificity) < 0) {\n minSpecificity = specificity\n }\n\n if (maxSpecificity !== undefined && compareSpecificity(maxSpecificity, specificity) > 0) {\n maxSpecificity = specificity\n }\n\n specificities.push(specificity)\n complexities.push(complexity)\n\n // Avoid deeper walking of selectors to not mess with\n // our specificity calculations in case of a selector\n // with :where() or :is() that contain SelectorLists\n // as children\n return this.skip\n }\n case 'Dimension': {\n if (!this.declaration) {\n break\n }\n\n units.push(node.unit, this.declaration.property)\n\n return this.skip\n }\n case 'Url': {\n if (startsWith('data:', node.value)) {\n embeds.push(node.value)\n }\n break\n }\n case 'Declaration': {\n totalDeclarations++\n\n const declaration = stringifyNode(node)\n if (declarationsCache[declaration]) {\n declarationsCache[declaration]++\n } else {\n declarationsCache[declaration] = 1\n }\n\n if (node.important) {\n importantDeclarations++\n\n if (this.atrule && endsWith('keyframes', this.atrule.name)) {\n importantsInKeyframes++\n }\n }\n\n const { value, property } = node\n\n properties.push(property)\n values.push(value)\n\n if (hasVendorPrefix(property)) {\n propertyVendorPrefixes.push(property)\n } else if (isHack(property)) {\n propertyHacks.push(property)\n } else if (isCustom(property)) {\n customProperties.push(property)\n }\n\n // Process properties first that don't have colors,\n // so we can avoid further walking them;\n if (isProperty('z-index', property)) {\n zindex.push(value)\n return this.skip\n } else if (isProperty('font', property)) {\n fontValues.push(value)\n break\n } else if (isProperty('font-size', property)) {\n fontSizeValues.push(stringifyNode(value))\n break\n } else if (isProperty('font-family', property)) {\n fontFamilyValues.push(stringifyNode(value))\n break\n } else if (isProperty('transition', property) || isProperty('animation', property)) {\n animations.push(value.children)\n break\n } else if (isProperty('animation-duration', property) || isProperty('transition-duration', property)) {\n durations.push(stringifyNode(value))\n break\n } else if (isProperty('transition-timing-function', property) || isProperty('animation-timing-function', property)) {\n timingFunctions.push(stringifyNode(value))\n break\n } else if (isProperty('text-shadow', property)) {\n textShadows.push(value)\n // no break here: potentially contains colors\n } else if (isProperty('box-shadow', property)) {\n boxShadows.push(value)\n // no break here: potentially contains colors\n }\n\n walk(value, function (valueNode) {\n switch (valueNode.type) {\n case 'Hash': {\n colors.push('#' + valueNode.value, property)\n\n return this.skip\n }\n case 'Identifier': {\n const { name } = valueNode\n // Bail out if it can't be a color name\n // 20 === 'lightgoldenrodyellow'.length\n // 3 === 'red'.length\n if (name.length > 20 || name.length < 3) {\n return this.skip\n }\n if (colorNames[name.toLowerCase()]) {\n colors.push(stringifyNode(valueNode), property)\n }\n return this.skip\n }\n case 'Function': {\n if (colorFunctions[valueNode.name.toLowerCase()]) {\n colors.push(stringifyNode(valueNode), property)\n }\n // No this.skip here intentionally,\n // otherwise we'll miss colors in linear-gradient() etc.\n }\n }\n })\n }\n }\n })\n\n const embeddedContent = embeds.count()\n const embedSize = Object.keys(embeddedContent.unique).join('').length\n\n const totalUniqueDeclarations = Object.keys(declarationsCache).length\n\n const totalSelectors = complexities.length\n const aggregatesA = specificityA.aggregate()\n const aggregatesB = specificityB.aggregate()\n const aggregatesC = specificityC.aggregate()\n const complexityCount = new CountableCollection(complexities).count()\n const totalUniqueSelectors = Object.values(selectorCounts).length\n\n return {\n stylesheet: {\n sourceLinesOfCode: atrules.length + totalSelectors + totalDeclarations + keyframeSelectors.size(),\n linesOfCode: lines.length,\n size: css.length,\n comments: {\n total: totalComments,\n size: commentsSize,\n },\n embeddedContent: Object.assign(embeddedContent, {\n size: {\n total: embedSize,\n ratio: css.length === 0 ? 0 : embedSize / css.length,\n },\n }),\n },\n atrules: analyzeAtRules({ atrules, stringifyNode }),\n rules: {\n total: totalRules,\n empty: {\n total: emptyRules,\n ratio: totalRules === 0 ? 0 : emptyRules / totalRules\n },\n selectors: {\n ...selectorsPerRule.aggregate(),\n items: selectorsPerRule.toArray(),\n },\n declarations: {\n ...declarationsPerRule.aggregate(),\n items: declarationsPerRule.toArray()\n },\n },\n selectors: {\n total: totalSelectors,\n totalUnique: totalUniqueSelectors,\n uniquenessRatio: totalSelectors === 0 ? 0 : totalUniqueSelectors / totalSelectors,\n specificity: {\n min: minSpecificity === undefined ? [0, 0, 0] : minSpecificity,\n max: maxSpecificity === undefined ? [0, 0, 0] : maxSpecificity,\n sum: [aggregatesA.sum, aggregatesB.sum, aggregatesC.sum],\n mean: [aggregatesA.mean, aggregatesB.mean, aggregatesC.mean],\n mode: [aggregatesA.mode, aggregatesB.mode, aggregatesC.mode],\n median: [aggregatesA.median, aggregatesB.median, aggregatesC.median],\n items: specificities\n },\n complexity: {\n ...complexityAggregator.aggregate(),\n ...complexityCount,\n items: complexities,\n },\n id: {\n ...ids.count(),\n ratio: totalSelectors === 0 ? 0 : ids.size() / totalSelectors,\n },\n accessibility: {\n ...a11y.count(),\n ratio: totalSelectors === 0 ? 0 : a11y.size() / totalSelectors,\n },\n keyframes: keyframeSelectors.count(),\n },\n declarations: {\n total: totalDeclarations,\n unique: {\n total: totalUniqueDeclarations,\n ratio: totalDeclarations === 0 ? 0 : totalUniqueDeclarations / totalDeclarations,\n },\n importants: {\n total: importantDeclarations,\n ratio: totalDeclarations === 0 ? 0 : importantDeclarations / totalDeclarations,\n inKeyframes: {\n total: importantsInKeyframes,\n ratio: importantDeclarations === 0 ? 0 : importantsInKeyframes / importantDeclarations,\n },\n },\n },\n properties: {\n ...properties.count(),\n prefixed: {\n ...propertyVendorPrefixes.count(),\n ratio: properties.size() === 0 ? 0 : propertyVendorPrefixes.size() / properties.size(),\n },\n custom: {\n ...customProperties.count(),\n ratio: properties.size() === 0 ? 0 : customProperties.size() / properties.size(),\n },\n browserhacks: {\n ...propertyHacks.count(),\n ratio: properties.size() === 0 ? 0 : propertyHacks.size() / properties.size(),\n }\n },\n values: {\n colors: colors.count(),\n fontFamilies: analyzeFontFamilies({ stringifyNode, fontValues, fontFamilyValues }),\n fontSizes: analyzeFontSizes({ stringifyNode, fontValues, fontSizeValues }),\n zindexes: analyzeValues({ values: zindex, stringifyNode }),\n textShadows: analyzeValues({ values: textShadows, stringifyNode }),\n boxShadows: analyzeValues({ values: boxShadows, stringifyNode }),\n animations: analyzeAnimations({ animations, timingFunctions, durations, stringifyNode }),\n prefixes: analyzeVendorPrefixes({ values, stringifyNode }),\n units: units.count(),\n },\n __meta__: {\n parseTime: startAnalysis - startParse,\n analyzeTime: new Date() - startAnalysis,\n total: new Date() - start\n }\n }\n}\n\nexport {\n analyze,\n compareSpecificity,\n}\n","import walk from 'css-tree/walker'\n\nconst analyzeRule = function (ruleNode) {\n let numSelectors = 0\n let numDeclarations = 0\n\n walk(ruleNode, function (childNode) {\n if (childNode.type === 'Selector') {\n numSelectors++\n return this.skip\n }\n\n if (childNode.type === 'Declaration') {\n numDeclarations++\n return this.skip\n }\n })\n\n return [numSelectors, numDeclarations]\n}\n\nexport {\n analyzeRule,\n}"],"names":["compareChar","referenceCode","testCode","strEquals","base","test","length","i","charCodeAt","endsWith","offset","startsWith","compareSpecificity","a","b","analyzeSpecificity","node","A","B","C","complexity","isA11y","walk","selector","type","Boolean","value","name","skip","selectorList","childSelectors","visit","enter","push","sort","specificity","listItem","isId","colorNames","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","green","greenyellow","grey","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","canvas","canvastext","linktext","visitedtext","activetext","buttonface","buttontext","buttonborder","field","fieldtext","highlight","highlighttext","selecteditem","selecteditemtext","mark","marktext","graytext","colorFunctions","rgb","rgba","hsl","hsla","hwb","lab","lch","oklab","oklch","color","CountableCollection","initial","this","items","total","totalUnique","index","item","size","count","unique","uniquenessRatio","systemKeywords","inherit","unset","revert","caption","icon","menu","keywordDisallowList","normal","small","medium","large","larger","smaller","bold","bolder","lighter","condensed","expanded","italic","oblique","analyzeFontFamilies","fontValues","stringifyNode","all","fontFamilyValues","firstChild","children","first","parts","reverse","fontNode","loc","start","quote","line","column","end","sizeKeywords","keywords","analyzeFontSizes","fontSizeValues","operator","auto","none","analyzeValues","values","timingKeywords","linear","ease","analyzeAnimations","animations","timingFunctions","allDurations","durations","allTimingFunctions","durationFound","forEach","child","hasVendorPrefix","keyword","indexOf","isAstVendorPrefixed","toArray","analyzeVendorPrefixes","analyzeAtRules","atrules","fontfaces","layers","imports","medias","charsets","supports","keyframes","prefixedKeyframes","containers","machine","descriptors","block","descriptor","property","media","prelude","import","charset","container","layer","trim","split","map","atRuleName","action","fontface","prefixed","ratio","ContextCollection","list","contexts","context","itemsPerContext","Object","assign","AggregateCollection","add","aggregate","min","max","mean","mode","median","range","sum","arr","middle","lowerMiddleRank","sorted","slice","reduce","num","frequencies","create","maxOccurrences","maxOccurenceCount","element","updatedCount","Mode","Math","floor","isCustom","isProperty","basename","css","Date","lines","substring","maxSpecificity","minSpecificity","startParse","totalComments","commentsSize","ast","parse","parseAtrulePrelude","parseCustomProperty","positions","onComment","comment","startAnalysis","embeds","totalRules","emptyRules","selectorsPerRule","declarationsPerRule","keyframeSelectors","declarationsCache","totalDeclarations","importantDeclarations","importantsInKeyframes","properties","propertyHacks","propertyVendorPrefixes","customProperties","zindex","textShadows","boxShadows","colors","units","selectorCounts","specificityA","specificityB","specificityC","complexityAggregator","specificities","complexities","ids","a11y","ruleNode","numSelectors","numDeclarations","childNode","analyzeRule","atrule","undefined","declaration","unit","important","code","isHack","valueNode","toLowerCase","embeddedContent","embedSize","keys","join","totalUniqueDeclarations","totalSelectors","aggregatesA","aggregatesB","aggregatesC","complexityCount","totalUniqueSelectors","stylesheet","sourceLinesOfCode","linesOfCode","comments","rules","empty","selectors","declarations","id","accessibility","importants","inKeyframes","custom","browserhacks","fontFamilies","fontSizes","zindexes","prefixes","__meta__","parseTime","analyzeTime"],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.umd.js","sources":["../src/string-utils.js","../src/selectors/specificity.js","../src/values/colors.js","../src/countable-collection.js","../src/values/font-families.js","../src/values/font-sizes.js","../src/values/values.js","../src/values/animations.js","../src/vendor-prefix.js","../src/values/vendor-prefix.js","../src/atrules/atrules.js","../src/context-collection.js","../src/aggregate-collection.js","../src/properties/property-utils.js","../src/occurrence-counter.js","../src/index.js","../src/rules/rules.js"],"sourcesContent":["/**\n * Case-insensitive compare two character codes\n * @param {string} charA\n * @param {string} charB\n * @see https://github.com/csstree/csstree/blob/41f276e8862d8223eeaa01a3d113ab70bb13d2d9/lib/tokenizer/utils.js#L22\n */\nfunction compareChar(referenceCode, testCode) {\n // if uppercase\n if (testCode >= 0x0041 && testCode <= 0x005A) {\n // shifting the 6th bit makes a letter lowercase\n testCode = testCode | 32\n }\n return referenceCode === testCode\n}\n\n/**\n * Case-insensitive string-comparison\n * @param {string} base\n * @param {string} test\n * @returns {boolean} true if the two strings are the same, false otherwise\n */\nexport function strEquals(base, test) {\n if (base.length !== test.length) return false\n\n for (let i = 0; i < base.length; i++) {\n if (compareChar(base.charCodeAt(i), test.charCodeAt(i)) === false) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Case-insensitive testing whether a string ends with a given substring\n * @param {string} base e.g. '-webkit-transform'\n * @param {string} cmp e.g. 'transform'\n * @returns {boolean} true if `test` ends with `base`, false otherwise\n */\nexport function endsWith(base, test) {\n const offset = test.length - base.length\n\n if (offset < 0) {\n return false\n }\n\n for (let i = test.length - 1; i >= offset; i--) {\n if (compareChar(base.charCodeAt(i - offset), test.charCodeAt(i)) === false) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Case-insensitive testing whether a string starts with a given substring\n * @param {string} base\n * @param {test} test\n * @returns {boolean} true if `test` starts with `base`, false otherwise\n */\nexport function startsWith(base, test) {\n if (test.length < base.length) return false\n\n for (let i = 0; i < base.length; i++) {\n if (compareChar(base.charCodeAt(i), test.charCodeAt(i)) === false) {\n return false\n }\n }\n\n return true\n}\n","import walk from 'css-tree/walker'\nimport { startsWith } from '../string-utils.js'\n\n/**\n * Compare specificity A to Specificity B\n * @param {[number,number,number]} a - Specificity A\n * @param {[number,number,number]} b - Specificity B\n * @returns {number} sortIndex - 0 when a==b, 1 when a<b, -1 when a>b\n */\nfunction compareSpecificity(a, b) {\n if (a[0] === b[0]) {\n if (a[1] === b[1]) {\n return b[2] - a[2]\n }\n\n return b[1] - a[1]\n }\n\n return b[0] - a[0]\n}\n\n/**\n *\n * @param {import('css-tree').SelectorList} selectorListAst\n * @returns {Selector} topSpecificitySelector\n */\nfunction selectorListSpecificities(selectorListAst) {\n const childSelectors = []\n walk(selectorListAst, {\n visit: 'Selector',\n enter(node) {\n childSelectors.push(analyzeSpecificity(node))\n }\n })\n\n return childSelectors.sort((a, b) => compareSpecificity(a.specificity, b.specificity))\n}\n\n/**\n * Get the Specificity for the AST of a Selector Node\n * @param {import('css-tree').Selector} ast - AST Node for a Selector\n * @return {Object}\n * @property {[number,number,number]} specificity\n * @property {number} complexity\n * @property {Boolean} isId\n * @property {Boolean} isA11y\n */\nconst analyzeSpecificity = (node) => {\n let A = 0\n let B = 0\n let C = 0\n let complexity = 0\n let isA11y = false\n\n walk(node, function (selector) {\n switch (selector.type) {\n case 'IdSelector': {\n A++\n complexity++\n break\n }\n case 'ClassSelector': {\n B++\n complexity++\n break\n }\n case 'AttributeSelector': {\n B++\n complexity++\n\n // Add 1 for [attr=value] (or any variation using *= $= ^= |= )\n if (Boolean(selector.value)) {\n complexity++\n }\n\n isA11y = selector.name.name === 'role' || startsWith('aria-', selector.name.name)\n break\n }\n case 'PseudoElementSelector':\n case 'TypeSelector': {\n complexity++\n\n // 42 === '*'.charCodeAt(0)\n if (selector.name.charCodeAt(0) === 42 && selector.name.length === 1) {\n break\n }\n\n C++\n break\n }\n case 'PseudoClassSelector': {\n switch (selector.name) {\n case 'before':\n case 'after':\n case 'first-letter':\n case 'first-line': {\n C++\n complexity++\n return this.skip\n }\n\n // The specificity of an :is(), :not(), or :has() pseudo-class is\n // replaced by the specificity of the most specific complex\n // selector in its selector list argument.\n case 'where':\n case 'is':\n case 'has':\n case 'matches':\n case '-webkit-any':\n case '-moz-any':\n case 'not':\n case 'nth-child':\n case 'nth-last-child': {\n // The specificity of an :nth-child() or :nth-last-child() selector\n // is the specificity of the pseudo class itself (counting as one\n // pseudo-class selector) plus the specificity of the most\n // specific complex selector in its selector list argument (if any).\n if (selector.name === 'nth-child' || selector.name === 'nth-last-child') {\n // +1 for the pseudo class itself\n B++\n }\n\n const selectorList = selectorListSpecificities(selector)\n\n // Bail out for empty/non-existent :nth-child() params\n if (selectorList.length === 0) return\n\n // The specificity of a :where() pseudo-class is replaced by zero,\n // but it does count towards complexity.\n if (selector.name !== 'where') {\n const [topA, topB, topC] = selectorList[0].specificity\n A += topA\n B += topB\n C += topC\n }\n\n for (let i = 0; i < selectorList.length; i++) {\n const listItem = selectorList[i]\n if (listItem.isA11y) {\n isA11y = true\n }\n complexity += listItem.complexity\n }\n\n complexity++\n return this.skip\n }\n\n default: {\n // Regular pseudo classes have specificity [0,1,0]\n complexity++\n B++\n return this.skip\n }\n }\n }\n case 'Combinator': {\n complexity++\n break\n }\n }\n })\n\n return {\n /** @type {[number,number,number]} */\n specificity: [A, B, C],\n complexity,\n isId: A > 0,\n isA11y\n }\n}\n\nexport {\n analyzeSpecificity,\n compareSpecificity,\n}","export const colorNames = {\n // CSS Named Colors\n // Spec: https://drafts.csswg.org/css-color/#named-colors\n aliceblue: 1,\n antiquewhite: 1,\n aqua: 1,\n aquamarine: 1,\n azure: 1,\n beige: 1,\n bisque: 1,\n black: 1,\n blanchedalmond: 1,\n blue: 1,\n blueviolet: 1,\n brown: 1,\n burlywood: 1,\n cadetblue: 1,\n chartreuse: 1,\n chocolate: 1,\n coral: 1,\n cornflowerblue: 1,\n cornsilk: 1,\n crimson: 1,\n cyan: 1,\n darkblue: 1,\n darkcyan: 1,\n darkgoldenrod: 1,\n darkgray: 1,\n darkgreen: 1,\n darkgrey: 1,\n darkkhaki: 1,\n darkmagenta: 1,\n darkolivegreen: 1,\n darkorange: 1,\n darkorchid: 1,\n darkred: 1,\n darksalmon: 1,\n darkseagreen: 1,\n darkslateblue: 1,\n darkslategray: 1,\n darkslategrey: 1,\n darkturquoise: 1,\n darkviolet: 1,\n deeppink: 1,\n deepskyblue: 1,\n dimgray: 1,\n dimgrey: 1,\n dodgerblue: 1,\n firebrick: 1,\n floralwhite: 1,\n forestgreen: 1,\n fuchsia: 1,\n gainsboro: 1,\n ghostwhite: 1,\n gold: 1,\n goldenrod: 1,\n gray: 1,\n green: 1,\n greenyellow: 1,\n grey: 1,\n honeydew: 1,\n hotpink: 1,\n indianred: 1,\n indigo: 1,\n ivory: 1,\n khaki: 1,\n lavender: 1,\n lavenderblush: 1,\n lawngreen: 1,\n lemonchiffon: 1,\n lightblue: 1,\n lightcoral: 1,\n lightcyan: 1,\n lightgoldenrodyellow: 1,\n lightgray: 1,\n lightgreen: 1,\n lightgrey: 1,\n lightpink: 1,\n lightsalmon: 1,\n lightseagreen: 1,\n lightskyblue: 1,\n lightslategray: 1,\n lightslategrey: 1,\n lightsteelblue: 1,\n lightyellow: 1,\n lime: 1,\n limegreen: 1,\n linen: 1,\n magenta: 1,\n maroon: 1,\n mediumaquamarine: 1,\n mediumblue: 1,\n mediumorchid: 1,\n mediumpurple: 1,\n mediumseagreen: 1,\n mediumslateblue: 1,\n mediumspringgreen: 1,\n mediumturquoise: 1,\n mediumvioletred: 1,\n midnightblue: 1,\n mintcream: 1,\n mistyrose: 1,\n moccasin: 1,\n navajowhite: 1,\n navy: 1,\n oldlace: 1,\n olive: 1,\n olivedrab: 1,\n orange: 1,\n orangered: 1,\n orchid: 1,\n palegoldenrod: 1,\n palegreen: 1,\n paleturquoise: 1,\n palevioletred: 1,\n papayawhip: 1,\n peachpuff: 1,\n peru: 1,\n pink: 1,\n plum: 1,\n powderblue: 1,\n purple: 1,\n rebeccapurple: 1,\n red: 1,\n rosybrown: 1,\n royalblue: 1,\n saddlebrown: 1,\n salmon: 1,\n sandybrown: 1,\n seagreen: 1,\n seashell: 1,\n sienna: 1,\n silver: 1,\n skyblue: 1,\n slateblue: 1,\n slategray: 1,\n slategrey: 1,\n snow: 1,\n springgreen: 1,\n steelblue: 1,\n tan: 1,\n teal: 1,\n thistle: 1,\n tomato: 1,\n turquoise: 1,\n violet: 1,\n wheat: 1,\n white: 1,\n whitesmoke: 1,\n yellow: 1,\n yellowgreen: 1,\n\n // CSS System Colors\n // Spec: https://drafts.csswg.org/css-color/#css-system-colors\n canvas: 1,\n canvastext: 1,\n linktext: 1,\n visitedtext: 1,\n activetext: 1,\n buttonface: 1,\n buttontext: 1,\n buttonborder: 1,\n field: 1,\n fieldtext: 1,\n highlight: 1,\n highlighttext: 1,\n selecteditem: 1,\n selecteditemtext: 1,\n mark: 1,\n marktext: 1,\n graytext: 1,\n\n // TODO: Deprecated CSS System colors\n // Spec: https://drafts.csswg.org/css-color/#deprecated-system-colors\n}\n\nexport const colorFunctions = {\n rgb: 1,\n rgba: 1,\n hsl: 1,\n hsla: 1,\n hwb: 1,\n lab: 1,\n lch: 1,\n oklab: 1,\n oklch: 1,\n color: 1,\n}\n","class CountableCollection {\n /**\n * @param {string[]} initial\n */\n constructor(initial) {\n /** @type [index: string]: string */\n this._items = {}\n /** @type number */\n this._total = 0\n /** @type number */\n this._totalUnique = 0\n\n if (initial) {\n for (let i = 0; i < initial.length; i++) {\n this.push(initial[i])\n }\n }\n }\n\n /**\n * Push an item to the end of this collection\n * @param {string} item\n * @returns {void}\n */\n push(item) {\n this._total++\n\n if (this._items[item]) {\n this._items[item]++\n return\n }\n\n this._items[item] = 1\n this._totalUnique++\n }\n\n /**\n * Get the size of this collection\n * @returns {number} the size of this collection\n */\n size() {\n return this._total\n }\n\n /**\n * Get the counts of this collection, like total, uniques, etc.\n */\n count() {\n return {\n total: this._total,\n totalUnique: this._totalUnique,\n unique: this._items,\n uniquenessRatio: this._total === 0 ? 0 : this._totalUnique / this._total,\n }\n }\n}\n\nexport {\n CountableCollection\n}","import walk from 'css-tree/walker'\nimport { CountableCollection } from '../countable-collection.js'\n\nconst systemKeywords = {\n // Global CSS keywords\n 'inherit': 1,\n 'initial': 1,\n 'unset': 1,\n 'revert': 1,\n\n // System font keywords\n 'caption': 1,\n 'icon': 1,\n 'menu': 1,\n 'message-box': 1,\n 'small-caption': 1,\n 'status-bar': 1,\n}\n\nconst keywordDisallowList = {\n // font-weight, font-stretch, font-style\n 'normal': 1,\n\n // font-size keywords\n 'xx-small': 1,\n 'x-small': 1,\n 'small': 1,\n 'medium': 1,\n 'large': 1,\n 'x-large': 1,\n 'xx-large': 1,\n 'larger': 1,\n 'smaller': 1,\n\n // font-weight keywords\n 'bold': 1,\n 'bolder': 1,\n 'lighter': 1,\n\n // font-stretch keywords\n 'ultra-condensed': 1,\n 'extra-condensed': 1,\n 'condensed': 1,\n 'semi-condensed': 1,\n 'semi-expanded': 1,\n 'expanded': 1,\n 'extra-expanded': 1,\n 'ultra-expanded': 1,\n\n // font-style keywords\n 'italic': 1,\n 'oblique': 1,\n}\n\nconst COMMA = 44 // ','.charCodeAt(0) === 44\n\nconst analyzeFontFamilies = ({ fontValues, fontFamilyValues, stringifyNode }) => {\n const all = new CountableCollection(fontFamilyValues)\n\n for (let index = 0; index < fontValues.length; index++) {\n const value = fontValues[index]\n\n // Avoid tree traversal as soon as possible\n const firstChild = value.children.first\n\n if (firstChild.type === 'Identifier' && systemKeywords[firstChild.name]) {\n continue\n }\n\n let parts = ''\n\n walk(value, {\n reverse: true,\n enter: function (fontNode) {\n if (fontNode.type === 'String') {\n const loc = fontNode.loc.start\n // Stringify the first character to get the correct quote character\n const quote = stringifyNode({\n loc: {\n start: {\n line: loc.line,\n column: loc.column\n },\n end: {\n line: loc.line,\n column: loc.column + 1\n }\n }\n })\n return parts = quote + fontNode.value + quote + parts\n }\n if (fontNode.type === 'Operator' && fontNode.value.charCodeAt(0) === COMMA) {\n return parts = fontNode.value + parts\n }\n if (fontNode.type === 'Identifier') {\n if (keywordDisallowList[fontNode.name]) {\n return this.skip\n }\n return parts = fontNode.name + parts\n }\n }\n })\n\n all.push(parts)\n }\n\n return all.count()\n}\n\nexport {\n analyzeFontFamilies\n}","import walk from 'css-tree/walker'\nimport { CountableCollection } from '../countable-collection.js'\n\nconst sizeKeywords = {\n 'xx-small': 1,\n 'x-small': 1,\n 'small': 1,\n 'medium': 1,\n 'large': 1,\n 'x-large': 1,\n 'xx-large': 1,\n 'larger': 1,\n 'smaller': 1,\n}\n\nconst keywords = {\n // Global CSS keywords\n 'inherit': 1,\n 'initial': 1,\n 'unset': 1,\n 'revert': 1,\n\n // System font keywords\n 'caption': 1,\n 'icon': 1,\n 'menu': 1,\n 'message-box': 1,\n 'small-caption': 1,\n 'status-bar': 1,\n}\n\nconst ZERO = 48 // '0'.charCodeAt(0) === 48\nconst SLASH = 47 // '/'.charCodeAt(0) === 47\n\nconst analyzeFontSizes = ({ stringifyNode, fontSizeValues, fontValues }) => {\n const all = new CountableCollection(fontSizeValues)\n\n for (let index = 0; index < fontValues.length; index++) {\n const fontNode = fontValues[index];\n // Try to eliminate a keyword before we continue\n const firstChild = fontNode.children.first\n\n if (firstChild.type === 'Identifier' && keywords[firstChild.name]) {\n continue\n }\n\n let operator = false\n let size\n\n walk(fontNode, function (fontNode) {\n switch (fontNode.type) {\n case 'Number': {\n // Special case for `font: 0/0 a`\n if (fontNode.value.charCodeAt(0) === ZERO) {\n size = '0'\n return this.break\n }\n }\n case 'Operator': {\n if (fontNode.value.charCodeAt(0) === SLASH) {\n operator = true\n }\n break\n }\n case 'Dimension': {\n if (!operator) {\n size = stringifyNode(fontNode)\n return this.break\n }\n }\n case 'Identifier': {\n if (sizeKeywords[fontNode.name]) {\n size = fontNode.name\n return this.break\n }\n }\n }\n })\n\n if (size) {\n all.push(size)\n }\n }\n\n return all.count()\n}\n\nexport {\n analyzeFontSizes\n}","import { CountableCollection } from '../countable-collection.js'\n\nconst keywords = {\n 'auto': 1,\n 'inherit': 1,\n 'initial': 1,\n 'unset': 1,\n 'revert': 1,\n 'none': 1, // for `text-shadow` and `box-shadow`\n}\n\nconst analyzeValues = ({ values, stringifyNode }) => {\n const all = new CountableCollection()\n\n for (let i = 0; i < values.length; i++) {\n const node = values[i]\n const firstChild = node.children.first\n\n if (!firstChild) continue\n if (firstChild.type === 'Identifier' && keywords[firstChild.name]) continue\n\n all.push(stringifyNode(node))\n }\n\n return all.count()\n}\n\nexport {\n analyzeValues\n}","import { CountableCollection } from '../countable-collection.js'\n\nconst timingKeywords = {\n 'linear': 1,\n 'ease': 1,\n 'ease-in': 1,\n 'ease-out': 1,\n 'ease-in-out': 1,\n 'step-start': 1,\n 'step-end': 1,\n}\n\nconst analyzeAnimations = ({ animations, durations, timingFunctions, stringifyNode }) => {\n const allDurations = new CountableCollection(durations)\n const allTimingFunctions = new CountableCollection(timingFunctions)\n\n for (let index = 0; index < animations.length; index++) {\n // Flag to know if we've grabbed the first Duration\n // yet (the first Dimension in a shorthand)\n let durationFound = false\n\n animations[index].forEach(child => {\n // Right after a ',' we start over again\n if (child.type === 'Operator') {\n return durationFound = false\n }\n if (child.type === 'Dimension' && durationFound === false) {\n durationFound = true\n return allDurations.push(stringifyNode(child))\n }\n if (child.type === 'Identifier' && timingKeywords[child.name]) {\n return allTimingFunctions.push(stringifyNode(child))\n }\n if (child.type === 'Function'\n && (\n child.name === 'cubic-bezier' || child.name === 'steps'\n )\n ) {\n return allTimingFunctions.push(stringifyNode(child))\n }\n })\n }\n\n return {\n durations: allDurations.count(),\n timingFunctions: allTimingFunctions.count(),\n }\n}\n\nexport {\n analyzeAnimations\n}","const HYPHENMINUS = 45; // '-'.charCodeAt()\n\n/**\n * @param {string} keyword\n * @returns {boolean}\n */\nfunction hasVendorPrefix(keyword) {\n if (keyword.charCodeAt(0) === HYPHENMINUS && keyword.charCodeAt(1) !== HYPHENMINUS) {\n // String must have a 2nd occurrence of '-', at least at position 3 (offset=2)\n if (keyword.indexOf('-', 2) !== -1) {\n return true\n }\n }\n\n return false\n}\n\nexport {\n hasVendorPrefix\n}","import { CountableCollection } from '../countable-collection.js'\nimport { hasVendorPrefix } from '../vendor-prefix.js'\n\nfunction isAstVendorPrefixed(children) {\n children = children.toArray()\n\n for (let index = 0; index < children.length; index++) {\n const child = children[index];\n\n if (child.type === 'Identifier' && child.name.length >= 3) {\n if (hasVendorPrefix(child.name)) {\n return true\n }\n }\n\n if (child.type === 'Function') {\n if (hasVendorPrefix(child.name)) {\n return true\n }\n\n if (child.children && isAstVendorPrefixed(child.children)) {\n return true\n }\n }\n }\n return false\n}\n\nconst analyzeVendorPrefixes = ({ values, stringifyNode }) => {\n const all = new CountableCollection()\n\n for (let i = 0; i < values.length; i++) {\n /** @type {import('css-tree').Value} */\n const value = values[i]\n\n if (value.children && isAstVendorPrefixed(value.children)) {\n all.push(stringifyNode(value))\n }\n }\n\n return all.count()\n}\n\nexport {\n analyzeVendorPrefixes\n}","import { CountableCollection } from '../countable-collection.js'\nimport { hasVendorPrefix } from '../vendor-prefix.js'\nimport { endsWith } from '../string-utils.js'\n\nconst analyzeAtRules = ({ atrules, stringifyNode }) => {\n /** @type {{[index: string]: string}[]} */\n const fontfaces = []\n const layers = new CountableCollection()\n const imports = new CountableCollection()\n const medias = new CountableCollection()\n const charsets = new CountableCollection()\n const supports = new CountableCollection()\n const keyframes = new CountableCollection()\n const prefixedKeyframes = new CountableCollection()\n const containers = new CountableCollection()\n\n const machine = {\n 'font-face': (node) => {\n /** @type {[index: string]: string} */\n const descriptors = {}\n\n node.block.children.forEach(\n /** @param {import('css-tree').Declaration} descriptor */\n descriptor => (descriptors[descriptor.property] = stringifyNode(descriptor.value))\n )\n\n fontfaces.push(descriptors)\n },\n 'media': node => medias.push(node.prelude),\n 'supports': node => supports.push(node.prelude),\n 'keyframes': node => keyframes.push(`@${node.name} ${node.prelude}`),\n 'import': node => imports.push(node.prelude),\n 'charset': node => charsets.push(node.prelude),\n 'container': node => containers.push(node.prelude),\n 'layer': node => {\n node.prelude.trim()\n .split(',')\n .map(name => name.trim())\n .forEach(name => layers.push(name))\n },\n }\n\n for (let i = 0; i < atrules.length; i++) {\n /** @type {import('css-tree').Atrule} */\n const node = atrules[i]\n const atRuleName = node.name\n const action = machine[atRuleName]\n if (action) {\n action(node)\n continue\n }\n\n if (endsWith('keyframes', atRuleName)) {\n const name = `@${atRuleName} ${node.prelude}`\n keyframes.push(name)\n\n if (hasVendorPrefix(atRuleName)) {\n prefixedKeyframes.push(name)\n }\n continue\n }\n }\n\n return {\n fontface: {\n total: fontfaces.length,\n totalUnique: fontfaces.length,\n unique: fontfaces,\n uniquenessRatio: fontfaces.length === 0 ? 0 : 1\n },\n import: imports.count(),\n media: medias.count(),\n charset: charsets.count(),\n supports: supports.count(),\n keyframes: Object.assign(\n keyframes.count(), {\n prefixed: Object.assign(\n prefixedKeyframes.count(), {\n ratio: keyframes.size() === 0 ? 0 : prefixedKeyframes.size() / keyframes.size()\n }),\n }),\n container: containers.count(),\n layer: layers.count(),\n }\n}\n\nexport {\n analyzeAtRules\n}","import { CountableCollection } from './countable-collection.js'\n\nclass ContextCollection {\n constructor() {\n this._list = new CountableCollection()\n /** @type {[index; string]: CountableCollection} */\n this._contexts = {}\n }\n\n /**\n * Add an item to this _list's context\n * @param {string} item Item to push\n * @param {string} context Context to push Item to\n */\n push(item, context) {\n this._list.push(item)\n\n if (!this._contexts[context]) {\n this._contexts[context] = new CountableCollection()\n }\n\n this._contexts[context].push(item)\n }\n\n count() {\n /** @type {[index: string]: string} */\n const itemsPerContext = {}\n\n for (let context in this._contexts) {\n itemsPerContext[context] = this._contexts[context].count()\n }\n\n return Object.assign(this._list.count(), {\n itemsPerContext\n })\n }\n}\n\nexport {\n ContextCollection\n}","/**\n * Find the mode (most occurring value) in an array of Numbers\n * Takes the mean/average of multiple values if multiple values occur the same amount of times.\n *\n * @see https://github.com/angus-c/just/blob/684af9ca0c7808bc78543ec89379b1fdfce502b1/packages/array-mode/index.js\n * @param {Array} arr - Array to find the mode value for\n * @returns {Number} mode - The `mode` value of `arr`\n */\nfunction Mode(arr) {\n const frequencies = Object.create(null)\n let maxOccurrences = -1\n let maxOccurenceCount = 0\n let sum = 0\n\n for (let i = 0; i < arr.length; i++) {\n const element = arr[i]\n const updatedCount = (frequencies[element] || 0) + 1\n frequencies[element] = updatedCount\n\n if (updatedCount > maxOccurrences) {\n maxOccurrences = updatedCount\n maxOccurenceCount = 0\n sum = 0\n }\n\n if (updatedCount >= maxOccurrences) {\n maxOccurenceCount++\n sum += element\n }\n }\n\n return sum / maxOccurenceCount\n}\n\n/**\n * Find the middle number in an Array of Numbers\n * Returns the average of 2 numbers if the Array length is an even number\n * @see https://github.com/angus-c/just/blob/684af9ca0c7808bc78543ec89379b1fdfce502b1/packages/array-median/index.js\n * @param {Array} arr - A sorted Array\n * @returns {Number} - The array's Median\n */\nfunction Median(arr) {\n const middle = arr.length / 2\n const lowerMiddleRank = Math.floor(middle)\n\n if (middle !== lowerMiddleRank) {\n return arr[lowerMiddleRank]\n }\n return (arr[lowerMiddleRank] + arr[lowerMiddleRank - 1]) / 2\n}\n\nclass AggregateCollection {\n constructor() {\n /** @type number[] */\n this._items = []\n }\n\n /**\n * Add a new Integer at the end of this AggregateCollection\n * @param {number} item - The item to add\n */\n add(item) {\n this._items.push(item)\n }\n\n aggregate() {\n if (this._items.length === 0) {\n return {\n min: 0,\n max: 0,\n mean: 0,\n mode: 0,\n median: 0,\n range: 0,\n sum: 0,\n }\n }\n\n /** @type Number[] */\n const sorted = this._items.slice().sort((a, b) => a - b)\n const min = sorted[0]\n const max = sorted[sorted.length - 1]\n\n const sum = this._items.reduce((total, num) => (total += num))\n const mode = Mode(this._items)\n const median = Median(sorted)\n\n return {\n min,\n max,\n mean: sum / this._items.length,\n mode,\n median,\n range: max - min,\n sum,\n }\n }\n\n /**\n * @returns {number[]} All _items in this collection\n */\n toArray() {\n return this._items\n }\n}\n\nexport {\n AggregateCollection\n}","import { hasVendorPrefix } from '../vendor-prefix.js'\nimport { endsWith } from '../string-utils.js'\n\n/**\n * @param {string} property\n * @see https://github.com/csstree/csstree/blob/master/lib/utils/names.js#L69\n */\nexport function isHack(property) {\n if (isCustom(property) || hasVendorPrefix(property)) return false\n\n let code = property.charCodeAt(0)\n\n return code === 47 // /\n || code === 95 // _\n || code === 43 // +\n || code === 42 // *\n || code === 38 // &\n || code === 36 // $\n || code === 35 // #\n}\n\nexport function isCustom(property) {\n if (property.length < 3) return false\n // 45 === '-'.charCodeAt(0)\n return property.charCodeAt(0) === 45 && property.charCodeAt(1) === 45\n}\n\nexport function isProperty(basename, property) {\n if (isCustom(property)) return false\n return endsWith(basename, property)\n}","export class OccurrenceCounter {\n constructor() {\n this._items = Object.create(null)\n }\n\n push(item) {\n if (this._items[item]) {\n return this._items[item]++\n }\n\n return this._items[item] = 1\n }\n\n count() {\n return Object.keys(this._items).length\n }\n}\n","import parse from 'css-tree/parser'\nimport walk from 'css-tree/walker'\nimport { analyzeRule } from './rules/rules.js'\nimport { analyzeSpecificity, compareSpecificity } from './selectors/specificity.js'\nimport { colorFunctions, colorNames } from './values/colors.js'\nimport { analyzeFontFamilies } from './values/font-families.js'\nimport { analyzeFontSizes } from './values/font-sizes.js'\nimport { analyzeValues } from './values/values.js'\nimport { analyzeAnimations } from './values/animations.js'\nimport { analyzeVendorPrefixes } from './values/vendor-prefix.js'\nimport { analyzeAtRules } from './atrules/atrules.js'\nimport { ContextCollection } from './context-collection.js'\nimport { CountableCollection } from './countable-collection.js'\nimport { AggregateCollection } from './aggregate-collection.js'\nimport { strEquals, startsWith, endsWith } from './string-utils.js'\nimport { hasVendorPrefix } from './vendor-prefix.js'\nimport { isCustom, isHack, isProperty } from './properties/property-utils.js'\nimport { OccurrenceCounter } from './occurrence-counter.js'\n\n/**\n * Analyze CSS\n * @param {string} css\n */\nconst analyze = (css) => {\n const start = new Date()\n\n // We need all lines later on when we need to stringify the AST again\n // e.g. for Selectors\n const lines = css.split(/\\r?\\n/)\n\n /**\n * Recreate the authored CSS from a CSSTree node\n * @param {import('css-tree').CssNode} node - Node from CSSTree AST to stringify\n * @returns {string} str - The stringified node\n */\n function stringifyNode(node) {\n const start = node.loc.start\n const end = node.loc.end\n const lineCount = end.line - start.line\n\n // Single-line nodes\n if (lineCount === 0) {\n return lines[start.line - 1].substring(start.column - 1, end.column - 1)\n }\n\n // Multi-line nodes\n let value = ''\n\n for (let i = start.line; i <= end.line; i++) {\n const line = lines[i - 1]\n // First line\n if (i === start.line) {\n value += line.substring(start.column - 1) + '\\n'\n continue\n }\n // Last line\n if (i === end.line) {\n value += line.substring(0, end.column - 1)\n continue\n }\n // All lines in between first and last\n value += line + '\\n'\n }\n\n return value\n }\n\n const startParse = new Date()\n let totalComments = 0\n let commentsSize = 0\n\n const ast = parse(css, {\n parseAtrulePrelude: false,\n parseCustomProperty: true, // To find font-families, colors, etc.\n positions: true, // So we can use stringifyNode()\n onComment: function (comment) {\n totalComments++\n commentsSize += comment.length\n },\n })\n\n const startAnalysis = new Date()\n const embeds = new CountableCollection()\n const atrules = []\n\n let totalRules = 0\n let emptyRules = 0\n const selectorsPerRule = new AggregateCollection()\n const declarationsPerRule = new AggregateCollection()\n\n const keyframeSelectors = new CountableCollection()\n const uniqueDeclarations = new OccurrenceCounter()\n let totalDeclarations = 0\n let importantDeclarations = 0\n let importantsInKeyframes = 0\n\n const properties = new CountableCollection()\n const propertyHacks = new CountableCollection()\n const propertyVendorPrefixes = new CountableCollection()\n const customProperties = new CountableCollection()\n\n const values = []\n const zindex = []\n const textShadows = []\n const boxShadows = []\n const fontValues = []\n const fontFamilyValues = []\n const fontSizeValues = []\n const animations = []\n const timingFunctions = []\n const durations = []\n const colors = new ContextCollection()\n const units = new ContextCollection()\n\n // SELECTORS\n /** @type number */\n const uniqueSelectors = new OccurrenceCounter()\n /** @type [number,number,number] */\n let maxSpecificity\n /** @type [number,number,number] */\n let minSpecificity\n let specificityA = new AggregateCollection()\n let specificityB = new AggregateCollection()\n let specificityC = new AggregateCollection()\n const complexityAggregator = new AggregateCollection()\n /** @type [number,number,number][] */\n const specificities = []\n /** @type number[] */\n const complexities = []\n const ids = new CountableCollection()\n const a11y = new CountableCollection()\n\n walk(ast, function (node) {\n switch (node.type) {\n case 'Atrule': {\n atrules.push({\n name: node.name,\n prelude: node.prelude && node.prelude.value,\n block: strEquals('font-face', node.name) && node.block,\n })\n break\n }\n case 'Rule': {\n const [numSelectors, numDeclarations] = analyzeRule(node)\n\n totalRules++\n\n if (numDeclarations === 0) {\n emptyRules++\n }\n\n selectorsPerRule.add(numSelectors)\n declarationsPerRule.add(numDeclarations)\n break\n }\n case 'Selector': {\n const selector = stringifyNode(node)\n\n if (this.atrule && endsWith('keyframes', this.atrule.name)) {\n keyframeSelectors.push(selector)\n return this.skip\n }\n\n const { specificity, complexity, isId, isA11y } = analyzeSpecificity(node)\n\n if (isId) {\n ids.push(selector)\n }\n\n if (isA11y) {\n a11y.push(selector)\n }\n\n uniqueSelectors.push(selector)\n complexityAggregator.add(complexity)\n\n if (maxSpecificity === undefined) {\n maxSpecificity = specificity\n }\n\n if (minSpecificity === undefined) {\n minSpecificity = specificity\n }\n\n specificityA.add(specificity[0])\n specificityB.add(specificity[1])\n specificityC.add(specificity[2])\n\n if (minSpecificity !== undefined && compareSpecificity(minSpecificity, specificity) < 0) {\n minSpecificity = specificity\n }\n\n if (maxSpecificity !== undefined && compareSpecificity(maxSpecificity, specificity) > 0) {\n maxSpecificity = specificity\n }\n\n specificities.push(specificity)\n complexities.push(complexity)\n\n // Avoid deeper walking of selectors to not mess with\n // our specificity calculations in case of a selector\n // with :where() or :is() that contain SelectorLists\n // as children\n return this.skip\n }\n case 'Dimension': {\n if (!this.declaration) {\n break\n }\n\n units.push(node.unit, this.declaration.property)\n\n return this.skip\n }\n case 'Url': {\n if (startsWith('data:', node.value)) {\n embeds.push(node.value)\n }\n break\n }\n case 'Value': {\n values.push(node)\n\n const property = this.declaration.property\n\n // Process properties first that don't have colors,\n // so we can avoid further walking them;\n if (isProperty('z-index', property)) {\n zindex.push(node)\n return this.skip\n } else if (isProperty('font', property)) {\n fontValues.push(node)\n break\n } else if (isProperty('font-size', property)) {\n fontSizeValues.push(stringifyNode(node))\n break\n } else if (isProperty('font-family', property)) {\n fontFamilyValues.push(stringifyNode(node))\n break\n } else if (isProperty('transition', property) || isProperty('animation', property)) {\n animations.push(node.children)\n break\n } else if (isProperty('animation-duration', property) || isProperty('transition-duration', property)) {\n durations.push(stringifyNode(node))\n break\n } else if (isProperty('transition-timing-function', property) || isProperty('animation-timing-function', property)) {\n timingFunctions.push(stringifyNode(node))\n break\n } else if (isProperty('text-shadow', property)) {\n textShadows.push(node)\n // no break here: potentially contains colors\n } else if (isProperty('box-shadow', property)) {\n boxShadows.push(node)\n // no break here: potentially contains colors\n }\n\n walk(node, function (valueNode) {\n switch (valueNode.type) {\n case 'Hash': {\n colors.push('#' + valueNode.value, property)\n\n return this.skip\n }\n case 'Identifier': {\n const { name } = valueNode\n // Bail out if it can't be a color name\n // 20 === 'lightgoldenrodyellow'.length\n // 3 === 'red'.length\n if (name.length > 20 || name.length < 3) {\n return this.skip\n }\n if (colorNames[name.toLowerCase()]) {\n colors.push(stringifyNode(valueNode), property)\n }\n return this.skip\n }\n case 'Function': {\n // Don't walk var() multiple times\n if (strEquals('var', valueNode.name)) {\n return this.skip\n }\n if (colorFunctions[valueNode.name.toLowerCase()]) {\n colors.push(stringifyNode(valueNode), property)\n }\n // No this.skip here intentionally,\n // otherwise we'll miss colors in linear-gradient() etc.\n }\n }\n })\n break\n }\n case 'Declaration': {\n totalDeclarations++\n\n const declaration = stringifyNode(node)\n uniqueDeclarations.push(declaration)\n\n if (node.important) {\n importantDeclarations++\n\n if (this.atrule && endsWith('keyframes', this.atrule.name)) {\n importantsInKeyframes++\n }\n }\n\n const { property } = node\n\n properties.push(property)\n\n if (hasVendorPrefix(property)) {\n propertyVendorPrefixes.push(property)\n } else if (isHack(property)) {\n propertyHacks.push(property)\n } else if (isCustom(property)) {\n customProperties.push(property)\n }\n break\n }\n }\n })\n\n const embeddedContent = embeds.count()\n const embedSize = Object.keys(embeddedContent.unique).join('').length\n\n const totalUniqueDeclarations = uniqueDeclarations.count()\n\n const totalSelectors = complexities.length\n const aggregatesA = specificityA.aggregate()\n const aggregatesB = specificityB.aggregate()\n const aggregatesC = specificityC.aggregate()\n const complexityCount = new CountableCollection(complexities).count()\n const totalUniqueSelectors = uniqueSelectors.count()\n\n return {\n stylesheet: {\n sourceLinesOfCode: atrules.length + totalSelectors + totalDeclarations + keyframeSelectors.size(),\n linesOfCode: lines.length,\n size: css.length,\n comments: {\n total: totalComments,\n size: commentsSize,\n },\n embeddedContent: Object.assign(embeddedContent, {\n size: {\n total: embedSize,\n ratio: css.length === 0 ? 0 : embedSize / css.length,\n },\n }),\n },\n atrules: analyzeAtRules({ atrules, stringifyNode }),\n rules: {\n total: totalRules,\n empty: {\n total: emptyRules,\n ratio: totalRules === 0 ? 0 : emptyRules / totalRules\n },\n selectors: Object.assign(\n selectorsPerRule.aggregate(), {\n items: selectorsPerRule.toArray(),\n }),\n declarations: Object.assign(\n declarationsPerRule.aggregate(), {\n items: declarationsPerRule.toArray()\n }),\n },\n selectors: {\n total: totalSelectors,\n totalUnique: totalUniqueSelectors,\n uniquenessRatio: totalSelectors === 0 ? 0 : totalUniqueSelectors / totalSelectors,\n specificity: {\n min: minSpecificity === undefined ? [0, 0, 0] : minSpecificity,\n max: maxSpecificity === undefined ? [0, 0, 0] : maxSpecificity,\n sum: [aggregatesA.sum, aggregatesB.sum, aggregatesC.sum],\n mean: [aggregatesA.mean, aggregatesB.mean, aggregatesC.mean],\n mode: [aggregatesA.mode, aggregatesB.mode, aggregatesC.mode],\n median: [aggregatesA.median, aggregatesB.median, aggregatesC.median],\n items: specificities\n },\n complexity: Object.assign(\n complexityAggregator.aggregate(),\n complexityCount, {\n items: complexities\n }),\n id: Object.assign(\n ids.count(), {\n ratio: totalSelectors === 0 ? 0 : ids.size() / totalSelectors,\n }),\n accessibility: Object.assign(\n a11y.count(), {\n ratio: totalSelectors === 0 ? 0 : a11y.size() / totalSelectors,\n }),\n keyframes: keyframeSelectors.count(),\n },\n declarations: {\n total: totalDeclarations,\n unique: {\n total: totalUniqueDeclarations,\n ratio: totalDeclarations === 0 ? 0 : totalUniqueDeclarations / totalDeclarations,\n },\n importants: {\n total: importantDeclarations,\n ratio: totalDeclarations === 0 ? 0 : importantDeclarations / totalDeclarations,\n inKeyframes: {\n total: importantsInKeyframes,\n ratio: importantDeclarations === 0 ? 0 : importantsInKeyframes / importantDeclarations,\n },\n },\n },\n properties: Object.assign(\n properties.count(), {\n prefixed: Object.assign(\n propertyVendorPrefixes.count(), {\n ratio: properties.size() === 0 ? 0 : propertyVendorPrefixes.size() / properties.size(),\n }),\n custom: Object.assign(\n customProperties.count(), {\n ratio: properties.size() === 0 ? 0 : customProperties.size() / properties.size(),\n }),\n browserhacks: Object.assign(\n propertyHacks.count(), {\n ratio: properties.size() === 0 ? 0 : propertyHacks.size() / properties.size(),\n }),\n }),\n values: {\n colors: colors.count(),\n fontFamilies: analyzeFontFamilies({ stringifyNode, fontValues, fontFamilyValues }),\n fontSizes: analyzeFontSizes({ stringifyNode, fontValues, fontSizeValues }),\n zindexes: analyzeValues({ values: zindex, stringifyNode }),\n textShadows: analyzeValues({ values: textShadows, stringifyNode }),\n boxShadows: analyzeValues({ values: boxShadows, stringifyNode }),\n animations: analyzeAnimations({ animations, timingFunctions, durations, stringifyNode }),\n prefixes: analyzeVendorPrefixes({ values, stringifyNode }),\n units: units.count(),\n },\n __meta__: {\n parseTime: startAnalysis - startParse,\n analyzeTime: new Date() - startAnalysis,\n total: new Date() - start\n }\n }\n}\n\nexport {\n analyze,\n compareSpecificity,\n}\n","import walk from 'css-tree/walker'\n\nconst analyzeRule = function (ruleNode) {\n let numSelectors = 0\n let numDeclarations = 0\n\n walk(ruleNode, function (childNode) {\n if (childNode.type === 'Selector') {\n numSelectors++\n return this.skip\n }\n\n if (childNode.type === 'Declaration') {\n numDeclarations++\n return this.skip\n }\n })\n\n return [numSelectors, numDeclarations]\n}\n\nexport {\n analyzeRule,\n}"],"names":["compareChar","referenceCode","testCode","strEquals","base","test","length","i","charCodeAt","endsWith","offset","startsWith","compareSpecificity","a","b","analyzeSpecificity","node","A","B","C","complexity","isA11y","walk","selector","type","Boolean","value","name","skip","selectorList","childSelectors","visit","enter","push","sort","specificity","listItem","isId","colorNames","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","green","greenyellow","grey","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","canvas","canvastext","linktext","visitedtext","activetext","buttonface","buttontext","buttonborder","field","fieldtext","highlight","highlighttext","selecteditem","selecteditemtext","mark","marktext","graytext","colorFunctions","rgb","rgba","hsl","hsla","hwb","lab","lch","oklab","oklch","color","CountableCollection","initial","this","_items","_total","_totalUnique","item","size","count","total","totalUnique","unique","uniquenessRatio","systemKeywords","inherit","unset","revert","caption","icon","menu","keywordDisallowList","normal","small","medium","large","larger","smaller","bold","bolder","lighter","condensed","expanded","italic","oblique","analyzeFontFamilies","fontValues","stringifyNode","all","fontFamilyValues","index","firstChild","children","first","parts","reverse","fontNode","loc","start","quote","line","column","end","sizeKeywords","keywords","analyzeFontSizes","fontSizeValues","operator","auto","none","analyzeValues","values","timingKeywords","linear","ease","analyzeAnimations","animations","timingFunctions","allDurations","durations","allTimingFunctions","durationFound","forEach","child","hasVendorPrefix","keyword","indexOf","isAstVendorPrefixed","toArray","analyzeVendorPrefixes","analyzeAtRules","atrules","fontfaces","layers","imports","medias","charsets","supports","keyframes","prefixedKeyframes","containers","machine","descriptors","block","descriptor","property","media","prelude","import","charset","container","layer","trim","split","map","atRuleName","action","fontface","Object","assign","prefixed","ratio","ContextCollection","_list","_contexts","context","itemsPerContext","AggregateCollection","add","aggregate","min","max","mean","mode","median","range","sum","arr","middle","lowerMiddleRank","sorted","slice","reduce","num","frequencies","create","maxOccurrences","maxOccurenceCount","element","updatedCount","Mode","Math","floor","isCustom","isProperty","basename","OccurrenceCounter","keys","css","Date","lines","substring","maxSpecificity","minSpecificity","startParse","totalComments","commentsSize","ast","parse","parseAtrulePrelude","parseCustomProperty","positions","onComment","comment","startAnalysis","embeds","totalRules","emptyRules","selectorsPerRule","declarationsPerRule","keyframeSelectors","uniqueDeclarations","totalDeclarations","importantDeclarations","importantsInKeyframes","properties","propertyHacks","propertyVendorPrefixes","customProperties","zindex","textShadows","boxShadows","colors","units","uniqueSelectors","specificityA","specificityB","specificityC","complexityAggregator","specificities","complexities","ids","a11y","ruleNode","numSelectors","numDeclarations","childNode","analyzeRule","atrule","undefined","declaration","unit","valueNode","toLowerCase","important","code","isHack","embeddedContent","embedSize","join","totalUniqueDeclarations","totalSelectors","aggregatesA","aggregatesB","aggregatesC","complexityCount","totalUniqueSelectors","stylesheet","sourceLinesOfCode","linesOfCode","comments","rules","empty","selectors","items","declarations","id","accessibility","importants","inKeyframes","custom","browserhacks","fontFamilies","fontSizes","zindexes","prefixes","__meta__","parseTime","analyzeTime"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -57,17 +57,19 @@ export function analyze(css: string): {
57
57
  uniquenessRatio: number;
58
58
  };
59
59
  keyframes: {
60
+ total: number;
61
+ totalUnique: number;
62
+ unique: [index: string];
63
+ uniquenessRatio: number;
64
+ } & {
60
65
  prefixed: {
61
- ratio: number;
62
66
  total: number;
63
67
  totalUnique: number;
64
68
  unique: [index: string];
65
69
  uniquenessRatio: number;
70
+ } & {
71
+ ratio: number;
66
72
  };
67
- total: number;
68
- totalUnique: number;
69
- unique: [index: string];
70
- uniquenessRatio: number;
71
73
  };
72
74
  container: {
73
75
  total: number;
@@ -89,7 +91,6 @@ export function analyze(css: string): {
89
91
  ratio: number;
90
92
  };
91
93
  selectors: {
92
- items: number[];
93
94
  min: number;
94
95
  max: number;
95
96
  mean: number;
@@ -97,9 +98,10 @@ export function analyze(css: string): {
97
98
  median: number;
98
99
  range: number;
99
100
  sum: number;
101
+ } & {
102
+ items: number[];
100
103
  };
101
104
  declarations: {
102
- items: number[];
103
105
  min: number;
104
106
  max: number;
105
107
  mean: number;
@@ -107,11 +109,13 @@ export function analyze(css: string): {
107
109
  median: number;
108
110
  range: number;
109
111
  sum: number;
112
+ } & {
113
+ items: number[];
110
114
  };
111
115
  };
112
116
  selectors: {
113
117
  total: number;
114
- totalUnique: number;
118
+ totalUnique: any;
115
119
  uniquenessRatio: number;
116
120
  specificity: {
117
121
  min: number[];
@@ -123,11 +127,6 @@ export function analyze(css: string): {
123
127
  items: [number, number, number][];
124
128
  };
125
129
  complexity: {
126
- items: number[];
127
- total: number;
128
- totalUnique: number;
129
- unique: [index: string];
130
- uniquenessRatio: number;
131
130
  min: number;
132
131
  max: number;
133
132
  mean: number;
@@ -135,20 +134,29 @@ export function analyze(css: string): {
135
134
  median: number;
136
135
  range: number;
137
136
  sum: number;
137
+ } & {
138
+ total: number;
139
+ totalUnique: number;
140
+ unique: [index: string];
141
+ uniquenessRatio: number;
142
+ } & {
143
+ items: number[];
138
144
  };
139
145
  id: {
140
- ratio: number;
141
146
  total: number;
142
147
  totalUnique: number;
143
148
  unique: [index: string];
144
149
  uniquenessRatio: number;
150
+ } & {
151
+ ratio: number;
145
152
  };
146
153
  accessibility: {
147
- ratio: number;
148
154
  total: number;
149
155
  totalUnique: number;
150
156
  unique: [index: string];
151
157
  uniquenessRatio: number;
158
+ } & {
159
+ ratio: number;
152
160
  };
153
161
  keyframes: {
154
162
  total: number;
@@ -173,31 +181,35 @@ export function analyze(css: string): {
173
181
  };
174
182
  };
175
183
  properties: {
184
+ total: number;
185
+ totalUnique: number;
186
+ unique: [index: string];
187
+ uniquenessRatio: number;
188
+ } & {
176
189
  prefixed: {
177
- ratio: number;
178
190
  total: number;
179
191
  totalUnique: number;
180
192
  unique: [index: string];
181
193
  uniquenessRatio: number;
194
+ } & {
195
+ ratio: number;
182
196
  };
183
197
  custom: {
184
- ratio: number;
185
198
  total: number;
186
199
  totalUnique: number;
187
200
  unique: [index: string];
188
201
  uniquenessRatio: number;
202
+ } & {
203
+ ratio: number;
189
204
  };
190
205
  browserhacks: {
191
- ratio: number;
192
206
  total: number;
193
207
  totalUnique: number;
194
208
  unique: [index: string];
195
209
  uniquenessRatio: number;
210
+ } & {
211
+ ratio: number;
196
212
  };
197
- total: number;
198
- totalUnique: number;
199
- unique: [index: string];
200
- uniquenessRatio: number;
201
213
  };
202
214
  values: {
203
215
  colors: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectwallace/css-analyzer",
3
- "version": "5.2.1",
3
+ "version": "5.3.0",
4
4
  "author": "Bart Veneman",
5
5
  "repository": {
6
6
  "type": "git",
@@ -51,5 +51,8 @@
51
51
  "microbundle": "^0.14.2",
52
52
  "uvu": "^0.5.3",
53
53
  "watchlist": "^0.2.3"
54
+ },
55
+ "mangle": {
56
+ "regex": "^_[^_]"
54
57
  }
55
58
  }