|
- let Prefixer = require('./prefixer')
- let Browsers = require('./browsers')
- let utils = require('./utils')
-
- class Declaration extends Prefixer {
- /**
- * Clone and add prefixes for declaration
- */
- add(decl, prefix, prefixes, result) {
- let prefixed = this.prefixed(decl.prop, prefix)
- if (
- this.isAlready(decl, prefixed) ||
- this.otherPrefixes(decl.value, prefix)
- ) {
- return undefined
- }
- return this.insert(decl, prefix, prefixes, result)
- }
-
- /**
- * Calculate indentation to create visual cascade
- */
- calcBefore(prefixes, decl, prefix = '') {
- let max = this.maxPrefixed(prefixes, decl)
- let diff = max - utils.removeNote(prefix).length
-
- let before = decl.raw('before')
- if (diff > 0) {
- before += Array(diff).fill(' ').join('')
- }
-
- return before
- }
-
- /**
- * Always true, because we already get prefixer by property name
- */
- check(/* decl */) {
- return true
- }
-
- /**
- * Clone and insert new declaration
- */
- insert(decl, prefix, prefixes) {
- let cloned = this.set(this.clone(decl), prefix)
- if (!cloned) return undefined
-
- let already = decl.parent.some(
- i => i.prop === cloned.prop && i.value === cloned.value
- )
- if (already) {
- return undefined
- }
-
- if (this.needCascade(decl)) {
- cloned.raws.before = this.calcBefore(prefixes, decl, prefix)
- }
- return decl.parent.insertBefore(decl, cloned)
- }
-
- /**
- * Did this declaration has this prefix above
- */
- isAlready(decl, prefixed) {
- let already = this.all.group(decl).up(i => i.prop === prefixed)
- if (!already) {
- already = this.all.group(decl).down(i => i.prop === prefixed)
- }
- return already
- }
-
- /**
- * Return maximum length of possible prefixed property
- */
- maxPrefixed(prefixes, decl) {
- if (decl._autoprefixerMax) {
- return decl._autoprefixerMax
- }
-
- let max = 0
- for (let prefix of prefixes) {
- prefix = utils.removeNote(prefix)
- if (prefix.length > max) {
- max = prefix.length
- }
- }
- decl._autoprefixerMax = max
-
- return decl._autoprefixerMax
- }
-
- /**
- * Should we use visual cascade for prefixes
- */
- needCascade(decl) {
- if (!decl._autoprefixerCascade) {
- decl._autoprefixerCascade =
- this.all.options.cascade !== false && decl.raw('before').includes('\n')
- }
- return decl._autoprefixerCascade
- }
-
- /**
- * Return unprefixed version of property
- */
- normalize(prop) {
- return prop
- }
-
- /**
- * Return list of prefixed properties to clean old prefixes
- */
- old(prop, prefix) {
- return [this.prefixed(prop, prefix)]
- }
-
- /**
- * Check `value`, that it contain other prefixes, rather than `prefix`
- */
- otherPrefixes(value, prefix) {
- for (let other of Browsers.prefixes()) {
- if (other === prefix) {
- continue
- }
- if (value.includes(other)) {
- return value.replace(/var\([^)]+\)/, '').includes(other)
- }
- }
- return false
- }
-
- /**
- * Return prefixed version of property
- */
- prefixed(prop, prefix) {
- return prefix + prop
- }
-
- /**
- * Add spaces for visual cascade
- */
- process(decl, result) {
- if (!this.needCascade(decl)) {
- super.process(decl, result)
- return
- }
-
- let prefixes = super.process(decl, result)
-
- if (!prefixes || !prefixes.length) {
- return
- }
-
- this.restoreBefore(decl)
- decl.raws.before = this.calcBefore(prefixes, decl)
- }
-
- /**
- * Remove visual cascade
- */
- restoreBefore(decl) {
- let lines = decl.raw('before').split('\n')
- let min = lines[lines.length - 1]
-
- this.all.group(decl).up(prefixed => {
- let array = prefixed.raw('before').split('\n')
- let last = array[array.length - 1]
- if (last.length < min.length) {
- min = last
- }
- })
-
- lines[lines.length - 1] = min
- decl.raws.before = lines.join('\n')
- }
-
- /**
- * Set prefix to declaration
- */
- set(decl, prefix) {
- decl.prop = this.prefixed(decl.prop, prefix)
- return decl
- }
- }
-
- module.exports = Declaration
|