blend.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. js-blend - Blend objects
  3. */
  4. function clone(src) {
  5. var result
  6. if (Array.isArray(src)) {
  7. result = src.slice(0)
  8. } else if (typeof src == 'object' && !(src instanceof Date || src instanceof RegExp || src == null)) {
  9. result = Object.create(Object.getPrototypeOf(src))
  10. var i, descriptor, keys = Object.getOwnPropertyNames(src)
  11. for (i = 0; i < keys.length; i ++) {
  12. descriptor = Object.getOwnPropertyDescriptor(src, keys[ i ])
  13. if (descriptor.value && typeof descriptor.value === 'object') {
  14. descriptor.value = clone(descriptor.value)
  15. }
  16. Object.defineProperty(result, keys[i], descriptor)
  17. }
  18. } else {
  19. result = src
  20. }
  21. return result
  22. }
  23. export function blend(dest, src, combine = '') {
  24. if (!src) {
  25. return dest
  26. }
  27. if (!dest || typeof dest != 'object' || Array.isArray(dest)) {
  28. return dest
  29. }
  30. for (let key of Object.getOwnPropertyNames(src)) {
  31. let property = key
  32. let op = key[0]
  33. if (op == '+') {
  34. property = key.slice(1)
  35. } else if (op == '-') {
  36. property = key.slice(1)
  37. } else if (op == '?') {
  38. property = key.slice(1)
  39. } else if (op == '=') {
  40. property = key.slice(1)
  41. } else if (combine) {
  42. op = combine
  43. } else {
  44. /* Default is to blend */
  45. op = ''
  46. }
  47. let s = src[key]
  48. if (!dest.hasOwnProperty(property)) {
  49. if (op == '-') {
  50. continue
  51. }
  52. dest[property] = clone(s)
  53. continue
  54. } else if (op == '?') {
  55. continue
  56. }
  57. let d = dest[property]
  58. if (Array.isArray(d)) {
  59. if (op == '+') {
  60. if (Array.isArray(s)) {
  61. for (let item of s) {
  62. if (d.indexOf(s) < 0) d.push(item)
  63. }
  64. } else {
  65. d.push(s)
  66. }
  67. } else if (op == '-') {
  68. if (Array.isArray(s)) {
  69. for (let item of s) {
  70. let index = d.indexOf(item)
  71. if (index >= 0) d.slice(index, 1)
  72. }
  73. } else {
  74. let index = d.indexOf(s)
  75. if (index >= 0) d.slice(index, 1)
  76. }
  77. } else {
  78. /* op == '=' */
  79. dest[property] = clone(s)
  80. }
  81. } else if (typeof d == 'object' && d !== null && d !== undefined) {
  82. if (op == '=') {
  83. dest[property] = clone(s)
  84. } else if (op == '-') {
  85. delete dest[property]
  86. } else if (typeof s == 'object') {
  87. blend(d, s, op)
  88. }
  89. } else if (typeof d == 'string') {
  90. if (op == '+') {
  91. dest[property] += ' ' + s
  92. } else if (op == '-') {
  93. if (d == s) {
  94. delete dest[property]
  95. } else {
  96. dest[property] = d.replace(s, '')
  97. }
  98. } else {
  99. /* op == '=' */
  100. dest[property] = s
  101. }
  102. } else if (typeof d == 'number') {
  103. if (op == '+') {
  104. dest[property] += s
  105. } else if (op == '-') {
  106. dest[property] -= s
  107. } else {
  108. /* op == '=' */
  109. dest[property] = s
  110. }
  111. } else {
  112. if (op == '=') {
  113. dest[property] = s
  114. } else if (op == '-') {
  115. delete dest[property]
  116. } else {
  117. dest[property] = s
  118. }
  119. }
  120. }
  121. return dest
  122. }