diff.js 3.7 KB

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