Skip to content

Commit

Permalink
chore: migrate on defaults eslint config (#643)
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi committed Dec 13, 2018
1 parent a80cdb1 commit bc3b848
Show file tree
Hide file tree
Showing 22 changed files with 489 additions and 128 deletions.
8 changes: 8 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
root: true,
extends: ['@webpack-contrib/eslint-config-webpack'],
rules: {
// Remove strict rule in next major
"strict": "off",
},
};
9 changes: 0 additions & 9 deletions .eslintrc.json

This file was deleted.

2 changes: 1 addition & 1 deletion .nycrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"lines": 97,
"statements": 97,
"functions": 100,
"branches": 91,
"branches": 90,
"check-coverage": true
}
33 changes: 19 additions & 14 deletions lib/formatSassError.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ const os = require("os");
const fs = require("fs");

// A typical sass error looks like this
const SassError = { // eslint-disable-line no-unused-vars
message: "invalid property name",
column: 14,
line: 1,
file: "stdin",
status: 1
};
// const SassError = {
// message: "invalid property name",
// column: 14,
// line: 1,
// file: "stdin",
// status: 1
// };

/**
* Enhances the sass error with additional information about what actually went wrong.
Expand All @@ -22,6 +22,7 @@ const SassError = { // eslint-disable-line no-unused-vars
function formatSassError(err, resourcePath) {
// Instruct webpack to hide the JS stack from the console
// Usually you're only interested in the SASS stack in this case.
// eslint-disable-next-line no-param-reassign
err.hideStack = true;

// The file property is missing in rare cases.
Expand All @@ -33,18 +34,22 @@ function formatSassError(err, resourcePath) {
let msg = err.message;

if (err.file === "stdin") {
// eslint-disable-next-line no-param-reassign
err.file = resourcePath;
}

// node-sass returns UNIX-style paths
// eslint-disable-next-line no-param-reassign
err.file = path.normalize(err.file);

// The 'Current dir' hint of node-sass does not help us, we're providing
// additional information by reading the err.file property
msg = msg.replace(/\s*Current dir:\s*/, "");

err.message = getFileExcerptIfPossible(err) +
msg.charAt(0).toUpperCase() + msg.slice(1) + os.EOL +
" in " + err.file + " (line " + err.line + ", column " + err.column + ")";
// eslint-disable-next-line no-param-reassign
err.message = `${getFileExcerptIfPossible(err) +
msg.charAt(0).toUpperCase() + msg.slice(1) + os.EOL
} in ${ err.file } (line ${ err.line }, column ${ err.column })`;
}

/**
Expand All @@ -60,11 +65,11 @@ function getFileExcerptIfPossible(err) {
try {
const content = fs.readFileSync(err.file, "utf8");

return os.EOL +
return `${os.EOL +
content.split(os.EOL)[err.line - 1] + os.EOL +
new Array(err.column - 1).join(" ") + "^" + os.EOL +
" ";
} catch (err) {
new Array(err.column - 1).join(" ") }^${ os.EOL
} `;
} catch (ignoreErr) {
// If anything goes wrong here, we don't want any errors to be reported to the user
return "";
}
Expand Down
3 changes: 2 additions & 1 deletion lib/importsToResolve.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"use strict";

const path = require("path");

const utils = require("loader-utils");

const matchModuleImport = /^~([^\/]+|@[^\/]+[\/][^\/]+)$/;
const matchModuleImport = /^~([^/]+|@[^/]+[/][^/]+)$/;

/**
* When libsass tries to resolve an import, it uses a special algorithm.
Expand Down
42 changes: 30 additions & 12 deletions lib/loader.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
"use strict";

const path = require("path");

const async = require("neo-async");

const pify = require("pify");

const semver = require("semver");

const formatSassError = require("./formatSassError");
const webpackImporter = require("./webpackImporter");
const normalizeOptions = require("./normalizeOptions");
const pify = require("pify");
const semver = require("semver");

let nodeSassJobQueue = null;

Expand All @@ -20,7 +24,7 @@ function sassLoader(content) {
const callback = this.async();
const isSync = typeof callback !== "function";
const self = this;
const resourcePath = this.resourcePath;
const { resourcePath } = this;

function addNormalizedDependency(file) {
// node-sass returns POSIX paths
Expand All @@ -43,36 +47,48 @@ function sassLoader(content) {
return;
}

// eslint-disable-next-line import/no-extraneous-dependencies, global-require
const render = getRenderFuncFromSassImpl(options.implementation || require("node-sass"));

render(options, (err, result) => {
if (err) {
formatSassError(err, this.resourcePath);
err.file && this.dependency(err.file);

if (err.file) {
this.dependency(err.file);
}

callback(err);
return;
}

if (result.map && result.map !== "{}") {
// eslint-disable-next-line no-param-reassign
result.map = JSON.parse(result.map);
// result.map.file is an optional property that provides the output filename.
// Since we don't know the final filename in the webpack build chain yet, it makes no sense to have it.
// eslint-disable-next-line no-param-reassign
delete result.map.file;
// The first source is 'stdin' according to node-sass because we've used the data input.
// Now let's override that value with the correct relative path.
// Since we specified options.sourceMap = path.join(process.cwd(), "/sass.map"); in normalizeOptions,
// we know that this path is relative to process.cwd(). This is how node-sass works.
// eslint-disable-next-line no-param-reassign
result.map.sources[0] = path.relative(process.cwd(), resourcePath);
// node-sass returns POSIX paths, that's why we need to transform them back to native paths.
// This fixes an error on windows where the source-map module cannot resolve the source maps.
// @see https://github.com/webpack-contrib/sass-loader/issues/366#issuecomment-279460722
// eslint-disable-next-line no-param-reassign
result.map.sourceRoot = path.normalize(result.map.sourceRoot);
// eslint-disable-next-line no-param-reassign
result.map.sources = result.map.sources.map(path.normalize);
} else {
// eslint-disable-next-line no-param-reassign
result.map = null;
}

result.stats.includedFiles.forEach(addNormalizedDependency);

callback(null, result.css.toString(), result.map);
});
}
Expand All @@ -84,29 +100,30 @@ function sassLoader(content) {
* @returns {Function}
*/
function getRenderFuncFromSassImpl(module) {
const info = module.info;
const { info } = module;
const components = info.split("\t");

if (components.length < 2) {
throw new Error("Unknown Sass implementation \"" + info + "\".");
throw new Error(`Unknown Sass implementation "${ info }".`);
}

const implementation = components[0];
const version = components[1];
const [implementation, version] = components;

if (!semver.valid(version)) {
throw new Error("Invalid Sass version \"" + version + "\".");
throw new Error(`Invalid Sass version "${ version }".`);
}

if (implementation === "dart-sass") {
if (!semver.satisfies(version, "^1.3.0")) {
throw new Error("Dart Sass version " + version + " is incompatible with ^1.3.0.");
throw new Error(`Dart Sass version ${ version } is incompatible with ^1.3.0.`);
}

return module.render.bind(module);
} else if (implementation === "node-sass") {
if (!semver.satisfies(version, "^4.0.0")) {
throw new Error("Node Sass version " + version + " is incompatible with ^4.0.0.");
throw new Error(`Node Sass version ${ version } is incompatible with ^4.0.0.`);
}

// There is an issue with node-sass when async custom importers are used
// See https://github.com/sass/node-sass/issues/857#issuecomment-93594360
// We need to use a job queue to make sure that one thread is always available to the UV lib
Expand All @@ -118,7 +135,8 @@ function getRenderFuncFromSassImpl(module) {

return nodeSassJobQueue.push.bind(nodeSassJobQueue);
}
throw new Error("Unknown Sass implementation \"" + implementation + "\".");

throw new Error(`Unknown Sass implementation "${ implementation }".`);
}

module.exports = sassLoader;
6 changes: 4 additions & 2 deletions lib/normalizeOptions.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"use strict";

const os = require("os");
const path = require("path");

const utils = require("loader-utils");
const cloneDeep = require("clone-deep");
const path = require("path");

const proxyCustomImporters = require("./proxyCustomImporters");

/**
Expand All @@ -19,7 +21,7 @@ const proxyCustomImporters = require("./proxyCustomImporters");
*/
function normalizeOptions(loaderContext, content, webpackImporter) {
const options = cloneDeep(utils.getOptions(loaderContext)) || {};
const resourcePath = loaderContext.resourcePath;
const { resourcePath } = loaderContext;

options.data = options.data ? (options.data + os.EOL + content) : content;

Expand Down
11 changes: 6 additions & 5 deletions lib/proxyCustomImporters.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
* @returns {Array<Function>}
*/
function proxyCustomImporters(importer, resourcePath) {
return [].concat(importer).map((importer) => {
return function (url, prev, done) {
return [].concat(importer).map(
// eslint-disable-next-line no-shadow
(importer) => function customImporter() {
return importer.apply(
this, // eslint-disable-line no-invalid-this
this,
// eslint-disable-next-line prefer-rest-params
Array.from(arguments)
.map((arg, i) => i === 1 && arg === "stdin" ? resourcePath : arg)
);
};
});
});
}

module.exports = proxyCustomImporters;
8 changes: 6 additions & 2 deletions lib/webpackImporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
*/

const path = require("path");

const tail = require("lodash.tail");

const importsToResolve = require("./importsToResolve");

const matchCss = /\.css$/;
Expand All @@ -41,6 +43,7 @@ function webpackImporter(resourcePath, resolve, addNormalizedDependency) {
);
}

// eslint-disable-next-line no-shadow
function startResolving(dir, importsToResolve) {
return importsToResolve.length === 0 ?
Promise.reject() :
Expand All @@ -63,8 +66,9 @@ function webpackImporter(resourcePath, resolve, addNormalizedDependency) {
startResolving(
dirContextFrom(prev),
importsToResolve(url)
) // Catch all resolving errors, return the original file and pass responsibility back to other custom importers
.catch(() => ({ file: url }))
)
// Catch all resolving errors, return the original file and pass responsibility back to other custom importers
.catch(() => { return { file: url } })
.then(done);
};
}
Expand Down
Loading

0 comments on commit bc3b848

Please sign in to comment.