1 | ;
|
2 |
|
3 | const { isRoot, isAtRule, isRule } = require('./typeGuards');
|
4 |
|
5 | /** @typedef {import('postcss').Root} Root */
|
6 | /** @typedef {import('postcss').Root} Document */
|
7 | /** @typedef {import('postcss').Node} PostcssNode */
|
8 | /** @typedef {import('postcss').ContainerBase} PostcssContainerNode */
|
9 |
|
10 | /**
|
11 | * @param {PostcssNode} node
|
12 | * @returns {node is PostcssContainerNode}
|
13 | */
|
14 | function isContainerNode(node) {
|
15 | return isRule(node) || isAtRule(node) || isRoot(node);
|
16 | }
|
17 |
|
18 | /**
|
19 | * In order to accommodate nested blocks (postcss-nested),
|
20 | * we need to run a shallow loop (instead of eachDecl() or eachRule(),
|
21 | * which loop recursively) and allow each nested block to accumulate
|
22 | * its own list of properties -- so that a property in a nested rule
|
23 | * does not conflict with the same property in the parent rule
|
24 | * executes a provided function once for each declaration block.
|
25 | *
|
26 | * @param {Root | Document} root - root element of file.
|
27 | * @param {function} cb - Function to execute for each declaration block
|
28 | *
|
29 | * @returns {void}
|
30 | */
|
31 | module.exports = function (root, cb) {
|
32 | /**
|
33 | * @param {PostcssNode} statement
|
34 | *
|
35 | * @returns {void}
|
36 | */
|
37 | function each(statement) {
|
38 | if (!isContainerNode(statement)) return;
|
39 |
|
40 | if (statement.nodes && statement.nodes.length) {
|
41 | /** @type {PostcssNode[]} */
|
42 | const decls = [];
|
43 |
|
44 | statement.nodes.forEach((node) => {
|
45 | if (node.type === 'decl') {
|
46 | decls.push(node);
|
47 | }
|
48 |
|
49 | each(node);
|
50 | });
|
51 |
|
52 | if (decls.length) {
|
53 | cb(decls.forEach.bind(decls));
|
54 | }
|
55 | }
|
56 | }
|
57 |
|
58 | each(root);
|
59 | };
|