From c2e79a08833276bc29ef1b7f8a100a0ede12d8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juho=20Veps=C3=A4l=C3=A4inen?= Date: Thu, 10 Dec 2020 09:42:46 +0100 Subject: [PATCH] feat - Add a syntax for adjusting merge behavior without matching (#152) Closes #151. Closes #159. --- README.md | 6 +- src/index.ts | 26 ++++++++ test/merge-with-rules.test.ts | 108 ++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5f5df52..e9641d0 100644 --- a/README.md +++ b/README.md @@ -150,8 +150,8 @@ The first `` is the config property to look through for duplicates. `` represents the values that should be unique when you run the field => field function on each duplicate. -When the order of elements of the `` in the first configuration differs from the order in the second configuration, the latter is preserved. - +When the order of elements of the `` in the first configuration differs from the order in the second configuration, the latter is preserved. + ```javascript const { mergeWithCustomize, unique } = require("webpack-merge"); @@ -241,7 +241,7 @@ assert.deepStrictEqual( ); ``` -The way it works is that you should annotate fields to match using `match` (or `CustomizeRule.Match` if you are using TypeScript) matching your configuration structure and then use specific strategies to define how particular fields should be transformed. +The way it works is that you should annotate fields to match using `match` (or `CustomizeRule.Match` if you are using TypeScript) matching your configuration structure and then use specific strategies to define how particular fields should be transformed. If a match doesn't exist above a rule, then it will apply the rule automatically. ## Using with TypeScript diff --git a/src/index.ts b/src/index.ts index 424e93d..ecc30dd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -106,6 +106,10 @@ function mergeWithRules(rules: Rules) { return mergeWithRule({ currentRule, a, b }); } + if (typeof currentRule === "string") { + return mergeIndividualRule({ currentRule, a, b }); + } + return undefined; }, }); @@ -207,6 +211,28 @@ function mergeWithRule({ return ret.concat(b.filter((o) => !bAllMatches.includes(o))); } +function mergeIndividualRule({ + currentRule, + a, + b, +}: { + currentRule: CustomizeRule; + a: Array; + b: Array; +}) { + // What if there's no match? + switch (currentRule) { + case CustomizeRule.Append: + return a.concat(b); + case CustomizeRule.Prepend: + return b.concat(a); + case CustomizeRule.Replace: + return b; + } + + return a; +} + function last(arr) { return arr[arr.length - 1]; } diff --git a/test/merge-with-rules.test.ts b/test/merge-with-rules.test.ts index fc9d754..bb540ab 100644 --- a/test/merge-with-rules.test.ts +++ b/test/merge-with-rules.test.ts @@ -496,4 +496,112 @@ describe("Merge with rules", function () { expect(() => _mergeWithoutRule(config, config)).not.toThrow(); }); + + it("should merge with append without match (#151)", function () { + const _mergeWithExplicitRule = mergeWithRules({ + resolve: { + extensions: CustomizeRule.Append, + }, + }); + const a = { resolve: { extensions: [".js"] } }; + const b = { resolve: { extensions: [".css"] } }; + const result = { resolve: { extensions: [".js", ".css"] } }; + + expect(_mergeWithExplicitRule(a, b)).toEqual(result); + }); + + it("should merge with prepend without match (#151)", function () { + const _mergeWithExplicitRule = mergeWithRules({ + resolve: { + extensions: CustomizeRule.Prepend, + }, + }); + const a = { resolve: { extensions: [".js"] } }; + const b = { resolve: { extensions: [".css"] } }; + const result = { resolve: { extensions: [".css", ".js"] } }; + + expect(_mergeWithExplicitRule(a, b)).toEqual(result); + }); + + it("should merge with replace without match (#151)", function () { + const _mergeWithExplicitRule = mergeWithRules({ + resolve: { + extensions: CustomizeRule.Replace, + }, + }); + const a = { resolve: { extensions: [".js"] } }; + const b = { resolve: { extensions: [".css"] } }; + const result = { resolve: { extensions: [".css"] } }; + + expect(_mergeWithExplicitRule(a, b)).toEqual(result); + }); + + it("should merge mixed rules", function () { + const a = { + resolve: { extensions: [".js"] }, + module: { + rules: [ + { + test: /\.css$/, + use: [{ loader: "style-loader" }, { loader: "sass-loader" }], + }, + ], + }, + }; + const b = { + resolve: { extensions: [".css"] }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: "style-loader", + options: { + modules: true, + }, + }, + ], + }, + ], + }, + }; + const result = { + resolve: { extensions: [".js", ".css"] }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: "style-loader", + options: { + modules: true, + }, + }, + { loader: "sass-loader" }, + ], + }, + ], + }, + }; + + assert.deepStrictEqual( + mergeWithRules({ + resolve: { + extensions: CustomizeRule.Append, + }, + module: { + rules: { + test: CustomizeRule.Match, + use: { + loader: CustomizeRule.Match, + options: CustomizeRule.Replace, + }, + }, + }, + })(a, b), + result + ); + }); });