I would like to create a PostCSS plugin, where I can generate a new rule for all direct descendants.
For example, I would like to generate rule:
div > * {
color: black;
}
For all divs
, which are display: block
.
I didn't find a good example how to do this.
module.exports = () => {
let skipped = Symbol("isSkipped"); // skipped flag
let counter = Symbol("skippedCounter"); // counter for test "isSkipped" optimization
function generateRule(decl) {
let rules = decl.parent;
rules[counter] = Number.isInteger(rules[counter]) ? rules[counter] : 0;
if (!rules[skipped]) {
if (decl.value === "block") {
// generate a new rule here
rules[skipped] = true;
rules[counter]++;
}
}
}
return {
postcssPlugin: "postcss-example-plugin",
Declaration: {
display: (decl) => generateRule(decl),
},
};
};
module.exports.postcss = true;
I'm not 100% certain on what part you're looking for, so if this doesn't answer your question, feel free to clarify and I'll update the response.
Here's some code that I think does what you want - though it's mostly what you've already written without the optimizations:
module.exports = {
postcssPlugin: "add-rule-to-descendants",
Declaration: {
// https://postcss.org/api/#declarationprocessor
display(displayDecl, { Rule, Declaration }) {
if (displayDecl.value === 'block') {
// Add the new rule after the parent https://postcss.org/api/#rule-after
displayDecl.parent.after(
new Rule({
selector: `${displayDecl.parent.selector} > *`,
nodes: [
new Declaration({ prop: 'color', value: 'black' })
]
})
);
}
}
}
}
I've also prepped the example with some quick tests on Repl.it https://repl.it/@dcwither/postcss-all-decendants-rule#plugin.js.