blob: 0d2e4a8a71ef87f57a3fffb9fd8c400c83758203 [file] [log] [blame]
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);
};