UNPKG

wed

Version:

Wed is a schema-aware editor for XML documents.

160 lines (124 loc) 3.39 kB
define(function(require,exports,module){ 'use strict'; var isOptionObject = require('is-plain-obj'); var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.propertyIsEnumerable; var globalThis = this; var defaultMergeOpts = { concatArrays: false }; function getEnumerableOwnPropertyKeys(value) { var keys = []; for (var key in value) { if (hasOwnProperty.call(value, key)) { keys.push(key); } } if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(value); for (var i = 0; i < symbols.length; i++) { if (propIsEnumerable.call(value, symbols[i])) { keys.push(symbols[i]); } } } return keys; } function clone(value) { if (Array.isArray(value)) { return cloneArray(value); } if (isOptionObject(value)) { return cloneOptionObject(value); } return value; } function cloneArray(array) { var result = array.slice(0, 0); getEnumerableOwnPropertyKeys(array).forEach(function (key) { result[key] = clone(array[key]); }); return result; } function cloneOptionObject(obj) { var result = Object.getPrototypeOf(obj) === null ? Object.create(null) : {}; getEnumerableOwnPropertyKeys(obj).forEach(function (key) { result[key] = clone(obj[key]); }); return result; } /** * @param merged {already cloned} * @return {cloned Object} */ function mergeKeys(merged, source, keys, mergeOpts) { keys.forEach(function (key) { if (key in merged) { merged[key] = merge(merged[key], source[key], mergeOpts); } else { merged[key] = clone(source[key]); } }); return merged; } /** * @param merged {already cloned} * @return {cloned Object} * * see [Array.prototype.concat ( ...arguments )](http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat) */ function concatArrays(merged, source, mergeOpts) { var result = merged.slice(0, 0); var resultIndex = 0; [merged, source].forEach(function (array) { var indices = []; // result.concat(array) with cloning for (var k = 0; k < array.length; k++) { if (!hasOwnProperty.call(array, k)) { continue; } indices.push(String(k)); if (array === merged) { // already cloned result[resultIndex++] = array[k]; } else { result[resultIndex++] = clone(array[k]); } } // merge non-index keys result = mergeKeys(result, array, getEnumerableOwnPropertyKeys(array).filter(function (key) { return indices.indexOf(key) === -1; }), mergeOpts); }); return result; } /** * @param merged {already cloned} * @return {cloned Object} */ function merge(merged, source, mergeOpts) { if (mergeOpts.concatArrays && Array.isArray(merged) && Array.isArray(source)) { return concatArrays(merged, source, mergeOpts); } if (!isOptionObject(source) || !isOptionObject(merged)) { return clone(source); } return mergeKeys(merged, source, getEnumerableOwnPropertyKeys(source), mergeOpts); } module.exports = function () { var mergeOpts = merge(clone(defaultMergeOpts), (this !== globalThis && this) || {}, defaultMergeOpts); var merged = {}; for (var i = 0; i < arguments.length; i++) { var option = arguments[i]; if (option === undefined) { continue; } if (!isOptionObject(option)) { throw new TypeError('`' + option + '` is not an Option Object'); } merged = merge(merged, option, mergeOpts); } return merged; }; return module.exports; });