Skip to content

Commit 2202572

Browse files
feat(plugins/import): add @import filter support (options.import) (#656)
1 parent d2332f9 commit 2202572

File tree

17 files changed

+164
-74
lines changed

17 files changed

+164
-74
lines changed

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ To disable `url()` resolving by `css-loader` set the option to `false`
103103

104104
#### `{Function}`
105105

106+
106107
**webpack.config.js**
107108
```js
108109
{
@@ -145,6 +146,32 @@ To disable `@import` resolving by `css-loader` set the option to `false`
145146
}
146147
```
147148

149+
#### `{RegExp}`
150+
151+
**webpack.config.js**
152+
```js
153+
{
154+
loader: 'css-loader',
155+
options: {
156+
import: /filter/
157+
}
158+
}
159+
```
160+
161+
#### `{Function}`
162+
163+
**webpack.config.js**
164+
```js
165+
{
166+
loader: 'css-loader',
167+
options: {
168+
import (url) {
169+
return /filter/.test(url)
170+
}
171+
}
172+
}
173+
```
174+
148175
### `minimize`
149176

150177
#### `{Boolean}`

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
"defaults": "webpack-defaults"
3333
},
3434
"dependencies": {
35-
"cssnano": "^4.0.0-rc.2",
3635
"loader-utils": "^1.1.0",
3736
"postcss": "^6.0.15",
3837
"postcss-value-parser": "^3.3.0",

src/index.js

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import postcss from 'postcss';
1313
// replace with postcss-icss-{url, import}
1414
import urls from './plugins/url';
1515
import imports from './plugins/import';
16-
import minifier from 'cssnano';
1716

1817
// import runtime from './runtime';
1918
import SyntaxError from './Error';
@@ -22,20 +21,19 @@ import SyntaxError from './Error';
2221
const DEFAULTS = {
2322
url: true,
2423
import: true,
25-
minimize: false,
2624
sourceMap: false,
2725
};
2826

2927
export default function loader(css, map, meta) {
28+
// Loader Mode (Async)
29+
const cb = this.async();
30+
const file = this.resourcePath;
31+
3032
// Loader Options
3133
const options = Object.assign({}, DEFAULTS, getOptions(this));
3234

3335
validateOptions(schema, options, 'CSS Loader');
3436

35-
// Loader Mode (Async)
36-
const cb = this.async();
37-
const file = this.resourcePath;
38-
3937
if (options.sourceMap) {
4038
if (map && typeof map !== 'string') {
4139
map = JSON.stringify(map);
@@ -53,12 +51,7 @@ export default function loader(css, map, meta) {
5351

5452
// Import Plugin
5553
if (options.import) {
56-
plugins.push(imports());
57-
}
58-
59-
// Minifier
60-
if (options.minimize) {
61-
plugins.push(minifier());
54+
plugins.push(imports(options));
6255
}
6356

6457
if (meta) {
@@ -91,7 +84,7 @@ export default function loader(css, map, meta) {
9184
}
9285

9386
// CSS Imports
94-
const imports = messages
87+
let imports = messages
9588
.filter((msg) => (msg.type === 'import' ? msg : false))
9689
.reduce((imports, msg) => {
9790
try {
@@ -108,7 +101,7 @@ export default function loader(css, map, meta) {
108101
}, '');
109102

110103
// CSS Exports
111-
const exports = messages
104+
let exports = messages
112105
.filter((msg) => (msg.type === 'export' ? msg : false))
113106
.reduce((exports, msg) => {
114107
try {
@@ -124,15 +117,13 @@ export default function loader(css, map, meta) {
124117
return exports;
125118
}, '');
126119

120+
imports = imports ? `// CSS Imports\n${imports}\n` : false;
121+
exports = exports ? `// CSS Exports\n${exports}\n` : false;
122+
css = `// CSS\nexport default \`${css}\``;
123+
127124
// TODO(michael-ciniawsky)
128125
// triage if and add CSS runtime back
129-
const result = [
130-
imports ? `// CSS Imports\n${imports}\n` : false,
131-
exports ? `// CSS Exports\n${exports}\n` : false,
132-
`// CSS\nexport default \`${css}\``,
133-
]
134-
.filter(Boolean)
135-
.join('\n');
126+
const result = [imports, exports, css].filter(Boolean).join('\n');
136127

137128
cb(null, result, map ? map.toJSON() : null);
138129

src/options.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
]
1111
},
1212
"import": {
13-
"type": "boolean"
13+
"anyOf": [
14+
{ "type": "string" },
15+
{ "type": "boolean" },
16+
{ "instanceof": "RegExp" },
17+
{ "instanceof": "Function" }
18+
]
1419
},
1520
"minimize": {
1621
"type": "boolean"

src/plugins/import.js

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/* eslint-disable */
22
import postcss from 'postcss';
33
import valueParser from 'postcss-value-parser';
4-
// ICSS {String}
5-
// import { createICSSRules } from "icss-utils";
4+
5+
const plugin = 'postcss-icss-import';
66

77
const getArg = nodes =>
88
(nodes.length !== 0 && nodes[0].type === 'string'
@@ -38,19 +38,39 @@ const parseImport = (params) => {
3838
};
3939
};
4040

41-
const isExternalUrl = url => /^\w+:\/\//.test(url) || url.startsWith('//');
41+
const URL = /^\w+:\/\//;
42+
43+
const filter = (url, options) => {
44+
if (URL.test(url)) {
45+
return true;
46+
}
47+
48+
if (url.startsWith('//')) {
49+
return true;
50+
}
51+
52+
if (options.import instanceof RegExp) {
53+
return options.import.test(url);
54+
}
55+
56+
if (typeof options.import === 'function') {
57+
return options.import(url);
58+
}
4259

43-
const walkImports = (css, callback) => {
60+
return false;
61+
}
62+
63+
const walkImports = (css, cb) => {
4464
css.each((node) => {
4565
if (node.type === 'atrule' && node.name.toLowerCase() === 'import') {
46-
callback(node);
66+
cb(node);
4767
}
4868
});
4969
};
5070

51-
const plugin = 'postcss-icss-import';
71+
export default postcss.plugin(plugin, (options) => (css, result) => {
72+
let idx = 0;
5273

53-
export default postcss.plugin(plugin, () => (css, result) => {
5474
walkImports(css, (atrule) => {
5575
if (atrule.nodes) {
5676
return result.warn(
@@ -62,15 +82,15 @@ export default postcss.plugin(plugin, () => (css, result) => {
6282
const parsed = parseImport(atrule.params);
6383

6484
if (parsed === null) {
65-
return result.warn(`Unable to find uri in '${atrule.toString()}'`, {
85+
return result.warn(`Unable to find URI in '${atrule.toString()}'`, {
6686
node: atrule,
6787
});
6888
}
6989

7090
let idx = 0;
7191
const url = parsed.url;
7292

73-
if (!isExternalUrl(url)) {
93+
if (!filter(url, options)) {
7494
atrule.remove();
7595

7696
result.messages.push({
@@ -82,4 +102,4 @@ export default postcss.plugin(plugin, () => (css, result) => {
82102
idx++;
83103
}
84104
});
85-
});
105+
});

test/Errors.test.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/* eslint-disable
22
prefer-destructuring,
33
*/
4-
import loader from '../src';
54
import webpack from './helpers/compiler';
65

76
describe('Errors', () => {
@@ -23,8 +22,21 @@ describe('Errors', () => {
2322
expect(err).toThrowErrorMatchingSnapshot();
2423
});
2524

26-
test('Validation Error', () => {
27-
const err = () => loader.call({ query: { sourceMap: 1 } });
25+
test('Validation Error', async () => {
26+
const config = {
27+
loader: {
28+
test: /\.css$/,
29+
options: {
30+
sourceMap: 1,
31+
},
32+
},
33+
};
34+
35+
const stats = await webpack('error.js', config);
36+
const { source } = stats.toJson().modules[1];
37+
38+
// eslint-disable-next-line
39+
const err = () => eval(source);
2840

2941
expect(err).toThrow();
3042
expect(err).toThrowErrorMatchingSnapshot();

test/__snapshots__/Errors.test.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ exports[`Errors Loader Error 1`] = `
1313
`;
1414
1515
exports[`Errors Validation Error 1`] = `
16-
"CSS Loader Invalid Options
16+
"Module build failed: ValidationError: CSS Loader Invalid Options
1717
1818
options.sourceMap should be boolean
1919
"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@import './import.css';
2+
@import './filter/import.css';
3+
4+
.css {
5+
width: 100%;
6+
}
File renamed without changes.

0 commit comments

Comments
 (0)