Skip to content

Commit 7cc2db1

Browse files
nex3xzyfer
authored andcommittedOct 16, 2018
Make this package implementation-agnostic
Rather than always loading Node Sass, this now requires users to pass in either Dart Sass or Node Sass to the require() call. Closes #672
1 parent 643f73b commit 7cc2db1

File tree

6 files changed

+162
-140
lines changed

6 files changed

+162
-140
lines changed
 

‎CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Gulp Sass Changelog
22

3+
## v5.0.0
4+
5+
https://github.com/dlmanning/gulp-sass/releases/tag/v5.0.0
6+
37
## v3.2.0
48
**March 11, 2018**
59

‎CONTRIBUTING.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
# Contributing to Gulp Sass
22

3-
Gulp Sass is a very light-weight [Gulp](https://github.com/gulpjs/gulp) wrapper for [`node-sass`](https://github.com/sass/node-sass), which in turn is a Node binding for [`libsass`](https://github.com/sass/libsass), which in turn is a port of [`Sass`](https://github.com/sass/sass).
3+
`gulp-sass` is a very light-weight wrapper around either [Dart Sass][] or [Node Sass][] (which in turn is a Node binding for [LibSass][]. All of these are implementations of the [Sass][] language.
4+
5+
[Dart Sass]: http://sass-lang.com/dart-sass
6+
[Node Sass]: https://github.com/sass/node-sass
7+
[LibSass]: https://sass-lang.com/libsass
8+
[Sass]: https://sass-lang.com
49

510
## Submitting Issues
611

7-
* Before creating a new issue, perform a [cursory search](https://github.com/issues?utf8=%E2%9C%93&q=repo%3Adlmanning%2Fgulp-sass+repo%3Asass%2Fnode-sass+repo%3Asass%2Flibsass+repo%3Asass%2Fsass+repo%3Asass-eyeglass%2Feyeglass) in the Gulp Sass, Node Sass, Libsass, and main Sass repos to see if a similar issue has already been submitted. Please also refer to our [Common Issues and Their Fixes](https://github.com/dlmanning/gulp-sass/wiki/Common-Issues-and-Their-Fixes) page for some basic troubleshooting.
12+
* Before creating a new issue, perform a [cursory search](https://github.com/issues?utf8=%E2%9C%93&q=repo%3Adlmanning%2Fgulp-sass+repo%3Asass%2Fdart-sass+repo%3Asass%2Fnode-sass+repo%3Asass%2Flibsass+repo%3Asass%2Fsass+repo%3Asass-eyeglass%2Feyeglass) in the Gulp Sass, Dart Sass, Node Sass, Libsass, and main Sass repos to see if a similar issue has already been submitted. Please also refer to our [Common Issues and Their Fixes](https://github.com/dlmanning/gulp-sass/wiki/Common-Issues-and-Their-Fixes) page for some basic troubleshooting.
813
* You can create an issue [here](https://github.com/dlmanning/gulp-sass/issues). Please include as many details as possible in your report.
914
* Issue titles should be descriptive, explaining at the high level what it is about.
1015
* Please include the version of `gulp-sass`, Node, and NPM you are using, as well as what operating system you are having a problem on.

‎README.md

+15-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Only [Active LTS and Current releases][1] are supported.
1313
# Install
1414

1515
```
16-
npm install gulp-sass --save-dev
16+
npm install sass gulp-sass --save-dev
1717
```
1818

1919
# Basic Usage
@@ -24,7 +24,7 @@ Something like this will compile your Sass files:
2424
'use strict';
2525

2626
var gulp = require('gulp');
27-
var sass = require('gulp-sass');
27+
var sass = require('gulp-sass')(require('sass'));
2828

2929
gulp.task('sass', function () {
3030
return gulp.src('./sass/**/*.scss')
@@ -43,7 +43,7 @@ You can also compile synchronously, doing something like this:
4343
'use strict';
4444

4545
var gulp = require('gulp');
46-
var sass = require('gulp-sass');
46+
var sass = require('gulp-sass')(require('sass'));
4747

4848
gulp.task('sass', function () {
4949
return gulp.src('./sass/**/*.scss')
@@ -58,7 +58,12 @@ gulp.task('sass:watch', function () {
5858

5959
## Options
6060

61-
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`. Except for the `data` option which is used by gulp-sass internally. Using the `file` option is also unsupported and results in undefined behaviour that may change without notice.
61+
`gulp-sass` supports both [Dart Sass][] and [Node Sass][]. You choose which one to use by writing either `require('gulp-sass')(require('sass'))` for Dart Sass or `require('gulp-sass')(require('node-sass'))` for Node Sass. One or the other must be passed in.
62+
63+
[Dart Sass]: http://sass-lang.com/dart-sass
64+
[Node Sass]: https://github.com/sass/node-sass
65+
66+
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. Except for the `data` option which is used by gulp-sass internally. Using the `file` option is also unsupported and results in undefined behaviour that may change without notice.
6267

6368
For example:
6469

@@ -111,10 +116,13 @@ gulp.task('sass', function () {
111116

112117
# Issues
113118

114-
`gulp-sass` is a very light-weight wrapper around [`node-sass`](https://github.com/sass/node-sass), which in turn is a Node binding for [`libsass`](https://github.com/sass/libsass), which in turn is a port of [`Sass`](https://github.com/sass/sass). Because of this, the issue you're having likely isn't a `gulp-sass` issue, but an issue with one of those three projects.
119+
`gulp-sass` is a very light-weight wrapper around either [Dart Sass][] or [Node Sass][] (which in turn is a Node binding for [LibSass][]. Because of this, the issue you're having likely isn't a `gulp-sass` issue, but an issue with one those projects or with [Sass][] as a whole.
120+
121+
[LibSass]: https://sass-lang.com/libsass
122+
[Sass]: https://sass-lang.com
115123

116-
If you have a feature request/question how Sass works/concerns on how your Sass gets compiled/errors in your compiling, it's likely a `libsass` or `Sass` issue and you should file your issue with one of those projects.
124+
If you have a feature request/question how Sass works/concerns on how your Sass gets compiled/errors in your compiling, it's likely a Dart Sass or LibSass issue and you should file your issue with one of those projects.
117125

118-
If you're having problems with the options you're passing in, it's likely a `node-sass` or `libsass` issue and you should file your issue with one of those projects.
126+
If you're having problems with the options you're passing in, it's likely a Dart Sass or Node Sass issue and you should file your issue with one of those projects.
119127

120128
We may, in the course of resolving issues, direct you to one of these other projects. If we do so, please follow up by searching that project's issue queue (both open and closed) for your problem and, if it doesn't exist, filing an issue with them.

‎index.js

+133-128
Original file line numberDiff line numberDiff line change
@@ -9,156 +9,161 @@ const applySourceMap = require('vinyl-sourcemaps-apply');
99

1010
const PLUGIN_NAME = 'gulp-sass';
1111

12-
//////////////////////////////
13-
// Main Gulp Sass function
14-
//////////////////////////////
15-
const gulpSass = (options, sync) => through.obj((file, enc, cb) => { // eslint-disable-line consistent-return
16-
if (file.isNull()) {
17-
return cb(null, file);
12+
module.exports = (compiler) => {
13+
if (!compiler || !compiler.render) {
14+
throw new PluginError(
15+
PLUGIN_NAME,
16+
'gulp-sass 5 requires you to pass in a Sass implementation. For example:\n\n' +
17+
' var sass = require(\'gulp-sass\')(require(\'node-sass\'));\n',
18+
);
1819
}
1920

20-
if (file.isStream()) {
21-
return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
22-
}
21+
//////////////////////////////
22+
// Main Gulp Sass function
23+
//////////////////////////////
24+
const gulpSass = (options, sync) => through.obj((file, enc, cb) => { // eslint-disable-line consistent-return
25+
if (file.isNull()) {
26+
return cb(null, file);
27+
}
2328

24-
if (path.basename(file.path).indexOf('_') === 0) {
25-
return cb();
26-
}
29+
if (file.isStream()) {
30+
return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
31+
}
2732

28-
if (!file.contents.length) {
29-
file.path = replaceExtension(file.path, '.css'); // eslint-disable-line no-param-reassign
30-
return cb(null, file);
31-
}
33+
if (path.basename(file.path).indexOf('_') === 0) {
34+
return cb();
35+
}
3236

33-
const opts = clonedeep(options || {});
34-
opts.data = file.contents.toString();
37+
if (!file.contents.length) {
38+
file.path = replaceExtension(file.path, '.css'); // eslint-disable-line no-param-reassign
39+
return cb(null, file);
40+
}
3541

36-
// we set the file path here so that libsass can correctly resolve import paths
37-
opts.file = file.path;
42+
const opts = clonedeep(options || {});
43+
opts.data = file.contents.toString();
3844

39-
// Ensure `indentedSyntax` is true if a `.sass` file
40-
if (path.extname(file.path) === '.sass') {
41-
opts.indentedSyntax = true;
42-
}
45+
// we set the file path here so that libsass can correctly resolve import paths
46+
opts.file = file.path;
4347

44-
// Ensure file's parent directory in the include path
45-
if (opts.includePaths) {
46-
if (typeof opts.includePaths === 'string') {
47-
opts.includePaths = [opts.includePaths];
48+
// Ensure `indentedSyntax` is true if a `.sass` file
49+
if (path.extname(file.path) === '.sass') {
50+
opts.indentedSyntax = true;
4851
}
49-
} else {
50-
opts.includePaths = [];
51-
}
5252

53-
opts.includePaths.unshift(path.dirname(file.path));
54-
55-
// Generate Source Maps if plugin source-map present
56-
if (file.sourceMap) {
57-
opts.sourceMap = file.path;
58-
opts.omitSourceMapUrl = true;
59-
opts.sourceMapContents = true;
60-
}
61-
62-
//////////////////////////////
63-
// Handles returning the file to the stream
64-
//////////////////////////////
65-
const filePush = (sassObj) => {
66-
let sassMap;
67-
let sassMapFile;
68-
let sassFileSrc;
69-
let sassFileSrcPath;
70-
let sourceFileIndex;
71-
72-
// Build Source Maps!
73-
if (sassObj.map) {
74-
// Transform map into JSON
75-
sassMap = JSON.parse(sassObj.map.toString());
76-
// Grab the stdout and transform it into stdin
77-
sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
78-
// Grab the base file name that's being worked on
79-
sassFileSrc = file.relative;
80-
// Grab the path portion of the file that's being worked on
81-
sassFileSrcPath = path.dirname(sassFileSrc);
82-
if (sassFileSrcPath) {
83-
// Prepend the path to all files in the sources array except the file that's being worked on
84-
sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
85-
sassMap.sources = sassMap.sources.map((source, index) => { // eslint-disable-line arrow-body-style
86-
return index === sourceFileIndex ? source : path.join(sassFileSrcPath, source);
87-
});
53+
// Ensure file's parent directory in the include path
54+
if (opts.includePaths) {
55+
if (typeof opts.includePaths === 'string') {
56+
opts.includePaths = [opts.includePaths];
8857
}
89-
90-
// Remove 'stdin' from souces and replace with filenames!
91-
sassMap.sources = sassMap.sources.filter(src => src !== 'stdin' && src);
92-
93-
// Replace the map file with the original file name (but new extension)
94-
sassMap.file = replaceExtension(sassFileSrc, '.css');
95-
// Apply the map
96-
applySourceMap(file, sassMap);
58+
} else {
59+
opts.includePaths = [];
9760
}
9861

99-
file.contents = sassObj.css; // eslint-disable-line no-param-reassign
100-
file.path = replaceExtension(file.path, '.css'); // eslint-disable-line no-param-reassign
101-
102-
cb(null, file);
103-
};
104-
105-
//////////////////////////////
106-
// Handles error message
107-
//////////////////////////////
108-
const errorM = (error) => {
109-
const filePath = (error.file === 'stdin' ? file.path : error.file) || file.path;
110-
const relativePath = path.relative(process.cwd(), filePath);
111-
const message = [chalk.underline(relativePath), error.formatted].join('\n');
112-
113-
error.messageFormatted = message; // eslint-disable-line no-param-reassign
114-
error.messageOriginal = error.message; // eslint-disable-line no-param-reassign
115-
error.message = stripAnsi(message); // eslint-disable-line no-param-reassign
116-
error.relativePath = relativePath; // eslint-disable-line no-param-reassign
62+
opts.includePaths.unshift(path.dirname(file.path));
11763

118-
return cb(new PluginError(PLUGIN_NAME, error));
119-
};
64+
// Generate Source Maps if plugin source-map present
65+
if (file.sourceMap) {
66+
opts.sourceMap = file.path;
67+
opts.omitSourceMapUrl = true;
68+
opts.sourceMapContents = true;
69+
}
12070

121-
if (sync !== true) {
12271
//////////////////////////////
123-
// Async Sass render
72+
// Handles returning the file to the stream
12473
//////////////////////////////
125-
const callback = (error, obj) => { // eslint-disable-line consistent-return
126-
if (error) {
127-
return errorM(error);
74+
const filePush = (sassObj) => {
75+
let sassMap;
76+
let sassMapFile;
77+
let sassFileSrc;
78+
let sassFileSrcPath;
79+
let sourceFileIndex;
80+
81+
// Build Source Maps!
82+
if (sassObj.map) {
83+
// Transform map into JSON
84+
sassMap = JSON.parse(sassObj.map.toString());
85+
// Grab the stdout and transform it into stdin
86+
sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
87+
// Grab the base file name that's being worked on
88+
sassFileSrc = file.relative;
89+
// Grab the path portion of the file that's being worked on
90+
sassFileSrcPath = path.dirname(sassFileSrc);
91+
if (sassFileSrcPath) {
92+
// Prepend the path to all files in the sources array except the file that's being worked on
93+
sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
94+
sassMap.sources = sassMap.sources.map((source, index) => { // eslint-disable-line arrow-body-style
95+
return index === sourceFileIndex ? source : path.join(sassFileSrcPath, source);
96+
});
97+
}
98+
99+
// Remove 'stdin' from souces and replace with filenames!
100+
sassMap.sources = sassMap.sources.filter(src => src !== 'stdin' && src);
101+
102+
// Replace the map file with the original file name (but new extension)
103+
sassMap.file = replaceExtension(sassFileSrc, '.css');
104+
// Apply the map
105+
applySourceMap(file, sassMap);
128106
}
129-
filePush(obj);
107+
108+
file.contents = sassObj.css; // eslint-disable-line no-param-reassign
109+
file.path = replaceExtension(file.path, '.css'); // eslint-disable-line no-param-reassign
110+
111+
cb(null, file);
130112
};
131113

132-
gulpSass.compiler.render(opts, callback);
133-
} else {
134114
//////////////////////////////
135-
// Sync Sass render
115+
// Handles error message
136116
//////////////////////////////
137-
try {
138-
filePush(gulpSass.compiler.renderSync(opts));
139-
} catch (error) {
140-
return errorM(error);
117+
const errorM = (error) => {
118+
const filePath = (error.file === 'stdin' ? file.path : error.file) || file.path;
119+
const relativePath = path.relative(process.cwd(), filePath);
120+
const message = [chalk.underline(relativePath), error.formatted].join('\n');
121+
122+
error.messageFormatted = message; // eslint-disable-line no-param-reassign
123+
error.messageOriginal = error.message; // eslint-disable-line no-param-reassign
124+
error.message = stripAnsi(message); // eslint-disable-line no-param-reassign
125+
error.relativePath = relativePath; // eslint-disable-line no-param-reassign
126+
127+
return cb(new PluginError(PLUGIN_NAME, error));
128+
};
129+
130+
if (sync !== true) {
131+
//////////////////////////////
132+
// Async Sass render
133+
//////////////////////////////
134+
const callback = (error, obj) => { // eslint-disable-line consistent-return
135+
if (error) {
136+
return errorM(error);
137+
}
138+
filePush(obj);
139+
};
140+
141+
compiler.render(opts, callback);
142+
} else {
143+
//////////////////////////////
144+
// Sync Sass render
145+
//////////////////////////////
146+
try {
147+
filePush(compiler.renderSync(opts));
148+
} catch (error) {
149+
return errorM(error);
150+
}
141151
}
142-
}
143-
});
144-
145-
//////////////////////////////
146-
// Sync Sass render
147-
//////////////////////////////
148-
gulpSass.sync = options => gulpSass(options, true);
149-
150-
//////////////////////////////
151-
// Log errors nicely
152-
//////////////////////////////
153-
gulpSass.logError = function logError(error) {
154-
const message = new PluginError('sass', error.messageFormatted).toString();
155-
process.stderr.write(`${message}\n`);
156-
this.emit('end');
157-
};
152+
});
158153

159-
//////////////////////////////
160-
// Store compiler in a prop
161-
//////////////////////////////
162-
gulpSass.compiler = require('node-sass');
154+
//////////////////////////////
155+
// Sync Sass render
156+
//////////////////////////////
157+
gulpSass.sync = options => gulpSass(options, true);
163158

164-
module.exports = gulpSass;
159+
//////////////////////////////
160+
// Log errors nicely
161+
//////////////////////////////
162+
gulpSass.logError = function logError(error) {
163+
const message = new PluginError('sass', error.messageFormatted).toString();
164+
process.stderr.write(`${message}\n`);
165+
this.emit('end');
166+
};
167+
168+
return gulpSass;
169+
};

‎package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gulp-sass",
3-
"version": "4.0.1",
3+
"version": "5.0.0",
44
"description": "Gulp plugin for sass",
55
"main": "index.js",
66
"engines": {
@@ -26,7 +26,6 @@
2626
"dependencies": {
2727
"chalk": "^2.3.0",
2828
"lodash.clonedeep": "^4.3.2",
29-
"node-sass": "^4.8.3",
3029
"plugin-error": "^1.0.1",
3130
"replace-ext": "^1.0.0",
3231
"strip-ansi": "^4.0.0",
@@ -44,6 +43,7 @@
4443
"gulp-sourcemaps": "^2.6.4",
4544
"gulp-tap": "^0.1.3",
4645
"mocha": "^5.0.4",
46+
"node-sass": "^4.8.3",
4747
"rimraf": "^2.4.3",
4848
"should": "^13.2.1",
4949
"vinyl": "^2.1.0"

‎test/main.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const should = require('should');
22
const Vinyl = require('vinyl');
33
const path = require('path');
44
const fs = require('fs');
5-
const sass = require('../index');
5+
const sass = require('../index')(require('node-sass'));
66
const rimraf = require('rimraf');
77
const gulp = require('gulp');
88
const sourcemaps = require('gulp-sourcemaps');

0 commit comments

Comments
 (0)
Please sign in to comment.