95 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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);
 | |
| };
 | 
