object-diagram-js-differ 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,188 @@
1
+ 'use strict';
2
+
3
+ var minDash = require('min-dash');
4
+ var jsondiffpatch = require('jsondiffpatch');
5
+
6
+ /* eslint no-cond-assign: 0 */
7
+
8
+ function is(element, type) {
9
+ return element.$instanceOf(type);
10
+ }
11
+
12
+ function isAny(element, types) {
13
+ return types.some(function(t) {
14
+ return is(element, t);
15
+ });
16
+ }
17
+
18
+ function isTracked(element) {
19
+
20
+ const track = isAny(element, [
21
+ 'od:OdBoard',
22
+ 'od:Object',
23
+ 'od:Link',
24
+ ]);
25
+
26
+ if (track) {
27
+ return {
28
+ element: element,
29
+ property: ''
30
+ };
31
+ }
32
+ }
33
+
34
+ function ChangeHandler() {
35
+ this._layoutChanged = {};
36
+ this._changed = {};
37
+ this._removed = {};
38
+ this._added = {};
39
+ }
40
+
41
+
42
+ ChangeHandler.prototype.removed = function(model, property, element, idx) {
43
+
44
+ let tracked;
45
+
46
+ if (tracked = isTracked(element)) {
47
+ if (!this._removed[tracked.element.id]) {
48
+ this._removed[tracked.element.id] = element;
49
+ }
50
+ } else
51
+
52
+ if (tracked = isTracked(model)) {
53
+ this.changed(tracked.element, tracked.property + property + '[' + idx + ']', null, element);
54
+ }
55
+ };
56
+
57
+ ChangeHandler.prototype.changed = function(model, property, newValue, oldValue) {
58
+
59
+ let tracked;
60
+
61
+ if (tracked = isTracked(model)) {
62
+ let changed = this._changed[tracked.element.id];
63
+
64
+ if (!changed) {
65
+ changed = this._changed[tracked.element.id] = { model: model, attrs: { } };
66
+ }
67
+
68
+ if (oldValue !== undefined || newValue !== undefined) {
69
+ changed.attrs[property] = { oldValue: oldValue, newValue: newValue };
70
+ }
71
+ }
72
+ };
73
+
74
+ ChangeHandler.prototype.added = function(model, property, element, idx) {
75
+
76
+ let tracked;
77
+
78
+ if (tracked = isTracked(element)) {
79
+ if (!this._added[tracked.element.id]) {
80
+ this._added[tracked.element.id] = element;
81
+ }
82
+ } else
83
+
84
+ if (tracked = isTracked(model)) {
85
+ this.changed(tracked.element, tracked.property + property + '[' + idx + ']', element, null);
86
+ }
87
+ };
88
+
89
+ ChangeHandler.prototype.moved = function(model, property, oldIndex, newIndex) {
90
+
91
+ // noop
92
+ };
93
+
94
+ function Differ() { }
95
+
96
+
97
+ Differ.prototype.createDiff = function(a, b) {
98
+
99
+ // create a configured instance, match objects by name
100
+ const diffpatcher = new jsondiffpatch.DiffPatcher({
101
+ objectHash: function(obj) {
102
+ return obj.id || JSON.stringify(obj);
103
+ },
104
+ propertyFilter: function(name, context) {
105
+ return name !== '$instanceOf';
106
+ }
107
+ });
108
+
109
+ return diffpatcher.diff(a, b);
110
+ };
111
+
112
+
113
+ Differ.prototype.diff = function(a, b, handler) {
114
+
115
+ handler = handler || new ChangeHandler();
116
+
117
+ function walk(diff, model) {
118
+
119
+ minDash.forEach(diff, function(d, key) {
120
+
121
+ if (d._t !== 'a' && minDash.isArray(d)) {
122
+
123
+ // take into account that collection properties are lazily
124
+ // initialized; this means that adding to an empty collection
125
+ // looks like setting an undefined variable to []
126
+ //
127
+ // ensure we detect this case and change it to an array diff
128
+ if (minDash.isArray(d[0])) {
129
+
130
+ d = minDash.reduce(d[0], function(newDelta, element, idx) {
131
+ const prefix = d.length === 3 ? '_' : '';
132
+
133
+ newDelta[prefix + idx] = [ element ];
134
+
135
+ return newDelta;
136
+ }, { _t: 'a' });
137
+ }
138
+
139
+ }
140
+
141
+
142
+ // is array
143
+ if (d._t === 'a') {
144
+
145
+ minDash.forEach(d, function(val, idx) {
146
+
147
+ if (idx === '_t') {
148
+ return;
149
+ }
150
+
151
+ const removed = /^_/.test(idx),
152
+ added = !removed && minDash.isArray(val),
153
+ moved = removed && val[0] === '';
154
+
155
+ idx = parseInt(removed ? idx.slice(1) : idx, 10);
156
+
157
+ if (added || (removed && !moved)) {
158
+ handler[removed ? 'removed' : 'added'](model, key, val[0], idx);
159
+ } else
160
+ if (moved) {
161
+ handler.moved(model, key, val[1], val[2]);
162
+ } else {
163
+ walk(val, model[key][idx]);
164
+ }
165
+ });
166
+ } else {
167
+ if (minDash.isArray(d)) {
168
+ handler.changed(model, key, d[0], d[1]);
169
+ } else {
170
+ handler.changed(model, key);
171
+ walk(d, model[key]);
172
+ }
173
+ }
174
+ });
175
+ }
176
+
177
+ const diff = this.createDiff(a, b);
178
+
179
+ walk(diff, b);
180
+
181
+ return handler;
182
+ };
183
+
184
+ function diff(a, b, handler) {
185
+ return new Differ().diff(a, b, handler);
186
+ }
187
+
188
+ module.exports = diff;
@@ -0,0 +1,186 @@
1
+ import { forEach, isArray, reduce } from 'min-dash';
2
+ import { DiffPatcher } from 'jsondiffpatch';
3
+
4
+ /* eslint no-cond-assign: 0 */
5
+
6
+ function is(element, type) {
7
+ return element.$instanceOf(type);
8
+ }
9
+
10
+ function isAny(element, types) {
11
+ return types.some(function(t) {
12
+ return is(element, t);
13
+ });
14
+ }
15
+
16
+ function isTracked(element) {
17
+
18
+ const track = isAny(element, [
19
+ 'od:OdBoard',
20
+ 'od:Object',
21
+ 'od:Link',
22
+ ]);
23
+
24
+ if (track) {
25
+ return {
26
+ element: element,
27
+ property: ''
28
+ };
29
+ }
30
+ }
31
+
32
+ function ChangeHandler() {
33
+ this._layoutChanged = {};
34
+ this._changed = {};
35
+ this._removed = {};
36
+ this._added = {};
37
+ }
38
+
39
+
40
+ ChangeHandler.prototype.removed = function(model, property, element, idx) {
41
+
42
+ let tracked;
43
+
44
+ if (tracked = isTracked(element)) {
45
+ if (!this._removed[tracked.element.id]) {
46
+ this._removed[tracked.element.id] = element;
47
+ }
48
+ } else
49
+
50
+ if (tracked = isTracked(model)) {
51
+ this.changed(tracked.element, tracked.property + property + '[' + idx + ']', null, element);
52
+ }
53
+ };
54
+
55
+ ChangeHandler.prototype.changed = function(model, property, newValue, oldValue) {
56
+
57
+ let tracked;
58
+
59
+ if (tracked = isTracked(model)) {
60
+ let changed = this._changed[tracked.element.id];
61
+
62
+ if (!changed) {
63
+ changed = this._changed[tracked.element.id] = { model: model, attrs: { } };
64
+ }
65
+
66
+ if (oldValue !== undefined || newValue !== undefined) {
67
+ changed.attrs[property] = { oldValue: oldValue, newValue: newValue };
68
+ }
69
+ }
70
+ };
71
+
72
+ ChangeHandler.prototype.added = function(model, property, element, idx) {
73
+
74
+ let tracked;
75
+
76
+ if (tracked = isTracked(element)) {
77
+ if (!this._added[tracked.element.id]) {
78
+ this._added[tracked.element.id] = element;
79
+ }
80
+ } else
81
+
82
+ if (tracked = isTracked(model)) {
83
+ this.changed(tracked.element, tracked.property + property + '[' + idx + ']', element, null);
84
+ }
85
+ };
86
+
87
+ ChangeHandler.prototype.moved = function(model, property, oldIndex, newIndex) {
88
+
89
+ // noop
90
+ };
91
+
92
+ function Differ() { }
93
+
94
+
95
+ Differ.prototype.createDiff = function(a, b) {
96
+
97
+ // create a configured instance, match objects by name
98
+ const diffpatcher = new DiffPatcher({
99
+ objectHash: function(obj) {
100
+ return obj.id || JSON.stringify(obj);
101
+ },
102
+ propertyFilter: function(name, context) {
103
+ return name !== '$instanceOf';
104
+ }
105
+ });
106
+
107
+ return diffpatcher.diff(a, b);
108
+ };
109
+
110
+
111
+ Differ.prototype.diff = function(a, b, handler) {
112
+
113
+ handler = handler || new ChangeHandler();
114
+
115
+ function walk(diff, model) {
116
+
117
+ forEach(diff, function(d, key) {
118
+
119
+ if (d._t !== 'a' && isArray(d)) {
120
+
121
+ // take into account that collection properties are lazily
122
+ // initialized; this means that adding to an empty collection
123
+ // looks like setting an undefined variable to []
124
+ //
125
+ // ensure we detect this case and change it to an array diff
126
+ if (isArray(d[0])) {
127
+
128
+ d = reduce(d[0], function(newDelta, element, idx) {
129
+ const prefix = d.length === 3 ? '_' : '';
130
+
131
+ newDelta[prefix + idx] = [ element ];
132
+
133
+ return newDelta;
134
+ }, { _t: 'a' });
135
+ }
136
+
137
+ }
138
+
139
+
140
+ // is array
141
+ if (d._t === 'a') {
142
+
143
+ forEach(d, function(val, idx) {
144
+
145
+ if (idx === '_t') {
146
+ return;
147
+ }
148
+
149
+ const removed = /^_/.test(idx),
150
+ added = !removed && isArray(val),
151
+ moved = removed && val[0] === '';
152
+
153
+ idx = parseInt(removed ? idx.slice(1) : idx, 10);
154
+
155
+ if (added || (removed && !moved)) {
156
+ handler[removed ? 'removed' : 'added'](model, key, val[0], idx);
157
+ } else
158
+ if (moved) {
159
+ handler.moved(model, key, val[1], val[2]);
160
+ } else {
161
+ walk(val, model[key][idx]);
162
+ }
163
+ });
164
+ } else {
165
+ if (isArray(d)) {
166
+ handler.changed(model, key, d[0], d[1]);
167
+ } else {
168
+ handler.changed(model, key);
169
+ walk(d, model[key]);
170
+ }
171
+ }
172
+ });
173
+ }
174
+
175
+ const diff = this.createDiff(a, b);
176
+
177
+ walk(diff, b);
178
+
179
+ return handler;
180
+ };
181
+
182
+ function diff(a, b, handler) {
183
+ return new Differ().diff(a, b, handler);
184
+ }
185
+
186
+ export { diff as default };