Merge pull request #224 from Snugug/2.x-sync

2.x sync
This commit is contained in:
David Manning 2015-03-30 15:15:42 -07:00
commit d59befea89
5 changed files with 220 additions and 33 deletions

View file

@ -1,6 +1,9 @@
# Gulp Sass Changelog
## v2.0.0-alpha.1
### March 26, 2015
* **New** Added `renderSync` option that can be used through `sass.sync()`
### March 24, 2015
* **Change** Updated to `node-sass` 3.0.0-alpha.1
* **New** Added support for `gulp-sourcemaps` including tests

View file

@ -10,11 +10,10 @@ npm install gulp-sass --save-dev
# Basic Usage
Something like this:
Something like this will compile your Sass files:
```javascript
var gulp = require('gulp');
var gutil = require('gulp-util');
var sass = require('gulp-sass');
gulp.task('sass', function () {
@ -24,6 +23,19 @@ gulp.task('sass', function () {
});
```
You can also compile synchronously, doing something like this:
```javascript
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('sass', function () {
gulp.src('./scss/*.scss')
.pipe(sass.sync().on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
```
## Options
Pass in options just like you would for [`node-sass`](https://github.com/sass/node-sass#options); they will be passed along just as if you were using `node-sass`.
@ -42,7 +54,7 @@ gulp.src('./scss/*.scss')
.pipe(gulp.dest('./css'));
```
By default, [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) writes the source maps inline in the compiled CSS files. To write them to a separate file, specify a relative file path in the `sourcemaps.write()` function.
By default, [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) writes the source maps inline in the compiled CSS files. To write them to a separate file, specify a path relative to the `gulp.dest()` destination in the `sourcemaps.write()` function.
```javascript
var sourcemaps = require('gulp-sourcemaps');

View file

@ -1,3 +1,5 @@
'use strict';
var gutil = require('gulp-util');
var through = require('through2');
var assign = require('object-assign');
@ -10,12 +12,13 @@ var PLUGIN_NAME = 'gulp-sass';
//////////////////////////////
// Main Gulp Sass function
//////////////////////////////
var gulpSass = function gulpSass(options) {
'use strict';
var gulpSass = function gulpSass(options, sync) {
return through.obj(function(file, enc, cb) {
var opts,
callback;
filePush,
errorM,
callback,
result;
if (file.isNull()) {
return cb(null, file);
@ -36,33 +39,77 @@ var gulpSass = function gulpSass(options) {
opts.omitSourceMapUrl = true;
}
callback = function(error, obj) {
if (error) {
return cb(new gutil.PluginError(
PLUGIN_NAME, error.message + ' ' + gutil.colors.cyan('line ' + error.line) + ' in ' + gutil.colors.magenta(error.file)
));
}
//////////////////////////////
// Handles returning the file to the stream
//////////////////////////////
filePush = function filePush(sassObj) {
// Build Source Maps!
if (obj.map) {
applySourceMap(file, JSON.parse(obj.map.toString()));
if (sassObj.map) {
applySourceMap(file, JSON.parse(sassObj.map.toString()));
}
file.contents = obj.css;
file.contents = sassObj.css;
file.path = gutil.replaceExtension(file.path, '.css');
cb(null, file);
};
sass.render(opts, callback);
//////////////////////////////
// Handles error message
//////////////////////////////
errorM = function errorM(error) {
var relativePath = path.relative(process.cwd(), error.file),
message = '';
message += gutil.colors.underline(relativePath) + '\n';
message += gutil.colors.gray(' ' + error.line + ':' + error.column) + ' ';
message += error.message;
return cb(new gutil.PluginError(
PLUGIN_NAME, message
));
};
if (sync !== true) {
//////////////////////////////
// Async Sass render
//////////////////////////////
callback = function(error, obj) {
if (error) {
return errorM(error);
}
filePush(obj);
};
sass.render(opts, callback);
}
else {
//////////////////////////////
// Sync Sass render
//////////////////////////////
try {
result = sass.renderSync(opts);
filePush(result);
}
catch(error) {
return errorM(error);
}
}
});
};
//////////////////////////////
// Sync Sass render
//////////////////////////////
gulpSass.sync = function sync(options) {
return gulpSass(options, true);
};
//////////////////////////////
// Log errors nicely
//////////////////////////////
gulpSass.logError = function logError(error) {
'use strict';
gutil.log(gutil.colors.red('[' + PLUGIN_NAME + '] ') + error.message);
};

View file

@ -10,11 +10,6 @@ var report;
describe('code style guide', function() {
it('index.js should follow our lint style guide', function(done) {
cli = new eslint.CLIEngine({
'rules': {
'strict': [ 2, 'function' ]
}
});
report = cli.executeOnFiles(['index.js']);
if (report.errorCount > 0 || report.warningCount > 0) {
console.log(formatter(report.results));
@ -26,11 +21,6 @@ describe('code style guide', function() {
});
it('test/main.js should follow our lint style guide', function(done) {
cli = new eslint.CLIEngine({
'rules': {
'strict': [ 2, 'global' ]
}
});
report = cli.executeOnFiles(['test/main.js']);
if (report.errorCount > 0 || report.warningCount > 0) {
console.log(formatter(report.results));
@ -44,8 +34,7 @@ describe('code style guide', function() {
it('test/lint.js should follow our lint style guide', function(done) {
cli = new eslint.CLIEngine({
'rules': {
'no-console': 0,
'strict': [ 2, 'global' ]
'no-console': 0
}
});
report = cli.executeOnFiles(['test/lint.js']);

View file

@ -19,7 +19,7 @@ var createVinyl = function createVinyl(filename, contents) {
});
};
describe('gulp-sass', function() {
describe('gulp-sass -- async compile', function() {
it('should pass file when it isNull()', function(done) {
var stream = sass();
var emptyFile = {
@ -119,7 +119,7 @@ describe('gulp-sass', function() {
var stream = sass();
stream.on('error', function(err) {
err.message.indexOf('property "font" must be followed by a \':\'').should.equal(0);
err.message.indexOf('property "font" must be followed by a \':\'').should.not.equal(-1);
done();
});
stream.write(errorFile);
@ -154,3 +154,139 @@ describe('gulp-sass', function() {
stream.write(sassFile);
});
});
describe('gulp-sass -- sync compile', function() {
it('should pass file when it isNull()', function(done) {
var stream = sass.sync();
var emptyFile = {
'isNull': function () {
return true;
}
};
stream.on('data', function(data) {
data.should.equal(emptyFile);
done();
});
stream.write(emptyFile);
});
it('should emit error when file isStream()', function (done) {
var stream = sass.sync();
var streamFile = {
'isNull': function () {
return false;
},
'isStream': function () {
return true;
}
};
stream.on('error', function(err) {
err.message.should.equal('Streaming not supported');
done();
});
stream.write(streamFile);
});
it('should compile a single sass file', function(done) {
var sassFile = createVinyl('mixins.scss');
var stream = sass.sync();
stream.on('data', function(cssFile) {
should.exist(cssFile);
should.exist(cssFile.path);
should.exist(cssFile.relative);
should.exist(cssFile.contents);
String(cssFile.contents).should.equal(
fs.readFileSync(path.join(__dirname, 'expected/mixins.css'), 'utf8')
);
done();
});
stream.write(sassFile);
});
it('should compile multiple sass files', function(done) {
var files = [
createVinyl('mixins.scss'),
createVinyl('variables.scss')
];
var stream = sass.sync();
var mustSee = files.length;
var expectedPath = 'expected/mixins.css';
stream.on('data', function(cssFile) {
should.exist(cssFile);
should.exist(cssFile.path);
should.exist(cssFile.relative);
should.exist(cssFile.contents);
if (cssFile.path.indexOf('variables') !== -1) {
expectedPath = 'expected/variables.css';
}
String(cssFile.contents).should.equal(
fs.readFileSync(path.join(__dirname, expectedPath), 'utf8')
);
mustSee--;
if (mustSee <= 0) {
done();
}
});
files.forEach(function (file) {
stream.write(file);
});
});
it('should compile files with partials in another folder', function(done) {
var sassFile = createVinyl('inheritance.scss');
var stream = sass.sync();
stream.on('data', function(cssFile) {
should.exist(cssFile);
should.exist(cssFile.path);
should.exist(cssFile.relative);
should.exist(cssFile.contents);
String(cssFile.contents).should.equal(
fs.readFileSync(path.join(__dirname, 'expected/inheritance.css'), 'utf8')
);
done();
});
stream.write(sassFile);
});
it('should handle sass errors', function(done) {
var errorFile = createVinyl('error.scss');
var stream = sass.sync();
stream.on('error', function(err) {
err.message.indexOf('property "font" must be followed by a \':\'').should.not.equal(-1);
done();
});
stream.write(errorFile);
});
it('should work with gulp-sourcemaps', function(done) {
var sassFile = createVinyl('inheritance.scss');
// Expected sources are relative to file.base
var expectedSources = [
'includes/_cats.scss',
'inheritance.scss'
];
var stream;
sassFile.sourceMap = '{' +
'"version": 3,' +
'"file": "scss/subdir/multilevelimport.scss",' +
'"names": [],' +
'"mappings": "",' +
'"sources": [ "scss/subdir/multilevelimport.scss" ],' +
'"sourcesContent": [ "@import ../inheritance;" ]' +
'}';
stream = sass.sync();
stream.on('data', function(cssFile) {
should.exist(cssFile.sourceMap);
assert.deepEqual(cssFile.sourceMap.sources, expectedSources);
done();
});
stream.write(sassFile);
});
});