3 var gutil = require('gulp-util');
4 var through = require('through2');
5 var clonedeep = require('lodash.clonedeep');
6 var path = require('path');
7 var applySourceMap = require('vinyl-sourcemaps-apply');
9 var PLUGIN_NAME = 'gulp-sass';
11 //////////////////////////////
12 // Main Gulp Sass function
13 //////////////////////////////
14 var gulpSass = function gulpSass(options, sync) {
15 return through.obj(function(file, enc, cb) {
23 return cb(null, file);
25 if (file.isStream()) {
26 return cb(new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'));
28 if (path.basename(file.path).indexOf('_') === 0) {
31 if (!file.contents.length) {
32 file.path = gutil.replaceExtension(file.path, '.css');
33 return cb(null, file);
37 opts = clonedeep(options || {});
38 opts.data = file.contents.toString();
40 // we set the file path here so that libsass can correctly resolve import paths
41 opts.file = file.path;
43 // Ensure `indentedSyntax` is true if a `.sass` file
44 if (path.extname(file.path) === '.sass') {
45 opts.indentedSyntax = true;
48 // Ensure file's parent directory in the include path
49 if (opts.includePaths) {
50 if (typeof opts.includePaths === 'string') {
51 opts.includePaths = [opts.includePaths];
55 opts.includePaths = [];
58 opts.includePaths.unshift(path.dirname(file.path));
60 // Generate Source Maps if plugin source-map present
62 opts.sourceMap = file.path;
63 opts.omitSourceMapUrl = true;
64 opts.sourceMapContents = true;
67 //////////////////////////////
68 // Handles returning the file to the stream
69 //////////////////////////////
70 filePush = function filePush(sassObj) {
79 // Transform map into JSON
80 sassMap = JSON.parse(sassObj.map.toString());
81 // Grab the stdout and transform it into stdin
82 sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
83 // Grab the base file name that's being worked on
84 sassFileSrc = file.relative;
85 // Grab the path portion of the file that's being worked on
86 sassFileSrcPath = path.dirname(sassFileSrc);
87 if (sassFileSrcPath) {
88 //Prepend the path to all files in the sources array except the file that's being worked on
89 sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
90 sassMap.sources = sassMap.sources.map(function(source, index) {
91 return (index === sourceFileIndex) ? source : path.join(sassFileSrcPath, source);
95 // Remove 'stdin' from souces and replace with filenames!
96 sassMap.sources = sassMap.sources.filter(function(src) {
97 if (src !== 'stdin') {
102 // Replace the map file with the original file name (but new extension)
103 sassMap.file = gutil.replaceExtension(sassFileSrc, '.css');
105 applySourceMap(file, sassMap);
108 file.contents = sassObj.css;
109 file.path = gutil.replaceExtension(file.path, '.css');
114 //////////////////////////////
115 // Handles error message
116 //////////////////////////////
117 errorM = function errorM(error) {
118 var relativePath = '',
119 filePath = error.file === 'stdin' ? file.path : error.file,
122 filePath = filePath ? filePath : file.path;
123 relativePath = path.relative(process.cwd(), filePath);
125 message += gutil.colors.underline(relativePath) + '\n';
126 message += error.formatted;
128 error.messageFormatted = message;
129 error.messageOriginal = error.message;
130 error.message = gutil.colors.stripColor(message);
132 error.relativePath = relativePath;
134 return cb(new gutil.PluginError(
140 //////////////////////////////
142 //////////////////////////////
143 callback = function(error, obj) {
145 return errorM(error);
150 gulpSass.compiler.render(opts, callback);
153 //////////////////////////////
155 //////////////////////////////
157 result = gulpSass.compiler.renderSync(opts);
162 return errorM(error);
168 //////////////////////////////
170 //////////////////////////////
171 gulpSass.sync = function sync(options) {
172 return gulpSass(options, true);
175 //////////////////////////////
177 //////////////////////////////
178 gulpSass.logError = function logError(error) {
179 var message = new gutil.PluginError('sass', error.messageFormatted).toString();
180 process.stderr.write(message + '\n');
184 //////////////////////////////
185 // Store compiler in a prop
186 //////////////////////////////
187 gulpSass.compiler = require('node-sass');
189 module.exports = gulpSass;