UNPKG

1.53 kBJavaScriptView Raw
1'use strict';
2
3const { 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 */
14function 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 */
31module.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};