diff --git a/README.md b/README.md index ff56fd5..7143654 100644 --- a/README.md +++ b/README.md @@ -73,17 +73,32 @@ If you do not use PostCSS, add it according to [official docs] and set this plug module.exports = { plugins: [ require('autoprefixer'), -+ require('postcss-assign-layer')({ -+ include: '**/*.module.css', -+ layerName: 'components', -+ }), ++ require('postcss-assign-layer')(/* Optional configuration */), ], } ``` ### **Step 4:** Configure the plugin -It's possible to configure the include glob, as well as the layer name. +It's possible to configure the include glob and the layer name, and more than one set of rules can be provided. + +```diff +module.exports = { + plugins: [ + require('autoprefixer'), ++ require('postcss-assign-layer')([ ++ { ++ include: '**/*.module.css', ++ layerName: 'components', ++ }, ++ { ++ include: 'global/*.css', ++ layerName: 'base', ++ }, ++ ]), + ], +} +``` #### `include` diff --git a/index.js b/index.js index 248d774..b880f7d 100644 --- a/index.js +++ b/index.js @@ -1,27 +1,47 @@ const { createFilter } = require("@rollup/pluginutils"); +const DEFAULT_INCLUDE = "**/*.module.css"; +const DEFAULT_LAYERNAME = "components"; + /** * @type {import('postcss').PluginCreator} */ -module.exports = ({ - include = "**/*.module.css", - layerName = "components", -} = {}) => { - const filter = createFilter(include); +module.exports = ( + configItems = [ + { + include: DEFAULT_INCLUDE, + layerName: DEFAULT_LAYERNAME, + }, + ] +) => { + const filters = []; + + for (const config of configItems) { + const filter = createFilter(config.include ?? DEFAULT_INCLUDE); + filters.push({ filter, layerName: config.layerName ?? DEFAULT_LAYERNAME }); + } return { postcssPlugin: "postcss-assign-layers", async Once(root, { AtRule }) { const inputFile = root.source.input.file; - if (!filter(inputFile)) return; + const layerNames = []; + + for (const { filter, layerName } of filters) { + if (filter(inputFile)) { + layerNames.push(layerName); + } + } - const layer = new AtRule({ - name: "layer", - params: layerName, - nodes: root.nodes, - }); - root.removeAll(); - root.append(layer); + for (const layerName of layerNames) { + const layer = new AtRule({ + name: "layer", + params: layerName, + nodes: root.nodes, + }); + root.removeAll(); + root.append(layer); + } }, }; }; diff --git a/index.test.mjs b/index.test.mjs index ca6a3d3..679915b 100644 --- a/index.test.mjs +++ b/index.test.mjs @@ -53,7 +53,7 @@ describe("postcss-assign-layer", () => { color: WhiteSmoke; } }`, - { layerName: "custom" }, + [{ layerName: "custom" }], { from: filePath, } @@ -85,9 +85,11 @@ describe("postcss-assign-layer", () => { color: FireBrick; } }`, - { - include: "**/base.css", - }, + [ + { + include: "**/base.css", + }, + ], { from: filePath, } @@ -106,11 +108,82 @@ describe("postcss-assign-layer", () => { i { color: WhiteSmoke; }`, + [ + { + include: "**/base.css", + }, + ], + { + from: filePath, + } + ); + }); + + it("allows specifying layer name and pattern", async () => { + const filePath = path.resolve("test/fixtures/base.css"); + const file = readFileSync(filePath, "utf-8"); + await run( + file, + `@layer styles { + a { + color: FireBrick; + } + }`, + [ + { + include: "**/base.css", + layerName: "styles", + }, + ], + { + from: filePath, + } + ); + }); + + it("allows multiple patterns and layers", async () => { + const basePath = path.resolve("test/fixtures/base.css"); + const componentPath = path.resolve("test/fixtures/component.module.css"); + const baseFile = readFileSync(basePath, "utf-8"); + const componentFile = readFileSync(componentPath, "utf-8"); + const config = [ { include: "**/base.css", + layerName: "styles", }, { - from: filePath, + // include: "**/*.module.css", <- the default is still used for unspecified properties + layerName: "components", + }, + ]; + + await run( + baseFile, + `@layer styles { + a { + color: FireBrick; + } + }`, + config, + { + from: basePath, + } + ); + + await run( + componentFile, + `@layer components { + a { + color: BurlyWood; + } + + i { + color: WhiteSmoke; + } + }`, + config, + { + from: componentPath, } ); });