167 lines
4.0 KiB
JavaScript
Vendored
167 lines
4.0 KiB
JavaScript
Vendored
let File = require('../File');
|
|
let path = require('path');
|
|
let spawn = require('child_process').spawn;
|
|
let notifier = require('node-notifier');
|
|
|
|
class StandaloneSass {
|
|
/**
|
|
* Create a new StandaloneSass instance.
|
|
*
|
|
* @param {string} src
|
|
* @param {string} output
|
|
* @param {object} pluginOptions
|
|
*/
|
|
constructor(src, output, pluginOptions) {
|
|
src = new File(path.resolve(src)).parsePath();
|
|
output = new File(output).parsePath();
|
|
|
|
if (output.isDir) {
|
|
output = new File(
|
|
path.join(output.path, src.name + '.css')
|
|
).parsePath();
|
|
}
|
|
|
|
this.src = src;
|
|
this.output = output;
|
|
this.pluginOptions = pluginOptions;
|
|
this.shouldWatch = process.argv.includes('--watch');
|
|
}
|
|
|
|
|
|
/**
|
|
* Run the node-sass compiler.
|
|
*/
|
|
run() {
|
|
this.compile();
|
|
|
|
if (this.shouldWatch) this.watch();
|
|
}
|
|
|
|
|
|
/**
|
|
* Compile Sass.
|
|
*
|
|
* @param {Boolean} watch
|
|
*/
|
|
compile(watch = false) {
|
|
let output = this.output.path;
|
|
|
|
if (! output.startsWith(options.publicPath)) {
|
|
output = path.join(options.publicPath, output);
|
|
}
|
|
|
|
this.command = spawn(
|
|
'node-sass', [this.src.path, output].concat(this.options(watch)), { shell: true }
|
|
);
|
|
|
|
this.whenOutputIsAvailable((output, event) => {
|
|
if (event === 'error') this.onFail(output);
|
|
if (event === 'success') this.onSuccess(output);
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Fetch the node-sass options.
|
|
*
|
|
* @param {Boolean} watch
|
|
*/
|
|
options(watch) {
|
|
let sassOptions = [
|
|
'--precision=8',
|
|
'--output-style=' + (global.options.production ? 'compressed' : 'expanded'),
|
|
];
|
|
|
|
if (watch) sassOptions.push('--watch');
|
|
|
|
if (this.pluginOptions.includePaths) {
|
|
this.pluginOptions.includePaths.forEach(
|
|
path => sassOptions.push('--include-path=' + path)
|
|
);
|
|
}
|
|
|
|
if (global.options.sourcemaps && ! global.options.production) {
|
|
sassOptions.push('--source-map-embed');
|
|
}
|
|
|
|
return sassOptions;
|
|
}
|
|
|
|
|
|
/**
|
|
* Compile Sass, while registering a watcher.
|
|
*/
|
|
watch() {
|
|
return this.compile(true);
|
|
}
|
|
|
|
|
|
/**
|
|
* Register a callback for when output is available.
|
|
*
|
|
* @param {Function} callback
|
|
*/
|
|
whenOutputIsAvailable(callback) {
|
|
this.command.stderr.on('data', output => {
|
|
output = output.toString();
|
|
|
|
let event = 'change';
|
|
if (/Error/.test(output)) event = 'error';
|
|
if (/Wrote CSS/.test(output)) event = 'success';
|
|
|
|
callback(output, event);
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle successful compilation.
|
|
*
|
|
* @param {string} output
|
|
*/
|
|
onSuccess(output) {
|
|
console.log("\n");
|
|
console.log(output);
|
|
|
|
if (global.options.notifications) {
|
|
notifier.notify({
|
|
title: 'Laravel Mix',
|
|
message: 'Sass Compilation Successful',
|
|
contentImage: 'node_modules/laravel-mix/icons/laravel.png'
|
|
});
|
|
}
|
|
|
|
global.events.fire(
|
|
'standalone-sass-compiled', File.find(this.output.path)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle failed compilation.
|
|
*
|
|
* @param {string} output
|
|
*/
|
|
onFail(output) {
|
|
output = output.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
|
|
console.log("\n");
|
|
console.log('Sass Compilation Failed!');
|
|
console.log();
|
|
console.log(output);
|
|
|
|
if (global.options.notifications) {
|
|
notifier.notify({
|
|
title: 'Laravel Mix',
|
|
subtitle: 'Sass Compilation Failed',
|
|
message: JSON.parse(output).message,
|
|
contentImage: 'node_modules/laravel-mix/icons/laravel.png'
|
|
});
|
|
}
|
|
|
|
if (! this.shouldWatch) process.exit();
|
|
}
|
|
}
|
|
|
|
module.exports = StandaloneSass;
|