object-diagram-js-differ 1.0.0 → 1.0.2
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/README.md +5 -1
- package/dist/index.cjs +188 -0
- package/dist/index.esm.js +186 -0
- package/dist/object-diagram-js-differ.js +1465 -0
- package/dist/object-diagram-js-differ.min.js +1 -0
- package/package.json +28 -9
- package/.eslintignore +0 -1
- package/.eslintrc +0 -3
- package/.github/workflows/CI.yml +0 -32
- package/lib/change-handler.js +0 -87
- package/lib/diff.js +0 -5
- package/lib/differ.js +0 -102
- package/lib/index.js +0 -7
- package/spec/.eslintrc +0 -6
- package/spec/DifferSpec.js +0 -88
- package/spec/fixtures/add.xml +0 -44
- package/spec/fixtures/base.xml +0 -29
- package/spec/fixtures/change.xml +0 -29
- package/spec/fixtures/remove.xml +0 -13
- package/spec/support/jasmine.json +0 -13
package/README.md
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
Diffing for object diagrams adapted from bpmn-js-differ.
|
|
1
|
+
Diffing for object diagrams adapted from [bpmn-js-differ](https://github.com/bpmn-io/bpmn-js-differ).
|
|
2
|
+
|
|
3
|
+
The diffing tool is used to highlight changes while debugging in the [visual debugger plugin](https://plugins.jetbrains.com/plugin/16851-visual-debugger).
|
|
4
|
+
For example:
|
|
5
|
+

|
|
2
6
|
|
|
3
7
|
## License
|
|
4
8
|
|
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 };
|