You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
3.9 KiB
187 lines
3.9 KiB
let Prefixer = require('./prefixer') |
|
let Browsers = require('./browsers') |
|
let utils = require('./utils') |
|
|
|
class Declaration extends Prefixer { |
|
/** |
|
* Always true, because we already get prefixer by property name |
|
*/ |
|
check(/* decl */) { |
|
return true |
|
} |
|
|
|
/** |
|
* Return prefixed version of property |
|
*/ |
|
prefixed(prop, prefix) { |
|
return prefix + prop |
|
} |
|
|
|
/** |
|
* Return unprefixed version of property |
|
*/ |
|
normalize(prop) { |
|
return prop |
|
} |
|
|
|
/** |
|
* 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 true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
/** |
|
* Set prefix to declaration |
|
*/ |
|
set(decl, prefix) { |
|
decl.prop = this.prefixed(decl.prop, prefix) |
|
return decl |
|
} |
|
|
|
/** |
|
* 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 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 |
|
} |
|
|
|
/** |
|
* 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 |
|
} |
|
|
|
/** |
|
* 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') |
|
} |
|
|
|
/** |
|
* 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 |
|
} |
|
|
|
/** |
|
* 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) |
|
} |
|
|
|
/** |
|
* 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) |
|
} |
|
|
|
/** |
|
* Return list of prefixed properties to clean old prefixes |
|
*/ |
|
old(prop, prefix) { |
|
return [this.prefixed(prop, prefix)] |
|
} |
|
} |
|
|
|
module.exports = Declaration
|
|
|