function gulpRubySass(sources, options) {
var stream = new Readable({objectMode: true});
// redundant but necessary
stream._read = function () {};
options = assign({}, defaults, options);
// alert user that `container` is deprecated
if (options.container) {
gutil.log(gutil.colors.yellow('The container option has been deprecated. Simultaneous tasks work automatically now!'));
}
// error if user tries to watch their files with the Sass gem
if (options.watch || options.poll) {
emitErr(stream, '`watch` and `poll` are not valid options for gulp-ruby-sass. Use `gulp.watch` to rebuild your files on change
.');
}
// error if user tries to pass a Sass option to sourcemap
if (typeof options.sourcemap !== 'boolean') {
emitErr(stream, 'The sourcemap option must be true or false. See the readme for instructions on using Sass sourcemaps with gulp
.');
}
options.sourcemap = options.sourcemap === true ? 'file' : 'none';
options.update = true;
// simplified handling of array sources, like gulp.src
if (!Array.isArray(sources)) {
sources = [sources];
}
var matches = [];
var bases = [];
sources.forEach(function (source) {
matches.push(glob.sync(source));
bases.push(options.base || utils.calculateBase(source));
});
// log and return stream if there are no file matches
if (matches[0].length < 1) {
gutil.log('No files matched your Sass source.');
stream.push(null);
return stream;
}
var intermediateDir = createIntermediatePath(sources, matches, options);
var compileMappings = [];
var baseMappings = {};
matches.forEach(function (matchArray, i) {
var base = bases[i];
matchArray.filter(function (match) {
// remove _partials
return path.basename(match).indexOf('_') !== 0;
})
.forEach(function (match) {
var dest = gutil.replaceExtension(
replaceLocation(match, base, intermediateDir),
'.css'
);
var relative = path.relative(intermediateDir, dest);
// source:dest mappings for the Sass CLI
compileMappings.push(match + ':' + dest);
// store base values by relative file path
baseMappings[relative] = base;
});
});
var args = dargs(options, [
'bundleExec',
'watch',
'poll',
'tempDir',
'verbose',
'emitCompileError',
'base',
'container'
]).concat(compileMappings);
var command;
if (options.bundleExec) {
command = 'bundle';
args.unshift('exec', 'sass');
}
else {
command = 'sass';
}
// plugin logging
if (options.verbose) {
logger.verbose(command, args);
}
var sass = spawn(command, args);
sass.stdout.setEncoding('utf8');
sass.stderr.setEncoding('utf8');
sass.stdout.on('data', function (data) {
logger.stdout(stream, intermediateDir, data);
});
sass.stderr.on('data', function (data) {
logger.stderr(stream, intermediateDir, data);
});
sass.on('error', function (err) {
logger.error(stream, err);
});
sass.on('close', function (code) {
if (options.emitCompileError && code !== 0) {
emitErr(stream, 'Sass compilation failed. See console output for more information.');
}
glob(path.join(intermediateDir, '**', '*'), function (err, files) {
if (err) {
emitErr(stream, err);
}
eachAsync(files, function (file, i, next) {
if (fs.statSync(file).isDirectory() || path.extname(file) === '.map') {
next();
return;
}
var relative = path.relative(intermediateDir, file);
var base = baseMappings[relative];
fs.readFile(file, function (err, data) {
if (err) {
emitErr(stream, err);
next();
return;
}
// rewrite file paths so gulp thinks the file came from cwd, not the
// intermediate directory
var vinylFile = new gutil.File({
cwd: process.cwd(),
base: base,
path: replaceLocation(file, intermediateDir, base)
});
// sourcemap integration
if (options.sourcemap === 'file' && pathExists.sync(file + '.map')) {
// remove sourcemap comment; gulp-sourcemaps will add it back in
data = new Buffer(convert.removeMapFileComments(data.toString()));
var sourceMapObject = JSON.parse(fs.readFileSyn ...n/a
clearCache = function (tempDir) {
tempDir = tempDir || defaults.tempDir;
rimraf.sync(tempDir);
}...
);
```
### sass.logError(err)
Convenience function for pretty error logging.
### sass.clearCache([tempDir])
In rare cases you may need to clear gulp-ruby-sass's cache. This sync function deletes all files used for Sass caching. If
you've set a custom temporary directory in your task you must pass it to `clearCache`.
## Issues
This plugin wraps the Sass gem for the gulp build system. It does not alter Sass's output in any way. Any issues with Sass
output should be reported to the [Sass issue tracker](https://github.com/sass/sass/issues).
...logError = function (err) {
var message = new gutil.PluginError('gulp-ruby-sass', err);
process.stderr.write(message + '\n');
this.emit('end');
}...
loadPath: [ 'library', '../../shared-components' ]
})
.on('error', sass.logError)
.pipe(gulp.dest('result'))
);
```
### sass.logError(err)
Convenience function for pretty error logging.
### sass.clearCache([tempDir])
In rare cases you may need to clear gulp-ruby-sass's cache. This sync function deletes all files used for Sass caching. If
you've set a custom temporary directory in your task you must pass it to `clearCache`.
...error = function (stream, err) {
if (err.code === 'ENOENT') {
// Spawn error: gems not installed
emitErr(stream, 'Gem ' + err.path + ' is not installed.');
}
else {
// Other errors
emitErr(stream, err);
}
}...
});
sass.stderr.on('data', function (data) {
logger.stderr(stream, intermediateDir, data);
});
sass.on('error', function (err) {
logger.error(stream, err);
});
sass.on('close', function (code) {
if (options.emitCompileError && code !== 0) {
emitErr(stream, 'Sass compilation failed. See console output for more information.');
}
...prettifyDirectoryLogging = function (msg, intermediateDir) {
var escapedDir = escapeStringRegexp(intermediateDir);
return msg.replace(new RegExp(escapedDir + '/?', 'g'), './');
}...
}
// Sass error: directory missing
else if (/No such file or directory @ rb_sysopen/.test(data)) {
emitErr(stream, data.trim());
}
// Not an error: Sass logging
else {
data = logger.prettifyDirectoryLogging(data, intermediateDir);
data = data.trim();
gutil.log(data);
}
};
logger.stderr = function (stream, intermediateDir, data) {
var bundlerMissing = /Could not find 'bundler' \((.*?)\)/.exec(data);
...stderr = function (stream, intermediateDir, data) {
var bundlerMissing = /Could not find 'bundler' \((.*?)\)/.exec(data);
var sassVersionMissing = /Could not find gem 'sass \((.*?)\) ruby'/.exec(data);
// Ruby error: Bundler gem not installed
if (bundlerMissing) {
emitErr(stream, 'ruby: Could not find \'bundler\' (' + bundlerMissing[1] + ').');
}
// Bundler error: no matching Sass version
else if (sassVersionMissing) {
emitErr(stream, 'bundler: Could not find gem \'sass (' + sassVersionMissing[1] + ')\'.');
}
// Sass error: file missing
else if (/No such file or directory @ rb_sysopen/.test(data)) {
emitErr(stream, data.trim());
}
// Not an error: Sass warnings, debug statements
else {
data = logger.prettifyDirectoryLogging(data, intermediateDir);
data = data.trim();
gutil.log(data);
}
}...
sass.stderr.setEncoding('utf8');
sass.stdout.on('data', function (data) {
logger.stdout(stream, intermediateDir, data);
});
sass.stderr.on('data', function (data) {
logger.stderr(stream, intermediateDir, data);
});
sass.on('error', function (err) {
logger.error(stream, err);
});
sass.on('close', function (code) {
...stdout = function (stream, intermediateDir, data) {
// Bundler error: no Sass version found
if (/bundler: command not found: sass/.test(data)) {
emitErr(stream, 'bundler: command not found: sass');
}
// Bundler error: Gemfile not found
else if (/Could not locate Gemfile or .bundle\/ directory/.test(data)) {
emitErr(stream, 'bundler: could not locate Gemfile or .bundle directory');
}
// Sass error: directory missing
else if (/No such file or directory @ rb_sysopen/.test(data)) {
emitErr(stream, data.trim());
}
// Not an error: Sass logging
else {
data = logger.prettifyDirectoryLogging(data, intermediateDir);
data = data.trim();
gutil.log(data);
}
}...
var sass = spawn(command, args);
sass.stdout.setEncoding('utf8');
sass.stderr.setEncoding('utf8');
sass.stdout.on('data', function (data) {
logger.stdout(stream, intermediateDir, data);
});
sass.stderr.on('data', function (data) {
logger.stderr(stream, intermediateDir, data);
});
sass.on('error', function (err) {
...verbose = function (command, args) {
gutil.log('Running command ' + command + ' ' + args.join(' '));
}...
}
else {
command = 'sass';
}
// plugin logging
if (options.verbose) {
logger.verbose(command, args);
}
var sass = spawn(command, args);
sass.stdout.setEncoding('utf8');
sass.stderr.setEncoding('utf8');
...calculateBase = function (source) {
return glob2base(new glob.Glob(source));
}...
}
var matches = [];
var bases = [];
sources.forEach(function (source) {
matches.push(glob.sync(source));
bases.push(options.base || utils.calculateBase(source));
});
// log and return stream if there are no file matches
if (matches[0].length < 1) {
gutil.log('No files matched your Sass source.');
stream.push(null);
return stream;
...createIntermediatePath = function (sources, matches, options) {
return path.join(
options.tempDir,
md5Hex(
process.cwd() +
JSON.stringify(sources) +
JSON.stringify(matches) +
JSON.stringify(options)
)
);
}n/a
emitErr = function (stream, err) {
stream.emit('error', new gutil.PluginError('gulp-ruby-sass', err));
}n/a
replaceLocation = function (origPath, currentLoc, newLoc) {
return path.join(
newLoc,
path.relative(currentLoc, origPath)
);
}n/a