source: node_modules/autoprefixer/lib/prefixes.js@ 2058e5c

Last change on this file since 2058e5c was 2058e5c, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Working / before login

  • Property mode set to 100644
File size: 12.8 KB
Line 
1let AtRule = require('./at-rule')
2let Browsers = require('./browsers')
3let Declaration = require('./declaration')
4let hackAlignContent = require('./hacks/align-content')
5let hackAlignItems = require('./hacks/align-items')
6let hackAlignSelf = require('./hacks/align-self')
7let hackAnimation = require('./hacks/animation')
8let hackAppearance = require('./hacks/appearance')
9let hackAutofill = require('./hacks/autofill')
10let hackBackdropFilter = require('./hacks/backdrop-filter')
11let hackBackgroundClip = require('./hacks/background-clip')
12let hackBackgroundSize = require('./hacks/background-size')
13let hackBlockLogical = require('./hacks/block-logical')
14let hackBorderImage = require('./hacks/border-image')
15let hackBorderRadius = require('./hacks/border-radius')
16let hackBreakProps = require('./hacks/break-props')
17let hackCrossFade = require('./hacks/cross-fade')
18let hackDisplayFlex = require('./hacks/display-flex')
19let hackDisplayGrid = require('./hacks/display-grid')
20let hackFileSelectorButton = require('./hacks/file-selector-button')
21let hackFilter = require('./hacks/filter')
22let hackFilterValue = require('./hacks/filter-value')
23let hackFlex = require('./hacks/flex')
24let hackFlexBasis = require('./hacks/flex-basis')
25let hackFlexDirection = require('./hacks/flex-direction')
26let hackFlexFlow = require('./hacks/flex-flow')
27let hackFlexGrow = require('./hacks/flex-grow')
28let hackFlexShrink = require('./hacks/flex-shrink')
29let hackFlexWrap = require('./hacks/flex-wrap')
30let hackFullscreen = require('./hacks/fullscreen')
31let hackGradient = require('./hacks/gradient')
32let hackGridArea = require('./hacks/grid-area')
33let hackGridColumnAlign = require('./hacks/grid-column-align')
34let hackGridEnd = require('./hacks/grid-end')
35let hackGridRowAlign = require('./hacks/grid-row-align')
36let hackGridRowColumn = require('./hacks/grid-row-column')
37let hackGridRowsColumns = require('./hacks/grid-rows-columns')
38let hackGridStart = require('./hacks/grid-start')
39let hackGridTemplate = require('./hacks/grid-template')
40let hackGridTemplateAreas = require('./hacks/grid-template-areas')
41let hackImageRendering = require('./hacks/image-rendering')
42let hackImageSet = require('./hacks/image-set')
43let hackInlineLogical = require('./hacks/inline-logical')
44let hackIntrinsic = require('./hacks/intrinsic')
45let hackJustifyContent = require('./hacks/justify-content')
46let hackMaskBorder = require('./hacks/mask-border')
47let hackMaskComposite = require('./hacks/mask-composite')
48let hackOrder = require('./hacks/order')
49let hackOverscrollBehavior = require('./hacks/overscroll-behavior')
50let hackPixelated = require('./hacks/pixelated')
51let hackPlaceSelf = require('./hacks/place-self')
52let hackPlaceholder = require('./hacks/placeholder')
53let hackPlaceholderShown = require('./hacks/placeholder-shown')
54let hackPrintColorAdjust = require('./hacks/print-color-adjust')
55let hackTextDecoration = require('./hacks/text-decoration')
56let hackTextDecorationSkipInk = require('./hacks/text-decoration-skip-ink')
57let hackTextEmphasisPosition = require('./hacks/text-emphasis-position')
58let hackTransformDecl = require('./hacks/transform-decl')
59let hackUserSelect = require('./hacks/user-select')
60let hackWritingMode = require('./hacks/writing-mode')
61let Processor = require('./processor')
62let Resolution = require('./resolution')
63let Selector = require('./selector')
64let Supports = require('./supports')
65let Transition = require('./transition')
66let utils = require('./utils')
67let Value = require('./value')
68let vendor = require('./vendor')
69
70Selector.hack(hackAutofill)
71Selector.hack(hackFullscreen)
72Selector.hack(hackPlaceholder)
73Selector.hack(hackPlaceholderShown)
74Selector.hack(hackFileSelectorButton)
75Declaration.hack(hackFlex)
76Declaration.hack(hackOrder)
77Declaration.hack(hackFilter)
78Declaration.hack(hackGridEnd)
79Declaration.hack(hackAnimation)
80Declaration.hack(hackFlexFlow)
81Declaration.hack(hackFlexGrow)
82Declaration.hack(hackFlexWrap)
83Declaration.hack(hackGridArea)
84Declaration.hack(hackPlaceSelf)
85Declaration.hack(hackGridStart)
86Declaration.hack(hackAlignSelf)
87Declaration.hack(hackAppearance)
88Declaration.hack(hackFlexBasis)
89Declaration.hack(hackMaskBorder)
90Declaration.hack(hackMaskComposite)
91Declaration.hack(hackAlignItems)
92Declaration.hack(hackUserSelect)
93Declaration.hack(hackFlexShrink)
94Declaration.hack(hackBreakProps)
95Declaration.hack(hackWritingMode)
96Declaration.hack(hackBorderImage)
97Declaration.hack(hackAlignContent)
98Declaration.hack(hackBorderRadius)
99Declaration.hack(hackBlockLogical)
100Declaration.hack(hackGridTemplate)
101Declaration.hack(hackInlineLogical)
102Declaration.hack(hackGridRowAlign)
103Declaration.hack(hackTransformDecl)
104Declaration.hack(hackFlexDirection)
105Declaration.hack(hackImageRendering)
106Declaration.hack(hackBackdropFilter)
107Declaration.hack(hackBackgroundClip)
108Declaration.hack(hackTextDecoration)
109Declaration.hack(hackJustifyContent)
110Declaration.hack(hackBackgroundSize)
111Declaration.hack(hackGridRowColumn)
112Declaration.hack(hackGridRowsColumns)
113Declaration.hack(hackGridColumnAlign)
114Declaration.hack(hackOverscrollBehavior)
115Declaration.hack(hackGridTemplateAreas)
116Declaration.hack(hackPrintColorAdjust)
117Declaration.hack(hackTextEmphasisPosition)
118Declaration.hack(hackTextDecorationSkipInk)
119Value.hack(hackGradient)
120Value.hack(hackIntrinsic)
121Value.hack(hackPixelated)
122Value.hack(hackImageSet)
123Value.hack(hackCrossFade)
124Value.hack(hackDisplayFlex)
125Value.hack(hackDisplayGrid)
126Value.hack(hackFilterValue)
127
128let declsCache = new Map()
129
130class Prefixes {
131 constructor(data, browsers, options = {}) {
132 this.data = data
133 this.browsers = browsers
134 this.options = options
135 ;[this.add, this.remove] = this.preprocess(this.select(this.data))
136 this.transition = new Transition(this)
137 this.processor = new Processor(this)
138 }
139
140 /**
141 * Return clone instance to remove all prefixes
142 */
143 cleaner() {
144 if (this.cleanerCache) {
145 return this.cleanerCache
146 }
147
148 if (this.browsers.selected.length) {
149 let empty = new Browsers(this.browsers.data, [])
150 this.cleanerCache = new Prefixes(this.data, empty, this.options)
151 } else {
152 return this
153 }
154
155 return this.cleanerCache
156 }
157
158 /**
159 * Declaration loader with caching
160 */
161 decl(prop) {
162 if (!declsCache.has(prop)) {
163 declsCache.set(prop, Declaration.load(prop))
164 }
165
166 return declsCache.get(prop)
167 }
168
169 /**
170 * Group declaration by unprefixed property to check them
171 */
172 group(decl) {
173 let rule = decl.parent
174 let index = rule.index(decl)
175 let { length } = rule.nodes
176 let unprefixed = this.unprefixed(decl.prop)
177
178 let checker = (step, callback) => {
179 index += step
180 while (index >= 0 && index < length) {
181 let other = rule.nodes[index]
182 if (other.type === 'decl') {
183 if (step === -1 && other.prop === unprefixed) {
184 if (!Browsers.withPrefix(other.value)) {
185 break
186 }
187 }
188
189 if (this.unprefixed(other.prop) !== unprefixed) {
190 break
191 } else if (callback(other) === true) {
192 return true
193 }
194
195 if (step === +1 && other.prop === unprefixed) {
196 if (!Browsers.withPrefix(other.value)) {
197 break
198 }
199 }
200 }
201
202 index += step
203 }
204 return false
205 }
206
207 return {
208 down(callback) {
209 return checker(+1, callback)
210 },
211 up(callback) {
212 return checker(-1, callback)
213 }
214 }
215 }
216
217 /**
218 * Normalize prefix for remover
219 */
220 normalize(prop) {
221 return this.decl(prop).normalize(prop)
222 }
223
224 /**
225 * Return prefixed version of property
226 */
227 prefixed(prop, prefix) {
228 prop = vendor.unprefixed(prop)
229 return this.decl(prop).prefixed(prop, prefix)
230 }
231
232 /**
233 * Cache prefixes data to fast CSS processing
234 */
235 preprocess(selected) {
236 let add = {
237 '@supports': new Supports(Prefixes, this),
238 'selectors': []
239 }
240 for (let name in selected.add) {
241 let prefixes = selected.add[name]
242 if (name === '@keyframes' || name === '@viewport') {
243 add[name] = new AtRule(name, prefixes, this)
244 } else if (name === '@resolution') {
245 add[name] = new Resolution(name, prefixes, this)
246 } else if (this.data[name].selector) {
247 add.selectors.push(Selector.load(name, prefixes, this))
248 } else {
249 let props = this.data[name].props
250
251 if (props) {
252 let value = Value.load(name, prefixes, this)
253 for (let prop of props) {
254 if (!add[prop]) {
255 add[prop] = { values: [] }
256 }
257 add[prop].values.push(value)
258 }
259 } else {
260 let values = (add[name] && add[name].values) || []
261 add[name] = Declaration.load(name, prefixes, this)
262 add[name].values = values
263 }
264 }
265 }
266
267 let remove = { selectors: [] }
268 for (let name in selected.remove) {
269 let prefixes = selected.remove[name]
270 if (this.data[name].selector) {
271 let selector = Selector.load(name, prefixes)
272 for (let prefix of prefixes) {
273 remove.selectors.push(selector.old(prefix))
274 }
275 } else if (name === '@keyframes' || name === '@viewport') {
276 for (let prefix of prefixes) {
277 let prefixed = `@${prefix}${name.slice(1)}`
278 remove[prefixed] = { remove: true }
279 }
280 } else if (name === '@resolution') {
281 remove[name] = new Resolution(name, prefixes, this)
282 } else {
283 let props = this.data[name].props
284 if (props) {
285 let value = Value.load(name, [], this)
286 for (let prefix of prefixes) {
287 let old = value.old(prefix)
288 if (old) {
289 for (let prop of props) {
290 if (!remove[prop]) {
291 remove[prop] = {}
292 }
293 if (!remove[prop].values) {
294 remove[prop].values = []
295 }
296 remove[prop].values.push(old)
297 }
298 }
299 }
300 } else {
301 for (let p of prefixes) {
302 let olds = this.decl(name).old(name, p)
303 if (name === 'align-self') {
304 let a = add[name] && add[name].prefixes
305 if (a) {
306 if (p === '-webkit- 2009' && a.includes('-webkit-')) {
307 continue
308 } else if (p === '-webkit-' && a.includes('-webkit- 2009')) {
309 continue
310 }
311 }
312 }
313 for (let prefixed of olds) {
314 if (!remove[prefixed]) {
315 remove[prefixed] = {}
316 }
317 remove[prefixed].remove = true
318 }
319 }
320 }
321 }
322 }
323
324 return [add, remove]
325 }
326
327 /**
328 * Select prefixes from data, which is necessary for selected browsers
329 */
330 select(list) {
331 let selected = { add: {}, remove: {} }
332
333 for (let name in list) {
334 let data = list[name]
335 let add = data.browsers.map(i => {
336 let params = i.split(' ')
337 return {
338 browser: `${params[0]} ${params[1]}`,
339 note: params[2]
340 }
341 })
342
343 let notes = add
344 .filter(i => i.note)
345 .map(i => `${this.browsers.prefix(i.browser)} ${i.note}`)
346 notes = utils.uniq(notes)
347
348 add = add
349 .filter(i => this.browsers.isSelected(i.browser))
350 .map(i => {
351 let prefix = this.browsers.prefix(i.browser)
352 if (i.note) {
353 return `${prefix} ${i.note}`
354 } else {
355 return prefix
356 }
357 })
358 add = this.sort(utils.uniq(add))
359
360 if (this.options.flexbox === 'no-2009') {
361 add = add.filter(i => !i.includes('2009'))
362 }
363
364 let all = data.browsers.map(i => this.browsers.prefix(i))
365 if (data.mistakes) {
366 all = all.concat(data.mistakes)
367 }
368 all = all.concat(notes)
369 all = utils.uniq(all)
370
371 if (add.length) {
372 selected.add[name] = add
373 if (add.length < all.length) {
374 selected.remove[name] = all.filter(i => !add.includes(i))
375 }
376 } else {
377 selected.remove[name] = all
378 }
379 }
380
381 return selected
382 }
383
384 /**
385 * Sort vendor prefixes
386 */
387 sort(prefixes) {
388 return prefixes.sort((a, b) => {
389 let aLength = utils.removeNote(a).length
390 let bLength = utils.removeNote(b).length
391
392 if (aLength === bLength) {
393 return b.length - a.length
394 } else {
395 return bLength - aLength
396 }
397 })
398 }
399
400 /**
401 * Return unprefixed version of property
402 */
403 unprefixed(prop) {
404 let value = this.normalize(vendor.unprefixed(prop))
405 if (value === 'flex-direction') {
406 value = 'flex-flow'
407 }
408 return value
409 }
410
411 /**
412 * Return values, which must be prefixed in selected property
413 */
414 values(type, prop) {
415 let data = this[type]
416
417 let global = data['*'] && data['*'].values
418 let values = data[prop] && data[prop].values
419
420 if (global && values) {
421 return utils.uniq(global.concat(values))
422 } else {
423 return global || values || []
424 }
425 }
426}
427
428module.exports = Prefixes
Note: See TracBrowser for help on using the repository browser.