UNPKG

4.65 kBJavaScriptView Raw
1var loaderUtils = require('loader-utils');
2var loadConfig = require('postcss-load-config');
3var postcss = require('postcss');
4var assign = require('object-assign');
5var path = require('path');
6
7var PostCSSLoaderError = require('./error');
8
9function 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
41module.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 // Allow plugins to add or remove postcss plugins
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};