Spaces:
Sleeping
Sleeping
| import postcss from 'postcss' | |
| import postcssNested from 'postcss-nested' | |
| export function nesting(opts = postcssNested) { | |
| return (root, result) => { | |
| root.walkAtRules('screen', (rule) => { | |
| rule.name = 'media' | |
| rule.params = `screen(${rule.params})` | |
| }) | |
| root.walkAtRules('apply', (rule) => { | |
| rule.before(postcss.decl({ prop: '__apply', value: rule.params, source: rule.source })) | |
| rule.remove() | |
| }) | |
| let plugin = (() => { | |
| if ( | |
| typeof opts === 'function' || | |
| (typeof opts === 'object' && opts?.hasOwnProperty?.('postcssPlugin')) | |
| ) { | |
| return opts | |
| } | |
| if (typeof opts === 'string') { | |
| return require(opts) | |
| } | |
| if (Object.keys(opts).length <= 0) { | |
| return postcssNested | |
| } | |
| throw new Error('tailwindcss/nesting should be loaded with a nesting plugin.') | |
| })() | |
| postcss([plugin]).process(root, result.opts).sync() | |
| root.walkDecls('__apply', (decl) => { | |
| decl.before(postcss.atRule({ name: 'apply', params: decl.value, source: decl.source })) | |
| decl.remove() | |
| }) | |
| /** | |
| * Use a private PostCSS API to remove the "clean" flag from the entire AST. | |
| * This is done because running process() on the AST will set the "clean" | |
| * flag on all nodes, which we don't want. | |
| * | |
| * This causes downstream plugins using the visitor API to be skipped. | |
| * | |
| * This is guarded because the PostCSS API is not public | |
| * and may change in future versions of PostCSS. | |
| * | |
| * See https://github.com/postcss/postcss/issues/1712 for more details | |
| * | |
| * @param {import('postcss').Node} node | |
| */ | |
| function markDirty(node) { | |
| if (!('markDirty' in node)) { | |
| return | |
| } | |
| // Traverse the tree down to the leaf nodes | |
| if (node.nodes) { | |
| node.nodes.forEach((n) => markDirty(n)) | |
| } | |
| // If it's a leaf node mark it as dirty | |
| // We do this here because marking a node as dirty | |
| // will walk up the tree and mark all parents as dirty | |
| // resulting in a lot of unnecessary work if we did this | |
| // for every single node | |
| if (!node.nodes) { | |
| node.markDirty() | |
| } | |
| } | |
| markDirty(root) | |
| return root | |
| } | |
| } | |