| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 | let AtRule = require('./at-rule')let Browsers = require('./browsers')let Declaration = require('./declaration')let hackAlignContent = require('./hacks/align-content')let hackAlignItems = require('./hacks/align-items')let hackAlignSelf = require('./hacks/align-self')let hackAnimation = require('./hacks/animation')let hackAppearance = require('./hacks/appearance')let hackAutofill = require('./hacks/autofill')let hackBackdropFilter = require('./hacks/backdrop-filter')let hackBackgroundClip = require('./hacks/background-clip')let hackBackgroundSize = require('./hacks/background-size')let hackBlockLogical = require('./hacks/block-logical')let hackBorderImage = require('./hacks/border-image')let hackBorderRadius = require('./hacks/border-radius')let hackBreakProps = require('./hacks/break-props')let hackCrossFade = require('./hacks/cross-fade')let hackDisplayFlex = require('./hacks/display-flex')let hackDisplayGrid = require('./hacks/display-grid')let hackFileSelectorButton = require('./hacks/file-selector-button')let hackFilter = require('./hacks/filter')let hackFilterValue = require('./hacks/filter-value')let hackFlex = require('./hacks/flex')let hackFlexBasis = require('./hacks/flex-basis')let hackFlexDirection = require('./hacks/flex-direction')let hackFlexFlow = require('./hacks/flex-flow')let hackFlexGrow = require('./hacks/flex-grow')let hackFlexShrink = require('./hacks/flex-shrink')let hackFlexWrap = require('./hacks/flex-wrap')let hackFullscreen = require('./hacks/fullscreen')let hackGradient = require('./hacks/gradient')let hackGridArea = require('./hacks/grid-area')let hackGridColumnAlign = require('./hacks/grid-column-align')let hackGridEnd = require('./hacks/grid-end')let hackGridRowAlign = require('./hacks/grid-row-align')let hackGridRowColumn = require('./hacks/grid-row-column')let hackGridRowsColumns = require('./hacks/grid-rows-columns')let hackGridStart = require('./hacks/grid-start')let hackGridTemplate = require('./hacks/grid-template')let hackGridTemplateAreas = require('./hacks/grid-template-areas')let hackImageRendering = require('./hacks/image-rendering')let hackImageSet = require('./hacks/image-set')let hackInlineLogical = require('./hacks/inline-logical')let hackIntrinsic = require('./hacks/intrinsic')let hackJustifyContent = require('./hacks/justify-content')let hackMaskBorder = require('./hacks/mask-border')let hackMaskComposite = require('./hacks/mask-composite')let hackOrder = require('./hacks/order')let hackOverscrollBehavior = require('./hacks/overscroll-behavior')let hackPixelated = require('./hacks/pixelated')let hackPlaceSelf = require('./hacks/place-self')let hackPlaceholder = require('./hacks/placeholder')let hackPlaceholderShown = require('./hacks/placeholder-shown')let hackPrintColorAdjust = require('./hacks/print-color-adjust')let hackTextDecoration = require('./hacks/text-decoration')let hackTextDecorationSkipInk = require('./hacks/text-decoration-skip-ink')let hackTextEmphasisPosition = require('./hacks/text-emphasis-position')let hackTransformDecl = require('./hacks/transform-decl')let hackUserSelect = require('./hacks/user-select')let hackWritingMode = require('./hacks/writing-mode')let Processor = require('./processor')let Resolution = require('./resolution')let Selector = require('./selector')let Supports = require('./supports')let Transition = require('./transition')let utils = require('./utils')let Value = require('./value')let vendor = require('./vendor')Selector.hack(hackAutofill)Selector.hack(hackFullscreen)Selector.hack(hackPlaceholder)Selector.hack(hackPlaceholderShown)Selector.hack(hackFileSelectorButton)Declaration.hack(hackFlex)Declaration.hack(hackOrder)Declaration.hack(hackFilter)Declaration.hack(hackGridEnd)Declaration.hack(hackAnimation)Declaration.hack(hackFlexFlow)Declaration.hack(hackFlexGrow)Declaration.hack(hackFlexWrap)Declaration.hack(hackGridArea)Declaration.hack(hackPlaceSelf)Declaration.hack(hackGridStart)Declaration.hack(hackAlignSelf)Declaration.hack(hackAppearance)Declaration.hack(hackFlexBasis)Declaration.hack(hackMaskBorder)Declaration.hack(hackMaskComposite)Declaration.hack(hackAlignItems)Declaration.hack(hackUserSelect)Declaration.hack(hackFlexShrink)Declaration.hack(hackBreakProps)Declaration.hack(hackWritingMode)Declaration.hack(hackBorderImage)Declaration.hack(hackAlignContent)Declaration.hack(hackBorderRadius)Declaration.hack(hackBlockLogical)Declaration.hack(hackGridTemplate)Declaration.hack(hackInlineLogical)Declaration.hack(hackGridRowAlign)Declaration.hack(hackTransformDecl)Declaration.hack(hackFlexDirection)Declaration.hack(hackImageRendering)Declaration.hack(hackBackdropFilter)Declaration.hack(hackBackgroundClip)Declaration.hack(hackTextDecoration)Declaration.hack(hackJustifyContent)Declaration.hack(hackBackgroundSize)Declaration.hack(hackGridRowColumn)Declaration.hack(hackGridRowsColumns)Declaration.hack(hackGridColumnAlign)Declaration.hack(hackOverscrollBehavior)Declaration.hack(hackGridTemplateAreas)Declaration.hack(hackPrintColorAdjust)Declaration.hack(hackTextEmphasisPosition)Declaration.hack(hackTextDecorationSkipInk)Value.hack(hackGradient)Value.hack(hackIntrinsic)Value.hack(hackPixelated)Value.hack(hackImageSet)Value.hack(hackCrossFade)Value.hack(hackDisplayFlex)Value.hack(hackDisplayGrid)Value.hack(hackFilterValue)let declsCache = new Map()class Prefixes {  constructor(data, browsers, options = {}) {    this.data = data    this.browsers = browsers    this.options = options    ;[this.add, this.remove] = this.preprocess(this.select(this.data))    this.transition = new Transition(this)    this.processor = new Processor(this)  }  /**   * Return clone instance to remove all prefixes   */  cleaner() {    if (this.cleanerCache) {      return this.cleanerCache    }    if (this.browsers.selected.length) {      let empty = new Browsers(this.browsers.data, [])      this.cleanerCache = new Prefixes(this.data, empty, this.options)    } else {      return this    }    return this.cleanerCache  }  /**   * Declaration loader with caching   */  decl(prop) {    if (!declsCache.has(prop)) {      declsCache.set(prop, Declaration.load(prop))    }    return declsCache.get(prop)  }  /**   * Group declaration by unprefixed property to check them   */  group(decl) {    let rule = decl.parent    let index = rule.index(decl)    let { length } = rule.nodes    let unprefixed = this.unprefixed(decl.prop)    let checker = (step, callback) => {      index += step      while (index >= 0 && index < length) {        let other = rule.nodes[index]        if (other.type === 'decl') {          if (step === -1 && other.prop === unprefixed) {            if (!Browsers.withPrefix(other.value)) {              break            }          }          if (this.unprefixed(other.prop) !== unprefixed) {            break          } else if (callback(other) === true) {            return true          }          if (step === +1 && other.prop === unprefixed) {            if (!Browsers.withPrefix(other.value)) {              break            }          }        }        index += step      }      return false    }    return {      down(callback) {        return checker(+1, callback)      },      up(callback) {        return checker(-1, callback)      }    }  }  /**   * Normalize prefix for remover   */  normalize(prop) {    return this.decl(prop).normalize(prop)  }  /**   * Return prefixed version of property   */  prefixed(prop, prefix) {    prop = vendor.unprefixed(prop)    return this.decl(prop).prefixed(prop, prefix)  }  /**   * Cache prefixes data to fast CSS processing   */  preprocess(selected) {    let add = {      '@supports': new Supports(Prefixes, this),      'selectors': []    }    for (let name in selected.add) {      let prefixes = selected.add[name]      if (name === '@keyframes' || name === '@viewport') {        add[name] = new AtRule(name, prefixes, this)      } else if (name === '@resolution') {        add[name] = new Resolution(name, prefixes, this)      } else if (this.data[name].selector) {        add.selectors.push(Selector.load(name, prefixes, this))      } else {        let props = this.data[name].props        if (props) {          let value = Value.load(name, prefixes, this)          for (let prop of props) {            if (!add[prop]) {              add[prop] = { values: [] }            }            add[prop].values.push(value)          }        } else {          let values = (add[name] && add[name].values) || []          add[name] = Declaration.load(name, prefixes, this)          add[name].values = values        }      }    }    let remove = { selectors: [] }    for (let name in selected.remove) {      let prefixes = selected.remove[name]      if (this.data[name].selector) {        let selector = Selector.load(name, prefixes)        for (let prefix of prefixes) {          remove.selectors.push(selector.old(prefix))        }      } else if (name === '@keyframes' || name === '@viewport') {        for (let prefix of prefixes) {          let prefixed = `@${prefix}${name.slice(1)}`          remove[prefixed] = { remove: true }        }      } else if (name === '@resolution') {        remove[name] = new Resolution(name, prefixes, this)      } else {        let props = this.data[name].props        if (props) {          let value = Value.load(name, [], this)          for (let prefix of prefixes) {            let old = value.old(prefix)            if (old) {              for (let prop of props) {                if (!remove[prop]) {                  remove[prop] = {}                }                if (!remove[prop].values) {                  remove[prop].values = []                }                remove[prop].values.push(old)              }            }          }        } else {          for (let p of prefixes) {            let olds = this.decl(name).old(name, p)            if (name === 'align-self') {              let a = add[name] && add[name].prefixes              if (a) {                if (p === '-webkit- 2009' && a.includes('-webkit-')) {                  continue                } else if (p === '-webkit-' && a.includes('-webkit- 2009')) {                  continue                }              }            }            for (let prefixed of olds) {              if (!remove[prefixed]) {                remove[prefixed] = {}              }              remove[prefixed].remove = true            }          }        }      }    }    return [add, remove]  }  /**   * Select prefixes from data, which is necessary for selected browsers   */  select(list) {    let selected = { add: {}, remove: {} }    for (let name in list) {      let data = list[name]      let add = data.browsers.map(i => {        let params = i.split(' ')        return {          browser: `${params[0]} ${params[1]}`,          note: params[2]        }      })      let notes = add        .filter(i => i.note)        .map(i => `${this.browsers.prefix(i.browser)} ${i.note}`)      notes = utils.uniq(notes)      add = add        .filter(i => this.browsers.isSelected(i.browser))        .map(i => {          let prefix = this.browsers.prefix(i.browser)          if (i.note) {            return `${prefix} ${i.note}`          } else {            return prefix          }        })      add = this.sort(utils.uniq(add))      if (this.options.flexbox === 'no-2009') {        add = add.filter(i => !i.includes('2009'))      }      let all = data.browsers.map(i => this.browsers.prefix(i))      if (data.mistakes) {        all = all.concat(data.mistakes)      }      all = all.concat(notes)      all = utils.uniq(all)      if (add.length) {        selected.add[name] = add        if (add.length < all.length) {          selected.remove[name] = all.filter(i => !add.includes(i))        }      } else {        selected.remove[name] = all      }    }    return selected  }  /**   * Sort vendor prefixes   */  sort(prefixes) {    return prefixes.sort((a, b) => {      let aLength = utils.removeNote(a).length      let bLength = utils.removeNote(b).length      if (aLength === bLength) {        return b.length - a.length      } else {        return bLength - aLength      }    })  }  /**   * Return unprefixed version of property   */  unprefixed(prop) {    let value = this.normalize(vendor.unprefixed(prop))    if (value === 'flex-direction') {      value = 'flex-flow'    }    return value  }  /**   * Return values, which must be prefixed in selected property   */  values(type, prop) {    let data = this[type]    let global = data['*'] && data['*'].values    let values = data[prop] && data[prop].values    if (global && values) {      return utils.uniq(global.concat(values))    } else {      return global || values || []    }  }}module.exports = Prefixes
 |