diff --git a/@commitlint/resolve-extends/src/index.js b/@commitlint/resolve-extends/src/index.js index 8da447f297..08af0fdf05 100644 --- a/@commitlint/resolve-extends/src/index.js +++ b/@commitlint/resolve-extends/src/index.js @@ -3,13 +3,18 @@ import path from 'path'; import 'resolve-global'; // eslint-disable-line import/no-unassigned-import import requireUncached from 'require-uncached'; import resolveFrom from 'resolve-from'; -import {merge, omit} from 'lodash'; +import {isArray, merge, mergeWith, omit} from 'lodash'; // Resolve extend configs export default function resolveExtends(config = {}, context = {}) { const {extends: e} = config; const extended = loadExtends(config, context).reduceRight( - (r, c) => merge(r, omit(c, 'extends')), + (r, c) => + mergeWith(r, omit(c, 'extends'), (objValue, srcValue) => { + if (isArray(objValue)) { + return srcValue; + } + }), e ? {extends: e} : {} ); diff --git a/@commitlint/resolve-extends/src/index.test.js b/@commitlint/resolve-extends/src/index.test.js index 50a01298e1..fe4af27701 100644 --- a/@commitlint/resolve-extends/src/index.test.js +++ b/@commitlint/resolve-extends/src/index.test.js @@ -190,6 +190,34 @@ test('propagates contents recursively', t => { t.deepEqual(actual, expected); }); +test('propagates contents recursively with overlap', t => { + const input = {extends: ['extender-name']}; + + const actual = resolveExtends(input, { + resolve: id, + require(id) { + if (id === 'extender-name') { + return { + extends: ['recursive-extender-name'], + rules: {rule: ['zero', 'one']} + }; + } + if (id === 'recursive-extender-name') { + return {rules: {rule: ['two', 'three', 'four']}}; + } + } + }); + + const expected = { + extends: ['extender-name'], + rules: { + rule: ['zero', 'one'] + } + }; + + t.deepEqual(actual, expected); +}); + test('extending contents should take precedence', t => { const input = {extends: ['extender-name'], zero: 'root'};