Skip to content
Permalink
Browse files

feat(processor): allow composes anywhere in a rule (#646)

* feat(processor): allow composes anywhere in a rule

Fixes #645

BREAKING CHANGE: previously `modular-css` would require that `composes` be the first declaration in  a rule. This restriction has been removed due to better solutions for enforcing that behavior existing now (stylelint-order).
  • Loading branch information...
tivac committed Aug 12, 2019
1 parent bc3b711 commit 31b57a269b0fab502426007820430a6e9eae1190
@@ -11,22 +11,6 @@ const parser = require("../parsers/composes.js");

const plugin = "modular-css-composition";

// Loop through all previous nodes in the container to ensure
// that composes (or a comment) comes first
const composesFirst = (decl) => {
let prev = decl.prev();

while(prev) {
if(prev.type !== "comment") {
throw decl.error("composes must be the first declaration", {
word : "composes",
});
}

prev = prev.prev();
}
};

module.exports = (css, result) => {
const { opts } = result;

@@ -47,8 +31,6 @@ module.exports = (css, result) => {
const details = parser.parse(decl.value);
const selectors = decl.parent.selectors.map(identifiers.parse);

composesFirst(decl);

// https://github.com/tivac/modular-css/issues/238
if(selectors.some(({ length }) => length > 1)) {
throw decl.error(
@@ -9,6 +9,16 @@ Object {
}
`;

exports[`/processor.js composition should allow composes anywhere 1`] = `
Object {
"multiple-composes.css": Object {
"a": "a",
"b": "a b",
"c": "a b c",
},
}
`;

exports[`/processor.js composition should compose a single class 1`] = `
Object {
"single-composes.css": Object {
@@ -69,23 +69,6 @@ describe("/processor.js", () => {
}
});

it("should fail if composes isn't the first property", async () => {
try {
await processor.string(
"./invalid/composes-first.css",
dedent(`
.a { color: red; }
.b {
color: blue;
composes: a;
}
`)
);
} catch({ message }) {
expect(message).toMatch(`composes must be the first declaration`);
}
});

it("should fail on rules that use multiple selectors", async () => {
try {
await processor.string(
@@ -130,6 +113,29 @@ describe("/processor.js", () => {

expect(compositions).toMatchSnapshot();
});

it("should allow composes anywhere", async () => {
await processor.string(
"./multiple-composes.css",
dedent(`
.a { color: red; }
.b {
background: blue;
composes: a;
}
.c {
border: 1px solid red;
composes: a;
text-weight: bold;
composes: b;
}
`)
);

const { compositions } = await processor.output();

expect(compositions).toMatchSnapshot();
});

it("should compose from globals", async () => {
await processor.string(
@@ -93,3 +93,7 @@ CSS Modules allows for importing multiple values from an external file.
### Support

CSS Modules is really only fully-supported as part of webpack these days. The repo is effectively mothballed, and there appears to be almost no one supporting the current codebase. Since webpack is the only live version & we prefer to use rollup for it's cleaner output and smaller bundles we needed an approach that could be flexibly be used with a [variety](#rollup) [of](#browserify) [tools](#cli).

### `composes` location

After a long time with `composes` being required to be the first declaration in a rule the ability to use a tool like [`stylelint-order`](https://github.com/hudochenkov/stylelint-order) has reduced the need for `modular-css` to enforce positional requirements. After a push in [#645](https://github.com/tivac/modular-css/issues/645) the requirement was removed in [#646](https://github.com/tivac/modular-css/pull/646), which was published in v25. This is a change from CSS Modules, which continues to require that `composes` be the first declaration in a rule.

0 comments on commit 31b57a2

Please sign in to comment.
You can’t perform that action at this time.