123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- let Browsers = require('./browsers')
- let vendor = require('./vendor')
- let utils = require('./utils')
- /**
- * Recursively clone objects
- */
- function clone(obj, parent) {
- let cloned = new obj.constructor()
- for (let i of Object.keys(obj || {})) {
- let value = obj[i]
- if (i === 'parent' && typeof value === 'object') {
- if (parent) {
- cloned[i] = parent
- }
- } else if (i === 'source' || i === null) {
- cloned[i] = value
- } else if (Array.isArray(value)) {
- cloned[i] = value.map(x => clone(x, cloned))
- } else if (
- i !== '_autoprefixerPrefix' &&
- i !== '_autoprefixerValues' &&
- i !== 'proxyCache'
- ) {
- if (typeof value === 'object' && value !== null) {
- value = clone(value, cloned)
- }
- cloned[i] = value
- }
- }
- return cloned
- }
- class Prefixer {
- /**
- * Add hack to selected names
- */
- static hack(klass) {
- if (!this.hacks) {
- this.hacks = {}
- }
- return klass.names.map(name => {
- this.hacks[name] = klass
- return this.hacks[name]
- })
- }
- /**
- * Load hacks for some names
- */
- static load(name, prefixes, all) {
- let Klass = this.hacks && this.hacks[name]
- if (Klass) {
- return new Klass(name, prefixes, all)
- } else {
- return new this(name, prefixes, all)
- }
- }
- /**
- * Clone node and clean autprefixer custom caches
- */
- static clone(node, overrides) {
- let cloned = clone(node)
- for (let name in overrides) {
- cloned[name] = overrides[name]
- }
- return cloned
- }
- constructor(name, prefixes, all) {
- this.prefixes = prefixes
- this.name = name
- this.all = all
- }
- /**
- * Find prefix in node parents
- */
- parentPrefix(node) {
- let prefix
- if (typeof node._autoprefixerPrefix !== 'undefined') {
- prefix = node._autoprefixerPrefix
- } else if (node.type === 'decl' && node.prop[0] === '-') {
- prefix = vendor.prefix(node.prop)
- } else if (node.type === 'root') {
- prefix = false
- } else if (
- node.type === 'rule' &&
- node.selector.includes(':-') &&
- /:(-\w+-)/.test(node.selector)
- ) {
- prefix = node.selector.match(/:(-\w+-)/)[1]
- } else if (node.type === 'atrule' && node.name[0] === '-') {
- prefix = vendor.prefix(node.name)
- } else {
- prefix = this.parentPrefix(node.parent)
- }
- if (!Browsers.prefixes().includes(prefix)) {
- prefix = false
- }
- node._autoprefixerPrefix = prefix
- return node._autoprefixerPrefix
- }
- /**
- * Clone node with prefixes
- */
- process(node, result) {
- if (!this.check(node)) {
- return undefined
- }
- let parent = this.parentPrefix(node)
- let prefixes = this.prefixes.filter(
- prefix => !parent || parent === utils.removeNote(prefix)
- )
- let added = []
- for (let prefix of prefixes) {
- if (this.add(node, prefix, added.concat([prefix]), result)) {
- added.push(prefix)
- }
- }
- return added
- }
- /**
- * Shortcut for Prefixer.clone
- */
- clone(node, overrides) {
- return Prefixer.clone(node, overrides)
- }
- }
- module.exports = Prefixer
|