| let { list } = require('postcss') |
|
|
| let OldSelector = require('./old-selector') |
| let Prefixer = require('./prefixer') |
| let Browsers = require('./browsers') |
| let utils = require('./utils') |
|
|
| class Selector extends Prefixer { |
| constructor(name, prefixes, all) { |
| super(name, prefixes, all) |
| this.regexpCache = new Map() |
| } |
|
|
| |
| |
| |
| add(rule, prefix) { |
| let prefixeds = this.prefixeds(rule) |
|
|
| if (this.already(rule, prefixeds, prefix)) { |
| return |
| } |
|
|
| let cloned = this.clone(rule, { selector: prefixeds[this.name][prefix] }) |
| rule.parent.insertBefore(rule, cloned) |
| } |
|
|
| |
| |
| |
| already(rule, prefixeds, prefix) { |
| let index = rule.parent.index(rule) - 1 |
|
|
| while (index >= 0) { |
| let before = rule.parent.nodes[index] |
|
|
| if (before.type !== 'rule') { |
| return false |
| } |
|
|
| let some = false |
| for (let key in prefixeds[this.name]) { |
| let prefixed = prefixeds[this.name][key] |
| if (before.selector === prefixed) { |
| if (prefix === key) { |
| return true |
| } else { |
| some = true |
| break |
| } |
| } |
| } |
| if (!some) { |
| return false |
| } |
|
|
| index -= 1 |
| } |
|
|
| return false |
| } |
|
|
| |
| |
| |
| check(rule) { |
| if (rule.selector.includes(this.name)) { |
| return !!rule.selector.match(this.regexp()) |
| } |
|
|
| return false |
| } |
|
|
| |
| |
| |
| old(prefix) { |
| return new OldSelector(this, prefix) |
| } |
|
|
| |
| |
| |
| possible() { |
| return Browsers.prefixes() |
| } |
|
|
| |
| |
| |
| prefixed(prefix) { |
| return this.name.replace(/^(\W*)/, `$1${prefix}`) |
| } |
|
|
| |
| |
| |
| prefixeds(rule) { |
| if (rule._autoprefixerPrefixeds) { |
| if (rule._autoprefixerPrefixeds[this.name]) { |
| return rule._autoprefixerPrefixeds |
| } |
| } else { |
| rule._autoprefixerPrefixeds = {} |
| } |
|
|
| let prefixeds = {} |
| if (rule.selector.includes(',')) { |
| let ruleParts = list.comma(rule.selector) |
| let toProcess = ruleParts.filter(el => el.includes(this.name)) |
|
|
| for (let prefix of this.possible()) { |
| prefixeds[prefix] = toProcess |
| .map(el => this.replace(el, prefix)) |
| .join(', ') |
| } |
| } else { |
| for (let prefix of this.possible()) { |
| prefixeds[prefix] = this.replace(rule.selector, prefix) |
| } |
| } |
|
|
| rule._autoprefixerPrefixeds[this.name] = prefixeds |
| return rule._autoprefixerPrefixeds |
| } |
|
|
| |
| |
| |
| regexp(prefix) { |
| if (!this.regexpCache.has(prefix)) { |
| let name = prefix ? this.prefixed(prefix) : this.name |
| this.regexpCache.set( |
| prefix, |
| new RegExp(`(^|[^:"'=])${utils.escapeRegexp(name)}`, 'gi') |
| ) |
| } |
|
|
| return this.regexpCache.get(prefix) |
| } |
|
|
| |
| |
| |
| replace(selector, prefix) { |
| return selector.replace(this.regexp(), `$1${this.prefixed(prefix)}`) |
| } |
| } |
|
|
| module.exports = Selector |
|
|