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