-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #77 from TehShrike/v2
deepmerge 2: merge harder
- Loading branch information
Showing
9 changed files
with
649 additions
and
673 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,64 @@ | ||
var isMergeableObject = require('is-mergeable-object') | ||
|
||
function emptyTarget(val) { | ||
return Array.isArray(val) ? [] : {} | ||
return Array.isArray(val) ? [] : {} | ||
} | ||
|
||
function cloneIfNecessary(value, optionsArgument) { | ||
var clone = optionsArgument && optionsArgument.clone === true | ||
return (clone && isMergeableObject(value)) ? deepmerge(emptyTarget(value), value, optionsArgument) : value | ||
function cloneUnlessOtherwiseSpecified(value, optionsArgument) { | ||
var clone = !optionsArgument || optionsArgument.clone !== false | ||
|
||
return (clone && isMergeableObject(value)) | ||
? deepmerge(emptyTarget(value), value, optionsArgument) | ||
: value | ||
} | ||
|
||
function defaultArrayMerge(target, source, optionsArgument) { | ||
var destination = target.slice() | ||
source.forEach(function(e, i) { | ||
if (typeof destination[i] === 'undefined') { | ||
destination[i] = cloneIfNecessary(e, optionsArgument) | ||
} else if (isMergeableObject(e)) { | ||
destination[i] = deepmerge(target[i], e, optionsArgument) | ||
} else if (target.indexOf(e) === -1) { | ||
destination.push(cloneIfNecessary(e, optionsArgument)) | ||
} | ||
}) | ||
return destination | ||
return target.concat(source).map(function(element) { | ||
return cloneUnlessOtherwiseSpecified(element, optionsArgument) | ||
}) | ||
} | ||
|
||
function mergeObject(target, source, optionsArgument) { | ||
var destination = {} | ||
if (isMergeableObject(target)) { | ||
Object.keys(target).forEach(function(key) { | ||
destination[key] = cloneIfNecessary(target[key], optionsArgument) | ||
}) | ||
} | ||
Object.keys(source).forEach(function(key) { | ||
if (!isMergeableObject(source[key]) || !target[key]) { | ||
destination[key] = cloneIfNecessary(source[key], optionsArgument) | ||
} else { | ||
destination[key] = deepmerge(target[key], source[key], optionsArgument) | ||
} | ||
}) | ||
return destination | ||
var destination = {} | ||
if (isMergeableObject(target)) { | ||
Object.keys(target).forEach(function(key) { | ||
destination[key] = cloneUnlessOtherwiseSpecified(target[key], optionsArgument) | ||
}) | ||
} | ||
Object.keys(source).forEach(function(key) { | ||
if (!isMergeableObject(source[key]) || !target[key]) { | ||
destination[key] = cloneUnlessOtherwiseSpecified(source[key], optionsArgument) | ||
} else { | ||
destination[key] = deepmerge(target[key], source[key], optionsArgument) | ||
} | ||
}) | ||
return destination | ||
} | ||
|
||
function deepmerge(target, source, optionsArgument) { | ||
var sourceIsArray = Array.isArray(source) | ||
var targetIsArray = Array.isArray(target) | ||
var options = optionsArgument || { arrayMerge: defaultArrayMerge } | ||
var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray | ||
var sourceIsArray = Array.isArray(source) | ||
var targetIsArray = Array.isArray(target) | ||
var options = optionsArgument || { arrayMerge: defaultArrayMerge } | ||
var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray | ||
|
||
if (!sourceAndTargetTypesMatch) { | ||
return cloneIfNecessary(source, optionsArgument) | ||
} else if (sourceIsArray) { | ||
var arrayMerge = options.arrayMerge || defaultArrayMerge | ||
return arrayMerge(target, source, optionsArgument) | ||
} else { | ||
return mergeObject(target, source, optionsArgument) | ||
} | ||
if (!sourceAndTargetTypesMatch) { | ||
return cloneUnlessOtherwiseSpecified(source, optionsArgument) | ||
} else if (sourceIsArray) { | ||
var arrayMerge = options.arrayMerge || defaultArrayMerge | ||
return arrayMerge(target, source, optionsArgument) | ||
} else { | ||
return mergeObject(target, source, optionsArgument) | ||
} | ||
} | ||
|
||
deepmerge.all = function deepmergeAll(array, optionsArgument) { | ||
if (!Array.isArray(array) || array.length < 2) { | ||
throw new Error('first argument should be an array with at least two elements') | ||
} | ||
if (!Array.isArray(array)) { | ||
throw new Error('first argument should be an array') | ||
} | ||
|
||
// we are sure there are at least 2 values, so it is safe to have no initial value | ||
return array.reduce(function(prev, next) { | ||
return deepmerge(prev, next, optionsArgument) | ||
}) | ||
return array.reduce(function(prev, next) { | ||
return deepmerge(prev, next, optionsArgument) | ||
}, {}) | ||
} | ||
|
||
module.exports = deepmerge |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.