Skip to content

Commit

Permalink
refactor: code (#745)
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi committed Aug 23, 2019
1 parent fcea88e commit fab50ab
Show file tree
Hide file tree
Showing 15 changed files with 91,580 additions and 335 deletions.
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
testEnvironment: 'node',
};
61 changes: 15 additions & 46 deletions src/getRenderFunctionFromSassImplementation.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,33 @@
import semver from 'semver';
import async from 'neo-async';

let nodeSassJobQueue = null;

/**
* Verifies that the implementation and version of Sass is supported by this loader.
*
* @param {Object} module
* @param {Object} implementation
* @returns {Function}
*/
function getRenderFunctionFromSassImplementation(module) {
const { info } = module;
function getRenderFunctionFromSassImplementation(implementation) {
const isDartSass = implementation.info.includes('dart-sass');

if (!info) {
throw new Error('Unknown Sass implementation.');
if (isDartSass) {
return implementation.render.bind(implementation);
}

const components = info.split('\t');
// 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
if (nodeSassJobQueue === null) {
const threadPoolSize = Number(process.env.UV_THREADPOOL_SIZE || 4);

if (components.length < 2) {
throw new Error(`Unknown Sass implementation "${info}".`);
nodeSassJobQueue = async.queue(
implementation.render.bind(implementation),
threadPoolSize - 1
);
}

const [implementation, version] = components;

if (!semver.valid(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.`
);
}

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.`
);
}

// 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
if (nodeSassJobQueue === null) {
const threadPoolSize = Number(process.env.UV_THREADPOOL_SIZE || 4);

nodeSassJobQueue = async.queue(
module.render.bind(module),
threadPoolSize - 1
);
}

return nodeSassJobQueue.push.bind(nodeSassJobQueue);
}

throw new Error(`Unknown Sass implementation "${implementation}".`);
return nodeSassJobQueue.push.bind(nodeSassJobQueue);
}

export default getRenderFunctionFromSassImplementation;
48 changes: 48 additions & 0 deletions src/getSassImplementation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import semver from 'semver';

import getDefaultSassImplementation from './getDefaultSassImplementation';

function getSassImplementation(implementation) {
let resolvedImplementation = implementation;

if (!resolvedImplementation) {
// eslint-disable-next-line no-param-reassign
resolvedImplementation = getDefaultSassImplementation();
}

const { info } = resolvedImplementation;

if (!info) {
throw new Error('Unknown Sass implementation.');
}

const infoParts = info.split('\t');

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

const [implementationName, version] = infoParts;

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

return resolvedImplementation;
} else if (implementationName === 'node-sass') {
if (!semver.satisfies(version, '^4.0.0')) {
throw new Error(
`Node Sass version ${version} is incompatible with ^4.0.0.`
);
}

return resolvedImplementation;
}

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

export default getSassImplementation;
8 changes: 4 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import validateOptions from 'schema-utils';
import { getOptions } from 'loader-utils';

import schema from './options.json';
import getSassImplementation from './getSassImplementation';
import getSassOptions from './getSassOptions';
import webpackImporter from './webpackImporter';
import getDefaultSassImplementation from './getDefaultSassImplementation';
import getRenderFunctionFromSassImplementation from './getRenderFunctionFromSassImplementation';
import SassError from './SassError';

Expand All @@ -24,6 +24,8 @@ function loader(content) {
baseDataPath: 'options',
});

const implementation = getSassImplementation(options.implementation);

const callback = this.async();
const addNormalizedDependency = (file) => {
// node-sass returns POSIX paths
Expand Down Expand Up @@ -55,9 +57,7 @@ function loader(content) {
return;
}

const render = getRenderFunctionFromSassImplementation(
options.implementation || getDefaultSassImplementation()
);
const render = getRenderFunctionFromSassImplementation(implementation);

render(sassOptions, (error, result) => {
if (error) {
Expand Down
2 changes: 1 addition & 1 deletion test/__snapshots__/implementation-option.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Error: Unknown Sass implementation "strange-sass".

exports[`implementation option should throw an error when the "info" is unparseable #2 1`] = `
[Error: Module build failed (from ../src/cjs.js):
Error: Invalid Sass version "1".
Error: Node Sass version 1 is incompatible with ^4.0.0.
at ReplacedStackEntry
at ReplacedStackEntry]
`;
Expand Down

0 comments on commit fab50ab

Please sign in to comment.