Skip to content

Commit 023b5e9

Browse files
committed
update mcss
1 parent 803c90d commit 023b5e9

12 files changed

+4862
-6104
lines changed

README.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ Different compatibilty plugins can also be more finely enabled/disabled
9696
options: {
9797
compat: {
9898
scoping: false,
99-
valueAliasing: false,
99+
composesDelimiter: false,
100100
icssImports: true,
101101
icssExports: true,
102102
}
@@ -110,7 +110,7 @@ The compatiblity plugins are outlined below:
110110

111111
ref: https://m-css.com/guide/#global
112112

113-
`css-modules` allows `:global` and `:local` scoping to nest, wheras `modular-css` only allows the `:global(.foo)` pseudo for marking a selector
113+
`css-modules` allows `:global` and `:local` scoping to nest, whereas `modular-css` only allows the `:global(.foo)` pseudo for marking a selector
114114
as global.
115115

116116
**When to enable:** If your code contains none-parameterized `:global` or `:local` pseudos like
@@ -122,6 +122,28 @@ as global.
122122

123123
**How to migrate:** Change to the parameterized form `:global(.token) {}`
124124

125+
#### `composesDelimiter`
126+
127+
css-modules uses whitespace to delineate between `composes` classes for multiple classes:
128+
129+
```css
130+
.btn {
131+
composes: appearance-none text-white from global;
132+
}
133+
```
134+
135+
`modular-css` is a bit stricter, requiring a comma (`,`);
136+
137+
```css
138+
.btn {
139+
composes: appearance-none, text-white from global;
140+
}
141+
```
142+
143+
**When to enable:** Migrating code that uses composes with multiple classes
144+
145+
**How to migrate:** use comma seperators
146+
125147
#### `icssExports`
126148

127149
A very niche feature of css-modules that you may not even know is possible.

lib/loader.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const path = require('path');
22
const { promisify } = require('util');
33

44
const Processor = require('@modular-css/processor');
5-
const { getOptions } = require('loader-utils');
65

76
const getLocalName = require('./getLocalName');
87

@@ -14,6 +13,7 @@ const compatPlugins = {
1413
// valueAliasing: require('./plugins/compat-value-aliasing'),
1514
icssImport: require('./plugins/compat-icss-import'),
1615
icssExport: require('./plugins/compat-icss-export'),
16+
composesDelimiter: require('./plugins/compat-composes-delimiter'),
1717
};
1818

1919
function getLoadFilePrefix(loaderContext) {
@@ -31,7 +31,7 @@ function loader(src, prevMap, meta) {
3131
const cb = this.async();
3232
const fs = this._compilation.inputFileSystem;
3333

34-
const options = getOptions(this) || {};
34+
const options = this.options || {};
3535

3636
const prefix = getLoadFilePrefix(this);
3737

lib/plugins/at-composes.js

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const plugin = 'css-modules-loader-compat-composes-delimiter';
2+
3+
/**
4+
* use comma seperators for composes classes
5+
*/
6+
module.exports = (css) => {
7+
css.walkDecls('composes', (decl) => {
8+
const [, classes, rest = ''] = decl.value.match(/(.+?)(from.*)?$/);
9+
10+
// eslint-disable-next-line no-param-reassign
11+
decl.value = `${classes
12+
.split(/,?\s+/)
13+
.filter(Boolean)
14+
.join(', ')} ${rest}`;
15+
});
16+
};
17+
18+
module.exports.postcssPlugin = plugin;
19+
module.exports.phase = 'before';

lib/plugins/compat-icss-import.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const importPattern = /^:import\(("[^"]*"|'[^']*'|[^"']+)\)$/;
99
* Adds support for using the :import icss syntax.
1010
*/
1111
module.exports = (css, { opts }) => {
12-
const { files, resolve, from } = opts;
12+
const { processor, from } = opts;
1313

1414
const replacements = Object.create(null);
1515
// console.log(files);
@@ -20,7 +20,7 @@ module.exports = (css, { opts }) => {
2020
// rm quotes
2121
const path = matches[1].replace(/'|"/g, '');
2222

23-
const source = files[resolve(from, path)];
23+
const source = processor.files[processor.resolve(from, path)];
2424

2525
rule.walkDecls((decl) => {
2626
const localName = decl.prop;

lib/plugins/icss-import-export.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ const plugin = 'css-modules-loader-icss-import/exports';
1111
const DUMMY_LOCAL_NAME = '____a';
1212

1313
module.exports = (css, { opts, messages }) => {
14-
const { files, graph, from } = opts;
14+
const { processor, from } = opts;
1515

16-
const file = files[from];
16+
const file = processor.files[from];
1717

1818
// We only want direct dependencies, since those will be required
1919
// in the css-loader output, the dep tree will be realized
20-
const imported = graph.outgoingEdges[from];
20+
const imported = processor.graph.outgoingEdges[from];
2121
const exported = getExports(file, messages, opts);
2222

2323
imported.forEach((dep) =>

package.json

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -46,44 +46,44 @@
4646
},
4747
"release": {},
4848
"devDependencies": {
49-
"@4c/cli": "^2.1.8",
49+
"@4c/cli": "^3.0.1",
5050
"@4c/import-sort": "^4.3.6",
51-
"@4c/jest-preset": "^1.5.0",
51+
"@4c/jest-preset": "^1.6.2",
5252
"@4c/prettier-config": "^1.1.0",
53-
"css-loader": "^3.5.3",
54-
"eslint": "^6.8.0",
55-
"eslint-config-4catalyzer": "^1.1.1",
56-
"eslint-config-4catalyzer-jest": "^2.0.6",
57-
"eslint-config-prettier": "^6.11.0",
58-
"eslint-plugin-import": "^2.20.2",
59-
"eslint-plugin-jest": "^23.8.2",
60-
"eslint-plugin-prettier": "^3.1.3",
53+
"css-loader": "^6.5.0",
54+
"eslint": "^7.0.0",
55+
"eslint-config-4catalyzer": "^1.3.0",
56+
"eslint-config-4catalyzer-jest": "^2.1.2",
57+
"eslint-config-prettier": "^8.3.0",
58+
"eslint-plugin-import": "^2.25.2",
59+
"eslint-plugin-jest": "^25.2.2",
60+
"eslint-plugin-prettier": "^4.0.0",
6161
"husky": "^4.2.5",
62-
"jest": "^25.5.1",
63-
"jest-file-snapshot": "^0.3.8",
64-
"lint-staged": "^10.2.0",
65-
"memfs": "^3.1.2",
66-
"mini-css-extract-plugin": "^0.9.0",
67-
"prettier": "^2.0.5",
62+
"jest": "^27.3.1",
63+
"jest-file-snapshot": "^0.5.0",
64+
"lint-staged": "^11.2.6",
65+
"memfs": "^3.3.0",
66+
"mini-css-extract-plugin": "^2.4.3",
67+
"prettier": "^2.4.1",
6868
"sass": "^1.26.5",
6969
"strip-ansi": "^6.0.0",
70-
"webpack-atoms": "^13.0.1",
71-
"webpack-cli": "^3.3.11",
72-
"webpack-dev-server": "^3.10.3"
70+
"webpack-atoms": "^17.1.0",
71+
"webpack-cli": "^4.9.1",
72+
"webpack-dev-server": "^4.4.0"
7373
},
7474
"dependencies": {
75-
"@modular-css/processor": "^25.6.0",
75+
"@modular-css/processor": "^26.0.0",
7676
"cssesc": "^3.0.0",
77-
"fs-extra": "^9.0.0",
78-
"icss-utils": "^4.1.1",
79-
"loader-utils": "^2.0.0",
80-
"lodash": "^4.17.15",
77+
"fs-extra": "^10.0.0",
78+
"icss-utils": "^5.1.0",
79+
"loader-utils": "^3.1.0",
80+
"lodash": "^4.17.21",
8181
"memory-fs": "^0.5.0",
82-
"postcss": "^7.0.27",
83-
"postcss-selector-parser": "^6.0.2",
84-
"sass-loader": "^8.0.2",
85-
"semver": "^7.3.2",
86-
"webpack": "^4.43.0"
82+
"postcss": "^8.3.11",
83+
"postcss-selector-parser": "^6.0.6",
84+
"sass-loader": "^12.3.0",
85+
"semver": "^7.3.5",
86+
"webpack": "^5.60.0"
8787
},
8888
"bugs": {
8989
"url": "https://github.com/4Catalyzer/css-module-loader/issues"
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
const path = require('path');
2+
3+
const Processor = require('@modular-css/processor');
4+
5+
const plugin = require('../lib/plugins/compat-composes-delimiter');
6+
7+
describe('compat composes', () => {
8+
const run = async (str) => {
9+
const processor = new Processor({
10+
before: [plugin],
11+
resolvers: [(src, file) => path.resolve(path.dirname(src), file)],
12+
});
13+
14+
await processor.string(
15+
'./utils.css',
16+
`
17+
.foo {
18+
color: blue;
19+
}
20+
21+
.bar {
22+
bar: red;
23+
}
24+
.baz {
25+
baz: red;
26+
}
27+
`,
28+
);
29+
30+
return processor.string('./foo.css', str);
31+
};
32+
33+
it('should handle escapes', async () => {
34+
const results = await run(`
35+
.btn {
36+
composes: hover\\:md\\:bar from global;
37+
38+
color: red;
39+
}
40+
`);
41+
42+
expect(results.exports.btn).toHaveLength(2);
43+
});
44+
45+
test.each([
46+
['foo bar baz'],
47+
['foo bar, baz'],
48+
['foo bar \t baz'],
49+
['foo, bar, baz'],
50+
])('should handle: %s', async (input) => {
51+
const result = await run(`
52+
.btn {
53+
composes: ${input} from "./utils.css";
54+
55+
color: red;
56+
}
57+
`);
58+
59+
expect(result.exports.btn).toHaveLength(4);
60+
});
61+
62+
test.each([
63+
['foo bar baz'],
64+
['foo bar, baz'],
65+
['foo bar \t baz'],
66+
['foo, bar, baz'],
67+
])('should locally handle: %s', async (input) => {
68+
const result = await run(`
69+
.foo {color: blue;}
70+
71+
.bar { bar: red; }
72+
.baz { baz: red; }
73+
74+
.btn {
75+
composes: ${input};
76+
77+
color: red;
78+
}
79+
`);
80+
81+
expect(result.exports.btn).toHaveLength(4);
82+
});
83+
});

test/compat-export.test.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe('compat :export', () => {
1919
}
2020
`);
2121

22-
expect(result.exports).toEqual({
22+
expect(result.details.exported).toEqual({
2323
bar: '1px',
2424
foo: 'red',
2525
});
@@ -35,9 +35,8 @@ describe('compat :export', () => {
3535
}
3636
`);
3737

38-
expect(result.exports).toEqual({
38+
expect(result.details.exported).toEqual({
3939
baz: 'red',
40-
foo: 'red',
4140
});
4241

4342
expect(result.details.result.css.trim()).toEqual('');

test/helpers.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
const path = require('path');
22

33
const fs = require('fs-extra');
4-
const webpack = require('webpack');
54
const { createFsFromVolume, Volume } = require('memfs');
65
const prettier = require('prettier');
6+
const webpack = require('webpack');
77

88
const loader = require('../lib/loader');
99

@@ -68,7 +68,7 @@ function createRunner({
6868
([result]) => innerResolve(JSON.stringify(result)),
6969
innerReject,
7070
);
71-
}).then(r => cb(null, r), cb);
71+
}).then((r) => cb(null, r), cb);
7272
},
7373

7474
resolve(request, cb) {
@@ -91,8 +91,8 @@ function createRunner({
9191

9292
const fixtures = fs
9393
.readdirSync(`${__dirname}/fixtures`)
94-
.map(file => `${__dirname}/fixtures/${file}`)
95-
.filter(f => !f.endsWith('.json'));
94+
.map((file) => `${__dirname}/fixtures/${file}`)
95+
.filter((f) => !f.endsWith('.json'));
9696

9797
function runWebpack(config) {
9898
const compiler = webpack({

test/integration.test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
const path = require('path');
2+
23
const ExtractCSS = require('mini-css-extract-plugin');
4+
35
// const stripAnsi = require('strip-ansi');
46
const { runWebpack } = require('./helpers');
57

6-
const snapshot = name => path.join(__dirname, `__file_snapshots__/${name}`);
8+
const snapshot = (name) => path.join(__dirname, `__file_snapshots__/${name}`);
79

810
describe('webpack integration', () => {
911
function getConfig(entry, options, cssLoaderOptions = {}) {
@@ -95,7 +97,7 @@ describe('webpack integration', () => {
9597

9698
it.each([['camelCase'], ['camelCaseOnly'], ['dashes'], ['dashesOnly']])(
9799
'should work with localsConvention: %s',
98-
async localsConvention => {
100+
async (localsConvention) => {
99101
const assets = await runWebpack(
100102
getConfig(`./fixtures/complex-names.module.scss`, undefined, {
101103
localsConvention,

0 commit comments

Comments
 (0)