Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor tweaks and cleanup #822

Merged
merged 4 commits into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ env:
mocha: true
node: true

extends: "airbnb-base"

parserOptions:
sourceType: "script"

rules:
max-len:
- 2
- 120

extends: "airbnb-base"
no-multi-assign: "off"
xzyfer marked this conversation as resolved.
Show resolved Hide resolved
no-param-reassign: "off"
strict:
- "error"
- "safe"
206 changes: 107 additions & 99 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

const path = require('path');
const chalk = require('chalk');
const PluginError = require('plugin-error');
Expand All @@ -9,31 +11,103 @@ const applySourceMap = require('vinyl-sourcemaps-apply');

const PLUGIN_NAME = 'gulp-sass';

/// ///////////////////////////
// Main Gulp Sass function
/// ///////////////////////////
const gulpSass = (options, sync) => transfob((file, enc, cb) => { // eslint-disable-line consistent-return
const MISSING_COMPILER_MESSAGE = `
gulp-sass 5 does not have a default Sass compiler; please set one yourself.
Both the "sass" and "node-sass" packages are permitted.
For example, in your gulpfile:

const sass = require('gulp-sass')(require('sass'));
`;

/**
* Handles returning the file to the stream
*/
const filePush = (file, sassObject, callback) => {
// Build Source Maps!
if (sassObject.map) {
// Transform map into JSON
const sassMap = JSON.parse(sassObject.map.toString());
// Grab the stdout and transform it into stdin
const sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
// Grab the base filename that's being worked on
const sassFileSrc = file.relative;
// Grab the path portion of the file that's being worked on
const sassFileSrcPath = path.dirname(sassFileSrc);

if (sassFileSrcPath) {
const sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
// Prepend the path to all files in the sources array except the file that's being worked on
sassMap.sources = sassMap.sources.map((source, index) => (
index === sourceFileIndex
? source
: path.join(sassFileSrcPath, source)
));
}

// Remove 'stdin' from souces and replace with filenames!
sassMap.sources = sassMap.sources.filter((src) => src !== 'stdin' && src);

// Replace the map file with the original filename (but new extension)
sassMap.file = replaceExtension(sassFileSrc, '.css');
// Apply the map
applySourceMap(file, sassMap);
}

file.contents = sassObject.css;
file.path = replaceExtension(file.path, '.css');

if (file.stat) {
file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
}

callback(null, file);
};

/**
* Handles error message
*/
const handleError = (error, file, callback) => {
const filePath = (error.file === 'stdin' ? file.path : error.file) || file.path;
const relativePath = path.relative(process.cwd(), filePath);
const message = [chalk.underline(relativePath), error.formatted].join('\n');

error.messageFormatted = message;
error.messageOriginal = error.message;
error.message = stripAnsi(message);
error.relativePath = relativePath;

return callback(new PluginError(PLUGIN_NAME, error));
};

/**
* Main Gulp Sass function
*/

// eslint-disable-next-line arrow-body-style
const gulpSass = (options, sync) => {
// eslint-disable-next-line consistent-return
return transfob((file, encoding, callback) => {
if (file.isNull()) {
return cb(null, file);
return callback(null, file);
}

if (file.isStream()) {
return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
return callback(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
}

if (path.basename(file.path).startsWith('_')) {
return cb();
return callback();
}

if (!file.contents.length) {
file.path = replaceExtension(file.path, '.css'); // eslint-disable-line no-param-reassign
return cb(null, file);
file.path = replaceExtension(file.path, '.css');
return callback(null, file);
}

const opts = clonedeep(options || {});
opts.data = file.contents.toString();

// we set the file path here so that libsass can correctly resolve import paths
// We set the file path here so that libsass can correctly resolve import paths
opts.file = file.path;

// Ensure `indentedSyntax` is true if a `.sass` file
Expand All @@ -52,108 +126,46 @@ const gulpSass = (options, sync) => transfob((file, enc, cb) => { // eslint-disa

opts.includePaths.unshift(path.dirname(file.path));

// Generate Source Maps if plugin source-map present
// Generate Source Maps if the source-map plugin is present
if (file.sourceMap) {
opts.sourceMap = file.path;
opts.omitSourceMapUrl = true;
opts.sourceMapContents = true;
}

/// ///////////////////////////
// Handles returning the file to the stream
/// ///////////////////////////
const filePush = (sassObj) => {
let sassMap;
let sassMapFile;
let sassFileSrc;
let sassFileSrcPath;
let sourceFileIndex;

// Build Source Maps!
if (sassObj.map) {
// Transform map into JSON
sassMap = JSON.parse(sassObj.map.toString());
// Grab the stdout and transform it into stdin
sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
// Grab the base file name that's being worked on
sassFileSrc = file.relative;
// Grab the path portion of the file that's being worked on
sassFileSrcPath = path.dirname(sassFileSrc);
if (sassFileSrcPath) {
// Prepend the path to all files in the sources array except the file that's being worked on
sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
sassMap.sources = sassMap.sources.map((source, index) => { // eslint-disable-line arrow-body-style
return index === sourceFileIndex ? source : path.join(sassFileSrcPath, source);
});
}

// Remove 'stdin' from souces and replace with filenames!
sassMap.sources = sassMap.sources.filter((src) => src !== 'stdin' && src);

// Replace the map file with the original file name (but new extension)
sassMap.file = replaceExtension(sassFileSrc, '.css');
// Apply the map
applySourceMap(file, sassMap);
}

file.contents = sassObj.css; // eslint-disable-line no-param-reassign
file.path = replaceExtension(file.path, '.css'); // eslint-disable-line no-param-reassign

if (file.stat) {
file.stat.atime = file.stat.mtime = file.stat.ctime = new Date(); // eslint-disable-line
}

cb(null, file);
};

/// ///////////////////////////
// Handles error message
/// ///////////////////////////
const errorM = (error) => {
const filePath = (error.file === 'stdin' ? file.path : error.file) || file.path;
const relativePath = path.relative(process.cwd(), filePath);
const message = [chalk.underline(relativePath), error.formatted].join('\n');

error.messageFormatted = message; // eslint-disable-line no-param-reassign
error.messageOriginal = error.message; // eslint-disable-line no-param-reassign
error.message = stripAnsi(message); // eslint-disable-line no-param-reassign
error.relativePath = relativePath; // eslint-disable-line no-param-reassign

return cb(new PluginError(PLUGIN_NAME, error));
};

if (sync !== true) {
/// ///////////////////////////
// Async Sass render
/// ///////////////////////////
const callback = (error, obj) => { // eslint-disable-line consistent-return
/**
* Async Sass render
*/
// eslint-disable-next-line consistent-return
gulpSass.compiler.render(opts, (error, obj) => {
if (error) {
return errorM(error);
return handleError(error, file, callback);
}
filePush(obj);
};

gulpSass.compiler.render(opts, callback);
filePush(file, obj, callback);
});
} else {
/// ///////////////////////////
// Sync Sass render
/// ///////////////////////////
/**
* Sync Sass render
*/
try {
filePush(gulpSass.compiler.renderSync(opts));
filePush(file, gulpSass.compiler.renderSync(opts), callback);
} catch (error) {
return errorM(error);
return handleError(error, file, callback);
}
}
});
};

/// ///////////////////////////
// Sync Sass render
/// ///////////////////////////
/**
* Sync Sass render
*/
gulpSass.sync = (options) => gulpSass(options, true);

/// ///////////////////////////
// Log errors nicely
/// ///////////////////////////
/**
* Log errors nicely
*/
gulpSass.logError = function logError(error) {
const message = new PluginError('sass', error.messageFormatted).toString();
process.stderr.write(`${message}\n`);
Expand All @@ -164,17 +176,13 @@ module.exports = (compiler) => {
if (!compiler || !compiler.render) {
const message = new PluginError(
PLUGIN_NAME,
'\n'
+ 'gulp-sass 5 does not have a default Sass compiler; please set one yourself.\n'
+ 'Both the `sass` and `node-sass` packages are permitted.\n'

+ 'For example, in your gulpfile:\n\n'
+ ' var sass = require(\'gulp-sass\')(require(\'sass\'));\n',
MISSING_COMPILER_MESSAGE,
{ showProperties: false },
).toString();
process.stderr.write(`${message}\n`);
process.exit(1);
}

gulpSass.compiler = compiler;
return gulpSass;
};
2 changes: 2 additions & 0 deletions test/main.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

const fs = require('fs');
const path = require('path');
const should = require('should');
Expand Down