/
antdSassLoader.js
93 lines (76 loc) · 3.02 KB
/
antdSassLoader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import path from 'path';
import { getOptions, urlToRequest } from 'loader-utils';
import sassLoader from 'sass-loader';
import importsToResolve from 'sass-loader/dist/importsToResolve';
import { getScssThemePath } from './loaderUtils';
import {
compileThemeVariables,
} from './utils';
/**
* Utility returning a node-sass importer that provides access to all of antd's theme variables.
* @param {string} themeScssPath - Path to SCSS file containing Ant Design theme variables.
* @param {string} contents - The compiled content of the SCSS file at themeScssPath.
* @returns {function} Importer that provides access to all compiled Ant Design theme variables
* when importing the theme file at themeScssPath.
*/
export const themeImporter = (themeScssPath, contents) => (url, previousResolve, done) => {
const request = urlToRequest(url);
const pathsToTry = importsToResolve(request);
const baseDirectory = path.dirname(previousResolve);
for (let i = 0; i < pathsToTry.length; i += 1) {
const potentialResolve = pathsToTry[i];
if (path.resolve(baseDirectory, potentialResolve) === themeScssPath) {
done({ contents });
return;
}
}
done();
};
/**
* Modify sass-loader's options so that all antd variables are imported from the SCSS theme file.
* @param {Object} options - Options for sass-loader.
* @return {Object} Options modified to includ a custom importer that handles the SCSS theme file.
*/
export const overloadSassLoaderOptions = async (options) => {
const newOptions = { ...options };
const scssThemePath = getScssThemePath(options);
const contents = await compileThemeVariables(scssThemePath);
const extraImporter = themeImporter(scssThemePath, contents);
let importer;
if ('importer' in options) {
if (Array.isArray(options.importer)) {
importer = [...options.importer, extraImporter];
} else {
importer = [options.importer, extraImporter];
}
} else {
importer = extraImporter;
}
newOptions.importer = importer;
return newOptions;
};
/**
* A wrapper around sass-loader which overloads loader options to include a custom importer handling
* variable imports from the SCSS theme file, and registers the theme file as a watched dependency.
* @param {...*} args - Arguments passed to sass-loader.
* @return {undefined}
*/
export default function antdSassLoader(...args) {
const loaderContext = this;
const callback = loaderContext.async();
const options = getOptions(loaderContext);
const newLoaderContext = { ...loaderContext };
overloadSassLoaderOptions(options)
.then((newOptions) => {
delete newOptions.scssThemePath; // eslint-disable-line no-param-reassign
newLoaderContext.query = newOptions;
const scssThemePath = getScssThemePath(options);
newLoaderContext.addDependency(scssThemePath);
return sassLoader.call(newLoaderContext, ...args);
})
.catch((error) => {
// Remove unhelpful stack from error.
error.stack = undefined; // eslint-disable-line no-param-reassign
callback(error);
});
}