| var hasOwnProperty = Object.prototype.hasOwnProperty; |
| var shape = { |
| generic: true, |
| types: {}, |
| properties: {}, |
| parseContext: {}, |
| scope: {}, |
| atrule: ['parse'], |
| pseudo: ['parse'], |
| node: ['name', 'structure', 'parse', 'generate', 'walkContext'] |
| }; |
| |
| function isObject(value) { |
| return value && value.constructor === Object; |
| } |
| |
| function copy(value) { |
| if (isObject(value)) { |
| var res = {}; |
| for (var key in value) { |
| if (hasOwnProperty.call(value, key)) { |
| res[key] = value[key]; |
| } |
| } |
| return res; |
| } else { |
| return value; |
| } |
| } |
| |
| function extend(dest, src) { |
| for (var key in src) { |
| if (hasOwnProperty.call(src, key)) { |
| if (isObject(dest[key])) { |
| extend(dest[key], copy(src[key])); |
| } else { |
| dest[key] = copy(src[key]); |
| } |
| } |
| } |
| } |
| |
| function mix(dest, src, shape) { |
| for (var key in shape) { |
| if (hasOwnProperty.call(shape, key) === false) { |
| continue; |
| } |
| |
| if (shape[key] === true) { |
| if (key in src) { |
| if (hasOwnProperty.call(src, key)) { |
| dest[key] = copy(src[key]); |
| } |
| } |
| } else if (shape[key]) { |
| if (isObject(shape[key])) { |
| var res = {}; |
| extend(res, dest[key]); |
| extend(res, src[key]); |
| dest[key] = res; |
| } else if (Array.isArray(shape[key])) { |
| var res = {}; |
| var innerShape = shape[key].reduce(function(s, k) { |
| s[k] = true; |
| return s; |
| }, {}); |
| for (var name in dest[key]) { |
| if (hasOwnProperty.call(dest[key], name)) { |
| res[name] = {}; |
| if (dest[key] && dest[key][name]) { |
| mix(res[name], dest[key][name], innerShape); |
| } |
| } |
| } |
| for (var name in src[key]) { |
| if (hasOwnProperty.call(src[key], name)) { |
| if (!res[name]) { |
| res[name] = {}; |
| } |
| if (src[key] && src[key][name]) { |
| mix(res[name], src[key][name], innerShape); |
| } |
| } |
| } |
| dest[key] = res; |
| } |
| } |
| } |
| return dest; |
| } |
| |
| module.exports = function(dest, src) { |
| return mix(dest, src, shape); |
| }; |