AK-21/Graphite-Industrial-Intelligence
0
1let Browsers = require('./browsers')2let utils = require('./utils')3let vendor = require('./vendor')4 5/**6 * Recursively clone objects7 */8function clone(obj, parent) {9 let cloned = new obj.constructor()10 11 for (let i of Object.keys(obj || {})) {12 let value = obj[i]13 if (i === 'parent' && typeof value === 'object') {14 if (parent) {15 cloned[i] = parent16 }17 } else if (i === 'source' || i === null) {18 cloned[i] = value19 } else if (Array.isArray(value)) {20 cloned[i] = value.map(x => clone(x, cloned))21 } else if (22 i !== '_autoprefixerPrefix' &&23 i !== '_autoprefixerValues' &&24 i !== 'proxyCache'25 ) {26 if (typeof value === 'object' && value !== null) {27 value = clone(value, cloned)28 }29 cloned[i] = value30 }31 }32 33 return cloned34}35 36class Prefixer {37 constructor(name, prefixes, all) {38 this.prefixes = prefixes39 this.name = name40 this.all = all41 }42 43 /**44 * Clone node and clean autprefixer custom caches45 */46 static clone(node, overrides) {47 let cloned = clone(node)48 for (let name in overrides) {49 cloned[name] = overrides[name]50 }51 return cloned52 }53 54 /**55 * Add hack to selected names56 */57 static hack(klass) {58 if (!this.hacks) {59 this.hacks = {}60 }61 return klass.names.map(name => {62 this.hacks[name] = klass63 return this.hacks[name]64 })65 }66 67 /**68 * Load hacks for some names69 */70 static load(name, prefixes, all) {71 let Klass = this.hacks && this.hacks[name]72 if (Klass) {73 return new Klass(name, prefixes, all)74 } else {75 return new this(name, prefixes, all)76 }77 }78 79 /**80 * Shortcut for Prefixer.clone81 */82 clone(node, overrides) {83 return Prefixer.clone(node, overrides)84 }85 86 /**87 * Find prefix in node parents88 */89 parentPrefix(node) {90 let prefix91 92 if (typeof node._autoprefixerPrefix !== 'undefined') {93 prefix = node._autoprefixerPrefix94 } else if (node.type === 'decl' && node.prop[0] === '-') {95 prefix = vendor.prefix(node.prop)96 } else if (node.type === 'root') {97 prefix = false98 } else if (99 node.type === 'rule' &&100 node.selector.includes(':-') &&101 /:(-\w+-)/.test(node.selector)102 ) {103 prefix = node.selector.match(/:(-\w+-)/)[1]104 } else if (node.type === 'atrule' && node.name[0] === '-') {105 prefix = vendor.prefix(node.name)106 } else {107 prefix = this.parentPrefix(node.parent)108 }109 110 if (!Browsers.prefixes().includes(prefix)) {111 prefix = false112 }113 114 node._autoprefixerPrefix = prefix115 116 return node._autoprefixerPrefix117 }118 119 /**120 * Clone node with prefixes121 */122 process(node, result) {123 if (!this.check(node)) {124 return undefined125 }126 127 let parent = this.parentPrefix(node)128 129 let prefixes = this.prefixes.filter(130 prefix => !parent || parent === utils.removeNote(prefix)131 )132 133 let added = []134 for (let prefix of prefixes) {135 if (this.add(node, prefix, added.concat([prefix]), result)) {136 added.push(prefix)137 }138 }139 140 return added141 }142}143 144module.exports = Prefixer145 