source: node_modules/autoprefixer/lib/selector.js@ 2058e5c

Last change on this file since 2058e5c was 2058e5c, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Working / before login

  • Property mode set to 100644
File size: 3.1 KB
Line 
1let { list } = require('postcss')
2
3let Browsers = require('./browsers')
4let OldSelector = require('./old-selector')
5let Prefixer = require('./prefixer')
6let utils = require('./utils')
7
8class Selector extends Prefixer {
9 constructor(name, prefixes, all) {
10 super(name, prefixes, all)
11 this.regexpCache = new Map()
12 }
13
14 /**
15 * Clone and add prefixes for at-rule
16 */
17 add(rule, prefix) {
18 let prefixeds = this.prefixeds(rule)
19
20 if (this.already(rule, prefixeds, prefix)) {
21 return
22 }
23
24 let cloned = this.clone(rule, { selector: prefixeds[this.name][prefix] })
25 rule.parent.insertBefore(rule, cloned)
26 }
27
28 /**
29 * Is rule already prefixed before
30 */
31 already(rule, prefixeds, prefix) {
32 let index = rule.parent.index(rule) - 1
33
34 while (index >= 0) {
35 let before = rule.parent.nodes[index]
36
37 if (before.type !== 'rule') {
38 return false
39 }
40
41 let some = false
42 for (let key in prefixeds[this.name]) {
43 let prefixed = prefixeds[this.name][key]
44 if (before.selector === prefixed) {
45 if (prefix === key) {
46 return true
47 } else {
48 some = true
49 break
50 }
51 }
52 }
53 if (!some) {
54 return false
55 }
56
57 index -= 1
58 }
59
60 return false
61 }
62
63 /**
64 * Is rule selectors need to be prefixed
65 */
66 check(rule) {
67 if (rule.selector.includes(this.name)) {
68 return !!rule.selector.match(this.regexp())
69 }
70
71 return false
72 }
73
74 /**
75 * Return function to fast find prefixed selector
76 */
77 old(prefix) {
78 return new OldSelector(this, prefix)
79 }
80
81 /**
82 * All possible prefixes
83 */
84 possible() {
85 return Browsers.prefixes()
86 }
87
88 /**
89 * Return prefixed version of selector
90 */
91 prefixed(prefix) {
92 return this.name.replace(/^(\W*)/, `$1${prefix}`)
93 }
94
95 /**
96 * Return all possible selector prefixes
97 */
98 prefixeds(rule) {
99 if (rule._autoprefixerPrefixeds) {
100 if (rule._autoprefixerPrefixeds[this.name]) {
101 return rule._autoprefixerPrefixeds
102 }
103 } else {
104 rule._autoprefixerPrefixeds = {}
105 }
106
107 let prefixeds = {}
108 if (rule.selector.includes(',')) {
109 let ruleParts = list.comma(rule.selector)
110 let toProcess = ruleParts.filter(el => el.includes(this.name))
111
112 for (let prefix of this.possible()) {
113 prefixeds[prefix] = toProcess
114 .map(el => this.replace(el, prefix))
115 .join(', ')
116 }
117 } else {
118 for (let prefix of this.possible()) {
119 prefixeds[prefix] = this.replace(rule.selector, prefix)
120 }
121 }
122
123 rule._autoprefixerPrefixeds[this.name] = prefixeds
124 return rule._autoprefixerPrefixeds
125 }
126
127 /**
128 * Lazy loadRegExp for name
129 */
130 regexp(prefix) {
131 if (!this.regexpCache.has(prefix)) {
132 let name = prefix ? this.prefixed(prefix) : this.name
133 this.regexpCache.set(
134 prefix,
135 new RegExp(`(^|[^:"'=])${utils.escapeRegexp(name)}`, 'gi')
136 )
137 }
138
139 return this.regexpCache.get(prefix)
140 }
141
142 /**
143 * Replace selectors by prefixed one
144 */
145 replace(selector, prefix) {
146 return selector.replace(this.regexp(), `$1${this.prefixed(prefix)}`)
147 }
148}
149
150module.exports = Selector
Note: See TracBrowser for help on using the repository browser.