UNPKG

5.29 kBJavaScriptView Raw
1'use strict';
2
3var fs = require('fs');
4var path = require('path');
5var rollupPluginutils = require('rollup-pluginutils');
6
7function css (options) {
8 if ( options === void 0 ) options = {};
9
10 var filter = rollupPluginutils.createFilter(options.include || ['/**/*.css', '/**/*.scss', '/**/*.sass'], options.exclude);
11 var dest = options.output;
12
13 var styles = {};
14 var prefix = options.prefix ? options.prefix + '\n' : '';
15 var includePaths = options.includePaths || ['node_modules/'];
16 includePaths.push(process.cwd());
17
18 var compileToCSS = function (scss) {
19 // Compile SASS to CSS
20 if (scss.length) {
21 includePaths = includePaths.filter(function (v, i, a) { return a.indexOf(v) === i; });
22 try {
23 var sass = options.sass || require('node-sass');
24 var css = sass.renderSync(Object.assign({
25 data: prefix + scss,
26 includePaths: includePaths
27 }, options)).css.toString();
28 // Possibly process CSS (e.g. by PostCSS)
29 if (typeof options.processor === 'function') {
30 var processor = options.processor(css, styles);
31
32 // PostCSS support
33 if (typeof processor.process === 'function') {
34 return Promise.resolve(processor.process(css, { from: undefined }))
35 .then(function (result) { return result.css; })
36 }
37
38 return processor
39 }
40 return css
41 } catch (e) {
42 if (options.failOnError) {
43 throw e
44 }
45 console.log();
46 console.log(red('Error:\n\t' + e.message));
47 if (e.message.includes('Invalid CSS')) {
48 console.log(green('Solution:\n\t' + 'fix your Sass code'));
49 console.log('Line: ' + e.line);
50 console.log('Column: ' + e.column);
51 }
52 if (e.message.includes('node-sass') && e.message.includes('find module')) {
53 console.log(green('Solution:\n\t' + 'npm install --save node-sass'));
54 }
55 if (e.message.includes('node-sass') && e.message.includes('bindings')) {
56 console.log(green('Solution:\n\t' + 'npm rebuild node-sass --force'));
57 }
58 console.log();
59 }
60 }
61 };
62
63 return {
64 name: 'scss',
65 transform: function transform (code, id) {
66 var this$1 = this;
67
68 if (!filter(id)) {
69 return
70 }
71
72 // Add the include path before doing any processing
73 includePaths.push(path.dirname(id));
74
75 // Rebuild all scss files if anything happens to this folder
76 // TODO: check if it's possible to get a list of all dependent scss files
77 // and only watch those
78 if ('watch' in options) {
79 var files = Array.isArray(options.watch) ? options.watch : [options.watch];
80 files.forEach(function (file) { return this$1.addWatchFile(file); });
81 }
82
83 // When output is disabled, the stylesheet is exported as a string
84 if (options.output === false) {
85 return Promise.resolve(compileToCSS(code)).then(function (css) { return ({
86 code: 'export default ' + JSON.stringify(css),
87 map: { mappings: '' }
88 }); })
89 }
90
91 // Map of every stylesheet
92 styles[id] = code;
93
94 return ''
95 },
96 generateBundle: function generateBundle (opts) {
97 // No stylesheet needed
98 if (options.output === false) {
99 return
100 }
101
102 // Combine all stylesheets
103 var scss = '';
104 for (var id in styles) {
105 scss += styles[id] || '';
106 }
107
108 var css = compileToCSS(scss);
109
110 // Resolve if processor returned a Promise
111 Promise.resolve(css).then(function (css) {
112 // Emit styles through callback
113 if (typeof options.output === 'function') {
114 options.output(css, styles);
115 return
116 }
117
118 if (typeof css !== 'string') {
119 return
120 }
121
122 if (typeof dest !== 'string') {
123 // Don't create unwanted empty stylesheets
124 if (!css.length) {
125 return
126 }
127
128 // Guess destination filename
129 dest = opts.dest || opts.file || 'bundle.js';
130 if (dest.endsWith('.js')) {
131 dest = dest.slice(0, -3);
132 }
133 dest = dest + '.css';
134 }
135
136 // Ensure that dest parent folders exist (create the missing ones)
137 ensureParentDirsSync(path.dirname(dest));
138
139 // Emit styles to file
140 fs.writeFile(dest, css, function (err) {
141 if (opts.verbose !== false) {
142 if (err) {
143 console.error(red(err));
144 } else if (css) {
145 console.log(green(dest), getSize(css.length));
146 }
147 }
148 });
149 });
150 }
151 }
152}
153
154function red (text) {
155 return '\x1b[1m\x1b[31m' + text + '\x1b[0m'
156}
157
158function green (text) {
159 return '\x1b[1m\x1b[32m' + text + '\x1b[0m'
160}
161
162function getSize (bytes) {
163 return bytes < 10000
164 ? bytes.toFixed(0) + ' B'
165 : bytes < 1024000
166 ? (bytes / 1024).toPrecision(3) + ' kB'
167 : (bytes / 1024 / 1024).toPrecision(4) + ' MB'
168}
169
170function ensureParentDirsSync (dir) {
171 if (fs.existsSync(dir)) {
172 return
173 }
174
175 try {
176 fs.mkdirSync(dir);
177 } catch (err) {
178 if (err.code === 'ENOENT') {
179 ensureParentDirsSync(path.dirname(dir));
180 ensureParentDirsSync(dir);
181 }
182 }
183}
184
185module.exports = css;