autoprefixer 10.4.13 → 10.4.15

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 (44) hide show
  1. package/README.md +4 -4
  2. package/data/prefixes.js +187 -183
  3. package/lib/autoprefixer.js +16 -16
  4. package/lib/browsers.js +13 -13
  5. package/lib/declaration.js +92 -92
  6. package/lib/hacks/align-content.js +9 -9
  7. package/lib/hacks/align-items.js +7 -7
  8. package/lib/hacks/align-self.js +7 -7
  9. package/lib/hacks/block-logical.js +10 -10
  10. package/lib/hacks/border-radius.js +7 -7
  11. package/lib/hacks/break-props.js +16 -16
  12. package/lib/hacks/display-flex.js +9 -9
  13. package/lib/hacks/flex-direction.js +7 -7
  14. package/lib/hacks/flex.js +7 -7
  15. package/lib/hacks/gradient.js +259 -259
  16. package/lib/hacks/grid-column-align.js +6 -6
  17. package/lib/hacks/grid-row-align.js +6 -6
  18. package/lib/hacks/grid-rows-columns.js +23 -23
  19. package/lib/hacks/grid-template-areas.js +12 -12
  20. package/lib/hacks/grid-template.js +9 -9
  21. package/lib/hacks/grid-utils.js +26 -26
  22. package/lib/hacks/image-rendering.js +14 -14
  23. package/lib/hacks/inline-logical.js +6 -6
  24. package/lib/hacks/intrinsic.js +17 -17
  25. package/lib/hacks/justify-content.js +9 -9
  26. package/lib/hacks/mask-composite.js +2 -2
  27. package/lib/hacks/order.js +7 -7
  28. package/lib/hacks/overscroll-behavior.js +6 -6
  29. package/lib/hacks/pixelated.js +10 -10
  30. package/lib/hacks/print-color-adjust.js +7 -7
  31. package/lib/hacks/transform-decl.js +25 -25
  32. package/lib/hacks/user-select.js +10 -10
  33. package/lib/hacks/writing-mode.js +4 -4
  34. package/lib/info.js +6 -6
  35. package/lib/old-selector.js +16 -16
  36. package/lib/prefixer.js +20 -20
  37. package/lib/prefixes.js +124 -124
  38. package/lib/processor.js +159 -159
  39. package/lib/resolution.js +17 -17
  40. package/lib/selector.js +67 -67
  41. package/lib/supports.js +167 -167
  42. package/lib/transition.js +118 -118
  43. package/lib/value.js +26 -26
  44. package/package.json +7 -3
package/lib/supports.js CHANGED
@@ -1,5 +1,5 @@
1
1
  let featureQueries = require('caniuse-lite/data/features/css-featurequeries.js')
2
- let { feature } = require('caniuse-lite')
2
+ let feature = require('caniuse-lite/dist/unpacker/feature')
3
3
  let { parse } = require('postcss')
4
4
 
5
5
  let Browsers = require('./browsers')
@@ -27,73 +27,89 @@ class Supports {
27
27
  }
28
28
 
29
29
  /**
30
- * Return prefixer only with @supports supported browsers
30
+ * Add prefixes
31
31
  */
32
- prefixer() {
33
- if (this.prefixerCache) {
34
- return this.prefixerCache
35
- }
32
+ add(nodes, all) {
33
+ return nodes.map(i => {
34
+ if (this.isProp(i)) {
35
+ let prefixed = this.prefixed(i[0])
36
+ if (prefixed.length > 1) {
37
+ return this.convert(prefixed)
38
+ }
36
39
 
37
- let filtered = this.all.browsers.selected.filter(i => {
38
- return supported.includes(i)
39
- })
40
+ return i
41
+ }
40
42
 
41
- let browsers = new Browsers(
42
- this.all.browsers.data,
43
- filtered,
44
- this.all.options
45
- )
46
- this.prefixerCache = new this.Prefixes(
47
- this.all.data,
48
- browsers,
49
- this.all.options
50
- )
51
- return this.prefixerCache
43
+ if (typeof i === 'object') {
44
+ return this.add(i, all)
45
+ }
46
+
47
+ return i
48
+ })
52
49
  }
53
50
 
54
51
  /**
55
- * Parse string into declaration property and value
52
+ * Clean brackets with one child
56
53
  */
57
- parse(str) {
58
- let parts = str.split(':')
59
- let prop = parts[0]
60
- let value = parts[1]
61
- if (!value) value = ''
62
- return [prop.trim(), value.trim()]
54
+ cleanBrackets(nodes) {
55
+ return nodes.map(i => {
56
+ if (typeof i !== 'object') {
57
+ return i
58
+ }
59
+
60
+ if (i.length === 1 && typeof i[0] === 'object') {
61
+ return this.cleanBrackets(i[0])
62
+ }
63
+
64
+ return this.cleanBrackets(i)
65
+ })
63
66
  }
64
67
 
65
68
  /**
66
- * Create virtual rule to process it by prefixer
69
+ * Add " or " between properties and convert it to brackets format
67
70
  */
68
- virtual(str) {
69
- let [prop, value] = this.parse(str)
70
- let rule = parse('a{}').first
71
- rule.append({ prop, value, raws: { before: '' } })
72
- return rule
71
+ convert(progress) {
72
+ let result = ['']
73
+ for (let i of progress) {
74
+ result.push([`${i.prop}: ${i.value}`])
75
+ result.push(' or ')
76
+ }
77
+ result[result.length - 1] = ''
78
+ return result
73
79
  }
74
80
 
75
81
  /**
76
- * Return array of Declaration with all necessary prefixes
82
+ * Check global options
77
83
  */
78
- prefixed(str) {
79
- let rule = this.virtual(str)
80
- if (this.disabled(rule.first)) {
81
- return rule.nodes
84
+ disabled(node) {
85
+ if (!this.all.options.grid) {
86
+ if (node.prop === 'display' && node.value.includes('grid')) {
87
+ return true
88
+ }
89
+ if (node.prop.includes('grid') || node.prop === 'justify-items') {
90
+ return true
91
+ }
82
92
  }
83
93
 
84
- let result = { warn: () => null }
85
-
86
- let prefixer = this.prefixer().add[rule.first.prop]
87
- prefixer && prefixer.process && prefixer.process(rule.first, result)
88
-
89
- for (let decl of rule.nodes) {
90
- for (let value of this.prefixer().values('add', rule.first.prop)) {
91
- value.process(decl)
94
+ if (this.all.options.flexbox === false) {
95
+ if (node.prop === 'display' && node.value.includes('flex')) {
96
+ return true
97
+ }
98
+ let other = ['order', 'justify-content', 'align-items', 'align-content']
99
+ if (node.prop.includes('flex') || other.includes(node.prop)) {
100
+ return true
92
101
  }
93
- Value.save(this.all, decl)
94
102
  }
95
103
 
96
- return rule.nodes
104
+ return false
105
+ }
106
+
107
+ /**
108
+ * Return true if prefixed property has no unprefixed
109
+ */
110
+ isHack(all, unprefixed) {
111
+ let check = new RegExp(`(\\(|\\s)${utils.escapeRegexp(unprefixed)}:`)
112
+ return !check.test(all)
97
113
  }
98
114
 
99
115
  /**
@@ -121,99 +137,6 @@ class Supports {
121
137
  )
122
138
  }
123
139
 
124
- /**
125
- * Return true if prefixed property has no unprefixed
126
- */
127
- isHack(all, unprefixed) {
128
- let check = new RegExp(`(\\(|\\s)${utils.escapeRegexp(unprefixed)}:`)
129
- return !check.test(all)
130
- }
131
-
132
- /**
133
- * Return true if we need to remove node
134
- */
135
- toRemove(str, all) {
136
- let [prop, value] = this.parse(str)
137
- let unprefixed = this.all.unprefixed(prop)
138
-
139
- let cleaner = this.all.cleaner()
140
-
141
- if (
142
- cleaner.remove[prop] &&
143
- cleaner.remove[prop].remove &&
144
- !this.isHack(all, unprefixed)
145
- ) {
146
- return true
147
- }
148
-
149
- for (let checker of cleaner.values('remove', unprefixed)) {
150
- if (checker.check(value)) {
151
- return true
152
- }
153
- }
154
-
155
- return false
156
- }
157
-
158
- /**
159
- * Remove all unnecessary prefixes
160
- */
161
- remove(nodes, all) {
162
- let i = 0
163
- while (i < nodes.length) {
164
- if (
165
- !this.isNot(nodes[i - 1]) &&
166
- this.isProp(nodes[i]) &&
167
- this.isOr(nodes[i + 1])
168
- ) {
169
- if (this.toRemove(nodes[i][0], all)) {
170
- nodes.splice(i, 2)
171
- continue
172
- }
173
-
174
- i += 2
175
- continue
176
- }
177
-
178
- if (typeof nodes[i] === 'object') {
179
- nodes[i] = this.remove(nodes[i], all)
180
- }
181
-
182
- i += 1
183
- }
184
- return nodes
185
- }
186
-
187
- /**
188
- * Clean brackets with one child
189
- */
190
- cleanBrackets(nodes) {
191
- return nodes.map(i => {
192
- if (typeof i !== 'object') {
193
- return i
194
- }
195
-
196
- if (i.length === 1 && typeof i[0] === 'object') {
197
- return this.cleanBrackets(i[0])
198
- }
199
-
200
- return this.cleanBrackets(i)
201
- })
202
- }
203
-
204
- /**
205
- * Add " or " between properties and convert it to brackets format
206
- */
207
- convert(progress) {
208
- let result = ['']
209
- for (let i of progress) {
210
- result.push([`${i.prop}: ${i.value}`])
211
- result.push(' or ')
212
- }
213
- result[result.length - 1] = ''
214
- return result
215
- }
216
-
217
140
  /**
218
141
  * Compress value functions into a string nodes
219
142
  */
@@ -239,25 +162,63 @@ class Supports {
239
162
  }
240
163
 
241
164
  /**
242
- * Add prefixes
165
+ * Parse string into declaration property and value
243
166
  */
244
- add(nodes, all) {
245
- return nodes.map(i => {
246
- if (this.isProp(i)) {
247
- let prefixed = this.prefixed(i[0])
248
- if (prefixed.length > 1) {
249
- return this.convert(prefixed)
250
- }
167
+ parse(str) {
168
+ let parts = str.split(':')
169
+ let prop = parts[0]
170
+ let value = parts[1]
171
+ if (!value) value = ''
172
+ return [prop.trim(), value.trim()]
173
+ }
251
174
 
252
- return i
253
- }
175
+ /**
176
+ * Return array of Declaration with all necessary prefixes
177
+ */
178
+ prefixed(str) {
179
+ let rule = this.virtual(str)
180
+ if (this.disabled(rule.first)) {
181
+ return rule.nodes
182
+ }
254
183
 
255
- if (typeof i === 'object') {
256
- return this.add(i, all)
184
+ let result = { warn: () => null }
185
+
186
+ let prefixer = this.prefixer().add[rule.first.prop]
187
+ prefixer && prefixer.process && prefixer.process(rule.first, result)
188
+
189
+ for (let decl of rule.nodes) {
190
+ for (let value of this.prefixer().values('add', rule.first.prop)) {
191
+ value.process(decl)
257
192
  }
193
+ Value.save(this.all, decl)
194
+ }
258
195
 
259
- return i
196
+ return rule.nodes
197
+ }
198
+
199
+ /**
200
+ * Return prefixer only with @supports supported browsers
201
+ */
202
+ prefixer() {
203
+ if (this.prefixerCache) {
204
+ return this.prefixerCache
205
+ }
206
+
207
+ let filtered = this.all.browsers.selected.filter(i => {
208
+ return supported.includes(i)
260
209
  })
210
+
211
+ let browsers = new Browsers(
212
+ this.all.browsers.data,
213
+ filtered,
214
+ this.all.options
215
+ )
216
+ this.prefixerCache = new this.Prefixes(
217
+ this.all.data,
218
+ browsers,
219
+ this.all.options
220
+ )
221
+ return this.prefixerCache
261
222
  }
262
223
 
263
224
  /**
@@ -273,30 +234,69 @@ class Supports {
273
234
  }
274
235
 
275
236
  /**
276
- * Check global options
237
+ * Remove all unnecessary prefixes
277
238
  */
278
- disabled(node) {
279
- if (!this.all.options.grid) {
280
- if (node.prop === 'display' && node.value.includes('grid')) {
281
- return true
239
+ remove(nodes, all) {
240
+ let i = 0
241
+ while (i < nodes.length) {
242
+ if (
243
+ !this.isNot(nodes[i - 1]) &&
244
+ this.isProp(nodes[i]) &&
245
+ this.isOr(nodes[i + 1])
246
+ ) {
247
+ if (this.toRemove(nodes[i][0], all)) {
248
+ nodes.splice(i, 2)
249
+ continue
250
+ }
251
+
252
+ i += 2
253
+ continue
282
254
  }
283
- if (node.prop.includes('grid') || node.prop === 'justify-items') {
284
- return true
255
+
256
+ if (typeof nodes[i] === 'object') {
257
+ nodes[i] = this.remove(nodes[i], all)
285
258
  }
259
+
260
+ i += 1
286
261
  }
262
+ return nodes
263
+ }
287
264
 
288
- if (this.all.options.flexbox === false) {
289
- if (node.prop === 'display' && node.value.includes('flex')) {
290
- return true
291
- }
292
- let other = ['order', 'justify-content', 'align-items', 'align-content']
293
- if (node.prop.includes('flex') || other.includes(node.prop)) {
265
+ /**
266
+ * Return true if we need to remove node
267
+ */
268
+ toRemove(str, all) {
269
+ let [prop, value] = this.parse(str)
270
+ let unprefixed = this.all.unprefixed(prop)
271
+
272
+ let cleaner = this.all.cleaner()
273
+
274
+ if (
275
+ cleaner.remove[prop] &&
276
+ cleaner.remove[prop].remove &&
277
+ !this.isHack(all, unprefixed)
278
+ ) {
279
+ return true
280
+ }
281
+
282
+ for (let checker of cleaner.values('remove', unprefixed)) {
283
+ if (checker.check(value)) {
294
284
  return true
295
285
  }
296
286
  }
297
287
 
298
288
  return false
299
289
  }
290
+
291
+ /**
292
+ * Create virtual rule to process it by prefixer
293
+ */
294
+ virtual(str) {
295
+ let [prop, value] = this.parse(str)
296
+ let rule = parse('a{}').first
297
+ rule.append({ prop, raws: { before: '' }, value })
298
+ return rule
299
+ }
300
300
  }
301
301
 
302
302
  module.exports = Supports
package/lib/transition.js CHANGED
@@ -79,21 +79,6 @@ class Transition {
79
79
  }
80
80
  }
81
81
 
82
- /**
83
- * Find property name
84
- */
85
- findProp(param) {
86
- let prop = param[0].value
87
- if (/^\d/.test(prop)) {
88
- for (let [i, token] of param.entries()) {
89
- if (i !== 0 && token.type === 'word') {
90
- return token.value
91
- }
92
- }
93
- }
94
- return prop
95
- }
96
-
97
82
  /**
98
83
  * Does we already have this declaration
99
84
  */
@@ -101,15 +86,6 @@ class Transition {
101
86
  return decl.parent.some(i => i.prop === prop && i.value === value)
102
87
  }
103
88
 
104
- /**
105
- * Add declaration if it is not exist
106
- */
107
- cloneBefore(decl, prop, value) {
108
- if (!this.already(decl, prop, value)) {
109
- decl.cloneBefore({ prop, value })
110
- }
111
- }
112
-
113
89
  /**
114
90
  * Show transition-property warning
115
91
  */
@@ -156,79 +132,30 @@ class Transition {
156
132
  }
157
133
 
158
134
  /**
159
- * Process transition and remove all unnecessary properties
135
+ * Remove all non-webkit prefixes and unprefixed params if we have prefixed
160
136
  */
161
- remove(decl) {
162
- let params = this.parse(decl.value)
163
- params = params.filter(i => {
164
- let prop = this.prefixes.remove[this.findProp(i)]
165
- return !prop || !prop.remove
166
- })
167
- let value = this.stringify(params)
168
-
169
- if (decl.value === value) {
170
- return
171
- }
172
-
173
- if (params.length === 0) {
174
- decl.remove()
175
- return
176
- }
177
-
178
- let double = decl.parent.some(i => {
179
- return i.prop === decl.prop && i.value === value
180
- })
181
- let smaller = decl.parent.some(i => {
182
- return i !== decl && i.prop === decl.prop && i.value.length > value.length
183
- })
184
-
185
- if (double || smaller) {
186
- decl.remove()
187
- return
188
- }
189
-
190
- decl.value = value
191
- }
137
+ cleanFromUnprefixed(params, prefix) {
138
+ let remove = params
139
+ .map(i => this.findProp(i))
140
+ .filter(i => i.slice(0, prefix.length) === prefix)
141
+ .map(i => this.prefixes.unprefixed(i))
192
142
 
193
- /**
194
- * Parse properties list to array
195
- */
196
- parse(value) {
197
- let ast = parser(value)
198
143
  let result = []
199
- let param = []
200
- for (let node of ast.nodes) {
201
- param.push(node)
202
- if (node.type === 'div' && node.value === ',') {
144
+ for (let param of params) {
145
+ let prop = this.findProp(param)
146
+ let p = vendor.prefix(prop)
147
+ if (!remove.includes(prop) && (p === prefix || p === '')) {
203
148
  result.push(param)
204
- param = []
205
149
  }
206
150
  }
207
- result.push(param)
208
- return result.filter(i => i.length > 0)
151
+ return result
209
152
  }
210
153
 
211
- /**
212
- * Return properties string from array
213
- */
214
- stringify(params) {
215
- if (params.length === 0) {
216
- return ''
217
- }
218
- let nodes = []
219
- for (let param of params) {
220
- if (param[param.length - 1].type !== 'div') {
221
- param.push(this.div(params))
222
- }
223
- nodes = nodes.concat(param)
224
- }
225
- if (nodes[0].type === 'div') {
226
- nodes = nodes.slice(1)
227
- }
228
- if (nodes[nodes.length - 1].type === 'div') {
229
- nodes = nodes.slice(0, +-2 + 1 || undefined)
230
- }
231
- return parser.stringify({ nodes })
154
+ cleanOtherPrefixes(params, prefix) {
155
+ return params.filter(param => {
156
+ let current = vendor.prefix(this.findProp(param))
157
+ return current === '' || current === prefix
158
+ })
232
159
  }
233
160
 
234
161
  /**
@@ -248,6 +175,32 @@ class Transition {
248
175
  return result
249
176
  }
250
177
 
178
+ /**
179
+ * Add declaration if it is not exist
180
+ */
181
+ cloneBefore(decl, prop, value) {
182
+ if (!this.already(decl, prop, value)) {
183
+ decl.cloneBefore({ prop, value })
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Check property for disabled by option
189
+ */
190
+ disabled(prop, prefix) {
191
+ let other = ['order', 'justify-content', 'align-self', 'align-content']
192
+ if (prop.includes('flex') || other.includes(prop)) {
193
+ if (this.prefixes.options.flexbox === false) {
194
+ return true
195
+ }
196
+
197
+ if (this.prefixes.options.flexbox === 'no-2009') {
198
+ return prefix.includes('2009')
199
+ }
200
+ }
201
+ return undefined
202
+ }
203
+
251
204
  /**
252
205
  * Find or create separator
253
206
  */
@@ -259,51 +212,75 @@ class Transition {
259
212
  }
260
213
  }
261
214
  }
262
- return { type: 'div', value: ',', after: ' ' }
215
+ return { after: ' ', type: 'div', value: ',' }
263
216
  }
264
217
 
265
- cleanOtherPrefixes(params, prefix) {
266
- return params.filter(param => {
267
- let current = vendor.prefix(this.findProp(param))
268
- return current === '' || current === prefix
269
- })
218
+ /**
219
+ * Find property name
220
+ */
221
+ findProp(param) {
222
+ let prop = param[0].value
223
+ if (/^\d/.test(prop)) {
224
+ for (let [i, token] of param.entries()) {
225
+ if (i !== 0 && token.type === 'word') {
226
+ return token.value
227
+ }
228
+ }
229
+ }
230
+ return prop
270
231
  }
271
232
 
272
233
  /**
273
- * Remove all non-webkit prefixes and unprefixed params if we have prefixed
234
+ * Parse properties list to array
274
235
  */
275
- cleanFromUnprefixed(params, prefix) {
276
- let remove = params
277
- .map(i => this.findProp(i))
278
- .filter(i => i.slice(0, prefix.length) === prefix)
279
- .map(i => this.prefixes.unprefixed(i))
280
-
236
+ parse(value) {
237
+ let ast = parser(value)
281
238
  let result = []
282
- for (let param of params) {
283
- let prop = this.findProp(param)
284
- let p = vendor.prefix(prop)
285
- if (!remove.includes(prop) && (p === prefix || p === '')) {
239
+ let param = []
240
+ for (let node of ast.nodes) {
241
+ param.push(node)
242
+ if (node.type === 'div' && node.value === ',') {
286
243
  result.push(param)
244
+ param = []
287
245
  }
288
246
  }
289
- return result
247
+ result.push(param)
248
+ return result.filter(i => i.length > 0)
290
249
  }
291
250
 
292
251
  /**
293
- * Check property for disabled by option
252
+ * Process transition and remove all unnecessary properties
294
253
  */
295
- disabled(prop, prefix) {
296
- let other = ['order', 'justify-content', 'align-self', 'align-content']
297
- if (prop.includes('flex') || other.includes(prop)) {
298
- if (this.prefixes.options.flexbox === false) {
299
- return true
300
- }
254
+ remove(decl) {
255
+ let params = this.parse(decl.value)
256
+ params = params.filter(i => {
257
+ let prop = this.prefixes.remove[this.findProp(i)]
258
+ return !prop || !prop.remove
259
+ })
260
+ let value = this.stringify(params)
301
261
 
302
- if (this.prefixes.options.flexbox === 'no-2009') {
303
- return prefix.includes('2009')
304
- }
262
+ if (decl.value === value) {
263
+ return
305
264
  }
306
- return undefined
265
+
266
+ if (params.length === 0) {
267
+ decl.remove()
268
+ return
269
+ }
270
+
271
+ let double = decl.parent.some(i => {
272
+ return i.prop === decl.prop && i.value === value
273
+ })
274
+ let smaller = decl.parent.some(i => {
275
+ return i !== decl && i.prop === decl.prop && i.value.length > value.length
276
+ })
277
+
278
+ if (double || smaller) {
279
+ decl.remove()
280
+ return
281
+ }
282
+
283
+ decl.value = value
307
284
  }
308
285
 
309
286
  /**
@@ -324,6 +301,29 @@ class Transition {
324
301
 
325
302
  return selectors.length > 0 ? selectors : false
326
303
  }
304
+
305
+ /**
306
+ * Return properties string from array
307
+ */
308
+ stringify(params) {
309
+ if (params.length === 0) {
310
+ return ''
311
+ }
312
+ let nodes = []
313
+ for (let param of params) {
314
+ if (param[param.length - 1].type !== 'div') {
315
+ param.push(this.div(params))
316
+ }
317
+ nodes = nodes.concat(param)
318
+ }
319
+ if (nodes[0].type === 'div') {
320
+ nodes = nodes.slice(1)
321
+ }
322
+ if (nodes[nodes.length - 1].type === 'div') {
323
+ nodes = nodes.slice(0, +-2 + 1 || undefined)
324
+ }
325
+ return parser.stringify({ nodes })
326
+ }
327
327
  }
328
328
 
329
329
  module.exports = Transition