pax_global_header00006660000000000000000000000064130335165660014522gustar00rootroot0000000000000052 comment=f05d86c820167b43dd563c88d7384063490d5448 webpack-merge-2.2.0/000077500000000000000000000000001303351656600142345ustar00rootroot00000000000000webpack-merge-2.2.0/.babelrc000066400000000000000000000000361303351656600156260ustar00rootroot00000000000000{ "presets": ["es2015"] } webpack-merge-2.2.0/.eslintignore000066400000000000000000000000051303351656600167320ustar00rootroot00000000000000lib/ webpack-merge-2.2.0/.eslintrc000066400000000000000000000013631303351656600160630ustar00rootroot00000000000000// -*- mode: Javascript -*- // Use this file as a starting point for your project's .eslintrc. // Copy this file, and add rule overrides as needed. { "extends": "airbnb/base", /** * Overrides to the airbnb rules */ "rules": { "func-names": 0, "comma-dangle": [2, "never"], "no-undef": [2], "no-undefined": 1, "no-underscore-dangle": 0, "no-use-before-define": 0, // http://eslint.org/docs/rules/prefer-const "prefer-const": 1, // http://eslint.org/docs/rules/no-unused-vars.html "no-unused-vars": [1, {"vars": "all", "args": "after-used"}], "padded-blocks": [0, "always"], // TODO: enable these again "prefer-arrow-callback": 0, "prefer-template": 0, "no-param-reassign": 0 } } webpack-merge-2.2.0/.gitignore000066400000000000000000000000411303351656600162170ustar00rootroot00000000000000node_modules/ lib/ .eslintcache webpack-merge-2.2.0/.travis.yml000066400000000000000000000001651303351656600163470ustar00rootroot00000000000000language: node_js node_js: - "4" - "5" - "6" script: - npm run build - npm run test:lint - npm run test webpack-merge-2.2.0/CHANGELOG.md000066400000000000000000000166341303351656600160570ustar00rootroot000000000000002.2.0 / 2017-01-05 ================== * Bug fix - Drop `merge.smartStrategy(rules, plugins)` as that caused other issues (prototype copying for complex cases). That needs a better approach. #55 2.1.1 / 2017-01-05 ================== * Bug fix - Avoid recursion at `merge.smart`. #53 2.1.0 / 2017-01-05 ================== * Feature - Allow `merge.smartStrategy` to merge plugin contents. API: `merge.smartStrategy(rules, plugins)`. #44. Example: ```javascript const output = merge.smartStrategy( { entry: 'prepend', // or 'replace' 'module.loaders': 'prepend' }, ['LoaderOptionsPlugin'] )(object1, object2, object3, ...); ``` 2.0.0 / 2016-12-22 ================== * Breaking - Disallow overriding configuration with empty arrays/objects (#48). If you want to override, use `merge.strategy`. Example: ```javascript const a = { entry: ['foo'] }; const b = { entry: [] }; merge(a, b); // Yields a result, not b like before. ``` 1.1.2 / 2016-12-18 ================== * Bug fix - `merge({ entry: {} })` should return the same result as input instead of a function. 1.1.1 / 2016-12-11 ================== * Bug fix - Support previously undocumented, yet used, `merge([])` format. This works with all available functions. #46 1.1.0 / 2016-12-09 ================== * Feature - Allow `merge` behavior to be customized with overrides. Example: ```javascript var output = merge({ customizeArray(a, b, key) { return [...a, ...b]; }, customizeObject(a, b, key) { return mergeWith(a, b); } })(object1, object2, object3, ...); ``` This allows you to guarantee array uniqueness and so on. 1.0.2 / 2016-11-29 ================== * Bug fix - `merge` should not mutate inputs with mismatched keys. 1.0.0 / 2016-11-28 ================== * Feature: Support merging Webpack 2 Rule.use. #38 * Bug fix - Don't concat loaders if the first matching entry's include/exclude doesn't match. #39 0.20.0 / 2016-11-27 =================== * Feature: Add support for merging functions. This feature has been designed `postcss` in mind. It executes the functions, picks their results, and packs them again. 0.19.0 / 2016-11-26 =================== * Feature: Add support for 'replace' option at `merge.strategy`. It literally replaces the old field value with the newer one. #40 0.18.0 / 2016-11-24 =================== * Feature: Add support for recursive definitions at `merge.strategy`. Example: ```javascript var output = merge.strategy({ entry: 'prepend', 'module.loaders': 'prepend' })(object1, object2, object3, ...); ``` * Feature: Add `merge.smartStrategy`. This combines the ideas of `merge.smart` and `merge.strategy` into one. Example: ```javascript var output = merge.smartStrategy({ entry: 'prepend', 'module.loaders': 'prepend' })(object1, object2, object3, ...); ``` 0.17.0 / 2016-11-16 =================== * Feature: Add support for `merge.strategy`. Now you can customize merging behavior per root level configuration field. Example: `merge.strategy({ entry: 'prepend' })(object1, object2, object3, ...);`. #17 0.16.0 / 2016-11-14 =================== * Feature: Add support for webpack 2 at `merge.smart`. It should pick up `module.rules` as you might expect now. #35 0.15.0 / 2016-10-18 =================== * Breaking: Rework `merge.smart` so that it **appends** loaders instead of **prepending** them. This is the logical thing to do as it allows you to specify behavior better as you `merge`. #32 0.14.1 / 2016-07-25 =================== * Docs: Improve package description. #23. * Bug fix - Let `merge.smart` merge loaders based on their full name instead of first letter. Thanks to @choffmeister. #26. 0.14.0 / 2016-06-05 =================== * Feature: Allow `merge.smart` to merge `loaders` if `exclude` is the same. Thanks to @mshwery. #21. 0.13.0 / 2016-05-24 =================== * Bug fix: Allow `merge.smart` to merge configuration if `include` is defined. Thanks to @blackrabbit99. #20. 0.12.0 / 2016-04-19 =================== * Feature: Support `include/exclude` at `merge.smart` for `loader` definition too. Thanks to @Whoaa512. #16. 0.11.0 / 2016-04-18 =================== * Feature: Support `include/exclude` at `merge.smart` when its set only in a parent. #15. 0.10.0 / 2016-04-10 =================== * Feature: Support `include/exclude` at `merge.smart`. Thanks to @siready. #14. 0.9.0 / 2016-04-08 ================== * Feature: Allow existing objects/arrays to be emptied with an empty object/array later in merge. This overriding behavior is useful for example emptying your `entry` configuration. 0.8.4 / 2016-03-17 ================== * Bug fix: *webpack-merge* should not mutate inputs. #12 0.8.3 / 2016-03-02 ================== * Bug fix: Drop `files` field from *package.json* as it wasn't including the dist correctly. 0.8.0 / 2016-03-02 ================== * Breaking: Change merging behavior so that only loaders get prepended. The rest follow appending logic. This makes `entry` array merging behavior logical. Prepend makes sense only for loaders after all. #10 0.7.3 / 2016-01-11 ================== * Bug fix: Do not error when there are no matching loaders. Thanks @GreenGremlin! 0.7.2 / 2016-01-08 ================== * Regenerate tarball. The problem was that there were some old dependencies included. Closes #7. 0.7.1 / 2016-01-03 ================== * Improve performance by defaulting to `concat` and by dropping a redundant check. Thanks @davegomez! 0.7.0 / 2015-12-31 ================== * Bug fix: Arrays get merged within nested structures correctly now. Array items are prepended (reverse order compared to earlier). This is related to the change made in *0.6.0*. Incidentally this change affects normal merge as well. * Smart merge: If a loader contains either `include` or `exclude`, it will generate separate entries instead of merging. Without this the configuration might change in an unpredictable manner. 0.6.0 / 2015-12-30 ================== * Support `preLoaders` and `postLoaders`. Previously only `loaders` were supported. * Breaking: Change smart merging behavior for `loaders` field so that it prepends loaders instead of appending them. The benefit of this is that now it's possible to specialize loader setup in a predictable manner. For example you can have a linter set up at the root and expect it to become evaluated first always. 0.5.1 / 2015-12-26 ================== * Fix `merge` object/array case (missing `bind`). The behavior should be correct now. 0.5.0 / 2015-12-26 ================== * Breaking: Push smart merging behind `merge.smart`. Now `merge` behaves exactly as in *0.3.0* series. 0.4.0 / 2015-12-23 ================== * Dropped changelog generator. It's better to write these by hand. * Breaking: Added smart merging (@GreenGremlin) 0.3.2 / 2015-11-23 ================== * Tweaked changelog generator process. 0.3.1 / 2015-11-23 ================== * Added changelog generator. 0.3.0 / 2015-11-13 ================== * Improved formatting * Allowed an arbitrary amount of objects to be merged 0.2.0 / 2015-08-30 ================== * Only require lodash modules used by the package (@montogeek) * Removed lodash.isarray dependency, use Array.isArray standard object 0.1.3 / 2015-08-10 ================== * Improved README example 0.1.2 / 2015-07-01 ================== * Simplified example 0.1.1 / 2015-06-26 ================== * Fixed travis link 0.1.0 / 2015-06-26 ================== * Initial implementation webpack-merge-2.2.0/CONTRIBUTORS.md000066400000000000000000000025731303351656600165220ustar00rootroot00000000000000# Contributors * [Fernando Montoya](https://github.com/montogeek) - Use separate lodash functions instead of the core package. Faster to install this way. * [Jonathan Felchlin](https://github.com/GreenGremlin) - Smart merging for loaders. * [David Gómez](https://github.com/davegomez) - Performance and cosmetic improvements. * [siready](https://github.com/siready) - Extend `merge.smart` to support `include/exclude`. * [C.J. Winslow](https://github.com/Whoaa512) - Make `merge.smart` `include/exclude` to work correctly with `loader`. * [Artem Zakharchenko](https://github.com/blackrabbit99) - Fix `merge.smart` duplication so that if `include` exists, it will merge. * [Matt Shwery](https://github.com/mshwery) - If `exclude` is the same while using `merge.smart`, merge `loaders`. * [Lucretiel](https://github.com/Lucretiel) - Added a more generic test to describe merge behavior better. * [Christian Hoffmeister](https://github.com/choffmeister) - Fix `merge.smart` behavior so that it checks against full loader names instead of just the first letter. * [Ken Powers](https://github.com/knpwrs) - Changed Travis icon to use SVG (scales better). * [Kyle Herock](https://github.com/rockmacaca) - Improved webpack 2 support, avoided concatenating loaders if the first matching entry's include/exclude doesn't match. #41 * [Steven Haddix](https://github.com/steven-haddix) - Clarify description. #42 webpack-merge-2.2.0/ISSUE_TEMPLATE.md000066400000000000000000000005571303351656600167500ustar00rootroot000000000000001. Check the version of **webpack-merge** you are using. If it's not the newest version, update and try again (see changelog while updating!). 2. If the issue is still there, write a minimal script showing the problem and expected output. You can also set up a repository (even better). 3. Include the script to the issue. Mention Node version and OS in your report. webpack-merge-2.2.0/LICENSE000066400000000000000000000020441303351656600152410ustar00rootroot00000000000000Copyright (c) 2015 Juho Vepsalainen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. webpack-merge-2.2.0/README.md000066400000000000000000000116121303351656600155140ustar00rootroot00000000000000[![build status](https://secure.travis-ci.org/survivejs/webpack-merge.svg)](http://travis-ci.org/survivejs/webpack-merge) # webpack-merge - Merge designed for Webpack **webpack-merge** provides a `merge` function that concatenates arrays and merges objects creating a new object. If functions are encountered, it will execute them, run the results through the algorithm, and then wrap the returned values within a function again. This behavior is particularly useful in configuring webpack although it has uses beyond it. Whenever you need to merge configuration objects, **webpack-merge** can come in handy. There's also a webpack specific merge variant known as `merge.smart` that's able to take webpack specifics into account (i.e., it can flatten loader definitions). ## API ```javascript // Default API var output = merge(object1, object2, object3, ...); // You can pass an array of objects directly. // This works with all available functions. var output = merge([object1, object2, object3]); // Customizing array/object behavior var output = merge( { customizeArray(a, b, key) { return [...a, ...b]; }, customizeObject(a, b, key) { return mergeWith(a, b); } } )(object1, object2, object3, ...); // Smarter merging for loaders, see below var output = merge.smart(object1, object2, object3, ...); // Merging with a specific merge strategy var output = merge.strategy( { entry: 'prepend', // or 'replace' 'module.loaders': 'prepend' } )(object1, object2, object3, ...); // The same idea works with smart merging too var output = merge.smartStrategy( { entry: 'prepend', // or 'replace' 'module.loaders': 'prepend' } )(object1, object2, object3, ...); ``` > Check out [SurviveJS - Webpack and React](http://survivejs.com/) to dig deeper into the topic. ## Example **package.json** ```json { "scripts": { "start": "webpack-dev-server", "build": "webpack" }, ... } ``` **webpack.config.js** ```javascript var path = require('path'); var merge = require('webpack-merge'); var TARGET = process.env.npm_lifecycle_event; var common = { entry: path.join(__dirname, 'app'), ... module: { loaders: [ { test: /\.css$/, loaders: ['style', 'css'], }, ], }, }; if(TARGET === 'start') { module.exports = merge(common, { module: { // loaders will get concatenated! loaders: [ { test: /\.jsx?$/, loader: 'babel?stage=1', include: path.join(ROOT_PATH, 'app'), }, ], }, ... }); } if(TARGET === 'build') { module.exports = merge(common, { ... }); } ... ``` ## Smart Merging of Loaders Webpack-merge tries to be smart about merging loaders when `merge.smart` is used. Loaders with matching tests will be merged into a single loader value. Note that the logic picks up webpack 2 `rules` kind of syntax as well. The examples below have been written in webpack 1 syntax. **Loader string values `loader: 'babel'` override each other.** ```javascript merge.smart({ loaders: [{ test: /\.js$/, loader: 'babel' }] }, { loaders: [{ test: /\.js$/, loader: 'coffee' }] }); // will become { loaders: [{ test: /\.js$/, loader: 'coffee' }] } ``` **Loader array values `loaders: ['babel']` will be merged, without duplication.** ```javascript merge.smart({ loaders: [{ test: /\.js$/, loaders: ['babel'] }] }, { loaders: [{ test: /\.js$/, loaders: ['coffee'] }] }); // will become { loaders: [{ test: /\.js$/, // appended because Webpack evaluated these from right to left // this way you can specialize behavior and build the loader chain loaders: ['babel', 'coffee'] }] } ``` **Loader query strings `loaders: ['babel?plugins[]=object-assign']` will be overridden** ```javascript merge.smart({ loaders: [{ test: /\.js$/, loaders: ['babel?plugins[]=object-assign'] }] }, { loaders: [{ test: /\.js$/, loaders: ['babel', 'coffee'] }] }); // will become { loaders: [{ test: /\.js$/, loaders: ['babel', 'coffee'] }] } ``` **Loader arrays in source values will have loader strings merged into them.** ```javascript merge.smart({ loaders: [{ test: /\.js$/, loader: 'babel' }] }, { loaders: [{ test: /\.js$/, loaders: ['coffee'] }] }); // will become { loaders: [{ test: /\.js$/, // appended because Webpack evaluated these from right to left! loaders: ['babel', 'coffee'] }] } ``` **Loader strings in source values will always override.** ```javascript merge.smart({ loaders: [{ test: /\.js$/, loaders: ['babel'] }] }, { loaders: [{ test: /\.js$/, loader: 'coffee' }] }); // will become { loaders: [{ test: /\.js$/, loader: 'coffee' }] } ``` ## Development 1. `npm i` 2. `npm run watch` Before contributing, please open an issue where to discuss. ## License *webpack-merge* is available under MIT. See LICENSE for more details. webpack-merge-2.2.0/package.json000066400000000000000000000033661303351656600165320ustar00rootroot00000000000000{ "name": "webpack-merge", "description": "Variant of merge that's useful for Webpack configuration", "author": "Juho Vepsalainen ", "version": "2.2.0", "scripts": { "build": "babel src -d lib", "watch": "npm-watch", "test": "mocha tests/test-*", "test:lint": "eslint . --cache", "preversion": "npm run test:lint && npm run build && npm test && git commit --allow-empty -am \"Update lib\"" }, "main": "lib/index.js", "files": [ "lib" ], "dependencies": { "lodash.clonedeep": "^4.5.0", "lodash.differencewith": "^4.5.0", "lodash.isequal": "^4.4.0", "lodash.isfunction": "^3.0.8", "lodash.isplainobject": "^4.0.6", "lodash.mergewith": "^4.6.0", "lodash.unionwith": "^4.6.0" }, "devDependencies": { "babel-cli": "^6.3.17", "babel-preset-es2015": "^6.3.13", "eslint": "^3.12.0", "eslint-config-airbnb": "^13.0.0", "eslint-plugin-jsx-a11y": "^2.2.3", "eslint-plugin-import": "^2.2.0", "eslint-plugin-react": "^6.8.0", "git-prepush-hook": "^1.0.1", "mocha": "^3.2.0", "npm-watch": "^0.1.6" }, "repository": { "type": "git", "url": "https://github.com/survivejs/webpack-merge.git" }, "homepage": "https://github.com/survivejs/webpack-merge", "bugs": { "url": "https://github.com/survivejs/webpack-merge/issues" }, "keywords": [ "webpack", "merge" ], "license": "MIT", "pre-push": [ "test:lint", "build", "test" ], "watch": { "build": { "patterns": [ "src/**/*.js" ] }, "test": { "patterns": [ "src/**/*.js", "tests/**/*.js" ] }, "test:lint": { "patterns": [ "src/**/*.js", "tests/**/*.js" ] } } } webpack-merge-2.2.0/src/000077500000000000000000000000001303351656600150235ustar00rootroot00000000000000webpack-merge-2.2.0/src/index.js000066400000000000000000000056621303351656600165010ustar00rootroot00000000000000const differenceWith = require('lodash.differencewith'); const mergeWith = require('lodash.mergewith'); const unionWith = require('lodash.unionwith'); const joinArrays = require('./join-arrays'); const joinArraysSmart = require('./join-arrays-smart'); function merge(...sources) { // This supports // merge([] | ...) // merge({ customizeArray: , customizeObject: })([] | ...) // where fn = (a, b, key) if (sources.length === 1) { if (Array.isArray(sources[0])) { return mergeWith({}, ...sources[0], joinArrays(sources[0])); } if (sources[0].customizeArray || sources[0].customizeObject) { return (...structures) => { if (Array.isArray(structures[0])) { return mergeWith({}, ...structures[0], joinArrays(sources[0])); } return mergeWith({}, ...structures, joinArrays(sources[0])); }; } return sources[0]; } return mergeWith({}, ...sources, joinArrays()); } // rules: { : <'append'|'prepend'|'replace'> } // All default to append but you can override here const mergeStrategy = (rules = {}) => merge({ customizeArray: customizeArray(rules), customizeObject: customizeObject(rules) }); const mergeSmartStrategy = (rules = {}, plugins = []) => merge({ customizeArray: (a, b, key) => { const topKey = key.split('.').slice(-1)[0]; if (isRule(topKey)) { const _uniteRules = (aRule, bRule) => joinArraysSmart.uniteRules(aRule, bRule, rules[key]); switch (rules[key]) { case 'prepend': return [...differenceWith(b, a, _uniteRules), ...a]; case 'replace': return b; default: // append return unionWith(a, b, _uniteRules); } } else if (topKey === 'plugins') { switch (rules[key]) { case 'prepend': return [ ...differenceWith(b, a, joinArraysSmart.unitePlugins.bind(null, plugins)), ...a ]; case 'replace': return b; default: // append return unionWith(a, b, joinArraysSmart.unitePlugins.bind(null, plugins)); } } return customizeArray(rules)(a, b, key); }, customizeObject: customizeObject(rules) }); function customizeArray(rules) { return (a, b, key) => { switch (rules[key]) { case 'prepend': return [...b, ...a]; case 'replace': return b; default: // append return false; } }; } function customizeObject(rules) { return (a, b, key) => { switch (rules[key]) { case 'prepend': return mergeWith({}, b, a, joinArrays()); case 'replace': return b; default: // append return false; } }; } function isRule(key) { return ['preLoaders', 'loaders', 'postLoaders', 'rules'].indexOf(key) >= 0; } module.exports = merge; module.exports.strategy = mergeStrategy; module.exports.smart = mergeSmartStrategy(); module.exports.smartStrategy = mergeSmartStrategy; webpack-merge-2.2.0/src/join-arrays-smart.js000066400000000000000000000100011303351656600207330ustar00rootroot00000000000000const isEqual = require('lodash.isequal'); const isFunction = require('lodash.isfunction'); const mergeWith = require('lodash.mergewith'); const unionWith = require('lodash.unionwith'); const differenceWith = require('lodash.differencewith'); const joinArrays = require('./join-arrays'); const isArray = Array.isArray; function uniteRules(newRule, rule, strategy) { if (String(rule.test) !== String(newRule.test) || (newRule.enforce && rule.enforce !== newRule.enforce) || (newRule.include && !isSameValue(rule.include, newRule.include)) || (newRule.exclude && !isSameValue(rule.exclude, newRule.exclude))) { return false; } else if (!rule.test && !rule.include && !rule.exclude && (rule.loader && rule.loader.split('?')[0]) !== (newRule.loader && newRule.loader.split('?')[0])) { // Don't merge the rule if there isn't any identifying fields and the loaders don't match return false; } // webpack 2 nested rules support if (rule.rules) { const _uniteRules = (b, a) => uniteRules(b, a, strategy); switch (strategy) { case 'prepend': rule.rules = [...differenceWith(newRule.rules, rule.rules, _uniteRules), ...rule.rules]; break; default: rule.rules = unionWith(rule.rules, newRule.rules, uniteRules); break; } } // newRule.loader should always override if (newRule.loader) { const optionsKey = newRule.options ? 'options' : newRule.query && 'query'; delete rule.use; delete rule.loaders; rule.loader = newRule.loader; if (optionsKey) { rule[optionsKey] = newRule[optionsKey]; } } else if ((rule.use || rule.loaders || rule.loader) && (newRule.use || newRule.loaders)) { const expandEntry = loader => ( typeof loader === 'string' ? { loader } : loader ); // this is only here to avoid breaking existing tests const unwrapEntry = entry => ( !entry.options && !entry.query ? entry.loader : entry ); let entries; if (rule.loader) { const optionsKey = rule.options ? 'options' : rule.query && 'query'; entries = [{ loader: rule.loader }]; if (optionsKey) { entries[0][optionsKey] = rule[optionsKey]; } delete rule.loader; if (optionsKey) { delete rule[optionsKey]; } } else { entries = [].concat(rule.use || rule.loaders).map(expandEntry); } const newEntries = [].concat(newRule.use || newRule.loaders).map(expandEntry); const loadersKey = rule.use || newRule.use ? 'use' : 'loaders'; switch (strategy) { case 'prepend': rule[loadersKey] = [ ...differenceWith(newEntries, entries, uniteEntries), ...entries ].map(unwrapEntry); break; default: rule[loadersKey] = unionWith(entries, newEntries, uniteEntries).map(unwrapEntry); break; } } if (newRule.include) { rule.include = newRule.include; } if (newRule.exclude) { rule.exclude = newRule.exclude; } return true; } /** * Check equality of two values using lodash's isEqual * Arrays need to be sorted for equality checking * but clone them first so as not to disrupt the sort order in tests */ function isSameValue(a, b) { const [propA, propB] = [a, b].map(value => ( isArray(value) ? [...value].sort() : value )); return isEqual(propA, propB); } function uniteEntries(newEntry, entry) { const loaderNameRe = /^([^?]+)/ig; const [loaderName] = entry.loader.match(loaderNameRe); const [newLoaderName] = newEntry.loader.match(loaderNameRe); if (loaderName !== newLoaderName) { return false; } // Replace query values with newer ones mergeWith(entry, newEntry); return true; } function unitePlugins(newPlugin, plugin) { if (!(newPlugin instanceof plugin.constructor)) return false; // functions shouldn't be merged here mergeWith(plugin, newPlugin, (a, b, k) => (isFunction(a) ? a : joinArrays()(a, b, k))); return true; } exports.uniteRules = uniteRules; exports.uniteEntries = uniteEntries; exports.unitePlugins = unitePlugins; webpack-merge-2.2.0/src/join-arrays.js000066400000000000000000000020241303351656600176150ustar00rootroot00000000000000const cloneDeep = require('lodash.clonedeep'); const isFunction = require('lodash.isfunction'); const isPlainObject = require('lodash.isplainobject'); const mergeWith = require('lodash.mergewith'); const isArray = Array.isArray; module.exports = function joinArrays({ customizeArray, customizeObject, key } = {}) { return function _joinArrays(a, b, k) { const newKey = key ? `${key}.${k}` : k; if (isFunction(a) && isFunction(b)) { return (...args) => _joinArrays(a(...args), b(...args), k); } if (isArray(a) && isArray(b)) { const customResult = customizeArray && customizeArray(a, b, newKey); return customResult || [...a, ...b]; } if (isPlainObject(a) && isPlainObject(b)) { const customResult = customizeObject && customizeObject(a, b, newKey); return customResult || mergeWith({}, a, b, joinArrays({ customizeArray, customizeObject, key: newKey })); } if (isPlainObject(b)) { return cloneDeep(b); } return b; }; }; webpack-merge-2.2.0/tests/000077500000000000000000000000001303351656600153765ustar00rootroot00000000000000webpack-merge-2.2.0/tests/loaders-keys.js000066400000000000000000000001161303351656600203340ustar00rootroot00000000000000module.exports = [ 'preLoaders', 'loaders', 'postLoaders', 'rules' ]; webpack-merge-2.2.0/tests/merge-smart-tests.js000066400000000000000000000312011303351656600213140ustar00rootroot00000000000000/* eslint-env mocha */ const assert = require('assert'); const loadersKeys = require('./loaders-keys'); function mergeSmartTests(merge) { commonTests(merge); loadersKeys.forEach(function (loadersKey) { mergeSmartTest(merge, loadersKey); }); } function commonTests(merge) { it('should merge with matching exclude and loaders', function () { const a = { module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loaders: ['babel'] } ] } }; const b = { module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loaders: ['coffee', 'foo'] } ] } }; const result = { module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loaders: ['babel', 'coffee', 'foo'] } ] } }; assert.deepEqual(merge(a, b), result); }); it('in lists with matching `test` properties, should merge with matching exclude and loaders', function () { const a = { module: { loaders: [ { test: /\.js$/, include: './src', loaders: ['babel'] }, { test: /\.js$/, exclude: /node_modules/, loaders: ['babel'] } ] } }; const b = { module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loaders: ['coffee', 'foo'] } ] } }; const result = { module: { loaders: [ { test: /\.js$/, include: './src', loaders: ['babel'] }, { test: /\.js$/, exclude: /node_modules/, loaders: ['babel', 'coffee', 'foo'] } ] } }; assert.deepEqual(merge(a, b), result); }); } function mergeSmartTest(merge, loadersKey) { it('should override loader string values with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loader: 'a' }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loader: 'b' }, { test: /\.css$/, loader: 'b' }]; assert.deepEqual(merge(a, result), result); }); it('should append loaders with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['a'] }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['b'] }, { test: /\.css$/, loader: 'b' }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, // loaders are evaluated from right to left so it makes sense to // prepend here!!! this is an exception given normally we want to // append instead. without this the loader order doesn't make // any sense in this case loaders: ['a', 'b'] }, { test: /\.css$/, loader: 'b' }]; assert.deepEqual(merge(a, b), result); }); it('should compare loaders by their whole name with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['aa'] }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['ab'] }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loaders: ['aa', 'ab'] }]; assert.deepEqual(merge(a, b), result); }); it('should be able to merge loaders referenced by path with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['/foo/bar-a.js?a=b'] }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['/foo/bar-b.js?c=d'] }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, // loaders are evaluated from right to left so it makes sense to // append here loaders: ['/foo/bar-a.js?a=b', '/foo/bar-b.js?c=d'] }]; assert.deepEqual(merge(a, b), result); }); it('should append loader and loaders with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loader: 'a' }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['b'] }, { test: /\.css$/, loader: 'b' }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, // loaders are evaluated from right to left so it makes sense to // append here so that last one added wins loaders: ['a', 'b'] }, { test: /\.css$/, loader: 'b' }]; assert.deepEqual(merge(a, b), result); }); it('should not duplicate loaders with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['a'] }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['a', 'b'] }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loaders: ['a', 'b'] }]; assert.deepEqual(merge(a, b), result); }); it('should override loaders with props include ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['a'], include: './path' }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['a', 'b'] }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loaders: ['a', 'b'], include: './path' }]; assert.deepEqual(merge(a, b), result); }); it('should override query options for the same loader with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['a?1'] }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['a?2', 'b'] }]; const c = {}; c[loadersKey] = [{ test: /\.js$/, loaders: ['a', 'b?3'] }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loaders: ['a', 'b?3'] }]; assert.deepEqual(merge(a, b, c), result); }); it('should merge module.loaders for ' + loadersKey, function () { const common = { module: {} }; common.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'] } ]; const isparta = { module: {} }; isparta.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['isparta-instrumenter'] } ]; const result = { module: {} }; result.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint', 'isparta-instrumenter'] } ]; assert.deepEqual(merge(common, isparta), result); }); it('should not merge if a loader has include for ' + loadersKey, function () { // these shouldn't be merged because `include` is defined. // instead, it should prepend to guarantee sane evaluation order const common = { module: {} }; common.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'], include: [ 'foo', 'bar' ] } ]; const isparta = { module: {} }; isparta.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['isparta-instrumenter'], include: 'baz' } ]; const result = { module: {} }; result.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'], include: [ 'foo', 'bar' ] }, { test: /\.jsx?$/, loaders: ['isparta-instrumenter'], include: 'baz' } ]; assert.deepEqual(merge(common, isparta), result); }); it('should not merge if a loader has include and string loader values for ' + loadersKey, function () { // these shouldn't be merged because `include` is defined. // instead, it should prepend to guarantee sane evaluation order const common = { module: {} }; common.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'], include: [ 'foo', 'bar' ] } ]; const isparta = { module: {} }; isparta.module[loadersKey] = [ { test: /\.jsx?$/, loader: 'isparta-instrumenter', include: 'baz' } ]; const result = { module: {} }; result.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'], include: [ 'foo', 'bar' ] }, { test: /\.jsx?$/, loader: 'isparta-instrumenter', include: 'baz' } ]; assert.deepEqual(merge(common, isparta), result); }); it('should not merge if a loader has exclude for ' + loadersKey, function () { // these shouldn't be merged because `exclude` is defined. // instead, it should prepend to guarantee sane evaluation order const common = { module: {} }; common.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'], exclude: [ 'foo', 'bar' ] } ]; const isparta = { module: {} }; isparta.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['isparta-instrumenter'], exclude: 'baz' } ]; const result = { module: {} }; result.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'], exclude: [ 'foo', 'bar' ] }, { test: /\.jsx?$/, loaders: ['isparta-instrumenter'], exclude: 'baz' } ]; assert.deepEqual(merge(common, isparta), result); }); it('should not merge if a loader has exclude and string loader values for ' + loadersKey, function () { // these shouldn't be merged because `exclude` is defined. // instead, it should prepend to guarantee sane evaluation order const common = { module: {} }; common.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'], exclude: [ 'foo', 'bar' ] } ]; const isparta = { module: {} }; isparta.module[loadersKey] = [ { test: /\.jsx?$/, loader: 'isparta-instrumenter', exclude: 'baz' } ]; const result = { module: {} }; result.module[loadersKey] = [ { test: /\.jsx?$/, loaders: ['eslint'], exclude: [ 'foo', 'bar' ] }, { test: /\.jsx?$/, loader: 'isparta-instrumenter', exclude: 'baz' } ]; assert.deepEqual(merge(common, isparta), result); }); it('should use parent include/exclude for ' + loadersKey, function () { const common = { module: {} }; common.module[loadersKey] = [ { test: /\.js$/, include: [ 'apps', 'lib', 'thirdparty' ], exclude: /node_modules/, loaders: ['babel'] } ]; const strip = { module: {} }; strip.module[loadersKey] = [ { test: /\.js$/, loaders: ['strip?strip[]=debug'] } ]; const result = { module: {} }; result.module[loadersKey] = [ { test: /\.js$/, loaders: ['babel', 'strip?strip[]=debug'], include: [ 'apps', 'lib', 'thirdparty' ], exclude: /node_modules/ } ]; assert.deepEqual(merge(common, strip), result); }); it('should use parent include/exclude even if only loader string is specified for ' + loadersKey, function () { const common = { module: {} }; common.module[loadersKey] = [ { test: /\.js$/, include: [ 'apps', 'lib', 'thirdparty' ], exclude: /node_modules/, loaders: 'eslint' } ]; const eslint = { module: {} }; eslint.module[loadersKey] = [ { test: /\.js$/, loader: 'eslint', query: { rules: { 'no-debugger': 0 } } } ]; const result = { module: {} }; result.module[loadersKey] = [ { test: /\.js$/, loader: 'eslint', query: { rules: { 'no-debugger': 0 } }, include: [ 'apps', 'lib', 'thirdparty' ], exclude: /node_modules/ } ]; assert.deepEqual(merge(common, eslint), result); }); } module.exports = mergeSmartTests; webpack-merge-2.2.0/tests/merge-strategy-tests.js000066400000000000000000000077161303351656600220460ustar00rootroot00000000000000/* eslint-env mocha */ const assert = require('assert'); function mergeStrategyTests(merge) { it('should allow setting to array append', function () { const a = { entry: ['foo', 'bar', 'baz'] }; const b = { entry: ['zoo'] }; const result = { entry: ['foo', 'bar', 'baz', 'zoo'] }; assert.deepEqual(merge({ entry: 'append' })(a, b), result); }); it('should allow setting to array prepend', function () { const a = { entry: ['foo', 'bar', 'baz'] }; const b = { entry: ['zoo'] }; const result = { entry: ['zoo', 'foo', 'bar', 'baz'] }; assert.deepEqual(merge({ entry: 'prepend' })(a, b), result); }); it('should allow setting to object append', function () { const a = { entry: { foo: 'bar' } }; const b = { entry: { bar: 'baz' } }; const result = { entry: { foo: 'bar', bar: 'baz' } }; assert.deepEqual( Object.keys(merge({ entry: 'append' })(a, b).entry), Object.keys(result.entry) ); }); it('should allow setting to object prepend', function () { const a = { entry: { foo: 'bar' } }; const b = { entry: { bar: 'baz' } }; const result = { entry: { bar: 'baz', foo: 'bar' } }; assert.deepEqual( Object.keys(merge({ entry: 'prepend' })(a, b).entry), Object.keys(result.entry) ); }); it('should allow replace strategy for arrays', function () { const a = { entry: [ 'foo' ] }; const b = { entry: [ 'bar' ] }; const result = { entry: [ 'bar' ] }; assert.deepEqual( Object.keys(merge({ entry: 'replace' })(a, b).entry), Object.keys(result.entry) ); }); it('should allow replace strategy for objects', function () { const a = { entry: { foo: 'bar' } }; const b = { entry: { bar: 'baz' } }; const result = { entry: { bar: 'baz' } }; assert.deepEqual( Object.keys(merge({ entry: 'replace' })(a, b).entry), Object.keys(result.entry) ); }); it('should merge functions returning arrays with prepend', function () { const a = { postcss() { return ['a']; } }; const b = { postcss() { return ['b']; } }; const expected = ['b', 'a']; assert.deepEqual( merge({ postcss: 'prepend' })(a, b).postcss(), expected ); }); it('should merge functions returning objects with prepend', function () { const a = { postcss() { return { a: 'foo' }; } }; const b = { postcss() { return { b: 'bar' }; } }; const result = { postcss() { return { b: 'bar', a: 'foo' }; } }; assert.deepEqual( Object.keys(merge({ postcss: 'prepend' })(a, b).postcss()), Object.keys(result.postcss()) ); }); it('should merge functions returning arrays with replace', function () { const a = { postcss() { return ['a']; } }; const b = { postcss() { return ['b']; } }; const expected = ['b']; assert.deepEqual( merge({ postcss: 'replace' })(a, b).postcss(), expected ); }); it('should merge functions returning objects with replace', function () { const a = { postcss() { return ['a']; } }; const b = { postcss() { return ['b']; } }; const expected = ['b']; assert.deepEqual( merge({ postcss: 'replace' })(a, b).postcss(), expected ); }); } module.exports = mergeStrategyTests; webpack-merge-2.2.0/tests/merge-tests.js000066400000000000000000000111511303351656600201720ustar00rootroot00000000000000/* eslint-env mocha */ const assert = require('assert'); function mergeTests(merge) { it('should return the same config', function () { const config = { entry: { app: 'app' }, output: { path: 'build', filename: '[name].js' }, plugins: [] }; assert.deepEqual(merge(config), config); }); it('should append arrays of multiple objects by default', function () { const a = { foo: ['a'] }; const b = { foo: ['b'] }; const c = { foo: ['c'] }; const result = { foo: ['a', 'b', 'c'] }; assert.deepEqual(merge(a, b, c), result); }); it('should work with an array of objects', function () { const a = { foo: ['a'] }; const b = { foo: ['b'] }; const c = { foo: ['c'] }; const result = { foo: ['a', 'b', 'c'] }; assert.deepEqual(merge([a, b, c]), result); }); it('should override objects', function () { const a = { foo: 'a' }; const result = { foo: 'b' }; assert.deepEqual(merge(a, result), result); }); it('should append arrays by default', function () { const a = { foo: ['a'] }; const b = { foo: ['b'] }; const result = { foo: ['a', 'b'] }; assert.deepEqual(merge(a, b), result); }); it('should append arrays without mutating', function () { const a = { foo: ['a'] }; const b = { foo: ['b'] }; const result = { foo: ['a', 'b'] }; // this should not mutate merge(a, b); assert.deepEqual(merge(a, b), result); }); it('should override objects of multiple objects', function () { const a = { foo: 'a' }; const b = { foo: 'b' }; const result = { foo: 'c' }; assert.deepEqual(merge(a, b, result), result); }); it('should deeply merge objects', function () { const a = { foo: { bar: 'a' } }; const b = { foo: { baz: 'b' } }; const result = { foo: { bar: 'a', baz: 'b' } }; assert.deepEqual(merge(a, b), result); }); it('should not error when there are no matching loaders', function () { const a = { loaders: [{ test: /\.js$/, loader: 'a' }] }; const b = { loaders: [{ test: /\.css$/, loader: 'b' }] }; const result = { loaders: [{ test: /\.js$/, loader: 'a' }, { test: /\.css$/, loader: 'b' }] }; assert.deepEqual(merge(a, b), result); }); it('should not mutate inputs', function () { const a = { output: { filename: 'bundle.js' } }; const b = { output: { path: 'path/b' } }; const aClone = JSON.parse(JSON.stringify(a)); merge({}, a, b); assert.deepEqual(a, aClone); }); it('should not allow overriding with an empty array', function () { const a = { entry: ['foo'] }; const b = { entry: [] }; assert.deepEqual(merge(a, b), a); }); it('should not allow overriding with an empty object', function () { const a = { entry: { a: 'foo' } }; const b = { entry: {} }; assert.deepEqual(merge(a, b), a); }); it('should merge functions that return arrays', function () { const a = { postcss() { return ['a']; } }; const b = { postcss() { return ['b']; } }; const expected = ['a', 'b']; assert.deepEqual(merge(a, b).postcss(), expected); }); it('should merge functions that return objects', function () { const a = { postcss() { return { a: 'foo' }; } }; const b = { postcss() { return { b: 'bar' }; } }; const expected = { a: 'foo', b: 'bar' }; assert.deepEqual(merge(a, b).postcss(), expected); }); it('should merge functions that take arguments', function () { const a = { postcss(arg) { return [arg]; } }; const b = { postcss(arg) { return [arg + 1, arg + 2]; } }; const expected = ['a', 'a1', 'a2']; assert.deepEqual(merge(a, b).postcss('a'), expected); }); it('should not mutate inputs with mismatched keys', function () { const a = { entry: {} }; const b = {}; const aClone = JSON.parse(JSON.stringify(a)); const config = merge({}, a, b); config.entry.main = 'src/index.js'; assert.deepEqual(a, aClone); }); } module.exports = mergeTests; webpack-merge-2.2.0/tests/test-merge-smart-strategy.js000066400000000000000000000037761303351656600230110ustar00rootroot00000000000000/* eslint-env mocha */ const assert = require('assert'); const webpackMerge = require('..'); const mergeTests = require('./merge-tests'); const mergeSmartTests = require('./merge-smart-tests'); const mergeStrategyTests = require('./merge-strategy-tests'); describe('Smart merge strategy', function () { const merge = webpackMerge.smartStrategy; mergeTests(merge()); mergeSmartTests(merge()); mergeStrategyTests(merge); mergeStrategySpecificTests(merge); }); function mergeStrategySpecificTests(merge) { it('should work with nested arrays and prepend', function () { const a = { module: { loaders: [ { test: /.jsx?$/, loaders: ['babel'], exclude: /node_modules/ } ] } }; const b = { module: { loaders: [ { test: /.jsx?$/, loaders: ['react-hot'], exclude: /node_modules/ } ] } }; const result = { module: { loaders: [ { test: /.jsx?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ } ] } }; assert.deepEqual(merge({ 'module.loaders': 'prepend' })(a, b), result); }); it('should work with nested arrays and replace', function () { const a = { module: { loaders: [ { test: /.jsx?$/, loaders: ['babel'], exclude: /node_modules/ } ] } }; const b = { module: { loaders: [ { test: /.jsx?$/, loaders: ['react-hot'], exclude: /node_modules/ } ] } }; const result = { module: { loaders: [ { test: /.jsx?$/, loaders: ['react-hot'], exclude: /node_modules/ } ] } }; assert.deepEqual(merge({ 'module.loaders': 'replace' })(a, b), result); }); } webpack-merge-2.2.0/tests/test-merge-smart.js000066400000000000000000000004371303351656600211400ustar00rootroot00000000000000/* eslint-env mocha */ const webpackMerge = require('..'); const mergeTests = require('./merge-tests'); const mergeSmartTests = require('./merge-smart-tests'); describe('Smart merge', function () { const merge = webpackMerge.smart; mergeTests(merge); mergeSmartTests(merge); }); webpack-merge-2.2.0/tests/test-merge-strategy.js000066400000000000000000000025461303351656600216570ustar00rootroot00000000000000/* eslint-env mocha */ const assert = require('assert'); const webpackMerge = require('..'); const normalMergeTests = require('./test-merge'); const mergeTests = require('./merge-tests'); const mergeStrategyTests = require('./merge-strategy-tests'); describe('Merge strategy', function () { const merge = webpackMerge.strategy; normalMergeTests(merge()); mergeTests(merge()); mergeStrategyTests(merge); mergeStrategySpecificTests(merge); }); function mergeStrategySpecificTests(merge) { it('should work with nested arrays and prepend', function () { const a = { module: { loaders: [ { test: /.jsx?$/, loaders: ['babel'], exclude: /node_modules/ } ] } }; const b = { module: { loaders: [ { test: /.jsx?$/, loaders: ['react-hot'], exclude: /node_modules/ } ] } }; const result = { module: { loaders: [ { test: /.jsx?$/, loaders: ['react-hot'], exclude: /node_modules/ }, { test: /.jsx?$/, loaders: ['babel'], exclude: /node_modules/ } ] } }; assert.deepEqual(merge({ 'module.loaders': 'prepend' })(a, b), result); }); } webpack-merge-2.2.0/tests/test-merge.js000066400000000000000000000104301303351656600200060ustar00rootroot00000000000000/* eslint-env mocha */ const assert = require('assert'); const webpackMerge = require('..'); const mergeTests = require('./merge-tests'); const loadersKeys = require('./loaders-keys'); describe('Merge', function () { const merge = webpackMerge; normalMergeTests(merge); mergeTests(merge); customizeMergeTests(merge); }); function normalMergeTests(merge) { loadersKeys.forEach(function (loadersKey) { normalMergeTest(merge, loadersKey); }); } function normalMergeTest(merge, loadersKey) { it('should append recursive structures with ' + loadersKey, function () { const a = { module: {} }; a.module[loadersKey] = [{ test: /\.js$/, loader: 'a' }, { test: /\.jade$/, loader: 'a' }]; const b = { module: {} }; b.module[loadersKey] = [{ test: /\.css$/, loader: 'b' }, { test: /\.sass$/, loader: 'b' }]; const result = { module: {} }; result.module[loadersKey] = [{ test: /\.js$/, loader: 'a' }, { test: /\.jade$/, loader: 'a' }, { test: /\.css$/, loader: 'b' }, { test: /\.sass$/, loader: 'b' }]; assert.deepEqual(merge(a, b), result); }); it('should not override loader string values with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loader: 'a' }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loader: 'b' }, { test: /\.css$/, loader: 'b' }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loader: 'a' }, { test: /\.js$/, loader: 'b' }, { test: /\.css$/, loader: 'b' }]; assert.deepEqual(merge(a, b), result); }); it('should not append loaders with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['a'] }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['b'] }, { test: /\.css$/, loader: 'b' }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loaders: ['a'] }, { test: /\.js$/, loaders: ['b'] }, { test: /\.css$/, loader: 'b' }]; assert.deepEqual(merge(a, b), result); }); it('should duplicate loaders with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['a'] }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['a', 'b'] }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loaders: ['a'] }, { test: /\.js$/, loaders: ['a', 'b'] }]; assert.deepEqual(merge(a, b), result); }); it('should not override query options for the same loader with ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['a?1'] }]; const b = {}; b[loadersKey] = [{ test: /\.js$/, loaders: ['a?2', 'b'] }]; const c = {}; c[loadersKey] = [{ test: /\.js$/, loaders: ['a', 'b?3'] }]; const result = {}; result[loadersKey] = [{ test: /\.js$/, loaders: ['a?1'] }, { test: /\.js$/, loaders: ['a?2', 'b'] }, { test: /\.js$/, loaders: ['a', 'b?3'] }]; assert.deepEqual(merge(a, b, c), result); }); it('should not allow overriding with an empty array in ' + loadersKey, function () { const a = {}; a[loadersKey] = [{ test: /\.js$/, loaders: ['a?1'] }]; const b = {}; b[loadersKey] = []; assert.deepEqual(merge(a, b), a); }); } function customizeMergeTests(merge) { it('should allow overriding array behavior', function () { const first = { entry: ['a'] }; const second = { entry: ['b'] }; assert.deepEqual(merge({ customizeArray(a) { return a; } })(first, second), first); }); it('should allow overriding object behavior', function () { const first = { entry: { a: 'foo' } }; const second = { entry: { a: 'bar' } }; assert.deepEqual(merge({ customizeObject(a) { return a; } })(first, second), first); }); } module.exports = normalMergeTests; webpack-merge-2.2.0/tests/testls000066400000000000000000000000001303351656600166250ustar00rootroot00000000000000