1 | var loaderUtils = require('loader-utils');
|
2 | var loadConfig = require('postcss-load-config');
|
3 | var postcss = require('postcss');
|
4 | var assign = require('object-assign');
|
5 | var path = require('path');
|
6 |
|
7 | var PostCSSLoaderError = require('./error');
|
8 |
|
9 | function parseOptions(options, pack) {
|
10 | if ( typeof options === 'function' ) {
|
11 | options = options.call(this, this);
|
12 | }
|
13 |
|
14 | var plugins;
|
15 | if ( typeof options === 'undefined') {
|
16 | plugins = [];
|
17 | } else if ( Array.isArray(options) ) {
|
18 | plugins = options;
|
19 | } else {
|
20 | plugins = options.plugins || options.defaults;
|
21 | }
|
22 |
|
23 | if ( pack ) {
|
24 | plugins = options[pack];
|
25 | if ( !plugins ) {
|
26 | throw new Error('PostCSS plugin pack is not defined in options');
|
27 | }
|
28 | }
|
29 |
|
30 | var opts = { };
|
31 | if ( typeof options !== 'undefined' ) {
|
32 | opts.stringifier = options.stringifier;
|
33 | opts.parser = options.parser;
|
34 | opts.syntax = options.syntax;
|
35 | }
|
36 |
|
37 | var exec = options && options.exec;
|
38 | return Promise.resolve({ options: opts, plugins: plugins, exec: exec });
|
39 | }
|
40 |
|
41 | module.exports = function (source, map) {
|
42 | if ( this.cacheable ) this.cacheable();
|
43 |
|
44 | var loader = this;
|
45 | var file = loader.resourcePath;
|
46 | var params = loaderUtils.getOptions(loader) || {};
|
47 |
|
48 | var options = params.plugins || loader.options.postcss;
|
49 | var pack = params.pack;
|
50 | var callback = loader.async();
|
51 |
|
52 | var configPath;
|
53 |
|
54 | if (params.config) {
|
55 | if (path.isAbsolute(params.config)) {
|
56 | configPath = params.config;
|
57 | } else {
|
58 | configPath = path.join(process.cwd(), params.config);
|
59 | }
|
60 | } else {
|
61 | configPath = path.dirname(file);
|
62 | }
|
63 |
|
64 | Promise.resolve().then(function () {
|
65 | if ( typeof options !== 'undefined' ) {
|
66 | return parseOptions.call(loader, options, pack);
|
67 | } else {
|
68 | if ( pack ) {
|
69 | throw new Error('PostCSS plugin pack is supported ' +
|
70 | 'only when use plugins in webpack config');
|
71 | }
|
72 | return loadConfig({ webpack: loader }, configPath, { argv: false });
|
73 | }
|
74 | }).then(function (config) {
|
75 | if ( !config ) config = { };
|
76 |
|
77 | if ( config.file ) loader.addDependency(config.file);
|
78 |
|
79 | var plugins = config.plugins || [];
|
80 |
|
81 | var opts = assign({}, config.options, {
|
82 | from: file,
|
83 | to: file,
|
84 | map: {
|
85 | inline: params.sourceMap === 'inline',
|
86 | annotation: false
|
87 | }
|
88 | });
|
89 |
|
90 | if ( typeof map === 'string' ) map = JSON.parse(map);
|
91 | if ( map && map.mappings ) opts.map.prev = map;
|
92 |
|
93 | if ( params.syntax ) {
|
94 | if ( typeof params.syntax === 'string' ) {
|
95 | opts.syntax = require(params.syntax);
|
96 | } else {
|
97 | opts.syntax = params.syntax;
|
98 | }
|
99 | }
|
100 | if ( params.parser ) {
|
101 | if ( typeof params.parser === 'string' ) {
|
102 | opts.parser = require(params.parser);
|
103 | } else {
|
104 | opts.parser = params.parser;
|
105 | }
|
106 | }
|
107 | if ( params.stringifier ) {
|
108 | if ( typeof params.stringifier === 'string' ) {
|
109 | opts.stringifier = require(params.stringifier);
|
110 | } else {
|
111 | opts.stringifier = params.stringifier;
|
112 | }
|
113 | }
|
114 |
|
115 | var exec = params.exec || config.exec;
|
116 | if ( params.parser === 'postcss-js' || exec ) {
|
117 | source = loader.exec(source, loader.resource);
|
118 | }
|
119 |
|
120 |
|
121 | if ( loader._compilation ) {
|
122 | plugins = loader._compilation.applyPluginsWaterfall(
|
123 | 'postcss-loader-before-processing',
|
124 | [].concat(plugins),
|
125 | params
|
126 | );
|
127 | }
|
128 |
|
129 | return postcss(plugins).process(source, opts).then(function (result) {
|
130 | result.warnings().forEach(function (msg) {
|
131 | loader.emitWarning(msg.toString());
|
132 | });
|
133 |
|
134 | result.messages.forEach(function (msg) {
|
135 | if ( msg.type === 'dependency' ) {
|
136 | loader.addDependency(msg.file);
|
137 | }
|
138 | });
|
139 |
|
140 | var resultMap = result.map ? result.map.toJSON() : null;
|
141 | callback(null, result.css, resultMap);
|
142 | return null;
|
143 | });
|
144 | }).catch(function (error) {
|
145 | if ( error.name === 'CssSyntaxError' ) {
|
146 | callback(new PostCSSLoaderError(error));
|
147 | } else {
|
148 | callback(error);
|
149 | }
|
150 | });
|
151 | };
|