mix.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. var hasOwnProperty = Object.prototype.hasOwnProperty;
  2. var shape = {
  3. generic: true,
  4. types: {},
  5. properties: {},
  6. parseContext: {},
  7. scope: {},
  8. atrule: ['parse'],
  9. pseudo: ['parse'],
  10. node: ['name', 'structure', 'parse', 'generate', 'walkContext']
  11. };
  12. function isObject(value) {
  13. return value && value.constructor === Object;
  14. }
  15. function copy(value) {
  16. if (isObject(value)) {
  17. var res = {};
  18. for (var key in value) {
  19. if (hasOwnProperty.call(value, key)) {
  20. res[key] = value[key];
  21. }
  22. }
  23. return res;
  24. } else {
  25. return value;
  26. }
  27. }
  28. function extend(dest, src) {
  29. for (var key in src) {
  30. if (hasOwnProperty.call(src, key)) {
  31. if (isObject(dest[key])) {
  32. extend(dest[key], copy(src[key]));
  33. } else {
  34. dest[key] = copy(src[key]);
  35. }
  36. }
  37. }
  38. }
  39. function mix(dest, src, shape) {
  40. for (var key in shape) {
  41. if (hasOwnProperty.call(shape, key) === false) {
  42. continue;
  43. }
  44. if (shape[key] === true) {
  45. if (key in src) {
  46. if (hasOwnProperty.call(src, key)) {
  47. dest[key] = copy(src[key]);
  48. }
  49. }
  50. } else if (shape[key]) {
  51. if (isObject(shape[key])) {
  52. var res = {};
  53. extend(res, dest[key]);
  54. extend(res, src[key]);
  55. dest[key] = res;
  56. } else if (Array.isArray(shape[key])) {
  57. var res = {};
  58. var innerShape = shape[key].reduce(function(s, k) {
  59. s[k] = true;
  60. return s;
  61. }, {});
  62. for (var name in dest[key]) {
  63. if (hasOwnProperty.call(dest[key], name)) {
  64. res[name] = {};
  65. if (dest[key] && dest[key][name]) {
  66. mix(res[name], dest[key][name], innerShape);
  67. }
  68. }
  69. }
  70. for (var name in src[key]) {
  71. if (hasOwnProperty.call(src[key], name)) {
  72. if (!res[name]) {
  73. res[name] = {};
  74. }
  75. if (src[key] && src[key][name]) {
  76. mix(res[name], src[key][name], innerShape);
  77. }
  78. }
  79. }
  80. dest[key] = res;
  81. }
  82. }
  83. }
  84. return dest;
  85. }
  86. module.exports = function(dest, src) {
  87. return mix(dest, src, shape);
  88. };