diff.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _typeof from "@babel/runtime/helpers/esm/typeof";
  3. export var STATUS_ADD = 'add';
  4. export var STATUS_KEEP = 'keep';
  5. export var STATUS_REMOVE = 'remove';
  6. export var STATUS_REMOVED = 'removed';
  7. export function wrapKeyToObject(key) {
  8. var keyObj;
  9. if (key && _typeof(key) === 'object' && 'key' in key) {
  10. keyObj = key;
  11. } else {
  12. keyObj = {
  13. key: key
  14. };
  15. }
  16. return _objectSpread(_objectSpread({}, keyObj), {}, {
  17. key: String(keyObj.key)
  18. });
  19. }
  20. export function parseKeys() {
  21. var keys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  22. return keys.map(wrapKeyToObject);
  23. }
  24. export function diffKeys() {
  25. var prevKeys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  26. var currentKeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  27. var list = [];
  28. var currentIndex = 0;
  29. var currentLen = currentKeys.length;
  30. var prevKeyObjects = parseKeys(prevKeys);
  31. var currentKeyObjects = parseKeys(currentKeys);
  32. // Check prev keys to insert or keep
  33. prevKeyObjects.forEach(function (keyObj) {
  34. var hit = false;
  35. for (var i = currentIndex; i < currentLen; i += 1) {
  36. var currentKeyObj = currentKeyObjects[i];
  37. if (currentKeyObj.key === keyObj.key) {
  38. // New added keys should add before current key
  39. if (currentIndex < i) {
  40. list = list.concat(currentKeyObjects.slice(currentIndex, i).map(function (obj) {
  41. return _objectSpread(_objectSpread({}, obj), {}, {
  42. status: STATUS_ADD
  43. });
  44. }));
  45. currentIndex = i;
  46. }
  47. list.push(_objectSpread(_objectSpread({}, currentKeyObj), {}, {
  48. status: STATUS_KEEP
  49. }));
  50. currentIndex += 1;
  51. hit = true;
  52. break;
  53. }
  54. }
  55. // If not hit, it means key is removed
  56. if (!hit) {
  57. list.push(_objectSpread(_objectSpread({}, keyObj), {}, {
  58. status: STATUS_REMOVE
  59. }));
  60. }
  61. });
  62. // Add rest to the list
  63. if (currentIndex < currentLen) {
  64. list = list.concat(currentKeyObjects.slice(currentIndex).map(function (obj) {
  65. return _objectSpread(_objectSpread({}, obj), {}, {
  66. status: STATUS_ADD
  67. });
  68. }));
  69. }
  70. /**
  71. * Merge same key when it remove and add again:
  72. * [1 - add, 2 - keep, 1 - remove] -> [1 - keep, 2 - keep]
  73. */
  74. var keys = {};
  75. list.forEach(function (_ref) {
  76. var key = _ref.key;
  77. keys[key] = (keys[key] || 0) + 1;
  78. });
  79. var duplicatedKeys = Object.keys(keys).filter(function (key) {
  80. return keys[key] > 1;
  81. });
  82. duplicatedKeys.forEach(function (matchKey) {
  83. // Remove `STATUS_REMOVE` node.
  84. list = list.filter(function (_ref2) {
  85. var key = _ref2.key,
  86. status = _ref2.status;
  87. return key !== matchKey || status !== STATUS_REMOVE;
  88. });
  89. // Update `STATUS_ADD` to `STATUS_KEEP`
  90. list.forEach(function (node) {
  91. if (node.key === matchKey) {
  92. // eslint-disable-next-line no-param-reassign
  93. node.status = STATUS_KEEP;
  94. }
  95. });
  96. });
  97. return list;
  98. }