source: imaps-frontend/node_modules/postcss/lib/container.js@ 0c6b92a

main
Last change on this file since 0c6b92a was 0c6b92a, checked in by stefan toskovski <stefantoska84@…>, 5 weeks ago

Pred finalna verzija

  • Property mode set to 100644
File size: 10.4 KB
Line 
1'use strict'
2
3let Comment = require('./comment')
4let Declaration = require('./declaration')
5let Node = require('./node')
6let { isClean, my } = require('./symbols')
7
8let AtRule, parse, Root, Rule
9
10function cleanSource(nodes) {
11 return nodes.map(i => {
12 if (i.nodes) i.nodes = cleanSource(i.nodes)
13 delete i.source
14 return i
15 })
16}
17
18function markTreeDirty(node) {
19 node[isClean] = false
20 if (node.proxyOf.nodes) {
21 for (let i of node.proxyOf.nodes) {
22 markTreeDirty(i)
23 }
24 }
25}
26
27class Container extends Node {
28 append(...children) {
29 for (let child of children) {
30 let nodes = this.normalize(child, this.last)
31 for (let node of nodes) this.proxyOf.nodes.push(node)
32 }
33
34 this.markDirty()
35
36 return this
37 }
38
39 cleanRaws(keepBetween) {
40 super.cleanRaws(keepBetween)
41 if (this.nodes) {
42 for (let node of this.nodes) node.cleanRaws(keepBetween)
43 }
44 }
45
46 each(callback) {
47 if (!this.proxyOf.nodes) return undefined
48 let iterator = this.getIterator()
49
50 let index, result
51 while (this.indexes[iterator] < this.proxyOf.nodes.length) {
52 index = this.indexes[iterator]
53 result = callback(this.proxyOf.nodes[index], index)
54 if (result === false) break
55
56 this.indexes[iterator] += 1
57 }
58
59 delete this.indexes[iterator]
60 return result
61 }
62
63 every(condition) {
64 return this.nodes.every(condition)
65 }
66
67 getIterator() {
68 if (!this.lastEach) this.lastEach = 0
69 if (!this.indexes) this.indexes = {}
70
71 this.lastEach += 1
72 let iterator = this.lastEach
73 this.indexes[iterator] = 0
74
75 return iterator
76 }
77
78 getProxyProcessor() {
79 return {
80 get(node, prop) {
81 if (prop === 'proxyOf') {
82 return node
83 } else if (!node[prop]) {
84 return node[prop]
85 } else if (
86 prop === 'each' ||
87 (typeof prop === 'string' && prop.startsWith('walk'))
88 ) {
89 return (...args) => {
90 return node[prop](
91 ...args.map(i => {
92 if (typeof i === 'function') {
93 return (child, index) => i(child.toProxy(), index)
94 } else {
95 return i
96 }
97 })
98 )
99 }
100 } else if (prop === 'every' || prop === 'some') {
101 return cb => {
102 return node[prop]((child, ...other) =>
103 cb(child.toProxy(), ...other)
104 )
105 }
106 } else if (prop === 'root') {
107 return () => node.root().toProxy()
108 } else if (prop === 'nodes') {
109 return node.nodes.map(i => i.toProxy())
110 } else if (prop === 'first' || prop === 'last') {
111 return node[prop].toProxy()
112 } else {
113 return node[prop]
114 }
115 },
116
117 set(node, prop, value) {
118 if (node[prop] === value) return true
119 node[prop] = value
120 if (prop === 'name' || prop === 'params' || prop === 'selector') {
121 node.markDirty()
122 }
123 return true
124 }
125 }
126 }
127
128 index(child) {
129 if (typeof child === 'number') return child
130 if (child.proxyOf) child = child.proxyOf
131 return this.proxyOf.nodes.indexOf(child)
132 }
133
134 insertAfter(exist, add) {
135 let existIndex = this.index(exist)
136 let nodes = this.normalize(add, this.proxyOf.nodes[existIndex]).reverse()
137 existIndex = this.index(exist)
138 for (let node of nodes) this.proxyOf.nodes.splice(existIndex + 1, 0, node)
139
140 let index
141 for (let id in this.indexes) {
142 index = this.indexes[id]
143 if (existIndex < index) {
144 this.indexes[id] = index + nodes.length
145 }
146 }
147
148 this.markDirty()
149
150 return this
151 }
152
153 insertBefore(exist, add) {
154 let existIndex = this.index(exist)
155 let type = existIndex === 0 ? 'prepend' : false
156 let nodes = this.normalize(
157 add,
158 this.proxyOf.nodes[existIndex],
159 type
160 ).reverse()
161 existIndex = this.index(exist)
162 for (let node of nodes) this.proxyOf.nodes.splice(existIndex, 0, node)
163
164 let index
165 for (let id in this.indexes) {
166 index = this.indexes[id]
167 if (existIndex <= index) {
168 this.indexes[id] = index + nodes.length
169 }
170 }
171
172 this.markDirty()
173
174 return this
175 }
176
177 normalize(nodes, sample) {
178 if (typeof nodes === 'string') {
179 nodes = cleanSource(parse(nodes).nodes)
180 } else if (typeof nodes === 'undefined') {
181 nodes = []
182 } else if (Array.isArray(nodes)) {
183 nodes = nodes.slice(0)
184 for (let i of nodes) {
185 if (i.parent) i.parent.removeChild(i, 'ignore')
186 }
187 } else if (nodes.type === 'root' && this.type !== 'document') {
188 nodes = nodes.nodes.slice(0)
189 for (let i of nodes) {
190 if (i.parent) i.parent.removeChild(i, 'ignore')
191 }
192 } else if (nodes.type) {
193 nodes = [nodes]
194 } else if (nodes.prop) {
195 if (typeof nodes.value === 'undefined') {
196 throw new Error('Value field is missed in node creation')
197 } else if (typeof nodes.value !== 'string') {
198 nodes.value = String(nodes.value)
199 }
200 nodes = [new Declaration(nodes)]
201 } else if (nodes.selector || nodes.selectors) {
202 nodes = [new Rule(nodes)]
203 } else if (nodes.name) {
204 nodes = [new AtRule(nodes)]
205 } else if (nodes.text) {
206 nodes = [new Comment(nodes)]
207 } else {
208 throw new Error('Unknown node type in node creation')
209 }
210
211 let processed = nodes.map(i => {
212 /* c8 ignore next */
213 if (!i[my]) Container.rebuild(i)
214 i = i.proxyOf
215 if (i.parent) i.parent.removeChild(i)
216 if (i[isClean]) markTreeDirty(i)
217
218 if (!i.raws) i.raws = {}
219 if (typeof i.raws.before === 'undefined') {
220 if (sample && typeof sample.raws.before !== 'undefined') {
221 i.raws.before = sample.raws.before.replace(/\S/g, '')
222 }
223 }
224 i.parent = this.proxyOf
225 return i
226 })
227
228 return processed
229 }
230
231 prepend(...children) {
232 children = children.reverse()
233 for (let child of children) {
234 let nodes = this.normalize(child, this.first, 'prepend').reverse()
235 for (let node of nodes) this.proxyOf.nodes.unshift(node)
236 for (let id in this.indexes) {
237 this.indexes[id] = this.indexes[id] + nodes.length
238 }
239 }
240
241 this.markDirty()
242
243 return this
244 }
245
246 push(child) {
247 child.parent = this
248 this.proxyOf.nodes.push(child)
249 return this
250 }
251
252 removeAll() {
253 for (let node of this.proxyOf.nodes) node.parent = undefined
254 this.proxyOf.nodes = []
255
256 this.markDirty()
257
258 return this
259 }
260
261 removeChild(child) {
262 child = this.index(child)
263 this.proxyOf.nodes[child].parent = undefined
264 this.proxyOf.nodes.splice(child, 1)
265
266 let index
267 for (let id in this.indexes) {
268 index = this.indexes[id]
269 if (index >= child) {
270 this.indexes[id] = index - 1
271 }
272 }
273
274 this.markDirty()
275
276 return this
277 }
278
279 replaceValues(pattern, opts, callback) {
280 if (!callback) {
281 callback = opts
282 opts = {}
283 }
284
285 this.walkDecls(decl => {
286 if (opts.props && !opts.props.includes(decl.prop)) return
287 if (opts.fast && !decl.value.includes(opts.fast)) return
288
289 decl.value = decl.value.replace(pattern, callback)
290 })
291
292 this.markDirty()
293
294 return this
295 }
296
297 some(condition) {
298 return this.nodes.some(condition)
299 }
300
301 walk(callback) {
302 return this.each((child, i) => {
303 let result
304 try {
305 result = callback(child, i)
306 } catch (e) {
307 throw child.addToError(e)
308 }
309 if (result !== false && child.walk) {
310 result = child.walk(callback)
311 }
312
313 return result
314 })
315 }
316
317 walkAtRules(name, callback) {
318 if (!callback) {
319 callback = name
320 return this.walk((child, i) => {
321 if (child.type === 'atrule') {
322 return callback(child, i)
323 }
324 })
325 }
326 if (name instanceof RegExp) {
327 return this.walk((child, i) => {
328 if (child.type === 'atrule' && name.test(child.name)) {
329 return callback(child, i)
330 }
331 })
332 }
333 return this.walk((child, i) => {
334 if (child.type === 'atrule' && child.name === name) {
335 return callback(child, i)
336 }
337 })
338 }
339
340 walkComments(callback) {
341 return this.walk((child, i) => {
342 if (child.type === 'comment') {
343 return callback(child, i)
344 }
345 })
346 }
347
348 walkDecls(prop, callback) {
349 if (!callback) {
350 callback = prop
351 return this.walk((child, i) => {
352 if (child.type === 'decl') {
353 return callback(child, i)
354 }
355 })
356 }
357 if (prop instanceof RegExp) {
358 return this.walk((child, i) => {
359 if (child.type === 'decl' && prop.test(child.prop)) {
360 return callback(child, i)
361 }
362 })
363 }
364 return this.walk((child, i) => {
365 if (child.type === 'decl' && child.prop === prop) {
366 return callback(child, i)
367 }
368 })
369 }
370
371 walkRules(selector, callback) {
372 if (!callback) {
373 callback = selector
374
375 return this.walk((child, i) => {
376 if (child.type === 'rule') {
377 return callback(child, i)
378 }
379 })
380 }
381 if (selector instanceof RegExp) {
382 return this.walk((child, i) => {
383 if (child.type === 'rule' && selector.test(child.selector)) {
384 return callback(child, i)
385 }
386 })
387 }
388 return this.walk((child, i) => {
389 if (child.type === 'rule' && child.selector === selector) {
390 return callback(child, i)
391 }
392 })
393 }
394
395 get first() {
396 if (!this.proxyOf.nodes) return undefined
397 return this.proxyOf.nodes[0]
398 }
399
400 get last() {
401 if (!this.proxyOf.nodes) return undefined
402 return this.proxyOf.nodes[this.proxyOf.nodes.length - 1]
403 }
404}
405
406Container.registerParse = dependant => {
407 parse = dependant
408}
409
410Container.registerRule = dependant => {
411 Rule = dependant
412}
413
414Container.registerAtRule = dependant => {
415 AtRule = dependant
416}
417
418Container.registerRoot = dependant => {
419 Root = dependant
420}
421
422module.exports = Container
423Container.default = Container
424
425/* c8 ignore start */
426Container.rebuild = node => {
427 if (node.type === 'atrule') {
428 Object.setPrototypeOf(node, AtRule.prototype)
429 } else if (node.type === 'rule') {
430 Object.setPrototypeOf(node, Rule.prototype)
431 } else if (node.type === 'decl') {
432 Object.setPrototypeOf(node, Declaration.prototype)
433 } else if (node.type === 'comment') {
434 Object.setPrototypeOf(node, Comment.prototype)
435 } else if (node.type === 'root') {
436 Object.setPrototypeOf(node, Root.prototype)
437 }
438
439 node[my] = true
440
441 if (node.nodes) {
442 node.nodes.forEach(child => {
443 Container.rebuild(child)
444 })
445 }
446}
447/* c8 ignore stop */
Note: See TracBrowser for help on using the repository browser.