Skip to content

Commit d0ea725

Browse files
refactor: config loading
BREAKING CHANGE: the `config` option can be `boolean` or `string`, context is frozen
1 parent 108d871 commit d0ea725

36 files changed

+1111
-1361
lines changed

README.md

+285-219
Large diffs are not rendered by default.

src/index.js

+2-30
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import path from 'path';
2-
31
import { getOptions } from 'loader-utils';
42
import validateOptions from 'schema-utils';
53

@@ -38,6 +36,7 @@ export default async function loader(content, sourceMap) {
3836
});
3937

4038
const callback = this.async();
39+
4140
const configOption =
4241
typeof options.postcssOptions === 'undefined' ||
4342
typeof options.postcssOptions.config === 'undefined'
@@ -46,35 +45,8 @@ export default async function loader(content, sourceMap) {
4645
let loadedConfig = {};
4746

4847
if (configOption) {
49-
const dataForLoadConfig = {
50-
path: path.dirname(this.resourcePath),
51-
ctx: {
52-
file: {
53-
extname: path.extname(this.resourcePath),
54-
dirname: path.dirname(this.resourcePath),
55-
basename: path.basename(this.resourcePath),
56-
},
57-
options: {},
58-
},
59-
};
60-
61-
if (typeof configOption.path !== 'undefined') {
62-
dataForLoadConfig.path = path.resolve(configOption.path);
63-
}
64-
65-
if (typeof configOption.ctx !== 'undefined') {
66-
dataForLoadConfig.ctx.options = configOption.ctx;
67-
}
68-
69-
dataForLoadConfig.ctx.webpack = this;
70-
7148
try {
72-
loadedConfig = await loadConfig(
73-
configOption,
74-
dataForLoadConfig.ctx,
75-
dataForLoadConfig.path,
76-
this
77-
);
49+
loadedConfig = await loadConfig(this, configOption);
7850
} catch (error) {
7951
callback(error);
8052

src/options.json

-14
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,6 @@
1111
"config": {
1212
"description": "Allows to specify PostCSS Config Path (https://github.com/postcss/postcss-loader#config)",
1313
"anyOf": [
14-
{
15-
"type": "object",
16-
"properties": {
17-
"path": {
18-
"description": "Allows to specify PostCSS Config Path (https://github.com/postcss/postcss-loader#path)",
19-
"type": "string"
20-
},
21-
"ctx": {
22-
"description": "Allows to specify PostCSS Config Context (https://github.com/postcss/postcss-loader#context-ctx)",
23-
"type": "object"
24-
}
25-
},
26-
"additionalProperties": false
27-
},
2814
{
2915
"description": "Allows to specify the path to the configuration file",
3016
"type": "string"

src/utils.js

+17-25
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,6 @@ const stat = (inputFileSystem, filePath) =>
1515
});
1616
});
1717

18-
const createContext = (context) => {
19-
const result = {
20-
cwd: process.cwd(),
21-
env: process.env.NODE_ENV,
22-
...context,
23-
};
24-
25-
if (!result.env) {
26-
process.env.NODE_ENV = 'development';
27-
}
28-
29-
return result;
30-
};
31-
3218
function exec(code, loaderContext) {
3319
const { resource, context } = loaderContext;
3420

@@ -44,12 +30,11 @@ function exec(code, loaderContext) {
4430
return module.exports;
4531
}
4632

47-
async function loadConfig(config, context, configPath, loaderContext) {
48-
let searchPath = configPath ? path.resolve(configPath) : process.cwd();
49-
50-
if (typeof config === 'string') {
51-
searchPath = path.resolve(config);
52-
}
33+
async function loadConfig(loaderContext, config) {
34+
const searchPath =
35+
typeof config === 'string'
36+
? path.resolve(config)
37+
: path.dirname(loaderContext.resourcePath);
5338

5439
let stats;
5540

@@ -77,17 +62,23 @@ async function loadConfig(config, context, configPath, loaderContext) {
7762
return {};
7863
}
7964

80-
const patchedContext = createContext(context);
81-
8265
let resultConfig = result.config || {};
8366

8467
if (typeof resultConfig === 'function') {
85-
resultConfig = resultConfig(patchedContext);
68+
const api = {
69+
env: process.env.NODE_ENV,
70+
mode: loaderContext.mode,
71+
file: loaderContext.resourcePath,
72+
// For complex use
73+
webpackLoaderContext: loaderContext,
74+
};
75+
76+
resultConfig = resultConfig(api);
8677
}
8778

8879
resultConfig.file = result.filepath;
8980

90-
loaderContext.addDependency(result.filepath);
81+
loaderContext.addDependency(resultConfig.file);
9182

9283
return resultConfig;
9384
}
@@ -126,7 +117,8 @@ function pluginFactory() {
126117
} else if (
127118
plugin &&
128119
Object.keys(plugin).length === 1 &&
129-
typeof plugin[Object.keys(plugin)[0]] === 'object' &&
120+
(typeof plugin[Object.keys(plugin)[0]] === 'object' ||
121+
typeof plugin[Object.keys(plugin)[0]] === 'boolean') &&
130122
plugin[Object.keys(plugin)[0]] !== null
131123
) {
132124
const [name] = Object.keys(plugin);
+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`"config" option should throw an error on the invalid config: errors 1`] = `
4+
Array [
5+
"ModuleBuildError: Module build failed (from \`replaced original path\`):
6+
Error: invalid postcss config",
7+
]
8+
`;
9+
10+
exports[`"config" option should throw an error on the invalid config: warnings 1`] = `Array []`;
11+
12+
exports[`"config" option should throw an error on the unresolved config: errors 1`] = `
13+
Array [
14+
"ModuleBuildError: Module build failed (from \`replaced original path\`):
15+
Error: No PostCSS Config found in: /test/fixtures/config-scope/css/unresolve.js",
16+
]
17+
`;
18+
19+
exports[`"config" option should throw an error on the unresolved config: warnings 1`] = `Array []`;
20+
21+
exports[`"config" option should work "String" value (relative path): css 1`] = `
22+
"a { color: rgba(0, 0, 0, 1.0) }
23+
24+
.foo {
25+
float: right;
26+
}
27+
"
28+
`;
29+
30+
exports[`"config" option should work "String" value (relative path): errors 1`] = `Array []`;
31+
32+
exports[`"config" option should work "String" value (relative path): warnings 1`] = `Array []`;
33+
34+
exports[`"config" option should work with "String" value (absolute path): css 1`] = `
35+
"a { color: rgba(0, 0, 0, 1.0) }
36+
37+
.foo {
38+
float: right;
39+
}
40+
"
41+
`;
42+
43+
exports[`"config" option should work with "String" value (absolute path): errors 1`] = `Array []`;
44+
45+
exports[`"config" option should work with "String" value (absolute path): warnings 1`] = `Array []`;
46+
47+
exports[`"config" option should work with "String" value (with path to the directory with the configuration): css 1`] = `
48+
"a { color: rgba(0, 0, 0, 1.0) }
49+
50+
.foo {
51+
float: right;
52+
}
53+
"
54+
`;
55+
56+
exports[`"config" option should work with "String" value (with path to the directory with the configuration): errors 1`] = `Array []`;
57+
58+
exports[`"config" option should work with "String" value (with path to the directory with the configuration): warnings 1`] = `Array []`;
59+
60+
exports[`"config" option should work with "String" value and respect all options: css 1`] = `
61+
"a {
62+
color: black
63+
}
64+
65+
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0eWxlLnNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFO0FBREYiLCJmaWxlIjoic3R5bGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiYVxuICBjb2xvcjogYmxhY2tcbiJdfQ== */"
66+
`;
67+
68+
exports[`"config" option should work with "String" value and respect all options: errors 1`] = `Array []`;
69+
70+
exports[`"config" option should work with "String" value and respect all options: warnings 1`] = `Array []`;
71+
72+
exports[`"config" option should work with "false" value: css 1`] = `
73+
"a { color: black }
74+
75+
.foo {
76+
float: right;
77+
}
78+
"
79+
`;
80+
81+
exports[`"config" option should work with "false" value: errors 1`] = `Array []`;
82+
83+
exports[`"config" option should work with "false" value: warnings 1`] = `Array []`;
84+
85+
exports[`"config" option should work with "package.json" configuration: css 1`] = `
86+
".import {
87+
color: red;
88+
}
89+
90+
.test {
91+
color: blue;
92+
}
93+
"
94+
`;
95+
96+
exports[`"config" option should work with "package.json" configuration: errors 1`] = `Array []`;
97+
98+
exports[`"config" option should work with "package.json" configuration: warnings 1`] = `Array []`;
99+
100+
exports[`"config" option should work with "true" value: css 1`] = `
101+
"a { color: rgba(0, 0, 0, 1.0) }
102+
103+
.foo {
104+
float: right;
105+
}
106+
"
107+
`;
108+
109+
exports[`"config" option should work with "true" value: errors 1`] = `Array []`;
110+
111+
exports[`"config" option should work with "true" value: warnings 1`] = `Array []`;
112+
113+
exports[`"config" option should work with the "postcssOptions" option: css 1`] = `
114+
"a { color: rgba(0, 0, 0, 1.0) }
115+
116+
[dir=ltr] .foo { float: right;
117+
}
118+
119+
[dir=rtl] .foo {
120+
float: left;
121+
}
122+
"
123+
`;
124+
125+
exports[`"config" option should work with the "postcssOptions" option: errors 1`] = `Array []`;
126+
127+
exports[`"config" option should work with the "postcssOptions" option: warnings 1`] = `Array []`;
128+
129+
exports[`"config" option should work without the specified value in the "postcssOptions" option: css 1`] = `
130+
"a { color: rgba(0, 0, 0, 1.0) }
131+
132+
.foo {
133+
float: right;
134+
}
135+
"
136+
`;
137+
138+
exports[`"config" option should work without the specified value in the "postcssOptions" option: errors 1`] = `Array []`;
139+
140+
exports[`"config" option should work without the specified value in the "postcssOptions" option: warnings 1`] = `Array []`;
141+
142+
exports[`"config" option should work without the specified value: css 1`] = `
143+
"a { color: rgba(0, 0, 0, 1.0) }
144+
145+
.foo {
146+
float: right;
147+
}
148+
"
149+
`;
150+
151+
exports[`"config" option should work without the specified value: errors 1`] = `Array []`;
152+
153+
exports[`"config" option should work without the specified value: warnings 1`] = `Array []`;

test/__snapshots__/exec.test.js.snap

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`"exec" option should work with "Boolean" value: css 1`] = `
4+
"a {
5+
color: green
6+
}"
7+
`;
8+
9+
exports[`"exec" option should work with "Boolean" value: errors 1`] = `Array []`;
10+
11+
exports[`"exec" option should work with "Boolean" value: warnings 1`] = `Array []`;
12+
13+
exports[`"exec" option should work with "JSS" parser: css 1`] = `
14+
"a {
15+
color: yellow
16+
}"
17+
`;
18+
19+
exports[`"exec" option should work with "JSS" parser: errors 1`] = `Array []`;
20+
21+
exports[`"exec" option should work with "JSS" parser: warnings 1`] = `Array []`;

test/__snapshots__/loader.test.js.snap

+22-22
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,10 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`loader should emit Syntax Error: errors 1`] = `
4-
Array [
5-
"ModuleBuildError: Module build failed (from \`replaced original path\`):
6-
SyntaxError
7-
8-
(1:3) Unnecessary curly bracket
9-
10-
> 1 | a {
11-
| ^
12-
2 | color: black;
13-
3 | }
14-
",
15-
]
16-
`;
17-
18-
exports[`loader should emit Syntax Error: warnings 1`] = `Array []`;
19-
20-
exports[`loader should emit asset: errors 1`] = `Array []`;
3+
exports[`loader should emit asset using the "messages" API: errors 1`] = `Array []`;
214

22-
exports[`loader should emit asset: warnings 1`] = `Array []`;
5+
exports[`loader should emit asset using the "messages" API: warnings 1`] = `Array []`;
236

24-
exports[`loader should emit warning: css 1`] = `
7+
exports[`loader should emit warning using the "messages" API: css 1`] = `
258
"a {
269
color: black;
2710
}
@@ -68,9 +51,9 @@ a {
6851
"
6952
`;
7053

71-
exports[`loader should emit warning: errors 1`] = `Array []`;
54+
exports[`loader should emit warning using the "messages" API: errors 1`] = `Array []`;
7255

73-
exports[`loader should emit warning: warnings 1`] = `
56+
exports[`loader should emit warning using the "messages" API: warnings 1`] = `
7457
Array [
7558
"ModuleWarning: Module Warning (from \`replaced original path\`):
7659
Warning
@@ -123,6 +106,23 @@ Warning
123106
]
124107
`;
125108
109+
exports[`loader should throw an error on invalid syntax: errors 1`] = `
110+
Array [
111+
"ModuleBuildError: Module build failed (from \`replaced original path\`):
112+
SyntaxError
113+
114+
(1:3) Unnecessary curly bracket
115+
116+
> 1 | a {
117+
| ^
118+
2 | color: black;
119+
3 | }
120+
",
121+
]
122+
`;
123+
124+
exports[`loader should throw an error on invalid syntax: warnings 1`] = `Array []`;
125+
126126
exports[`loader should work: css 1`] = `
127127
"a {
128128
color: black;

0 commit comments

Comments
 (0)