UNPKG

4.04 kBJavaScriptView Raw
1let Prefixer = require('./prefixer')
2let Browsers = require('./browsers')
3let utils = require('./utils')
4
5class Declaration extends Prefixer {
6 /**
7 * Always true, because we already get prefixer by property name
8 */
9 check (/* decl */) {
10 return true
11 }
12
13 /**
14 * Return prefixed version of property
15 */
16 prefixed (prop, prefix) {
17 return prefix + prop
18 }
19
20 /**
21 * Return unprefixed version of property
22 */
23 normalize (prop) {
24 return prop
25 }
26
27 /**
28 * Check `value`, that it contain other prefixes, rather than `prefix`
29 */
30 otherPrefixes (value, prefix) {
31 for (let other of Browsers.prefixes()) {
32 if (other === prefix) {
33 continue
34 }
35 if (value.includes(other)) {
36 return true
37 }
38 }
39 return false
40 }
41
42 /**
43 * Set prefix to declaration
44 */
45 set (decl, prefix) {
46 decl.prop = this.prefixed(decl.prop, prefix)
47 return decl
48 }
49
50 /**
51 * Should we use visual cascade for prefixes
52 */
53 needCascade (decl) {
54 if (!decl._autoprefixerCascade) {
55 decl._autoprefixerCascade =
56 this.all.options.cascade !== false && decl.raw('before').includes('\n')
57 }
58 return decl._autoprefixerCascade
59 }
60
61 /**
62 * Return maximum length of possible prefixed property
63 */
64 maxPrefixed (prefixes, decl) {
65 if (decl._autoprefixerMax) {
66 return decl._autoprefixerMax
67 }
68
69 let max = 0
70 for (let prefix of prefixes) {
71 prefix = utils.removeNote(prefix)
72 if (prefix.length > max) {
73 max = prefix.length
74 }
75 }
76 decl._autoprefixerMax = max
77
78 return decl._autoprefixerMax
79 }
80
81 /**
82 * Calculate indentation to create visual cascade
83 */
84 calcBefore (prefixes, decl, prefix = '') {
85 let max = this.maxPrefixed(prefixes, decl)
86 let diff = max - utils.removeNote(prefix).length
87
88 let before = decl.raw('before')
89 if (diff > 0) {
90 before += Array(diff).fill(' ').join('')
91 }
92
93 return before
94 }
95
96 /**
97 * Remove visual cascade
98 */
99 restoreBefore (decl) {
100 let lines = decl.raw('before').split('\n')
101 let min = lines[lines.length - 1]
102
103 this.all.group(decl).up(prefixed => {
104 let array = prefixed.raw('before').split('\n')
105 let last = array[array.length - 1]
106 if (last.length < min.length) {
107 min = last
108 }
109 })
110
111 lines[lines.length - 1] = min
112 decl.raws.before = lines.join('\n')
113 }
114
115 /**
116 * Clone and insert new declaration
117 */
118 insert (decl, prefix, prefixes) {
119 let cloned = this.set(this.clone(decl), prefix)
120 if (!cloned) return undefined
121
122 let already = decl.parent.some(
123 i => i.prop === cloned.prop && i.value === cloned.value
124 )
125 if (already) {
126 return undefined
127 }
128
129 if (this.needCascade(decl)) {
130 cloned.raws.before = this.calcBefore(prefixes, decl, prefix)
131 }
132 return decl.parent.insertBefore(decl, cloned)
133 }
134
135 /**
136 * Did this declaration has this prefix above
137 */
138 isAlready (decl, prefixed) {
139 let already = this.all.group(decl).up(i => i.prop === prefixed)
140 if (!already) {
141 already = this.all.group(decl).down(i => i.prop === prefixed)
142 }
143 return already
144 }
145
146 /**
147 * Clone and add prefixes for declaration
148 */
149 add (decl, prefix, prefixes, result) {
150 let prefixed = this.prefixed(decl.prop, prefix)
151 if (
152 this.isAlready(decl, prefixed) ||
153 this.otherPrefixes(decl.value, prefix)
154 ) {
155 return undefined
156 }
157 return this.insert(decl, prefix, prefixes, result)
158 }
159
160 /**
161 * Add spaces for visual cascade
162 */
163 process (decl, result) {
164 if (!this.needCascade(decl)) {
165 super.process(decl, result)
166 return
167 }
168
169 let prefixes = super.process(decl, result)
170
171 if (!prefixes || !prefixes.length) {
172 return
173 }
174
175 this.restoreBefore(decl)
176 decl.raws.before = this.calcBefore(prefixes, decl)
177 }
178
179 /**
180 * Return list of prefixed properties to clean old prefixes
181 */
182 old (prop, prefix) {
183 return [this.prefixed(prop, prefix)]
184 }
185}
186
187module.exports = Declaration