Skip to content

Commit c502e48

Browse files
committed
feat: add missing loaders, add more tests
1 parent f30504b commit c502e48

File tree

5 files changed

+205
-44
lines changed

5 files changed

+205
-44
lines changed

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,8 +1089,8 @@ class Encore {
10891089
* Encore
10901090
* .enableEslintLoader()
10911091
* .enableVueLoader()
1092-
* .configureLoaderRule('eslint', (loader) => {
1093-
* loader.test = /\.(jsx?|vue)/;
1092+
* .configureLoaderRule('eslint', (loaderRule) => {
1093+
* loaderRule.test = /\.(jsx?|vue)/;
10941094
* });
10951095
*
10961096
* @param {string} name

lib/WebpackConfig.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,20 @@ class WebpackConfig {
100100
this.tsConfigurationCallback = () => {};
101101
this.handlebarsConfigurationCallback = () => {};
102102
this.loaderConfigurationCallbacks = {
103-
'eslint': () => {},
103+
javascript: () => {},
104+
js: () => {},
105+
css: () => {},
106+
images: () => {},
107+
fonts: () => {},
108+
sass: () => {},
109+
scss: () => {},
110+
less: () => {},
111+
stylus: () => {},
112+
vue: () => {},
113+
eslint: () => {},
114+
typescript: () => {},
115+
ts: () => {},
116+
handlebars: () => {},
104117
};
105118

106119
// Plugins options

lib/config-generator.js

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,24 @@ class ConfigGenerator {
228228
return applyOptionsCallback(this.webpackConfig.loaderConfigurationCallbacks[name], defaultRules);
229229
};
230230

231+
const applyRuleConfigurationCallbacks = (names, defaultRules) => {
232+
let rules = defaultRules;
233+
234+
names.forEach(name => {
235+
rules = applyRuleConfigurationCallback(name, rules);
236+
});
237+
238+
return rules;
239+
};
240+
231241
let rules = [
232-
{
242+
applyRuleConfigurationCallbacks(['javascript', 'js'], {
233243
// match .js and .jsx
234244
test: /\.jsx?$/,
235245
exclude: this.webpackConfig.babelOptions.exclude,
236-
use: babelLoaderUtil.getLoaders(this.webpackConfig)
237-
},
238-
{
246+
use: babelLoaderUtil.getLoaders(this.webpackConfig),
247+
}),
248+
applyRuleConfigurationCallback('css', {
239249
test: /\.css$/,
240250
oneOf: [
241251
{
@@ -252,7 +262,7 @@ class ConfigGenerator {
252262
)
253263
}
254264
]
255-
}
265+
})
256266
];
257267

258268
if (this.webpackConfig.useImagesLoader) {
@@ -276,11 +286,11 @@ class ConfigGenerator {
276286
Object.assign(loaderOptions, this.webpackConfig.urlLoaderOptions.images);
277287
}
278288

279-
rules.push({
289+
rules.push(applyRuleConfigurationCallback('images', {
280290
test: /\.(png|jpg|jpeg|gif|ico|svg|webp)$/,
281291
loader: loaderName,
282292
options: loaderOptions
283-
});
293+
}));
284294
}
285295

286296
if (this.webpackConfig.useFontsLoader) {
@@ -304,39 +314,39 @@ class ConfigGenerator {
304314
Object.assign(loaderOptions, this.webpackConfig.urlLoaderOptions.fonts);
305315
}
306316

307-
rules.push({
317+
rules.push(applyRuleConfigurationCallback('fonts', {
308318
test: /\.(woff|woff2|ttf|eot|otf)$/,
309319
loader: loaderName,
310320
options: loaderOptions
311-
});
321+
}));
312322
}
313323

314324
if (this.webpackConfig.useSassLoader) {
315-
rules.push({
325+
rules.push(applyRuleConfigurationCallbacks(['sass', 'scss'], {
316326
test: /\.s[ac]ss$/,
317327
use: cssExtractLoaderUtil.prependLoaders(this.webpackConfig, sassLoaderUtil.getLoaders(this.webpackConfig))
318-
});
328+
}));
319329
}
320330

321331
if (this.webpackConfig.useLessLoader) {
322-
rules.push({
332+
rules.push(applyRuleConfigurationCallback('less', {
323333
test: /\.less/,
324334
use: cssExtractLoaderUtil.prependLoaders(this.webpackConfig, lessLoaderUtil.getLoaders(this.webpackConfig))
325-
});
335+
}));
326336
}
327337

328338
if (this.webpackConfig.useStylusLoader) {
329-
rules.push({
339+
rules.push(applyRuleConfigurationCallback('stylus', {
330340
test: /\.styl/,
331341
use: cssExtractLoaderUtil.prependLoaders(this.webpackConfig, stylusLoaderUtil.getLoaders(this.webpackConfig))
332-
});
342+
}));
333343
}
334344

335345
if (this.webpackConfig.useVueLoader) {
336-
rules.push({
346+
rules.push(applyRuleConfigurationCallback('vue', {
337347
test: /\.vue$/,
338348
use: vueLoaderUtil.getLoaders(this.webpackConfig)
339-
});
349+
}));
340350
}
341351

342352
if (this.webpackConfig.useEslintLoader) {
@@ -350,18 +360,18 @@ class ConfigGenerator {
350360
}
351361

352362
if (this.webpackConfig.useTypeScriptLoader) {
353-
rules.push({
363+
rules.push(applyRuleConfigurationCallbacks(['typescript', 'ts'], {
354364
test: /\.tsx?$/,
355365
exclude: /node_modules/,
356366
use: tsLoaderUtil.getLoaders(this.webpackConfig)
357-
});
367+
}));
358368
}
359369

360370
if (this.webpackConfig.useHandlebarsLoader) {
361-
rules.push({
371+
rules.push(applyRuleConfigurationCallback('handlebars', {
362372
test: /\.(handlebars|hbs)$/,
363373
use: handlebarsLoaderUtil.getLoaders(this.webpackConfig)
364-
});
374+
}));
365375
}
366376

367377
this.webpackConfig.loaders.forEach((loader) => {

test/WebpackConfig.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,8 +1099,8 @@ describe('WebpackConfig object', () => {
10991099
const config = createConfig();
11001100

11011101
expect(() => {
1102-
config.configureLoaderRule('vue');
1103-
}).to.throw('Loader "vue" is not configurable. Valid loaders are "eslint".');
1102+
config.configureLoaderRule('reason');
1103+
}).to.throw('Loader "reason" is not configurable. Valid loaders are "javascript", "js", "css", "images", "fonts", "sass", "scss", "less", "stylus", "vue", "eslint", "typescript", "ts", "handlebars".');
11041104
});
11051105

11061106
it('Call method with not a valid callback', () => {

test/config-generator.js

Lines changed: 156 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -979,34 +979,172 @@ describe('The config-generator function', () => {
979979
describe('Test configureLoaderRule()', () => {
980980
let config;
981981

982-
const getLoader = (loaderName) => {
983-
const webpackConfig = configGenerator(config);
984-
return webpackConfig.module.rules.find(rule => rule.loader === loaderName);
985-
};
986-
987982
beforeEach(() => {
988983
config = createConfig();
989984
config.outputPath = '/tmp/public/build';
990985
config.setPublicPath('/');
986+
config.enableSingleRuntimeChunk();
987+
});
988+
989+
it('configure rule for "javascript and "js"', () => {
990+
config.configureLoaderRule('javascript', (loaderRule) => {
991+
loaderRule.test = /\.m?js$/;
992+
});
993+
config.configureLoaderRule('js', (loaderRule) => {
994+
loaderRule.use[0].options.fooBar = 'fooBar';
995+
});
996+
997+
const webpackConfig = configGenerator(config);
998+
const rule = findRule(/\.m?js$/, webpackConfig.module.rules);
999+
1000+
expect('file.js').to.match(rule.test);
1001+
expect('file.mjs').to.match(rule.test);
1002+
expect(rule.use[0].options.fooBar).to.equal('fooBar');
1003+
});
1004+
1005+
it('configure rule for "css"', () => {
1006+
config.configureLoaderRule('css', (loaderRule) => {
1007+
loaderRule.camelCase = true;
1008+
});
1009+
1010+
const webpackConfig = configGenerator(config);
1011+
const rule = findRule(/\.css$/, webpackConfig.module.rules);
1012+
1013+
expect(rule.camelCase).to.be.true;
1014+
});
1015+
1016+
it('configure rule for "images"', () => {
1017+
config.configureLoaderRule('images', (loaderRule) => {
1018+
loaderRule.options.name = 'dirname-images/[hash:42].[ext]';
1019+
});
1020+
1021+
const webpackConfig = configGenerator(config);
1022+
const rule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, webpackConfig.module.rules);
1023+
1024+
expect(rule.options.name).to.equal('dirname-images/[hash:42].[ext]');
1025+
});
1026+
1027+
it('configure rule for "fonts"', () => {
1028+
config.configureLoaderRule('fonts', (loader) => {
1029+
loader.options.name = 'dirname-fonts/[hash:42].[ext]';
1030+
});
1031+
1032+
const webpackConfig = configGenerator(config);
1033+
const rule = findRule(/\.(woff|woff2|ttf|eot|otf)$/, webpackConfig.module.rules);
1034+
1035+
expect(rule.options.name).to.equal('dirname-fonts/[hash:42].[ext]');
1036+
});
1037+
1038+
it('configure rule for "sass" and "scss"', () => {
1039+
config.enableSassLoader();
1040+
config.configureLoaderRule('sass', (loaderRule) => {
1041+
loaderRule.use.push('Option pushed when configuring Sass.');
1042+
});
1043+
config.configureLoaderRule('scss', (loaderRule) => {
1044+
loaderRule.use.push('Option pushed when configuring SCSS.');
1045+
});
1046+
1047+
const webpackConfig = configGenerator(config);
1048+
const rule = findRule(/\.s[ac]ss$/, webpackConfig.module.rules);
1049+
1050+
expect(rule.use.pop()).to.equal('Option pushed when configuring SCSS.');
1051+
expect(rule.use.pop()).to.equal('Option pushed when configuring Sass.');
1052+
});
1053+
1054+
it('configure rule for "less"', () => {
1055+
config.enableLessLoader((options) => {
1056+
options.optionA = 'optionA';
1057+
});
1058+
config.configureLoaderRule('less', (loaderRule) => {
1059+
loaderRule.use[2].options.optionB = 'optionB';
1060+
});
1061+
1062+
const webpackConfig = configGenerator(config);
1063+
const rule = findRule(/\.less/, webpackConfig.module.rules);
1064+
1065+
expect(rule.use[2].options.optionA).to.equal('optionA');
1066+
expect(rule.use[2].options.optionB).to.equal('optionB');
1067+
});
1068+
1069+
it('configure rule for "stylus"', () => {
1070+
config.enableStylusLoader((options) => {
1071+
options.optionA = 'optionA';
1072+
});
1073+
config.configureLoaderRule('stylus', (loaderRule) => {
1074+
loaderRule.use[2].options.optionB = 'optionB';
1075+
});
1076+
1077+
const webpackConfig = configGenerator(config);
1078+
const rule = findRule(/\.styl/, webpackConfig.module.rules);
1079+
1080+
expect(rule.use[2].options.optionA).to.equal('optionA');
1081+
expect(rule.use[2].options.optionB).to.equal('optionB');
1082+
});
1083+
1084+
it('configure rule for "vue"', () => {
1085+
config.enableVueLoader((options) => {
1086+
options.shadowMode = true;
1087+
});
1088+
config.configureLoaderRule('vue', (loaderRule) => {
1089+
loaderRule.use[0].options.prettify = false;
1090+
});
1091+
1092+
const webpackConfig = configGenerator(config);
1093+
const rule = findRule(/\.vue$/, webpackConfig.module.rules);
1094+
1095+
expect(rule.use[0].options.shadowMode).to.be.true;
1096+
expect(rule.use[0].options.prettify).to.be.false;
9911097
});
9921098

9931099
it('configure rule for "eslint"', () => {
994-
config.enableEslintLoader();
995-
config.configureLoaderRule('eslint', (loader) => {
996-
loader.test = /\.(jsx?|vue)/;
1100+
config.enableEslintLoader((options) => {
1101+
options.extends = 'airbnb';
1102+
});
1103+
config.configureLoaderRule('eslint', (loaderRule) => {
1104+
loaderRule.test = /\.(jsx?|vue)/;
9971105
});
9981106

999-
expect(getLoader('eslint-loader')).to.deep.equals({
1000-
test: /\.(jsx?|vue)/,
1001-
enforce: 'pre',
1002-
exclude: /node_modules/,
1003-
loader: 'eslint-loader',
1004-
options: {
1005-
cache: true,
1006-
emitWarning: true,
1007-
parser: 'babel-eslint'
1008-
}
1107+
const webpackConfig = configGenerator(config);
1108+
const rule = findRule(/\.(jsx?|vue)/, webpackConfig.module.rules);
1109+
1110+
expect(rule.options.extends).to.equal('airbnb');
1111+
expect('file.js').to.match(rule.test);
1112+
expect('file.jsx').to.match(rule.test);
1113+
expect('file.vue').to.match(rule.test);
1114+
});
1115+
1116+
it('configure rule for "typescript" and "ts"', () => {
1117+
config.enableTypeScriptLoader((options) => {
1118+
options.silent = true;
1119+
});
1120+
config.configureLoaderRule('typescript', (loaderRule) => {
1121+
loaderRule.use[1].options.happyPackMode = true;
10091122
});
1123+
config.configureLoaderRule('ts', (loaderRule) => {
1124+
loaderRule.use[1].options.logInfoToStdOut = true;
1125+
});
1126+
1127+
const webpackConfig = configGenerator(config);
1128+
const rule = findRule(/\.tsx?$/, webpackConfig.module.rules);
1129+
1130+
expect(rule.use[1].options.silent).to.be.true;
1131+
expect(rule.use[1].options.happyPackMode).to.be.true;
1132+
expect(rule.use[1].options.logInfoToStdOut).to.be.true;
1133+
});
1134+
1135+
it('configure rule for "handlebars"', () => {
1136+
config.enableHandlebarsLoader((options) => {
1137+
options.debug = true;
1138+
});
1139+
config.configureLoaderRule('handlebars', (loaderRule) => {
1140+
loaderRule.use[0].options.fooBar = 'fooBar';
1141+
});
1142+
1143+
const webpackConfig = configGenerator(config);
1144+
const rule = findRule(/\.(handlebars|hbs)$/, webpackConfig.module.rules);
1145+
1146+
expect(rule.use[0].options.debug).to.be.true;
1147+
expect(rule.use[0].options.fooBar).to.be.equal('fooBar');
10101148
});
10111149
});
10121150
});

0 commit comments

Comments
 (0)