Skip to content

Commit 520a5f5

Browse files
refactor: move config autoload from postcss-load-config package
1 parent e3f8ee4 commit 520a5f5

35 files changed

+2120
-736
lines changed

package-lock.json

Lines changed: 1475 additions & 715 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@
4242
"webpack": "^4.0.0 || ^5.0.0"
4343
},
4444
"dependencies": {
45+
"cosmiconfig": "^6.0.0",
46+
"import-cwd": "^3.0.0",
4547
"loader-utils": "^2.0.0",
4648
"postcss": "^7.0.0",
47-
"postcss-load-config": "^2.0.0",
4849
"schema-utils": "^2.7.0"
4950
},
5051
"devDependencies": {
@@ -57,6 +58,7 @@
5758
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
5859
"babel-jest": "^26.2.2",
5960
"cross-env": "^7.0.2",
61+
"cssnano": "^4.1.10",
6062
"del": "^5.1.0",
6163
"del-cli": "^3.0.1",
6264
"eslint": "^7.6.0",
@@ -71,6 +73,7 @@
7173
"npm-run-all": "^4.1.5",
7274
"postcss-import": "^12.0.1",
7375
"postcss-js": "^2.0.0",
76+
"postcss-nested": "^4.2.3",
7477
"prettier": "^2.0.5",
7578
"standard": "^14.3.4",
7679
"standard-version": "^8.0.2",

src/index.js

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,15 @@
11
import path from 'path';
2-
import Module from 'module';
32

43
import { getOptions } from 'loader-utils';
54
import validateOptions from 'schema-utils';
65

76
import postcss from 'postcss';
8-
import postcssrc from 'postcss-load-config';
97

108
import Warning from './Warning';
119
import SyntaxError from './Error';
1210
import parseOptions from './options';
1311
import schema from './options.json';
14-
15-
const parentModule = module;
16-
17-
function exec(code, loaderContext) {
18-
const { resource, context } = loaderContext;
19-
20-
const module = new Module(resource, parentModule);
21-
22-
// eslint-disable-next-line no-underscore-dangle
23-
module.paths = Module._nodeModulePaths(context);
24-
module.filename = resource;
25-
26-
// eslint-disable-next-line no-underscore-dangle
27-
module._compile(code, resource);
28-
29-
return module.exports;
30-
}
12+
import { exec, loadConfig } from './utils';
3113

3214
/**
3315
* **PostCSS Loader**
@@ -100,7 +82,7 @@ export default async function loader(content, sourceMap, meta = {}) {
10082
rc.ctx.webpack = this;
10183

10284
try {
103-
config = await postcssrc(rc.ctx, rc.path);
85+
config = await loadConfig(rc.ctx, rc.path);
10486
} catch (error) {
10587
callback(error);
10688

src/utils.js

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import path from 'path';
2+
import Module from 'module';
3+
4+
import { cosmiconfig } from 'cosmiconfig';
5+
import importCwd from 'import-cwd';
6+
7+
const parentModule = module;
8+
9+
const createContext = (context) => {
10+
const result = {
11+
cwd: process.cwd(),
12+
env: process.env.NODE_ENV,
13+
...context,
14+
};
15+
16+
if (!result.env) {
17+
process.env.NODE_ENV = 'development';
18+
}
19+
20+
return result;
21+
};
22+
23+
const loadOptions = (config, file) => {
24+
const result = {};
25+
26+
if (config.parser && typeof config.parser === 'string') {
27+
try {
28+
result.parser = importCwd(config.parser);
29+
} catch (err) {
30+
throw new Error(
31+
`Loading PostCSS Parser failed: ${err.message}\n\n(@${file})`
32+
);
33+
}
34+
}
35+
36+
if (config.syntax && typeof config.syntax === 'string') {
37+
try {
38+
result.syntax = importCwd(config.syntax);
39+
} catch (err) {
40+
throw new Error(
41+
`Loading PostCSS Syntax failed: ${err.message}\n\n(@${file})`
42+
);
43+
}
44+
}
45+
46+
if (config.stringifier && typeof config.stringifier === 'string') {
47+
try {
48+
result.stringifier = importCwd(config.stringifier);
49+
} catch (err) {
50+
throw new Error(
51+
`Loading PostCSS Stringifier failed: ${err.message}\n\n(@${file})`
52+
);
53+
}
54+
}
55+
56+
if (config.plugins) {
57+
// eslint-disable-next-line no-param-reassign
58+
delete config.plugins;
59+
}
60+
61+
return { ...config, ...result };
62+
};
63+
64+
const load = (plugin, options, file) => {
65+
try {
66+
if (
67+
options === null ||
68+
typeof options === 'undefined' ||
69+
Object.keys(options).length === 0
70+
) {
71+
return importCwd(plugin);
72+
}
73+
74+
return importCwd(plugin)(options);
75+
} catch (err) {
76+
throw new Error(
77+
`Loading PostCSS Plugin failed: ${err.message}\n\n(@${file})`
78+
);
79+
}
80+
};
81+
82+
const loadPlugins = (config, file) => {
83+
let plugins = [];
84+
85+
if (Array.isArray(config.plugins)) {
86+
plugins = config.plugins.filter(Boolean);
87+
} else {
88+
plugins = Object.keys(config.plugins)
89+
.filter((plugin) => {
90+
return config.plugins[plugin] !== false ? plugin : '';
91+
})
92+
.map((plugin) => {
93+
return load(plugin, config.plugins[plugin], file);
94+
});
95+
}
96+
97+
if (plugins.length && plugins.length > 0) {
98+
plugins.forEach((plugin, i) => {
99+
if (plugin.postcss) {
100+
// eslint-disable-next-line no-param-reassign
101+
plugin = plugin.postcss;
102+
}
103+
104+
if (plugin.default) {
105+
// eslint-disable-next-line no-param-reassign
106+
plugin = plugin.default;
107+
}
108+
109+
if (
110+
// eslint-disable-next-line
111+
!(
112+
(typeof plugin === 'object' && Array.isArray(plugin.plugins)) ||
113+
typeof plugin === 'function'
114+
)
115+
) {
116+
throw new TypeError(
117+
`Invalid PostCSS Plugin found at: plugins[${i}]\n\n(@${file})`
118+
);
119+
}
120+
});
121+
}
122+
123+
return plugins;
124+
};
125+
126+
const processResult = (context, result) => {
127+
const file = result.filepath || '';
128+
let config = result.config || {};
129+
130+
if (typeof config === 'function') {
131+
config = config(context);
132+
} else {
133+
config = Object.assign({}, config, context);
134+
}
135+
136+
if (!config.plugins) {
137+
config.plugins = [];
138+
}
139+
140+
return {
141+
plugins: loadPlugins(config, file),
142+
options: loadOptions(config, file),
143+
file,
144+
};
145+
};
146+
147+
function exec(code, loaderContext) {
148+
const { resource, context } = loaderContext;
149+
150+
const module = new Module(resource, parentModule);
151+
152+
// eslint-disable-next-line no-underscore-dangle
153+
module.paths = Module._nodeModulePaths(context);
154+
module.filename = resource;
155+
156+
// eslint-disable-next-line no-underscore-dangle
157+
module._compile(code, resource);
158+
159+
return module.exports;
160+
}
161+
162+
function loadConfig(context, configPath) {
163+
const configPathResolved = configPath
164+
? path.resolve(configPath)
165+
: process.cwd();
166+
167+
return cosmiconfig('postcss')
168+
.search(configPathResolved)
169+
.then((result) => {
170+
if (!result) {
171+
throw new Error(`No PostCSS Config found in: ${configPathResolved}`);
172+
}
173+
174+
return processResult(createContext(context), result);
175+
});
176+
}
177+
178+
export { exec, loadConfig };

0 commit comments

Comments
 (0)