Skip to content

Commit

Permalink
feat: add missing loaders, add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Kocal committed Feb 8, 2019
1 parent f30504b commit c502e48
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 44 deletions.
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1089,8 +1089,8 @@ class Encore {
* Encore
* .enableEslintLoader()
* .enableVueLoader()
* .configureLoaderRule('eslint', (loader) => {
* loader.test = /\.(jsx?|vue)/;
* .configureLoaderRule('eslint', (loaderRule) => {
* loaderRule.test = /\.(jsx?|vue)/;
* });
*
* @param {string} name
Expand Down
15 changes: 14 additions & 1 deletion lib/WebpackConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,20 @@ class WebpackConfig {
this.tsConfigurationCallback = () => {};
this.handlebarsConfigurationCallback = () => {};
this.loaderConfigurationCallbacks = {
'eslint': () => {},
javascript: () => {},
js: () => {},
css: () => {},
images: () => {},
fonts: () => {},
sass: () => {},
scss: () => {},
less: () => {},
stylus: () => {},
vue: () => {},
eslint: () => {},
typescript: () => {},
ts: () => {},
handlebars: () => {},
};

// Plugins options
Expand Down
52 changes: 31 additions & 21 deletions lib/config-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,24 @@ class ConfigGenerator {
return applyOptionsCallback(this.webpackConfig.loaderConfigurationCallbacks[name], defaultRules);
};

const applyRuleConfigurationCallbacks = (names, defaultRules) => {
let rules = defaultRules;

names.forEach(name => {
rules = applyRuleConfigurationCallback(name, rules);
});

return rules;
};

let rules = [
{
applyRuleConfigurationCallbacks(['javascript', 'js'], {
// match .js and .jsx
test: /\.jsx?$/,
exclude: this.webpackConfig.babelOptions.exclude,
use: babelLoaderUtil.getLoaders(this.webpackConfig)
},
{
use: babelLoaderUtil.getLoaders(this.webpackConfig),
}),
applyRuleConfigurationCallback('css', {
test: /\.css$/,
oneOf: [
{
Expand All @@ -252,7 +262,7 @@ class ConfigGenerator {
)
}
]
}
})
];

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

rules.push({
rules.push(applyRuleConfigurationCallback('images', {
test: /\.(png|jpg|jpeg|gif|ico|svg|webp)$/,
loader: loaderName,
options: loaderOptions
});
}));
}

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

rules.push({
rules.push(applyRuleConfigurationCallback('fonts', {
test: /\.(woff|woff2|ttf|eot|otf)$/,
loader: loaderName,
options: loaderOptions
});
}));
}

if (this.webpackConfig.useSassLoader) {
rules.push({
rules.push(applyRuleConfigurationCallbacks(['sass', 'scss'], {
test: /\.s[ac]ss$/,
use: cssExtractLoaderUtil.prependLoaders(this.webpackConfig, sassLoaderUtil.getLoaders(this.webpackConfig))
});
}));
}

if (this.webpackConfig.useLessLoader) {
rules.push({
rules.push(applyRuleConfigurationCallback('less', {
test: /\.less/,
use: cssExtractLoaderUtil.prependLoaders(this.webpackConfig, lessLoaderUtil.getLoaders(this.webpackConfig))
});
}));
}

if (this.webpackConfig.useStylusLoader) {
rules.push({
rules.push(applyRuleConfigurationCallback('stylus', {
test: /\.styl/,
use: cssExtractLoaderUtil.prependLoaders(this.webpackConfig, stylusLoaderUtil.getLoaders(this.webpackConfig))
});
}));
}

if (this.webpackConfig.useVueLoader) {
rules.push({
rules.push(applyRuleConfigurationCallback('vue', {
test: /\.vue$/,
use: vueLoaderUtil.getLoaders(this.webpackConfig)
});
}));
}

if (this.webpackConfig.useEslintLoader) {
Expand All @@ -350,18 +360,18 @@ class ConfigGenerator {
}

if (this.webpackConfig.useTypeScriptLoader) {
rules.push({
rules.push(applyRuleConfigurationCallbacks(['typescript', 'ts'], {
test: /\.tsx?$/,
exclude: /node_modules/,
use: tsLoaderUtil.getLoaders(this.webpackConfig)
});
}));
}

if (this.webpackConfig.useHandlebarsLoader) {
rules.push({
rules.push(applyRuleConfigurationCallback('handlebars', {
test: /\.(handlebars|hbs)$/,
use: handlebarsLoaderUtil.getLoaders(this.webpackConfig)
});
}));
}

this.webpackConfig.loaders.forEach((loader) => {
Expand Down
4 changes: 2 additions & 2 deletions test/WebpackConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -1099,8 +1099,8 @@ describe('WebpackConfig object', () => {
const config = createConfig();

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

it('Call method with not a valid callback', () => {
Expand Down
174 changes: 156 additions & 18 deletions test/config-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -979,34 +979,172 @@ describe('The config-generator function', () => {
describe('Test configureLoaderRule()', () => {
let config;

const getLoader = (loaderName) => {
const webpackConfig = configGenerator(config);
return webpackConfig.module.rules.find(rule => rule.loader === loaderName);
};

beforeEach(() => {
config = createConfig();
config.outputPath = '/tmp/public/build';
config.setPublicPath('/');
config.enableSingleRuntimeChunk();
});

it('configure rule for "javascript and "js"', () => {
config.configureLoaderRule('javascript', (loaderRule) => {
loaderRule.test = /\.m?js$/;
});
config.configureLoaderRule('js', (loaderRule) => {
loaderRule.use[0].options.fooBar = 'fooBar';
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.m?js$/, webpackConfig.module.rules);

expect('file.js').to.match(rule.test);
expect('file.mjs').to.match(rule.test);
expect(rule.use[0].options.fooBar).to.equal('fooBar');
});

it('configure rule for "css"', () => {
config.configureLoaderRule('css', (loaderRule) => {
loaderRule.camelCase = true;
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.css$/, webpackConfig.module.rules);

expect(rule.camelCase).to.be.true;
});

it('configure rule for "images"', () => {
config.configureLoaderRule('images', (loaderRule) => {
loaderRule.options.name = 'dirname-images/[hash:42].[ext]';
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.(png|jpg|jpeg|gif|ico|svg|webp)$/, webpackConfig.module.rules);

expect(rule.options.name).to.equal('dirname-images/[hash:42].[ext]');
});

it('configure rule for "fonts"', () => {
config.configureLoaderRule('fonts', (loader) => {
loader.options.name = 'dirname-fonts/[hash:42].[ext]';
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.(woff|woff2|ttf|eot|otf)$/, webpackConfig.module.rules);

expect(rule.options.name).to.equal('dirname-fonts/[hash:42].[ext]');
});

it('configure rule for "sass" and "scss"', () => {
config.enableSassLoader();
config.configureLoaderRule('sass', (loaderRule) => {
loaderRule.use.push('Option pushed when configuring Sass.');
});
config.configureLoaderRule('scss', (loaderRule) => {
loaderRule.use.push('Option pushed when configuring SCSS.');
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.s[ac]ss$/, webpackConfig.module.rules);

expect(rule.use.pop()).to.equal('Option pushed when configuring SCSS.');
expect(rule.use.pop()).to.equal('Option pushed when configuring Sass.');
});

it('configure rule for "less"', () => {
config.enableLessLoader((options) => {
options.optionA = 'optionA';
});
config.configureLoaderRule('less', (loaderRule) => {
loaderRule.use[2].options.optionB = 'optionB';
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.less/, webpackConfig.module.rules);

expect(rule.use[2].options.optionA).to.equal('optionA');
expect(rule.use[2].options.optionB).to.equal('optionB');
});

it('configure rule for "stylus"', () => {
config.enableStylusLoader((options) => {
options.optionA = 'optionA';
});
config.configureLoaderRule('stylus', (loaderRule) => {
loaderRule.use[2].options.optionB = 'optionB';
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.styl/, webpackConfig.module.rules);

expect(rule.use[2].options.optionA).to.equal('optionA');
expect(rule.use[2].options.optionB).to.equal('optionB');
});

it('configure rule for "vue"', () => {
config.enableVueLoader((options) => {
options.shadowMode = true;
});
config.configureLoaderRule('vue', (loaderRule) => {
loaderRule.use[0].options.prettify = false;
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.vue$/, webpackConfig.module.rules);

expect(rule.use[0].options.shadowMode).to.be.true;
expect(rule.use[0].options.prettify).to.be.false;
});

it('configure rule for "eslint"', () => {
config.enableEslintLoader();
config.configureLoaderRule('eslint', (loader) => {
loader.test = /\.(jsx?|vue)/;
config.enableEslintLoader((options) => {
options.extends = 'airbnb';
});
config.configureLoaderRule('eslint', (loaderRule) => {
loaderRule.test = /\.(jsx?|vue)/;
});

expect(getLoader('eslint-loader')).to.deep.equals({
test: /\.(jsx?|vue)/,
enforce: 'pre',
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
cache: true,
emitWarning: true,
parser: 'babel-eslint'
}
const webpackConfig = configGenerator(config);
const rule = findRule(/\.(jsx?|vue)/, webpackConfig.module.rules);

expect(rule.options.extends).to.equal('airbnb');
expect('file.js').to.match(rule.test);
expect('file.jsx').to.match(rule.test);
expect('file.vue').to.match(rule.test);
});

it('configure rule for "typescript" and "ts"', () => {
config.enableTypeScriptLoader((options) => {
options.silent = true;
});
config.configureLoaderRule('typescript', (loaderRule) => {
loaderRule.use[1].options.happyPackMode = true;
});
config.configureLoaderRule('ts', (loaderRule) => {
loaderRule.use[1].options.logInfoToStdOut = true;
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.tsx?$/, webpackConfig.module.rules);

expect(rule.use[1].options.silent).to.be.true;
expect(rule.use[1].options.happyPackMode).to.be.true;
expect(rule.use[1].options.logInfoToStdOut).to.be.true;
});

it('configure rule for "handlebars"', () => {
config.enableHandlebarsLoader((options) => {
options.debug = true;
});
config.configureLoaderRule('handlebars', (loaderRule) => {
loaderRule.use[0].options.fooBar = 'fooBar';
});

const webpackConfig = configGenerator(config);
const rule = findRule(/\.(handlebars|hbs)$/, webpackConfig.module.rules);

expect(rule.use[0].options.debug).to.be.true;
expect(rule.use[0].options.fooBar).to.be.equal('fooBar');
});
});
});

0 comments on commit c502e48

Please sign in to comment.