CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
supports.js303 linesDownload Raw Back to lib
1let featureQueries = require('caniuse-lite/data/features/css-featurequeries.js')2let feature = require('caniuse-lite/dist/unpacker/feature')3let { parse } = require('postcss')4 5let brackets = require('./brackets')6let Browsers = require('./browsers')7let utils = require('./utils')8let Value = require('./value')9 10let data = feature(featureQueries)11 12let supported = []13for (let browser in data.stats) {14  let versions = data.stats[browser]15  for (let version in versions) {16    let support = versions[version]17    if (/y/.test(support)) {18      supported.push(browser + ' ' + version)19    }20  }21}22 23class Supports {24  constructor(Prefixes, all) {25    this.Prefixes = Prefixes26    this.all = all27  }28 29  /**30   * Add prefixes31   */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        }39 40        return i41      }42 43      if (typeof i === 'object') {44        return this.add(i, all)45      }46 47      return i48    })49  }50 51  /**52   * Clean brackets with one child53   */54  cleanBrackets(nodes) {55    return nodes.map(i => {56      if (typeof i !== 'object') {57        return i58      }59 60      if (i.length === 1 && typeof i[0] === 'object') {61        return this.cleanBrackets(i[0])62      }63 64      return this.cleanBrackets(i)65    })66  }67 68  /**69   * Add " or " between properties and convert it to brackets format70   */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 result79  }80 81  /**82   * Check global options83   */84  disabled(node) {85    if (!this.all.options.grid) {86      if (node.prop === 'display' && node.value.includes('grid')) {87        return true88      }89      if (node.prop.includes('grid') || node.prop === 'justify-items') {90        return true91      }92    }93 94    if (this.all.options.flexbox === false) {95      if (node.prop === 'display' && node.value.includes('flex')) {96        return true97      }98      let other = ['order', 'justify-content', 'align-items', 'align-content']99      if (node.prop.includes('flex') || other.includes(node.prop)) {100        return true101      }102    }103 104    return false105  }106 107  /**108   * Return true if prefixed property has no unprefixed109   */110  isHack(all, unprefixed) {111    let check = new RegExp(`(\\(|\\s)${utils.escapeRegexp(unprefixed)}:`)112    return !check.test(all)113  }114 115  /**116   * Return true if brackets node is "not" word117   */118  isNot(node) {119    return typeof node === 'string' && /not\s*/i.test(node)120  }121 122  /**123   * Return true if brackets node is "or" word124   */125  isOr(node) {126    return typeof node === 'string' && /\s*or\s*/i.test(node)127  }128 129  /**130   * Return true if brackets node is (prop: value)131   */132  isProp(node) {133    return (134      typeof node === 'object' &&135      node.length === 1 &&136      typeof node[0] === 'string'137    )138  }139 140  /**141   * Compress value functions into a string nodes142   */143  normalize(nodes) {144    if (typeof nodes !== 'object') {145      return nodes146    }147 148    nodes = nodes.filter(i => i !== '')149 150    if (typeof nodes[0] === 'string') {151      let firstNode = nodes[0].trim()152 153      if (154        firstNode.includes(':') ||155        firstNode === 'selector' ||156        firstNode === 'not selector'157      ) {158        return [brackets.stringify(nodes)]159      }160    }161    return nodes.map(i => this.normalize(i))162  }163 164  /**165   * Parse string into declaration property and value166   */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  }174 175  /**176   * Return array of Declaration with all necessary prefixes177   */178  prefixed(str) {179    let rule = this.virtual(str)180    if (this.disabled(rule.first)) {181      return rule.nodes182    }183 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)192      }193      Value.save(this.all, decl)194    }195 196    return rule.nodes197  }198 199  /**200   * Return prefixer only with @supports supported browsers201   */202  prefixer() {203    if (this.prefixerCache) {204      return this.prefixerCache205    }206 207    let filtered = this.all.browsers.selected.filter(i => {208      return supported.includes(i)209    })210 211    let browsers = new Browsers(212      this.all.browsers.data,213      filtered,214      this.all.options215    )216    this.prefixerCache = new this.Prefixes(217      this.all.data,218      browsers,219      this.all.options220    )221    return this.prefixerCache222  }223 224  /**225   * Add prefixed declaration226   */227  process(rule) {228    let ast = brackets.parse(rule.params)229    ast = this.normalize(ast)230    ast = this.remove(ast, rule.params)231    ast = this.add(ast, rule.params)232    ast = this.cleanBrackets(ast)233    rule.params = brackets.stringify(ast)234  }235 236  /**237   * Remove all unnecessary prefixes238   */239  remove(nodes, all) {240    let i = 0241    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          continue250        }251 252        i += 2253        continue254      }255 256      if (typeof nodes[i] === 'object') {257        nodes[i] = this.remove(nodes[i], all)258      }259 260      i += 1261    }262    return nodes263  }264 265  /**266   * Return true if we need to remove node267   */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 true280    }281 282    for (let checker of cleaner.values('remove', unprefixed)) {283      if (checker.check(value)) {284        return true285      }286    }287 288    return false289  }290 291  /**292   * Create virtual rule to process it by prefixer293   */294  virtual(str) {295    let [prop, value] = this.parse(str)296    let rule = parse('a{}').first297    rule.append({ prop, raws: { before: '' }, value })298    return rule299  }300}301 302module.exports = Supports303 
basant307/AI_Governance_Project · CoolFace