@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.
- package/dist/analyzer.cjs +2 -0
- package/dist/analyzer.cjs.map +1 -0
- package/dist/analyzer.modern.js +2 -0
- package/dist/analyzer.modern.js.map +1 -0
- package/dist/analyzer.module.js +2 -0
- package/dist/analyzer.module.js.map +1 -0
- package/dist/analyzer.umd.js +2 -0
- package/dist/analyzer.umd.js.map +1 -0
- package/package.json +27 -65
- package/readme.md +369 -237
- package/src/analyzer/atrules/charsets.js +0 -12
- package/src/analyzer/atrules/documents.js +0 -12
- package/src/analyzer/atrules/fontfaces.js +0 -30
- package/src/analyzer/atrules/imports.js +0 -12
- package/src/analyzer/atrules/index.js +0 -13
- package/src/analyzer/atrules/keyframes.js +0 -19
- package/src/analyzer/atrules/mediaqueries.js +0 -19
- package/src/analyzer/atrules/namespaces.js +0 -12
- package/src/analyzer/atrules/pages.js +0 -12
- package/src/analyzer/atrules/supports.js +0 -19
- package/src/analyzer/declarations/importants.js +0 -8
- package/src/analyzer/declarations/index.js +0 -13
- package/src/analyzer/index.js +0 -39
- package/src/analyzer/properties/browserhacks.js +0 -13
- package/src/analyzer/properties/index.js +0 -15
- package/src/analyzer/properties/prefixed.js +0 -13
- package/src/analyzer/rules/index.js +0 -53
- package/src/analyzer/selectors/accessibility.js +0 -14
- package/src/analyzer/selectors/browserhacks.js +0 -11
- package/src/analyzer/selectors/complexity.js +0 -44
- package/src/analyzer/selectors/id.js +0 -12
- package/src/analyzer/selectors/index.js +0 -23
- package/src/analyzer/selectors/js.js +0 -12
- package/src/analyzer/selectors/specificity.js +0 -42
- package/src/analyzer/selectors/universal.js +0 -13
- package/src/analyzer/stylesheets/browserhacks.js +0 -15
- package/src/analyzer/stylesheets/cohesion.js +0 -30
- package/src/analyzer/stylesheets/index.js +0 -33
- package/src/analyzer/stylesheets/lines-of-code.js +0 -14
- package/src/analyzer/stylesheets/simplicity.js +0 -7
- package/src/analyzer/stylesheets/size.js +0 -27
- package/src/analyzer/values/animations.js +0 -122
- package/src/analyzer/values/box-shadows.js +0 -17
- package/src/analyzer/values/browserhacks.js +0 -16
- package/src/analyzer/values/colors.js +0 -137
- package/src/analyzer/values/font-families.js +0 -30
- package/src/analyzer/values/font-sizes.js +0 -31
- package/src/analyzer/values/index.js +0 -26
- package/src/analyzer/values/prefixed.js +0 -22
- package/src/analyzer/values/text-shadows.js +0 -17
- package/src/analyzer/values/z-indexes.js +0 -20
- package/src/parser/atrules.js +0 -37
- package/src/parser/declarations.js +0 -15
- package/src/parser/index.js +0 -30
- package/src/parser/rules.js +0 -17
- package/src/parser/selectors.js +0 -26
- package/src/utils/css.js +0 -8
- package/src/utils/uniquer.js +0 -24
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
const {parse} = require('postcss-values-parser')
|
|
2
|
-
const splitValue = require('split-css-value')
|
|
3
|
-
const {sortFn: timeSortFn} = require('css-time-sort')
|
|
4
|
-
const uniquer = require('../../utils/uniquer')
|
|
5
|
-
const {KEYWORDS} = require('../../utils/css')
|
|
6
|
-
|
|
7
|
-
function getSingleDuration(animation) {
|
|
8
|
-
let duration
|
|
9
|
-
|
|
10
|
-
parse(animation).walkNumerics(node => {
|
|
11
|
-
// The first time-value is always the duration, as per spec
|
|
12
|
-
if (duration) {
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
duration = node.toString()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
return duration
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function getDuration(animation) {
|
|
23
|
-
return splitValue(animation)
|
|
24
|
-
.map(animation => getSingleDuration(animation))
|
|
25
|
-
.filter(Boolean)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function getSingleTimingFunction(animation) {
|
|
29
|
-
let timingFunction
|
|
30
|
-
|
|
31
|
-
parse(animation).walk(node => {
|
|
32
|
-
// There should only be one timing function per shorthand
|
|
33
|
-
if (timingFunction) {
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Look for timing keywords
|
|
38
|
-
if (
|
|
39
|
-
node.type === 'word' &&
|
|
40
|
-
[
|
|
41
|
-
'ease',
|
|
42
|
-
'ease-in',
|
|
43
|
-
'ease-in-out',
|
|
44
|
-
'ease-out',
|
|
45
|
-
'linear',
|
|
46
|
-
'step-start',
|
|
47
|
-
'step-end'
|
|
48
|
-
].includes(node.toString())
|
|
49
|
-
) {
|
|
50
|
-
timingFunction = node.toString()
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// If there's no keyword, it should either be cubic-bezier() or steps()
|
|
55
|
-
if (node.type === 'func' && ['cubic-bezier', 'steps'].includes(node.name)) {
|
|
56
|
-
timingFunction = node.toString()
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
return timingFunction
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function getTimingFunction(animation) {
|
|
64
|
-
return splitValue(animation)
|
|
65
|
-
.map(animation => getSingleTimingFunction(animation))
|
|
66
|
-
.filter(Boolean)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
module.exports = declarations => {
|
|
70
|
-
const all = declarations.filter(({value}) => !KEYWORDS.includes(value))
|
|
71
|
-
|
|
72
|
-
const durations = all
|
|
73
|
-
// First, find all durations directly
|
|
74
|
-
.filter(({property}) =>
|
|
75
|
-
['animation-duration', 'transition-duration'].includes(property)
|
|
76
|
-
)
|
|
77
|
-
.map(declaration => declaration.value)
|
|
78
|
-
// Then, find more through the shorthand declarations
|
|
79
|
-
.concat(
|
|
80
|
-
...all
|
|
81
|
-
.filter(({property}) => ['animation', 'transition'].includes(property))
|
|
82
|
-
.map(({value}) => getDuration(value))
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
const {unique: uniqueDurations, totalUnique: totalUniqueDurations} = uniquer(
|
|
86
|
-
durations,
|
|
87
|
-
timeSortFn
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
const timingFunctions = all
|
|
91
|
-
// First, find all timing-functions directly
|
|
92
|
-
.filter(({property}) =>
|
|
93
|
-
['animation-timing-function', 'transition-timing-function'].includes(
|
|
94
|
-
property
|
|
95
|
-
)
|
|
96
|
-
)
|
|
97
|
-
.map(declaration => declaration.value)
|
|
98
|
-
// Then, find more through the shorthand declarations
|
|
99
|
-
.concat(
|
|
100
|
-
...all
|
|
101
|
-
.filter(({property}) => ['animation', 'transition'].includes(property))
|
|
102
|
-
.map(({value}) => getTimingFunction(value))
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
const {
|
|
106
|
-
unique: uniqueTimingFunctions,
|
|
107
|
-
totalUnique: totalUniqueTimingFunctions
|
|
108
|
-
} = uniquer(timingFunctions)
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
durations: {
|
|
112
|
-
total: durations.length,
|
|
113
|
-
unique: uniqueDurations,
|
|
114
|
-
totalUnique: totalUniqueDurations
|
|
115
|
-
},
|
|
116
|
-
timingFunctions: {
|
|
117
|
-
total: timingFunctions.length,
|
|
118
|
-
unique: uniqueTimingFunctions,
|
|
119
|
-
totalUnique: totalUniqueTimingFunctions
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const uniquer = require('../../utils/uniquer')
|
|
2
|
-
const {KEYWORDS} = require('../../utils/css')
|
|
3
|
-
|
|
4
|
-
module.exports = declarations => {
|
|
5
|
-
const all = declarations
|
|
6
|
-
.filter(({property}) => property === 'box-shadow')
|
|
7
|
-
.filter(({value}) => !KEYWORDS.includes(value))
|
|
8
|
-
.map(declaration => declaration.value)
|
|
9
|
-
|
|
10
|
-
const {unique, totalUnique} = uniquer(all)
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
total: all.length,
|
|
14
|
-
unique,
|
|
15
|
-
totalUnique
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const isBrowserHack = require('css-value-browser-h4cks-analyzer')
|
|
2
|
-
const uniquer = require('../../utils/uniquer')
|
|
3
|
-
|
|
4
|
-
module.exports = declarations => {
|
|
5
|
-
const all = declarations
|
|
6
|
-
.filter(declaration => isBrowserHack(declaration.value))
|
|
7
|
-
.map(declaration => declaration.value)
|
|
8
|
-
|
|
9
|
-
const {unique, totalUnique} = uniquer(all)
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
total: all.length,
|
|
13
|
-
unique,
|
|
14
|
-
totalUnique
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
const {parse} = require('postcss-values-parser')
|
|
2
|
-
const tinycolor = require('tinycolor2')
|
|
3
|
-
const colorSorter = require('color-sorter')
|
|
4
|
-
|
|
5
|
-
const uniquer = require('../../utils/uniquer')
|
|
6
|
-
|
|
7
|
-
function extractColorsFromDeclaration(declaration) {
|
|
8
|
-
const colors = []
|
|
9
|
-
|
|
10
|
-
// Try-catch to ignore values that cannot be parsed with postcss-values-parser
|
|
11
|
-
// Examples:
|
|
12
|
-
// - Base64-encoded images
|
|
13
|
-
// - startColorstr=\'#5243AA\', endColorstr=\'#0079bf\', GradientType=1
|
|
14
|
-
// - opacity=50
|
|
15
|
-
// - 1.5deg
|
|
16
|
-
try {
|
|
17
|
-
parse(declaration.value, {loose: true}).walk(node => {
|
|
18
|
-
if (node.isColor) {
|
|
19
|
-
return colors.push(node)
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
} catch (_) {}
|
|
23
|
-
|
|
24
|
-
if (colors.length > 0) {
|
|
25
|
-
declaration.colors = colors.map(color => color.toString().trim())
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return declaration
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const addCount = color => {
|
|
32
|
-
return {
|
|
33
|
-
...color,
|
|
34
|
-
count: color.notations.reduce((total, {count}) => {
|
|
35
|
-
return total + count
|
|
36
|
-
}, 0)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const addMostCommonNotation = color => {
|
|
41
|
-
return {
|
|
42
|
-
...color,
|
|
43
|
-
value: [...color.notations]
|
|
44
|
-
.sort((a, b) => {
|
|
45
|
-
// If counts are the same, get the shortest notation
|
|
46
|
-
if (a.count === b.count) {
|
|
47
|
-
return a.value.length - b.value.length
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return b.count - a.count
|
|
51
|
-
})
|
|
52
|
-
.shift().value
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const addNotations = (acc, curr) => {
|
|
57
|
-
if (!acc[curr.normalized]) {
|
|
58
|
-
acc[curr.normalized] = {
|
|
59
|
-
notations: []
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
acc[curr.normalized] = {
|
|
64
|
-
notations: [...acc[curr.normalized].notations, curr]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return acc
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const filterDuplicateColors = color => {
|
|
71
|
-
// Filter out the actual duplicate colors
|
|
72
|
-
return color.notations.length > 1
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const validateColor = color => {
|
|
76
|
-
return tinycolor(color.value).isValid()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const normalizeColors = color => {
|
|
80
|
-
// Add a normalized value
|
|
81
|
-
|
|
82
|
-
// Avoid using TinyColor's toHslString() because it rounds
|
|
83
|
-
// the numbers and incorrectly reports duplicates
|
|
84
|
-
const {h, s, l, a} = tinycolor(color.value).toHsl()
|
|
85
|
-
const normalized = a === 0 ? 0 : `h${h}s${s}l${l}a${a}`
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
...color,
|
|
89
|
-
normalized
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const removeTemporaryProperties = color => {
|
|
94
|
-
// Remove temporary props that were needed for analysis
|
|
95
|
-
return {
|
|
96
|
-
...color,
|
|
97
|
-
notations: color.notations.map(notation => {
|
|
98
|
-
const {normalized, ...colorProps} = notation
|
|
99
|
-
return colorProps
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const withDuplicateNotations = colors =>
|
|
105
|
-
Object.values(
|
|
106
|
-
colors
|
|
107
|
-
.filter(validateColor)
|
|
108
|
-
.map(normalizeColors)
|
|
109
|
-
.reduce(addNotations, {})
|
|
110
|
-
)
|
|
111
|
-
.filter(filterDuplicateColors)
|
|
112
|
-
.map(addCount)
|
|
113
|
-
.map(addMostCommonNotation)
|
|
114
|
-
.map(removeTemporaryProperties)
|
|
115
|
-
|
|
116
|
-
module.exports = declarations => {
|
|
117
|
-
const all = declarations
|
|
118
|
-
.map(extractColorsFromDeclaration)
|
|
119
|
-
.filter(declaration => declaration.colors && declaration.colors.length > 0)
|
|
120
|
-
.map(declaration => declaration.colors)
|
|
121
|
-
.reduce((allColors, declarationColors) => {
|
|
122
|
-
return [...allColors, ...declarationColors]
|
|
123
|
-
}, [])
|
|
124
|
-
const {totalUnique, unique} = uniquer(all, colorSorter.sortFn)
|
|
125
|
-
const duplicates = withDuplicateNotations(unique)
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
total: all.length,
|
|
129
|
-
unique,
|
|
130
|
-
totalUnique,
|
|
131
|
-
duplicates: {
|
|
132
|
-
unique: duplicates,
|
|
133
|
-
totalUnique: duplicates.length,
|
|
134
|
-
total: duplicates.length
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const expand = require('css-shorthand-expand')
|
|
2
|
-
const uniquer = require('../../utils/uniquer')
|
|
3
|
-
const {KEYWORDS} = require('../../utils/css')
|
|
4
|
-
|
|
5
|
-
module.exports = declarations => {
|
|
6
|
-
const all = declarations.reduce((previous, {property, value}) => {
|
|
7
|
-
if (KEYWORDS.includes(value)) {
|
|
8
|
-
return previous
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (property === 'font-family') {
|
|
12
|
-
previous = [...previous, value]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (property === 'font') {
|
|
16
|
-
const expanded = expand('font', value)
|
|
17
|
-
|
|
18
|
-
if (expanded) {
|
|
19
|
-
previous = [...previous, expanded['font-family']]
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return previous
|
|
24
|
-
}, [])
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
total: all.length,
|
|
28
|
-
...uniquer(all)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const expand = require('css-shorthand-expand')
|
|
2
|
-
const unitSort = require('css-unit-sort')
|
|
3
|
-
const uniquer = require('../../utils/uniquer')
|
|
4
|
-
const {KEYWORDS} = require('../../utils/css')
|
|
5
|
-
|
|
6
|
-
module.exports = declarations => {
|
|
7
|
-
const all = declarations.reduce((previous, {property, value}) => {
|
|
8
|
-
if (KEYWORDS.includes(value)) {
|
|
9
|
-
return previous
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
if (property === 'font-size') {
|
|
13
|
-
previous = [...previous, value]
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (property === 'font') {
|
|
17
|
-
const expanded = expand('font', value)
|
|
18
|
-
|
|
19
|
-
if (expanded) {
|
|
20
|
-
previous = [...previous, expanded['font-size']]
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return previous
|
|
25
|
-
}, [])
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
total: all.length,
|
|
29
|
-
...uniquer(all, unitSort.sortFn)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
module.exports = declarations => {
|
|
2
|
-
const all = declarations.map(({value}) => value)
|
|
3
|
-
|
|
4
|
-
const prefixed = require('./prefixed.js')(all)
|
|
5
|
-
const fontsizes = require('./font-sizes.js')(declarations)
|
|
6
|
-
const fontfamilies = require('./font-families.js')(declarations)
|
|
7
|
-
const colors = require('./colors.js')(declarations)
|
|
8
|
-
const browserhacks = require('./browserhacks.js')(declarations)
|
|
9
|
-
const boxshadows = require('./box-shadows.js')(declarations)
|
|
10
|
-
const textshadows = require('./text-shadows.js')(declarations)
|
|
11
|
-
const zindexes = require('./z-indexes.js')(declarations)
|
|
12
|
-
const animations = require('./animations.js')(declarations)
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
total: all.length,
|
|
16
|
-
prefixed,
|
|
17
|
-
fontsizes,
|
|
18
|
-
fontfamilies,
|
|
19
|
-
colors,
|
|
20
|
-
browserhacks,
|
|
21
|
-
boxshadows,
|
|
22
|
-
textshadows,
|
|
23
|
-
zindexes,
|
|
24
|
-
animations
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
const vendorPrefixes = require('vendor-prefixes')()
|
|
2
|
-
const uniquer = require('../../utils/uniquer')
|
|
3
|
-
|
|
4
|
-
const PREFIX_REGEX = new RegExp(`^${vendorPrefixes.join('|')}`)
|
|
5
|
-
|
|
6
|
-
module.exports = values => {
|
|
7
|
-
const all = values.filter(property => PREFIX_REGEX.test(property))
|
|
8
|
-
|
|
9
|
-
const share = (() => {
|
|
10
|
-
if (values.length === 0) {
|
|
11
|
-
return 0
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return all.length / values.length
|
|
15
|
-
})()
|
|
16
|
-
|
|
17
|
-
return {
|
|
18
|
-
total: all.length,
|
|
19
|
-
...uniquer(all),
|
|
20
|
-
share
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const uniquer = require('../../utils/uniquer')
|
|
2
|
-
const {KEYWORDS} = require('../../utils/css')
|
|
3
|
-
|
|
4
|
-
module.exports = declarations => {
|
|
5
|
-
const all = declarations
|
|
6
|
-
.filter(({property}) => property === 'text-shadow')
|
|
7
|
-
.filter(({value}) => !KEYWORDS.includes(value))
|
|
8
|
-
.map(declaration => declaration.value)
|
|
9
|
-
|
|
10
|
-
const {unique, totalUnique} = uniquer(all)
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
total: all.length,
|
|
14
|
-
unique,
|
|
15
|
-
totalUnique
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const uniquer = require('../../utils/uniquer')
|
|
2
|
-
const {KEYWORDS} = require('../../utils/css')
|
|
3
|
-
|
|
4
|
-
module.exports = declarations => {
|
|
5
|
-
const all = declarations
|
|
6
|
-
// Ignore all declarations that are not z-index
|
|
7
|
-
.filter(({property}) => property === 'z-index')
|
|
8
|
-
// Ignore all CSS keywords and globals
|
|
9
|
-
.filter(({value}) => !KEYWORDS.includes(value))
|
|
10
|
-
// Create a list of integers
|
|
11
|
-
.map(({value}) => parseInt(value, 10))
|
|
12
|
-
|
|
13
|
-
const {unique, totalUnique} = uniquer(all, (a, b) => a - b)
|
|
14
|
-
|
|
15
|
-
return {
|
|
16
|
-
total: all.length,
|
|
17
|
-
unique,
|
|
18
|
-
totalUnique
|
|
19
|
-
}
|
|
20
|
-
}
|
package/src/parser/atrules.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
const declarations = require('./declarations')
|
|
2
|
-
|
|
3
|
-
const AT_RULES_WITH_DECLARATIONS = ['font-face']
|
|
4
|
-
|
|
5
|
-
function addDeclarations(atRule, tree) {
|
|
6
|
-
if (!AT_RULES_WITH_DECLARATIONS.includes(atRule.type)) {
|
|
7
|
-
return atRule
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
...atRule,
|
|
12
|
-
declarations: declarations(tree)
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = tree => {
|
|
17
|
-
const atRules = []
|
|
18
|
-
|
|
19
|
-
tree.walkAtRules(rule => {
|
|
20
|
-
const atRule = {
|
|
21
|
-
type: rule.name.trim(),
|
|
22
|
-
params: rule.params.trim()
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return atRules.push(addDeclarations(atRule, rule))
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
return atRules
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
module.exports.isKeyframes = rule => {
|
|
32
|
-
return (
|
|
33
|
-
rule.parent &&
|
|
34
|
-
rule.parent.type === 'atrule' &&
|
|
35
|
-
rule.parent.name.includes('keyframes')
|
|
36
|
-
)
|
|
37
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
module.exports = tree => {
|
|
2
|
-
const declarations = []
|
|
3
|
-
|
|
4
|
-
tree.walkDecls(declaration => {
|
|
5
|
-
declarations.push({
|
|
6
|
-
// Need to prefix with the 'before', otherwise PostCSS will
|
|
7
|
-
// trim off any browser hacks prefixes like * or _
|
|
8
|
-
property: declaration.raws.before.trim() + declaration.prop,
|
|
9
|
-
value: declaration.value,
|
|
10
|
-
important: Boolean(declaration.important)
|
|
11
|
-
})
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
return declarations
|
|
15
|
-
}
|
package/src/parser/index.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const {parse} = require('postcss')
|
|
2
|
-
const atRules = require('./atrules')
|
|
3
|
-
const rules = require('./rules')
|
|
4
|
-
const selectors = require('./selectors')
|
|
5
|
-
const declarations = require('./declarations')
|
|
6
|
-
|
|
7
|
-
function processNodes(tree) {
|
|
8
|
-
return {
|
|
9
|
-
atRules: atRules(tree),
|
|
10
|
-
rules: rules(tree),
|
|
11
|
-
selectors: selectors(tree),
|
|
12
|
-
declarations: declarations(tree)
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = async css => {
|
|
17
|
-
try {
|
|
18
|
-
const result = await parse(css)
|
|
19
|
-
const rootNode = result.toResult().root
|
|
20
|
-
|
|
21
|
-
return Promise.resolve(processNodes(rootNode))
|
|
22
|
-
} catch (error) {
|
|
23
|
-
const {line, column, reason, source} = error
|
|
24
|
-
const message = source && line && reason && column
|
|
25
|
-
? `${reason} at line ${line}, column ${column}:\n\n${source}`
|
|
26
|
-
: error.message
|
|
27
|
-
|
|
28
|
-
return Promise.reject(new SyntaxError(message))
|
|
29
|
-
}
|
|
30
|
-
}
|
package/src/parser/rules.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const {isKeyframes} = require('./atrules')
|
|
2
|
-
const getDeclarationsFromRule = require('./declarations')
|
|
3
|
-
const {getSelectorsFromRule} = require('./selectors')
|
|
4
|
-
|
|
5
|
-
module.exports = tree => {
|
|
6
|
-
const rules = []
|
|
7
|
-
|
|
8
|
-
tree.walkRules(rule => {
|
|
9
|
-
const declarations = getDeclarationsFromRule(rule)
|
|
10
|
-
// Don't include the 'selectors' (from, 50%, to, etc.) inside @keyframes
|
|
11
|
-
const selectors = isKeyframes(rule) ? [] : getSelectorsFromRule(rule)
|
|
12
|
-
|
|
13
|
-
rules.push({declarations, selectors})
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
return rules
|
|
17
|
-
}
|
package/src/parser/selectors.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const {isKeyframes} = require('./atrules')
|
|
2
|
-
|
|
3
|
-
module.exports = tree => {
|
|
4
|
-
const selectors = []
|
|
5
|
-
|
|
6
|
-
tree.walkRules(rule => {
|
|
7
|
-
// Don't include the 'selectors' (from, 50%, to, etc.) inside @keyframes
|
|
8
|
-
if (isKeyframes(rule)) {
|
|
9
|
-
return
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Get selectors: flatten the list, split each by ',' and trim the results
|
|
13
|
-
selectors.push(...getSelectorsFromRule(rule))
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
return selectors
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const getSelectorsFromRule = rule => {
|
|
20
|
-
return rule.selector
|
|
21
|
-
.split(',')
|
|
22
|
-
.map(s => s.trim())
|
|
23
|
-
.filter(Boolean)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports.getSelectorsFromRule = getSelectorsFromRule
|
package/src/utils/css.js
DELETED
package/src/utils/uniquer.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const stringSortFn = require('string-natural-compare')
|
|
2
|
-
|
|
3
|
-
module.exports = (values, sortFn) => {
|
|
4
|
-
sortFn =
|
|
5
|
-
sortFn ||
|
|
6
|
-
function(a, b) {
|
|
7
|
-
return stringSortFn(String(a), String(b), {caseInsensitive: true})
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// Create a Map of unique values and their counts
|
|
11
|
-
const reduced = [
|
|
12
|
-
...values.reduce((map, value) => {
|
|
13
|
-
return map.set(value, map.get(value) + 1 || 1)
|
|
14
|
-
}, new Map())
|
|
15
|
-
].map(([value, count]) => ({value, count}))
|
|
16
|
-
|
|
17
|
-
const sorted = reduced.map(element => element.value).sort(sortFn)
|
|
18
|
-
const unique = sorted.map(value => reduced.find(r => r.value === value))
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
unique,
|
|
22
|
-
totalUnique: unique.length
|
|
23
|
-
}
|
|
24
|
-
}
|