Skip to content

Commit 7d1ab11

Browse files
refactor: code
1 parent e4aa9e7 commit 7d1ab11

File tree

6 files changed

+178
-113
lines changed

6 files changed

+178
-113
lines changed

src/index.js

Lines changed: 3 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -5,81 +5,11 @@ import validateOptions from 'schema-utils';
55

66
import postcss from 'postcss';
77

8-
import postcssPkg from 'postcss/package.json';
9-
108
import Warning from './Warning';
119
import SyntaxError from './Error';
1210
import parseOptions from './options';
1311
import schema from './options.json';
14-
import { exec, loadConfig } from './utils';
15-
16-
const load = (plugin, options, file) => {
17-
try {
18-
if (
19-
options === null ||
20-
typeof options === 'undefined' ||
21-
Object.keys(options).length === 0
22-
) {
23-
// eslint-disable-next-line global-require,import/no-dynamic-require
24-
return require(plugin);
25-
}
26-
27-
// eslint-disable-next-line global-require,import/no-dynamic-require
28-
return require(plugin)(options);
29-
} catch (err) {
30-
throw new Error(
31-
`Loading PostCSS Plugin failed: ${err.message}\n\n(@${file})`
32-
);
33-
}
34-
};
35-
36-
const loadPlugins = (pluginEntry, file) => {
37-
let plugins = [];
38-
39-
if (Array.isArray(pluginEntry)) {
40-
plugins = pluginEntry.filter(Boolean);
41-
} else {
42-
plugins = Object.entries(pluginEntry).filter((i) => {
43-
const [, options] = i;
44-
45-
return options !== false ? pluginEntry : '';
46-
});
47-
}
48-
49-
plugins = plugins.map((plugin) => {
50-
const [pluginName, pluginOptions] = plugin;
51-
52-
return load(pluginName, pluginOptions, file);
53-
});
54-
55-
if (plugins.length && plugins.length > 0) {
56-
plugins.forEach((plugin, i) => {
57-
if (plugin.postcss) {
58-
// eslint-disable-next-line no-param-reassign
59-
plugin = plugin.postcss;
60-
}
61-
62-
if (plugin.default) {
63-
// eslint-disable-next-line no-param-reassign
64-
plugin = plugin.default;
65-
}
66-
67-
if (
68-
// eslint-disable-next-line
69-
!(
70-
(typeof plugin === 'object' && Array.isArray(plugin.plugins)) ||
71-
typeof plugin === 'function'
72-
)
73-
) {
74-
throw new TypeError(
75-
`Invalid PostCSS Plugin found at: plugins[${i}]\n\n(@${file})`
76-
);
77-
}
78-
});
79-
}
80-
81-
return plugins;
82-
};
12+
import { exec, loadConfig, createPostCssPlugins } from './utils';
8313

8414
/**
8515
* **PostCSS Loader**
@@ -182,17 +112,7 @@ export default async function loader(content, sourceMap, meta = {}) {
182112
});
183113

184114
if (length) {
185-
try {
186-
config = await parseOptions.call(this, mergedOptions);
187-
} catch (error) {
188-
callback(error);
189-
190-
return;
191-
}
192-
}
193-
194-
if (typeof config === 'undefined') {
195-
config = {};
115+
config = parseOptions.call(this, mergedOptions);
196116
}
197117

198118
if (config.file) {
@@ -261,21 +181,7 @@ export default async function loader(content, sourceMap, meta = {}) {
261181
postcssOptions.map.prev = sourceMap;
262182
}
263183

264-
let resultPlugins = [];
265-
266-
for (const plugin of plugins) {
267-
if (plugin === false) {
268-
// eslint-disable-next-line no-continue
269-
continue;
270-
}
271-
if (plugin.postcssVersion === postcssPkg.version) {
272-
resultPlugins.push(plugin);
273-
} else if (typeof plugin === 'function') {
274-
resultPlugins.push(plugin);
275-
} else {
276-
resultPlugins = resultPlugins.concat(loadPlugins(plugin, file));
277-
}
278-
}
184+
const resultPlugins = createPostCssPlugins(plugins, file);
279185

280186
let result;
281187

src/options.js

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,13 @@
1414
* @return {Promise} PostCSS Config
1515
*/
1616
function parseOptions({ exec, parser, syntax, stringifier, plugins }) {
17-
if (typeof plugins === 'function') {
18-
// eslint-disable-next-line no-param-reassign
19-
plugins = plugins.call(this, this);
20-
}
21-
22-
if (typeof plugins === 'undefined') {
23-
// eslint-disable-next-line no-param-reassign
24-
plugins = [];
25-
} else if (!Array.isArray(plugins)) {
26-
// eslint-disable-next-line no-param-reassign
27-
plugins = [plugins];
28-
}
29-
3017
const options = {};
3118

3219
options.parser = parser;
3320
options.syntax = syntax;
3421
options.stringifier = stringifier;
3522

36-
return Promise.resolve({ options, plugins, exec });
23+
return { options, plugins, exec };
3724
}
3825

3926
module.exports = parseOptions;

src/utils.js

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import path from 'path';
22

33
import Module from 'module';
44

5+
import postcssPkg from 'postcss/package.json';
56
import { cosmiconfig } from 'cosmiconfig';
67

78
const parentModule = module;
@@ -31,6 +32,26 @@ const createContext = (context) => {
3132
return result;
3233
};
3334

35+
const load = (plugin, options, file) => {
36+
try {
37+
if (
38+
options === null ||
39+
typeof options === 'undefined' ||
40+
Object.keys(options).length === 0
41+
) {
42+
// eslint-disable-next-line global-require,import/no-dynamic-require
43+
return require(plugin);
44+
}
45+
46+
// eslint-disable-next-line global-require,import/no-dynamic-require
47+
return require(plugin)(options);
48+
} catch (err) {
49+
throw new Error(
50+
`Loading PostCSS Plugin failed: ${err.message}\n\n(@${file})`
51+
);
52+
}
53+
};
54+
3455
const loadOptions = (config, file) => {
3556
const result = {};
3657

@@ -70,6 +91,54 @@ const loadOptions = (config, file) => {
7091
return { ...config, ...result };
7192
};
7293

94+
function loadPlugins(pluginEntry, file) {
95+
let plugins = [];
96+
97+
if (Array.isArray(pluginEntry)) {
98+
plugins = pluginEntry.filter(Boolean);
99+
} else {
100+
plugins = Object.entries(pluginEntry).filter((i) => {
101+
const [, options] = i;
102+
103+
return options !== false ? pluginEntry : '';
104+
});
105+
}
106+
107+
plugins = plugins.map((plugin) => {
108+
const [pluginName, pluginOptions] = plugin;
109+
110+
return load(pluginName, pluginOptions, file);
111+
});
112+
113+
if (plugins.length && plugins.length > 0) {
114+
plugins.forEach((plugin, i) => {
115+
if (plugin.postcss) {
116+
// eslint-disable-next-line no-param-reassign
117+
plugin = plugin.postcss;
118+
}
119+
120+
if (plugin.default) {
121+
// eslint-disable-next-line no-param-reassign
122+
plugin = plugin.default;
123+
}
124+
125+
if (
126+
// eslint-disable-next-line
127+
!(
128+
(typeof plugin === 'object' && Array.isArray(plugin.plugins)) ||
129+
typeof plugin === 'function'
130+
)
131+
) {
132+
throw new TypeError(
133+
`Invalid PostCSS Plugin found at: plugins[${i}]\n\n(@${file})`
134+
);
135+
}
136+
});
137+
}
138+
139+
return plugins;
140+
}
141+
73142
function exec(code, loaderContext) {
74143
const { resource, context } = loaderContext;
75144

@@ -137,4 +206,45 @@ async function loadConfig(config, context, configPath, inputFileSystem) {
137206
return { ...resultConfig, ...options };
138207
}
139208

140-
export { exec, loadConfig };
209+
function createPostCssPlugins(items, file) {
210+
function iterator(plugins, plugin, acc) {
211+
if (typeof plugin === 'undefined') {
212+
return acc;
213+
}
214+
215+
if (plugin === false) {
216+
return iterator(plugins, plugins.pop(), acc);
217+
}
218+
219+
if (plugin.postcssVersion === postcssPkg.version) {
220+
acc.push(plugin);
221+
return iterator(plugins, plugins.pop(), acc);
222+
}
223+
224+
if (typeof plugin === 'function') {
225+
const postcssPlugin = plugin.call(this, this);
226+
227+
if (Array.isArray(postcssPlugin)) {
228+
acc.concat(postcssPlugin);
229+
} else {
230+
acc.push(postcssPlugin);
231+
}
232+
233+
return iterator(plugins, plugins.pop(), acc);
234+
}
235+
236+
if (Object.keys(plugin).length === 0) {
237+
return iterator(plugins, plugins.pop(), acc);
238+
}
239+
240+
const concatPlugins = [...plugins, ...loadPlugins(plugin, file)];
241+
242+
return iterator(concatPlugins, concatPlugins.pop(), acc);
243+
}
244+
245+
const pl = [...items];
246+
247+
return iterator(pl, pl.pop(), []);
248+
}
249+
250+
export { exec, loadConfig, loadPlugins, createPostCssPlugins };

test/loader.test.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import postcss from 'postcss';
2+
13
import {
24
compile,
35
getCompiler,
@@ -28,8 +30,10 @@ describe('loader', () => {
2830
});
2931
};
3032

33+
const postcssPlugin = postcss.plugin('postcss-plugin', plugin);
34+
3135
const compiler = getCompiler('./css/index.js', {
32-
plugins: [plugin()],
36+
plugins: [postcssPlugin()],
3337
config: false,
3438
});
3539
const stats = await compile(compiler);

test/options/__snapshots__/plugins.test.js.snap

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`Options Plugins should work Plugins - {Array<Object>} + options: css 1`] = `
4+
"a {
5+
border-top-color: blue;
6+
border-right-color: blue;
7+
border-left-color: blue;
8+
background-color: #fafafa;
9+
}
10+
"
11+
`;
12+
13+
exports[`Options Plugins should work Plugins - {Array<Object>} + options: errors 1`] = `Array []`;
14+
15+
exports[`Options Plugins should work Plugins - {Array<Object>} + options: warnings 1`] = `Array []`;
16+
317
exports[`Options Plugins should work Plugins - {Array}: css 1`] = `
418
"a { color: rgba(255, 0, 0, 1.0) }
519
"
@@ -50,6 +64,20 @@ exports[`Options Plugins should work Plugins - {Object without require}: errors
5064
5165
exports[`Options Plugins should work Plugins - {Object without require}: warnings 1`] = `Array []`;
5266
67+
exports[`Options Plugins should work Plugins - {Object} + options: css 1`] = `
68+
"a {
69+
border-top-color: blue;
70+
border-right-color: blue;
71+
border-left-color: blue;
72+
background-color: #fafafa;
73+
}
74+
"
75+
`;
76+
77+
exports[`Options Plugins should work Plugins - {Object} + options: errors 1`] = `Array []`;
78+
79+
exports[`Options Plugins should work Plugins - {Object} + options: warnings 1`] = `Array []`;
80+
5381
exports[`Options Plugins should work Plugins - {Object}: css 1`] = `
5482
"a { color: rgba(255, 0, 0, 1.0) }
5583
"

test/options/plugins.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,34 @@ describe('Options Plugins', () => {
9898
expect(getWarnings(stats)).toMatchSnapshot('warnings');
9999
expect(getErrors(stats)).toMatchSnapshot('errors');
100100
});
101+
102+
it('should work Plugins - {Object} + options', async () => {
103+
const compiler = getCompiler('./css/index2.js', {
104+
// eslint-disable-next-line global-require
105+
plugins: require('postcss-short')({ prefix: 'x' }),
106+
config: false,
107+
});
108+
const stats = await compile(compiler);
109+
110+
const codeFromBundle = getCodeFromBundle('style2.css', stats);
111+
112+
expect(codeFromBundle.css).toMatchSnapshot('css');
113+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
114+
expect(getErrors(stats)).toMatchSnapshot('errors');
115+
});
116+
117+
it('should work Plugins - {Array<Object>} + options', async () => {
118+
const compiler = getCompiler('./css/index2.js', {
119+
// eslint-disable-next-line global-require
120+
plugins: [require('postcss-short')({ prefix: 'x' })],
121+
config: false,
122+
});
123+
const stats = await compile(compiler);
124+
125+
const codeFromBundle = getCodeFromBundle('style2.css', stats);
126+
127+
expect(codeFromBundle.css).toMatchSnapshot('css');
128+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
129+
expect(getErrors(stats)).toMatchSnapshot('errors');
130+
});
101131
});

0 commit comments

Comments
 (0)