Skip to content

Commit 29e279f

Browse files
committed
Support global config with load config package
1 parent d767948 commit 29e279f

27 files changed

+371
-128
lines changed

gulpfile.js

+19-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
var gulp = require('gulp');
22
var path = require('path');
33

4+
var BUILD_CONFIGS = [
5+
'./test/webpack-default.config',
6+
'./test/webpack-explicit-plugins.config',
7+
'./test/webpack-with-packs.config',
8+
'./test/webpack-incorrect-using-packs.config',
9+
'./test/webpack-custom-parser.config'
10+
];
11+
412
gulp.task('clean', function (done) {
513
var fs = require('fs-extra');
614
fs.remove(path.join(__dirname, 'build'), done);
@@ -17,12 +25,17 @@ gulp.task('lint', function () {
1725
.pipe(eslint.failAfterError());
1826
});
1927

20-
gulp.task('build', ['clean'], function () {
21-
var webpack = require('webpack-stream');
22-
return gulp.src('')
23-
.pipe(webpack(require('./test/webpack.config')))
24-
.pipe(gulp.dest('build/'));
25-
});
28+
BUILD_CONFIGS
29+
.forEach(function (configFile) {
30+
gulp.task(configFile, ['clean'], function () {
31+
var webpack = require('webpack-stream');
32+
return gulp.src('')
33+
.pipe(webpack(require(configFile)))
34+
.pipe(gulp.dest('build/'));
35+
});
36+
});
37+
38+
gulp.task('build', BUILD_CONFIGS);
2639

2740
gulp.task('test', ['build'], function () {
2841
var mocha = require('gulp-mocha');

index.js

+61-70
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
var loaderUtils = require('loader-utils');
22
var postcss = require('postcss');
3+
var assign = require('./lib/assign');
4+
var getConfiguration = require('./lib/configuration');
35

46
function PostCSSLoaderError(error) {
57
Error.call(this);
@@ -25,83 +27,72 @@ module.exports = function (source, map) {
2527
var file = this.resourcePath;
2628
var params = loaderUtils.parseQuery(this.query);
2729

28-
var opts = {
29-
from: file,
30-
to: file,
31-
map: {
32-
inline: params.sourceMap === 'inline',
33-
annotation: false
30+
var options = this.options.postcss;
31+
var pack = params.pack;
32+
var loader = this;
33+
var callback = this.async();
34+
35+
getConfiguration(options, pack, function (err, config) {
36+
if (err) {
37+
callback(err);
38+
return;
3439
}
35-
};
3640

37-
if ( typeof map === 'string' ) map = JSON.parse(map);
38-
if ( map && map.mappings ) opts.map.prev = map;
41+
var plugins = config.plugins;
42+
var exec = config.exec;
3943

40-
var options = this.options.postcss;
41-
if ( typeof options === 'function' ) {
42-
options = options.call(this, this);
43-
}
44+
var opts = assign({}, config.options, {
45+
from: file,
46+
to : file,
47+
map: {
48+
inline: params.sourceMap === 'inline',
49+
annotation: false
50+
}
51+
});
4452

45-
var plugins;
46-
var exec;
47-
if ( typeof options === 'undefined' ) {
48-
plugins = [];
49-
} else if ( Array.isArray(options) ) {
50-
plugins = options;
51-
} else {
52-
plugins = options.plugins || options.defaults;
53-
opts.stringifier = options.stringifier;
54-
opts.parser = options.parser;
55-
opts.syntax = options.syntax;
56-
exec = options.exec;
57-
}
58-
if ( params.pack ) {
59-
plugins = options[params.pack];
60-
if ( !plugins ) {
61-
throw new Error('PostCSS plugin pack is not defined in options');
62-
}
63-
}
53+
if ( typeof map === 'string' ) map = JSON.parse(map);
54+
if ( map && map.mappings ) opts.map.prev = map;
6455

65-
if ( params.syntax ) {
66-
opts.syntax = require(params.syntax);
67-
}
68-
if ( params.parser ) {
69-
opts.parser = require(params.parser);
70-
}
71-
if ( params.stringifier ) {
72-
opts.stringifier = require(params.stringifier);
73-
}
74-
if ( params.exec ) {
75-
exec = params.exec;
76-
}
56+
if ( params.syntax ) {
57+
opts.syntax = require(params.syntax);
58+
}
59+
if ( params.parser ) {
60+
opts.parser = require(params.parser);
61+
}
62+
if ( params.stringifier ) {
63+
opts.stringifier = require(params.stringifier);
64+
}
65+
if ( params.exec ) {
66+
exec = params.exec;
67+
}
7768

78-
var loader = this;
79-
var callback = this.async();
69+
if ( params.parser === 'postcss-js' || exec ) {
70+
source = loader.exec(source, loader.resource);
71+
}
8072

81-
if ( params.parser === 'postcss-js' || exec ) {
82-
source = this.exec(source, this.resource);
83-
}
73+
// Allow plugins to add or remove postcss plugins
74+
plugins = loader._compilation.applyPluginsWaterfall(
75+
'postcss-loader-before-processing',
76+
[].concat(plugins),
77+
params
78+
);
8479

85-
// Allow plugins to add or remove postcss plugins
86-
plugins = this._compilation.applyPluginsWaterfall(
87-
'postcss-loader-before-processing',
88-
[].concat(plugins),
89-
params
90-
);
80+
postcss(plugins).process(source, opts)
81+
.then(function (result) {
82+
result.warnings().forEach(function (msg) {
83+
loader.emitWarning(msg.toString());
84+
});
9185

92-
postcss(plugins).process(source, opts)
93-
.then(function (result) {
94-
result.warnings().forEach(function (msg) {
95-
loader.emitWarning(msg.toString());
96-
});
97-
callback(null, result.css, result.map ? result.map.toJSON() : null);
98-
return null;
99-
})
100-
.catch(function (error) {
101-
if ( error.name === 'CssSyntaxError' ) {
102-
callback(new PostCSSLoaderError(error));
103-
} else {
104-
callback(error);
105-
}
106-
});
86+
var resultMap = result.map ? result.map.toJSON() : null;
87+
callback(null, result.css, resultMap);
88+
return null;
89+
})
90+
.catch(function (error) {
91+
if ( error.name === 'CssSyntaxError' ) {
92+
callback(new PostCSSLoaderError(error));
93+
} else {
94+
callback(error);
95+
}
96+
});
97+
});
10798
};

lib/assign.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module.exports = Object.assign || function (target) {
2+
'use strict';
3+
// We must check against these specific cases.
4+
if (target === undefined || target === null) {
5+
throw new TypeError('Cannot convert undefined or null to object');
6+
}
7+
8+
var output = Object(target);
9+
for (var index = 1; index < arguments.length; index++) {
10+
var source = arguments[index];
11+
if (source !== undefined && source !== null) {
12+
for (var nextKey in source) {
13+
if (source.hasOwnProperty(nextKey)) {
14+
output[nextKey] = source[nextKey];
15+
}
16+
}
17+
}
18+
}
19+
return output;
20+
};

lib/configuration/index.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
var parseOptions = require('./parse_options');
2+
var loadConfig = require('postcss-load-config');
3+
4+
function loadConfigurationFromRc(pack, callback) {
5+
if ( pack ) {
6+
callback(new Error('PostCSS plugin pack is supported ' +
7+
'only when config is passed explicitly'));
8+
return;
9+
}
10+
11+
loadConfig()
12+
.then(function (config) {
13+
callback(null, { options: config.options, plugins: config.plugins });
14+
})
15+
.catch(function (err) {
16+
callback(err);
17+
});
18+
}
19+
20+
module.exports = function getConfiguration(options, pack, callback) {
21+
if ( typeof options === 'undefined' ) {
22+
loadConfigurationFromRc(pack, callback);
23+
return;
24+
}
25+
26+
parseOptions(options, pack, callback);
27+
};

lib/configuration/parse_options.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
function getPluginsFromOptions(options, pack) {
2+
var plugins;
3+
4+
if ( typeof options === 'undefined') {
5+
plugins = [];
6+
}
7+
else if ( Array.isArray(options) ) {
8+
plugins = options;
9+
} else {
10+
plugins = options.plugins || options.defaults;
11+
}
12+
13+
if ( pack ) {
14+
plugins = options[pack];
15+
if ( !plugins ) {
16+
throw new Error('PostCSS plugin pack is not defined in options');
17+
}
18+
}
19+
20+
return plugins;
21+
}
22+
23+
module.exports = function parseOptions(options, pack, callback) {
24+
var exec = options && options.exec;
25+
26+
if ( typeof options === 'function' ) {
27+
options = options.call(this, this);
28+
}
29+
30+
var plugins = getPluginsFromOptions(options, pack);
31+
var opts = {};
32+
33+
if ( typeof options !== 'undefined' ) {
34+
opts.stringifier = options.stringifier;
35+
opts.parser = options.parser;
36+
opts.syntax = options.syntax;
37+
}
38+
39+
callback(null, { options: opts, plugins: plugins, exec: exec });
40+
}
41+

package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"repository": "postcss/postcss-loader",
99
"dependencies": {
1010
"loader-utils": "^0.2.16",
11-
"postcss": "^5.2.0"
11+
"postcss": "^5.2.0",
12+
"postcss-load-config": "^1.0.0-alpha4"
1213
},
1314
"devDependencies": {
1415
"eslint-config-postcss": "2.0.2",
@@ -21,7 +22,8 @@
2122
"gulp-mocha": "3.0.1",
2223
"fs-extra": "0.30.0",
2324
"chai": "3.5.0",
24-
"gulp": "3.9.1"
25+
"gulp": "3.9.1",
26+
"sugarss": "^0.1.6"
2527
},
2628
"scripts": {
2729
"test": "gulp"

postcss.config.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
var config = {
2+
plugins: {}
3+
}
4+
5+
config.plugins[require.resolve(__dirname + '/test/support/plugins/blue')] = false;
6+
7+
module.exports = config

test/plugins/red.js

-14
This file was deleted.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

test/support/cases/sugar.css

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
a
2+
color: black
File renamed without changes.

test/support/plugins/red.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var warning = false;
2+
3+
module.exports = function (options) {
4+
var alpha = options.alpha || '1.0';
5+
6+
return {
7+
postcss: function (css, result) {
8+
if (!warning) {
9+
result.warn('Test red warning');
10+
warning = true;
11+
}
12+
13+
css.walkDecls(function (decl) {
14+
if (decl.value === 'blue') {
15+
decl.value = 'rgba(255, 0, 0, ' + alpha + ')';
16+
}
17+
});
18+
}
19+
};
20+
};

test/test-custom-parser.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var expect = require('chai').expect;
2+
3+
describe('postcss-loader', function () {
4+
5+
context('when config defines syntax function', function () {
6+
it('processes sugarss', function () {
7+
var css = require('!raw-loader!../!' +
8+
'./support/cases/sugar.css');
9+
expect(css).to.eql('a\n color: rgba(255, 0, 0, 0.1)\n');
10+
});
11+
});
12+
});

0 commit comments

Comments
 (0)