UNPKG

13.5 kBTypeScriptView Raw
1import AtRule from './at-rule.js'
2import Comment from './comment.js'
3import Declaration from './declaration.js'
4import Node, { ChildNode, ChildProps, NodeProps } from './node.js'
5import Rule from './rule.js'
6
7declare namespace Container {
8 export class ContainerWithChildren<
9 Child extends Node = ChildNode
10 > extends Container_<Child> {
11 nodes: Child[]
12 }
13
14 export interface ValueOptions {
15 /**
16 * String that’s used to narrow down values and speed up the regexp search.
17 */
18 fast?: string
19
20 /**
21 * An array of property names.
22 */
23 props?: string[]
24 }
25
26 export interface ContainerProps extends NodeProps {
27 nodes?: (ChildNode | ChildProps)[]
28 }
29
30 // eslint-disable-next-line @typescript-eslint/no-use-before-define
31 export { Container_ as default }
32}
33
34/**
35 * The `Root`, `AtRule`, and `Rule` container nodes
36 * inherit some common methods to help work with their children.
37 *
38 * Note that all containers can store any content. If you write a rule inside
39 * a rule, PostCSS will parse it.
40 */
41declare abstract class Container_<Child extends Node = ChildNode> extends Node {
42 /**
43 * An array containing the container’s children.
44 *
45 * ```js
46 * const root = postcss.parse('a { color: black }')
47 * root.nodes.length //=> 1
48 * root.nodes[0].selector //=> 'a'
49 * root.nodes[0].nodes[0].prop //=> 'color'
50 * ```
51 */
52 nodes: Child[] | undefined
53
54 /**
55 * Inserts new nodes to the end of the container.
56 *
57 * ```js
58 * const decl1 = new Declaration({ prop: 'color', value: 'black' })
59 * const decl2 = new Declaration({ prop: 'background-color', value: 'white' })
60 * rule.append(decl1, decl2)
61 *
62 * root.append({ name: 'charset', params: '"UTF-8"' }) // at-rule
63 * root.append({ selector: 'a' }) // rule
64 * rule.append({ prop: 'color', value: 'black' }) // declaration
65 * rule.append({ text: 'Comment' }) // comment
66 *
67 * root.append('a {}')
68 * root.first.append('color: black; z-index: 1')
69 * ```
70 *
71 * @param nodes New nodes.
72 * @return This node for methods chain.
73 */
74 append(
75 ...nodes: (
76 | ChildProps
77 | ChildProps[]
78 | Node
79 | Node[]
80 | string
81 | string[]
82 | undefined
83 )[]
84 ): this
85
86 assign(overrides: Container.ContainerProps | object): this
87 clone(overrides?: Partial<Container.ContainerProps>): Container<Child>
88 cloneAfter(overrides?: Partial<Container.ContainerProps>): Container<Child>
89 cloneBefore(overrides?: Partial<Container.ContainerProps>): Container<Child>
90
91 /**
92 * Iterates through the container’s immediate children,
93 * calling `callback` for each child.
94 *
95 * Returning `false` in the callback will break iteration.
96 *
97 * This method only iterates through the container’s immediate children.
98 * If you need to recursively iterate through all the container’s descendant
99 * nodes, use `Container#walk`.
100 *
101 * Unlike the for `{}`-cycle or `Array#forEach` this iterator is safe
102 * if you are mutating the array of child nodes during iteration.
103 * PostCSS will adjust the current index to match the mutations.
104 *
105 * ```js
106 * const root = postcss.parse('a { color: black; z-index: 1 }')
107 * const rule = root.first
108 *
109 * for (const decl of rule.nodes) {
110 * decl.cloneBefore({ prop: '-webkit-' + decl.prop })
111 * // Cycle will be infinite, because cloneBefore moves the current node
112 * // to the next index
113 * }
114 *
115 * rule.each(decl => {
116 * decl.cloneBefore({ prop: '-webkit-' + decl.prop })
117 * // Will be executed only for color and z-index
118 * })
119 * ```
120 *
121 * @param callback Iterator receives each node and index.
122 * @return Returns `false` if iteration was broke.
123 */
124 each(
125 callback: (node: Child, index: number) => false | void
126 ): false | undefined
127
128 /**
129 * Returns `true` if callback returns `true`
130 * for all of the container’s children.
131 *
132 * ```js
133 * const noPrefixes = rule.every(i => i.prop[0] !== '-')
134 * ```
135 *
136 * @param condition Iterator returns true or false.
137 * @return Is every child pass condition.
138 */
139 every(
140 condition: (node: Child, index: number, nodes: Child[]) => boolean
141 ): boolean
142 /**
143 * Returns a `child`’s index within the `Container#nodes` array.
144 *
145 * ```js
146 * rule.index( rule.nodes[2] ) //=> 2
147 * ```
148 *
149 * @param child Child of the current container.
150 * @return Child index.
151 */
152 index(child: Child | number): number
153
154 /**
155 * Insert new node after old node within the container.
156 *
157 * @param oldNode Child or child’s index.
158 * @param newNode New node.
159 * @return This node for methods chain.
160 */
161 insertAfter(
162 oldNode: Child | number,
163 newNode:
164 | Child
165 | Child[]
166 | ChildProps
167 | ChildProps[]
168 | string
169 | string[]
170 | undefined
171 ): this
172 /**
173 * Insert new node before old node within the container.
174 *
175 * ```js
176 * rule.insertBefore(decl, decl.clone({ prop: '-webkit-' + decl.prop }))
177 * ```
178 *
179 * @param oldNode Child or child’s index.
180 * @param newNode New node.
181 * @return This node for methods chain.
182 */
183 insertBefore(
184 oldNode: Child | number,
185 newNode:
186 | Child
187 | Child[]
188 | ChildProps
189 | ChildProps[]
190 | string
191 | string[]
192 | undefined
193 ): this
194
195 /**
196 * Traverses the container’s descendant nodes, calling callback
197 * for each comment node.
198 *
199 * Like `Container#each`, this method is safe
200 * to use if you are mutating arrays during iteration.
201 *
202 * ```js
203 * root.walkComments(comment => {
204 * comment.remove()
205 * })
206 * ```
207 *
208 * @param callback Iterator receives each node and index.
209 * @return Returns `false` if iteration was broke.
210 */
211
212 /**
213 * Inserts new nodes to the start of the container.
214 *
215 * ```js
216 * const decl1 = new Declaration({ prop: 'color', value: 'black' })
217 * const decl2 = new Declaration({ prop: 'background-color', value: 'white' })
218 * rule.prepend(decl1, decl2)
219 *
220 * root.append({ name: 'charset', params: '"UTF-8"' }) // at-rule
221 * root.append({ selector: 'a' }) // rule
222 * rule.append({ prop: 'color', value: 'black' }) // declaration
223 * rule.append({ text: 'Comment' }) // comment
224 *
225 * root.append('a {}')
226 * root.first.append('color: black; z-index: 1')
227 * ```
228 *
229 * @param nodes New nodes.
230 * @return This node for methods chain.
231 */
232 prepend(
233 ...nodes: (
234 | ChildProps
235 | ChildProps[]
236 | Node
237 | Node[]
238 | string
239 | string[]
240 | undefined
241 )[]
242 ): this
243 /**
244 * Add child to the end of the node.
245 *
246 * ```js
247 * rule.push(new Declaration({ prop: 'color', value: 'black' }))
248 * ```
249 *
250 * @param child New node.
251 * @return This node for methods chain.
252 */
253 push(child: Child): this
254
255 /**
256 * Removes all children from the container
257 * and cleans their parent properties.
258 *
259 * ```js
260 * rule.removeAll()
261 * rule.nodes.length //=> 0
262 * ```
263 *
264 * @return This node for methods chain.
265 */
266 removeAll(): this
267
268 /**
269 * Removes node from the container and cleans the parent properties
270 * from the node and its children.
271 *
272 * ```js
273 * rule.nodes.length //=> 5
274 * rule.removeChild(decl)
275 * rule.nodes.length //=> 4
276 * decl.parent //=> undefined
277 * ```
278 *
279 * @param child Child or child’s index.
280 * @return This node for methods chain.
281 */
282 removeChild(child: Child | number): this
283
284 replaceValues(
285 pattern: RegExp | string,
286 replaced: { (substring: string, ...args: any[]): string } | string
287 ): this
288
289 /**
290 * Passes all declaration values within the container that match pattern
291 * through callback, replacing those values with the returned result
292 * of callback.
293 *
294 * This method is useful if you are using a custom unit or function
295 * and need to iterate through all values.
296 *
297 * ```js
298 * root.replaceValues(/\d+rem/, { fast: 'rem' }, string => {
299 * return 15 * parseInt(string) + 'px'
300 * })
301 * ```
302 *
303 * @param pattern Replace pattern.
304 * @param {object} opts Options to speed up the search.
305 * @param callback String to replace pattern or callback
306 * that returns a new value. The callback
307 * will receive the same arguments
308 * as those passed to a function parameter
309 * of `String#replace`.
310 * @return This node for methods chain.
311 */
312 replaceValues(
313 pattern: RegExp | string,
314 options: Container.ValueOptions,
315 replaced: { (substring: string, ...args: any[]): string } | string
316 ): this
317
318 /**
319 * Returns `true` if callback returns `true` for (at least) one
320 * of the container’s children.
321 *
322 * ```js
323 * const hasPrefix = rule.some(i => i.prop[0] === '-')
324 * ```
325 *
326 * @param condition Iterator returns true or false.
327 * @return Is some child pass condition.
328 */
329 some(
330 condition: (node: Child, index: number, nodes: Child[]) => boolean
331 ): boolean
332
333 /**
334 * Traverses the container’s descendant nodes, calling callback
335 * for each node.
336 *
337 * Like container.each(), this method is safe to use
338 * if you are mutating arrays during iteration.
339 *
340 * If you only need to iterate through the container’s immediate children,
341 * use `Container#each`.
342 *
343 * ```js
344 * root.walk(node => {
345 * // Traverses all descendant nodes.
346 * })
347 * ```
348 *
349 * @param callback Iterator receives each node and index.
350 * @return Returns `false` if iteration was broke.
351 */
352 walk(
353 callback: (node: ChildNode, index: number) => false | void
354 ): false | undefined
355
356 /**
357 * Traverses the container’s descendant nodes, calling callback
358 * for each at-rule node.
359 *
360 * If you pass a filter, iteration will only happen over at-rules
361 * that have matching names.
362 *
363 * Like `Container#each`, this method is safe
364 * to use if you are mutating arrays during iteration.
365 *
366 * ```js
367 * root.walkAtRules(rule => {
368 * if (isOld(rule.name)) rule.remove()
369 * })
370 *
371 * let first = false
372 * root.walkAtRules('charset', rule => {
373 * if (!first) {
374 * first = true
375 * } else {
376 * rule.remove()
377 * }
378 * })
379 * ```
380 *
381 * @param name String or regular expression to filter at-rules by name.
382 * @param callback Iterator receives each node and index.
383 * @return Returns `false` if iteration was broke.
384 */
385 walkAtRules(
386 nameFilter: RegExp | string,
387 callback: (atRule: AtRule, index: number) => false | void
388 ): false | undefined
389
390 walkAtRules(
391 callback: (atRule: AtRule, index: number) => false | void
392 ): false | undefined
393 walkComments(
394 callback: (comment: Comment, indexed: number) => false | void
395 ): false | undefined
396
397 walkComments(
398 callback: (comment: Comment, indexed: number) => false | void
399 ): false | undefined
400
401 /**
402 * Traverses the container’s descendant nodes, calling callback
403 * for each declaration node.
404 *
405 * If you pass a filter, iteration will only happen over declarations
406 * with matching properties.
407 *
408 * ```js
409 * root.walkDecls(decl => {
410 * checkPropertySupport(decl.prop)
411 * })
412 *
413 * root.walkDecls('border-radius', decl => {
414 * decl.remove()
415 * })
416 *
417 * root.walkDecls(/^background/, decl => {
418 * decl.value = takeFirstColorFromGradient(decl.value)
419 * })
420 * ```
421 *
422 * Like `Container#each`, this method is safe
423 * to use if you are mutating arrays during iteration.
424 *
425 * @param prop String or regular expression to filter declarations
426 * by property name.
427 * @param callback Iterator receives each node and index.
428 * @return Returns `false` if iteration was broke.
429 */
430 walkDecls(
431 propFilter: RegExp | string,
432 callback: (decl: Declaration, index: number) => false | void
433 ): false | undefined
434
435 walkDecls(
436 callback: (decl: Declaration, index: number) => false | void
437 ): false | undefined
438
439 /**
440 * Traverses the container’s descendant nodes, calling callback
441 * for each rule node.
442 *
443 * If you pass a filter, iteration will only happen over rules
444 * with matching selectors.
445 *
446 * Like `Container#each`, this method is safe
447 * to use if you are mutating arrays during iteration.
448 *
449 * ```js
450 * const selectors = []
451 * root.walkRules(rule => {
452 * selectors.push(rule.selector)
453 * })
454 * console.log(`Your CSS uses ${ selectors.length } selectors`)
455 * ```
456 *
457 * @param selector String or regular expression to filter rules by selector.
458 * @param callback Iterator receives each node and index.
459 * @return Returns `false` if iteration was broke.
460 */
461 walkRules(
462 selectorFilter: RegExp | string,
463 callback: (rule: Rule, index: number) => false | void
464 ): false | undefined
465 walkRules(
466 callback: (rule: Rule, index: number) => false | void
467 ): false | undefined
468 /**
469 * The container’s first child.
470 *
471 * ```js
472 * rule.first === rules.nodes[0]
473 * ```
474 */
475 get first(): Child | undefined
476 /**
477 * The container’s last child.
478 *
479 * ```js
480 * rule.last === rule.nodes[rule.nodes.length - 1]
481 * ```
482 */
483 get last(): Child | undefined
484}
485
486declare class Container<
487 Child extends Node = ChildNode
488> extends Container_<Child> {}
489
490export = Container