AK-21/Graphite-Industrial-Intelligence
0
1let Browsers = require('./browsers')2let Prefixer = require('./prefixer')3let utils = require('./utils')4 5class Declaration extends Prefixer {6 /**7 * Clone and add prefixes for declaration8 */9 add(decl, prefix, prefixes, result) {10 let prefixed = this.prefixed(decl.prop, prefix)11 if (12 this.isAlready(decl, prefixed) ||13 this.otherPrefixes(decl.value, prefix)14 ) {15 return undefined16 }17 return this.insert(decl, prefix, prefixes, result)18 }19 20 /**21 * Calculate indentation to create visual cascade22 */23 calcBefore(prefixes, decl, prefix = '') {24 let max = this.maxPrefixed(prefixes, decl)25 let diff = max - utils.removeNote(prefix).length26 27 let before = decl.raw('before')28 if (diff > 0) {29 before += Array(diff).fill(' ').join('')30 }31 32 return before33 }34 35 /**36 * Always true, because we already get prefixer by property name37 */38 check(/* decl */) {39 return true40 }41 42 /**43 * Clone and insert new declaration44 */45 insert(decl, prefix, prefixes) {46 let cloned = this.set(this.clone(decl), prefix)47 if (!cloned) return undefined48 49 let already = decl.parent.some(50 i => i.prop === cloned.prop && i.value === cloned.value51 )52 if (already) {53 return undefined54 }55 56 if (this.needCascade(decl)) {57 cloned.raws.before = this.calcBefore(prefixes, decl, prefix)58 }59 return decl.parent.insertBefore(decl, cloned)60 }61 62 /**63 * Did this declaration has this prefix above64 */65 isAlready(decl, prefixed) {66 let already = this.all.group(decl).up(i => i.prop === prefixed)67 if (!already) {68 already = this.all.group(decl).down(i => i.prop === prefixed)69 }70 return already71 }72 73 /**74 * Return maximum length of possible prefixed property75 */76 maxPrefixed(prefixes, decl) {77 if (decl._autoprefixerMax) {78 return decl._autoprefixerMax79 }80 81 let max = 082 for (let prefix of prefixes) {83 prefix = utils.removeNote(prefix)84 if (prefix.length > max) {85 max = prefix.length86 }87 }88 decl._autoprefixerMax = max89 90 return decl._autoprefixerMax91 }92 93 /**94 * Should we use visual cascade for prefixes95 */96 needCascade(decl) {97 if (!decl._autoprefixerCascade) {98 decl._autoprefixerCascade =99 this.all.options.cascade !== false && decl.raw('before').includes('\n')100 }101 return decl._autoprefixerCascade102 }103 104 /**105 * Return unprefixed version of property106 */107 normalize(prop) {108 return prop109 }110 111 /**112 * Return list of prefixed properties to clean old prefixes113 */114 old(prop, prefix) {115 return [this.prefixed(prop, prefix)]116 }117 118 /**119 * Check `value`, that it contain other prefixes, rather than `prefix`120 */121 otherPrefixes(value, prefix) {122 for (let other of Browsers.prefixes()) {123 if (other === prefix) {124 continue125 }126 if (value.includes(other)) {127 return value.replace(/var\([^)]+\)/, '').includes(other)128 }129 }130 return false131 }132 133 /**134 * Return prefixed version of property135 */136 prefixed(prop, prefix) {137 return prefix + prop138 }139 140 /**141 * Add spaces for visual cascade142 */143 process(decl, result) {144 if (!this.needCascade(decl)) {145 super.process(decl, result)146 return147 }148 149 let prefixes = super.process(decl, result)150 151 if (!prefixes || !prefixes.length) {152 return153 }154 155 this.restoreBefore(decl)156 decl.raws.before = this.calcBefore(prefixes, decl)157 }158 159 /**160 * Remove visual cascade161 */162 restoreBefore(decl) {163 let lines = decl.raw('before').split('\n')164 let min = lines[lines.length - 1]165 166 this.all.group(decl).up(prefixed => {167 let array = prefixed.raw('before').split('\n')168 let last = array[array.length - 1]169 if (last.length < min.length) {170 min = last171 }172 })173 174 lines[lines.length - 1] = min175 decl.raws.before = lines.join('\n')176 }177 178 /**179 * Set prefix to declaration180 */181 set(decl, prefix) {182 decl.prop = this.prefixed(decl.prop, prefix)183 return decl184 }185}186 187module.exports = Declaration188 