@projectwallace/css-analyzer 4.0.3 → 5.0.1

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.
Files changed (58) hide show
  1. package/dist/analyzer.cjs +2 -0
  2. package/dist/analyzer.cjs.map +1 -0
  3. package/dist/analyzer.modern.js +2 -0
  4. package/dist/analyzer.modern.js.map +1 -0
  5. package/dist/analyzer.module.js +2 -0
  6. package/dist/analyzer.module.js.map +1 -0
  7. package/dist/analyzer.umd.js +2 -0
  8. package/dist/analyzer.umd.js.map +1 -0
  9. package/package.json +27 -65
  10. package/readme.md +369 -237
  11. package/src/analyzer/atrules/charsets.js +0 -12
  12. package/src/analyzer/atrules/documents.js +0 -12
  13. package/src/analyzer/atrules/fontfaces.js +0 -30
  14. package/src/analyzer/atrules/imports.js +0 -12
  15. package/src/analyzer/atrules/index.js +0 -13
  16. package/src/analyzer/atrules/keyframes.js +0 -19
  17. package/src/analyzer/atrules/mediaqueries.js +0 -19
  18. package/src/analyzer/atrules/namespaces.js +0 -12
  19. package/src/analyzer/atrules/pages.js +0 -12
  20. package/src/analyzer/atrules/supports.js +0 -19
  21. package/src/analyzer/declarations/importants.js +0 -8
  22. package/src/analyzer/declarations/index.js +0 -13
  23. package/src/analyzer/index.js +0 -39
  24. package/src/analyzer/properties/browserhacks.js +0 -13
  25. package/src/analyzer/properties/index.js +0 -15
  26. package/src/analyzer/properties/prefixed.js +0 -13
  27. package/src/analyzer/rules/index.js +0 -53
  28. package/src/analyzer/selectors/accessibility.js +0 -14
  29. package/src/analyzer/selectors/browserhacks.js +0 -11
  30. package/src/analyzer/selectors/complexity.js +0 -44
  31. package/src/analyzer/selectors/id.js +0 -12
  32. package/src/analyzer/selectors/index.js +0 -23
  33. package/src/analyzer/selectors/js.js +0 -12
  34. package/src/analyzer/selectors/specificity.js +0 -42
  35. package/src/analyzer/selectors/universal.js +0 -13
  36. package/src/analyzer/stylesheets/browserhacks.js +0 -15
  37. package/src/analyzer/stylesheets/cohesion.js +0 -30
  38. package/src/analyzer/stylesheets/index.js +0 -33
  39. package/src/analyzer/stylesheets/lines-of-code.js +0 -14
  40. package/src/analyzer/stylesheets/simplicity.js +0 -7
  41. package/src/analyzer/stylesheets/size.js +0 -27
  42. package/src/analyzer/values/animations.js +0 -122
  43. package/src/analyzer/values/box-shadows.js +0 -17
  44. package/src/analyzer/values/browserhacks.js +0 -16
  45. package/src/analyzer/values/colors.js +0 -137
  46. package/src/analyzer/values/font-families.js +0 -30
  47. package/src/analyzer/values/font-sizes.js +0 -31
  48. package/src/analyzer/values/index.js +0 -26
  49. package/src/analyzer/values/prefixed.js +0 -22
  50. package/src/analyzer/values/text-shadows.js +0 -17
  51. package/src/analyzer/values/z-indexes.js +0 -20
  52. package/src/parser/atrules.js +0 -37
  53. package/src/parser/declarations.js +0 -15
  54. package/src/parser/index.js +0 -30
  55. package/src/parser/rules.js +0 -17
  56. package/src/parser/selectors.js +0 -26
  57. package/src/utils/css.js +0 -8
  58. package/src/utils/uniquer.js +0 -24
@@ -1,30 +0,0 @@
1
- const uniquer = require('../../utils/uniquer')
2
-
3
- module.exports = atRules => {
4
- const all = atRules
5
- .filter(({type}) => type === 'font-face')
6
- .map(({declarations}) => declarations)
7
-
8
- // Tricky bit: uniqueness will be based on the `src` of the @font-face
9
- const allSrcValues = all.map(
10
- declarations =>
11
- declarations.find(descriptor => descriptor.property === 'src').value
12
- )
13
-
14
- // Once we have a list of unique @font-face sources,
15
- // we'll map it back to the original rules again
16
- const unique = uniquer(allSrcValues).unique.map(({count, value}) => {
17
- return {
18
- count,
19
- value: all.find(declarations =>
20
- declarations.find(descriptor => descriptor.value === value)
21
- )
22
- }
23
- })
24
-
25
- return {
26
- total: all.length,
27
- unique,
28
- totalUnique: unique.length
29
- }
30
- }
@@ -1,12 +0,0 @@
1
- const uniquer = require('../../utils/uniquer')
2
-
3
- module.exports = atRules => {
4
- const all = atRules
5
- .filter(rule => rule.type === 'import')
6
- .map(rule => rule.params)
7
-
8
- return {
9
- total: all.length,
10
- ...uniquer(all)
11
- }
12
- }
@@ -1,13 +0,0 @@
1
- module.exports = atRules => {
2
- return {
3
- charsets: require('./charsets')(atRules),
4
- documents: require('./documents')(atRules),
5
- fontfaces: require('./fontfaces')(atRules),
6
- imports: require('./imports')(atRules),
7
- keyframes: require('./keyframes')(atRules),
8
- mediaqueries: require('./mediaqueries')(atRules),
9
- namespaces: require('./namespaces')(atRules),
10
- pages: require('./pages')(atRules),
11
- supports: require('./supports')(atRules)
12
- }
13
- }
@@ -1,19 +0,0 @@
1
- const isVendorPrefixed = require('is-vendor-prefixed')
2
- const uniquer = require('../../utils/uniquer')
3
-
4
- module.exports = atRules => {
5
- const all = atRules.filter(rule => rule.type.includes('keyframes'))
6
- const prefixed = all
7
- .filter(rule => isVendorPrefixed(rule.type))
8
- .map(rule => `@${rule.type} ${rule.params}`)
9
-
10
- return {
11
- total: all.length,
12
- ...uniquer(all.map(rule => rule.params)),
13
- prefixed: {
14
- total: prefixed.length,
15
- ...uniquer(prefixed),
16
- share: prefixed.length === 0 ? 0 : all.length / prefixed.length
17
- }
18
- }
19
- }
@@ -1,19 +0,0 @@
1
- const isBrowserHack = require('css-media-query-browser-h4cks-analyzer')
2
- const uniquer = require('../../utils/uniquer')
3
-
4
- module.exports = atRules => {
5
- const all = atRules
6
- .filter(rule => rule.type === 'media')
7
- .map(rule => rule.params)
8
-
9
- const browserhacks = all.filter(isBrowserHack)
10
-
11
- return {
12
- total: all.length,
13
- ...uniquer(all),
14
- browserhacks: {
15
- total: browserhacks.length,
16
- ...uniquer(browserhacks)
17
- }
18
- }
19
- }
@@ -1,12 +0,0 @@
1
- const uniquer = require('../../utils/uniquer')
2
-
3
- module.exports = atRules => {
4
- const all = atRules
5
- .filter(rule => rule.type === 'namespace')
6
- .map(rule => rule.params)
7
-
8
- return {
9
- total: all.length,
10
- ...uniquer(all)
11
- }
12
- }
@@ -1,12 +0,0 @@
1
- const uniquer = require('../../utils/uniquer')
2
-
3
- module.exports = atRules => {
4
- const all = atRules
5
- .filter(rule => rule.type === 'page')
6
- .map(rule => rule.params)
7
-
8
- return {
9
- total: all.length,
10
- ...uniquer(all)
11
- }
12
- }
@@ -1,19 +0,0 @@
1
- const isBrowserHack = require('css-at-supports-browser-h4cks-analyzer')
2
- const uniquer = require('../../utils/uniquer')
3
-
4
- module.exports = atRules => {
5
- const all = atRules
6
- .filter(rule => rule.type === 'supports')
7
- .map(rule => rule.params)
8
-
9
- const browserhacks = all.filter(isBrowserHack)
10
-
11
- return {
12
- total: all.length,
13
- ...uniquer(all),
14
- browserhacks: {
15
- total: browserhacks.length,
16
- ...uniquer(browserhacks)
17
- }
18
- }
19
- }
@@ -1,8 +0,0 @@
1
- module.exports = declarations => {
2
- const all = declarations.filter(value => value.important)
3
-
4
- return {
5
- total: all.length,
6
- share: declarations.length === 0 ? 0 : all.length / declarations.length
7
- }
8
- }
@@ -1,13 +0,0 @@
1
- module.exports = declarations => {
2
- const all = declarations
3
- const totalUnique = new Set(
4
- all.map(({property, value}) => `${property} : ${value}`)
5
- ).size
6
- const importants = require('./importants')(all)
7
-
8
- return {
9
- total: all.length,
10
- totalUnique,
11
- importants
12
- }
13
- }
@@ -1,39 +0,0 @@
1
- const flat = require('flat')
2
- const parser = require('../parser')
3
-
4
- function flattenObject(object) {
5
- return flat(object, {safe: true})
6
- }
7
-
8
- module.exports = async rawCss => {
9
- const css = await parser(rawCss)
10
-
11
- const atrules = require('./atrules')(css.atRules)
12
- const rules = require('./rules')(css.rules)
13
- const selectors = require('./selectors')(css.selectors)
14
- const declarations = require('./declarations')(css.declarations)
15
- const properties = require('./properties')(css.declarations)
16
- const values = require('./values')(css.declarations)
17
- const stylesheets = require('./stylesheets')({
18
- rawCss,
19
- css,
20
- atrules,
21
- rules: css.rules,
22
- selectors,
23
- properties,
24
- values,
25
- declarations
26
- })
27
-
28
- return Promise.resolve(
29
- flattenObject({
30
- stylesheets,
31
- atrules,
32
- rules,
33
- selectors,
34
- declarations,
35
- properties,
36
- values
37
- })
38
- )
39
- }
@@ -1,13 +0,0 @@
1
- const isBrowserHack = require('css-property-browser-h4cks-analyzer')
2
- const uniquer = require('../../utils/uniquer')
3
-
4
- module.exports = properties => {
5
- const all = properties.filter(isBrowserHack)
6
- const {unique, totalUnique} = uniquer(all)
7
-
8
- return {
9
- total: all.length,
10
- unique,
11
- totalUnique
12
- }
13
- }
@@ -1,15 +0,0 @@
1
- const uniquer = require('../../utils/uniquer.js')
2
-
3
- module.exports = declarations => {
4
- const all = declarations.map(({property}) => property)
5
-
6
- const prefixed = require('./prefixed.js')(all)
7
- const browserhacks = require('./browserhacks.js')(all)
8
-
9
- return {
10
- total: all.length,
11
- ...uniquer(all),
12
- prefixed,
13
- browserhacks
14
- }
15
- }
@@ -1,13 +0,0 @@
1
- const isVendorPrefixed = require('is-vendor-prefixed')
2
- const uniquer = require('../../utils/uniquer')
3
-
4
- module.exports = properties => {
5
- const all = properties.filter(isVendorPrefixed)
6
- const share = properties.length === 0 ? 0 : all.length / properties.length
7
-
8
- return {
9
- total: all.length,
10
- ...uniquer(all),
11
- share
12
- }
13
- }
@@ -1,53 +0,0 @@
1
- const compareStrings = require('string-natural-compare')
2
-
3
- const isEmpty = rule => {
4
- return rule.declarations.length === 0
5
- }
6
-
7
- module.exports = rules => {
8
- const all = rules
9
- const total = all.length
10
- const empty = rules.filter(isEmpty)
11
-
12
- // We only want to deal with rules that have selectors.
13
- // While parsing the CSS we have stripped the 'selectors' from
14
- // @keyframes, so we need to ignore the accompanying
15
- // declarations here too
16
- const rulesSortedBySelectorCount = [...all]
17
- .filter(({selectors}) => selectors.length > 0)
18
- .sort((a, b) => {
19
- if (a.selectors.length === b.selectors.length) {
20
- return compareStrings(a.selectors.join(''), b.selectors.join(''), {
21
- caseInsensitive: true
22
- })
23
- }
24
-
25
- return a.selectors.length - b.selectors.length
26
- })
27
- const ruleWithLeastSelectors = [...rulesSortedBySelectorCount].shift()
28
- const ruleWithMostSelectors = [...rulesSortedBySelectorCount].pop()
29
-
30
- const selectorsPerRule = all.map(({selectors}) => selectors.length)
31
- const averageSelectorsPerRule =
32
- total === 0
33
- ? 0
34
- : selectorsPerRule.reduce((acc, curr) => acc + curr, 0) / total
35
-
36
- return {
37
- total,
38
- empty: {
39
- total: empty.length
40
- },
41
- selectors: {
42
- average: averageSelectorsPerRule,
43
- minimum: {
44
- count: total === 0 ? 0 : ruleWithLeastSelectors.selectors.length,
45
- value: total === 0 ? [] : ruleWithLeastSelectors.selectors
46
- },
47
- maximum: {
48
- count: total === 0 ? 0 : ruleWithMostSelectors.selectors.length,
49
- value: total === 0 ? [] : ruleWithMostSelectors.selectors
50
- }
51
- }
52
- }
53
- }
@@ -1,14 +0,0 @@
1
- const uniquer = require('../../utils/uniquer')
2
-
3
- function isA11ySelector(selector) {
4
- return selector.includes('[aria-') || selector.includes('[role=')
5
- }
6
-
7
- module.exports = selectors => {
8
- const all = selectors.filter(isA11ySelector)
9
-
10
- return {
11
- total: all.length,
12
- ...uniquer(all)
13
- }
14
- }
@@ -1,11 +0,0 @@
1
- const isBrowserHack = require('css-selector-browser-h4cks-analyzer')
2
- const uniquer = require('../../utils/uniquer.js')
3
-
4
- module.exports = selectors => {
5
- const all = selectors.filter(isBrowserHack)
6
-
7
- return {
8
- total: all.length,
9
- ...uniquer(all)
10
- }
11
- }
@@ -1,44 +0,0 @@
1
- const selectorComplexity = require('css-selector-complexity')
2
- const uniquer = require('../../utils/uniquer')
3
-
4
- module.exports = selectors => {
5
- const all = selectors.map(selector => {
6
- let complexity = 0
7
-
8
- try {
9
- complexity = selectorComplexity(selector)
10
- } catch (_) {
11
- // Fail silently, ignoring the error
12
- }
13
-
14
- return {
15
- selector,
16
- complexity
17
- }
18
- })
19
- const allComplexities = all.map(selector => selector.complexity)
20
- const maxComplexity = all.length === 0 ? 0 : Math.max(...allComplexities)
21
- const {
22
- unique: mostComplexSelectors,
23
- totalUnique: mostComplexSelectorsCount
24
- } = uniquer(
25
- all
26
- .filter(({complexity}) => complexity === maxComplexity)
27
- .map(({selector}) => selector)
28
- )
29
- const unique = uniquer(allComplexities)
30
- const totalComplexity = allComplexities.reduce((acc, curr) => acc + curr, 0)
31
- const averageComplexityPerSelector =
32
- all.length === 0 ? 0 : totalComplexity / all.length
33
-
34
- return {
35
- max: {
36
- value: maxComplexity,
37
- selectors: mostComplexSelectors,
38
- count: mostComplexSelectorsCount
39
- },
40
- average: averageComplexityPerSelector,
41
- sum: totalComplexity,
42
- ...unique
43
- }
44
- }
@@ -1,12 +0,0 @@
1
- const uniquer = require('../../utils/uniquer')
2
-
3
- const ID_REGEX = /(?![^[]*])#/
4
-
5
- module.exports = selectors => {
6
- const all = selectors.filter(selector => ID_REGEX.test(selector))
7
-
8
- return {
9
- total: all.length,
10
- ...uniquer(all)
11
- }
12
- }
@@ -1,23 +0,0 @@
1
- module.exports = selectors => {
2
- const all = selectors
3
- const unique = [...new Set(all)]
4
- const js = require('./js.js')(all)
5
- const id = require('./id.js')(all)
6
- const universal = require('./universal.js')(all)
7
- const accessibility = require('./accessibility.js')(all)
8
- const specificity = require('./specificity.js')(all)
9
- const complexity = require('./complexity.js')(all)
10
- const browserhacks = require('./browserhacks.js')(all)
11
-
12
- return {
13
- total: all.length,
14
- totalUnique: unique.length,
15
- js,
16
- id,
17
- universal,
18
- accessibility,
19
- specificity,
20
- complexity,
21
- browserhacks
22
- }
23
- }
@@ -1,12 +0,0 @@
1
- const uniquer = require('../../utils/uniquer')
2
-
3
- const JS_REGEX = /[.|#(?:=")]js/i
4
-
5
- module.exports = selectors => {
6
- const all = selectors.filter(selector => JS_REGEX.test(selector))
7
-
8
- return {
9
- total: all.length,
10
- ...uniquer(all)
11
- }
12
- }
@@ -1,42 +0,0 @@
1
- const {compare, calculate} = require('specificity')
2
- const uniquer = require('../../utils/uniquer')
3
-
4
- module.exports = selectors => {
5
- if (selectors.length === 0) {
6
- return {
7
- max: {
8
- count: 0,
9
- selectors: [],
10
- value: null
11
- },
12
- top: []
13
- }
14
- }
15
-
16
- const all = uniquer(selectors)
17
- .unique.map(({value, count}) => {
18
- const [a, b, c, d] = calculate(value).shift().specificityArray
19
-
20
- return {
21
- count,
22
- value,
23
- specificity: {a, b, c, d}
24
- }
25
- })
26
- .sort((a, b) => compare(b.value, a.value))
27
-
28
- const [maxSpecificitySelector] = all
29
- const maxSpecificity = maxSpecificitySelector.specificity
30
- const maxSpecificitySelectors = all.filter(
31
- selector => compare(selector.value, maxSpecificitySelector.value) === 0
32
- )
33
-
34
- return {
35
- top: [...all].slice(0, 5),
36
- max: {
37
- value: maxSpecificity,
38
- count: maxSpecificitySelectors.length,
39
- selectors: maxSpecificitySelectors
40
- }
41
- }
42
- }
@@ -1,13 +0,0 @@
1
- const uniquer = require('../../utils/uniquer')
2
-
3
- const UNIVERSAL_REGEX = /(?![^[]*])\*/
4
-
5
- module.exports = selectors => {
6
- const all = selectors
7
- .filter(selector => UNIVERSAL_REGEX.test(selector))
8
-
9
- return {
10
- total: all.length,
11
- ...uniquer(all)
12
- }
13
- }
@@ -1,15 +0,0 @@
1
- module.exports = (atrules, selectors, properties, values) => {
2
- return [atrules.mediaqueries, atrules.supports, selectors, properties, values]
3
- .map(metric => metric.browserhacks)
4
- .reduce(
5
- (totals, current) => {
6
- totals.total += current.total
7
- totals.totalUnique += current.totalUnique
8
- return totals
9
- },
10
- {
11
- total: 0,
12
- totalUnique: 0
13
- }
14
- )
15
- }
@@ -1,30 +0,0 @@
1
- module.exports = rules => {
2
- const totalRules = rules.length
3
- const totalDeclarations =
4
- totalRules === 0
5
- ? 0
6
- : rules.reduce((acc, curr) => acc + curr.declarations.length, 0)
7
- const rulesSortedByDeclarationCount = rules.sort(
8
- (a, b) => b.declarations.length - a.declarations.length
9
- )
10
-
11
- if (totalRules === 0 || totalDeclarations === 0) {
12
- return {
13
- average: 0,
14
- min: {
15
- count: 0,
16
- value: null
17
- }
18
- }
19
- }
20
-
21
- const [ruleWithMostDeclarations] = rulesSortedByDeclarationCount
22
-
23
- return {
24
- average: totalDeclarations / totalRules,
25
- min: {
26
- count: ruleWithMostDeclarations.declarations.length,
27
- value: ruleWithMostDeclarations
28
- }
29
- }
30
- }
@@ -1,33 +0,0 @@
1
- module.exports = ({
2
- rawCss,
3
- css,
4
- atrules,
5
- rules,
6
- selectors,
7
- properties,
8
- values
9
- }) => {
10
- const size = require('./size.js')(rawCss)
11
- const simplicity = require('./simplicity.js')(rules, selectors)
12
- const cohesion = require('./cohesion.js')(rules)
13
- const browserhacks = require('./browserhacks.js')(
14
- atrules,
15
- selectors,
16
- properties,
17
- values
18
- )
19
- const linesOfCode = require('./lines-of-code')({
20
- rawCss,
21
- atRules: css.atRules,
22
- selectors: css.selectors,
23
- declarations: css.declarations
24
- })
25
-
26
- return {
27
- size,
28
- simplicity,
29
- cohesion,
30
- browserhacks,
31
- linesOfCode
32
- }
33
- }
@@ -1,14 +0,0 @@
1
- const splitLines = require('split-lines')
2
-
3
- module.exports = ({rawCss, atRules, selectors, declarations}) => {
4
- const totalLinesOfCode = splitLines(rawCss).length
5
- const totalSourceLinesOfCode =
6
- atRules.length + selectors.length + declarations.length
7
-
8
- return {
9
- total: totalLinesOfCode,
10
- sourceLinesOfCode: {
11
- total: totalSourceLinesOfCode
12
- }
13
- }
14
- }
@@ -1,7 +0,0 @@
1
- module.exports = (rules, selectors) => {
2
- if (selectors.total === 0) {
3
- return 0
4
- }
5
-
6
- return rules.length / selectors.total
7
- }
@@ -1,27 +0,0 @@
1
- const gzipSize = require('gzip-size')
2
-
3
- function getCompressionRatio(rawSize, compressedSize) {
4
- if (rawSize === 0 || compressedSize === 0) {
5
- return 0
6
- }
7
-
8
- // eslint-disable-next-line no-mixed-operators
9
- return 1 - compressedSize / rawSize
10
- }
11
-
12
- module.exports = rawCss => {
13
- const rawBytes = Buffer.byteLength(rawCss, 'utf8')
14
- const gzipBytes = gzipSize.sync(rawCss)
15
-
16
- return {
17
- uncompressed: {
18
- totalBytes: rawBytes
19
- },
20
- compressed: {
21
- gzip: {
22
- totalBytes: gzipBytes,
23
- compressionRatio: getCompressionRatio(rawBytes, gzipBytes)
24
- }
25
- }
26
- }
27
- }