clapton 0.0.13 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/app/helpers/clapton/clapton_helper.rb +16 -1
  4. data/lib/clapton/engine.rb +20 -10
  5. data/lib/clapton/javascripts/dist/client.js +38 -27
  6. data/lib/clapton/javascripts/dist/components-for-test.js +439 -0
  7. data/lib/clapton/javascripts/dist/components.js +356 -382
  8. data/lib/clapton/javascripts/node_modules/diff-dom/LICENSE.txt +165 -0
  9. data/lib/clapton/javascripts/node_modules/diff-dom/README.md +224 -0
  10. data/lib/clapton/javascripts/node_modules/diff-dom/browser/diffDOM.js +2 -0
  11. data/lib/clapton/javascripts/node_modules/diff-dom/browser/diffDOM.js.map +1 -0
  12. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/TraceLogger.d.ts +28 -0
  13. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/dom/apply.d.ts +4 -0
  14. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/dom/fromVirtual.d.ts +2 -0
  15. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/dom/index.d.ts +2 -0
  16. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/dom/undo.d.ts +3 -0
  17. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/helpers.d.ts +11 -0
  18. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/index.d.ts +10 -0
  19. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/types.d.ts +104 -0
  20. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/virtual/apply.d.ts +3 -0
  21. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/virtual/diff.d.ts +22 -0
  22. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/virtual/fromDOM.d.ts +2 -0
  23. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/virtual/fromString.d.ts +2 -0
  24. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/virtual/helpers.d.ts +40 -0
  25. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/diffDOM/virtual/index.d.ts +3 -0
  26. data/lib/clapton/javascripts/node_modules/diff-dom/dist/dts/index.d.ts +2 -0
  27. data/lib/clapton/javascripts/node_modules/diff-dom/dist/index.d.ts +136 -0
  28. data/lib/clapton/javascripts/node_modules/diff-dom/dist/index.js +1996 -0
  29. data/lib/clapton/javascripts/node_modules/diff-dom/dist/index.js.map +1 -0
  30. data/lib/clapton/javascripts/node_modules/diff-dom/dist/index.min.js +2 -0
  31. data/lib/clapton/javascripts/node_modules/diff-dom/dist/index.min.js.map +1 -0
  32. data/lib/clapton/javascripts/node_modules/diff-dom/dist/module.js +1991 -0
  33. data/lib/clapton/javascripts/node_modules/diff-dom/dist/module.js.map +1 -0
  34. data/lib/clapton/javascripts/node_modules/diff-dom/index.html +62 -0
  35. data/lib/clapton/javascripts/node_modules/diff-dom/package.json +54 -0
  36. data/lib/clapton/javascripts/node_modules/diff-dom/rollup.config.mjs +67 -0
  37. data/lib/clapton/javascripts/node_modules/diff-dom/src/TraceLogger.ts +143 -0
  38. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/dom/apply.ts +227 -0
  39. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/dom/fromVirtual.ts +83 -0
  40. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/dom/index.ts +2 -0
  41. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/dom/undo.ts +90 -0
  42. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/helpers.ts +40 -0
  43. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/index.ts +121 -0
  44. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/types.ts +154 -0
  45. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/virtual/apply.ts +349 -0
  46. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/virtual/diff.ts +855 -0
  47. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/virtual/fromDOM.ts +74 -0
  48. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/virtual/fromString.ts +239 -0
  49. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/virtual/helpers.ts +461 -0
  50. data/lib/clapton/javascripts/node_modules/diff-dom/src/diffDOM/virtual/index.ts +3 -0
  51. data/lib/clapton/javascripts/node_modules/diff-dom/src/index.ts +2 -0
  52. data/lib/clapton/javascripts/node_modules/diff-dom/tsconfig.json +103 -0
  53. data/lib/clapton/javascripts/rollup.config.mjs +17 -2
  54. data/lib/clapton/javascripts/src/actions/handle-action.ts +6 -6
  55. data/lib/clapton/javascripts/src/actions/initialize-actions.ts +6 -3
  56. data/lib/clapton/javascripts/src/channel/clapton-channel.js +6 -3
  57. data/lib/clapton/javascripts/src/client.ts +15 -15
  58. data/lib/clapton/javascripts/src/components-for-test.ts +29 -0
  59. data/lib/clapton/javascripts/src/components.ts +4 -1
  60. data/lib/clapton/javascripts/src/dom/update-component.ts +4 -4
  61. data/lib/clapton/javascripts/src/inputs/initialize-inputs.ts +2 -2
  62. data/lib/clapton/test_helper/base.rb +1 -1
  63. data/lib/clapton/version.rb +1 -2
  64. metadata +49 -3
  65. data/lib/clapton/javascripts/src/dom/update-component.spec.ts +0 -32
@@ -0,0 +1,1996 @@
1
+ 'use strict';
2
+
3
+ /******************************************************************************
4
+ Copyright (c) Microsoft Corporation.
5
+
6
+ Permission to use, copy, modify, and/or distribute this software for any
7
+ purpose with or without fee is hereby granted.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
16
+ ***************************************************************************** */
17
+ /* global Reflect, Promise, SuppressedError, Symbol */
18
+
19
+
20
+ var __assign = function() {
21
+ __assign = Object.assign || function __assign(t) {
22
+ var arguments$1 = arguments;
23
+
24
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
25
+ s = arguments$1[i];
26
+ for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p)) { t[p] = s[p]; } }
27
+ }
28
+ return t;
29
+ };
30
+ return __assign.apply(this, arguments);
31
+ };
32
+
33
+ function __spreadArray(to, from, pack) {
34
+ if (pack || arguments.length === 2) { for (var i = 0, l = from.length, ar; i < l; i++) {
35
+ if (ar || !(i in from)) {
36
+ if (!ar) { ar = Array.prototype.slice.call(from, 0, i); }
37
+ ar[i] = from[i];
38
+ }
39
+ } }
40
+ return to.concat(ar || Array.prototype.slice.call(from));
41
+ }
42
+
43
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
44
+ var e = new Error(message);
45
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
46
+ };
47
+
48
+ var Diff = /** @class */ (function () {
49
+ function Diff(options) {
50
+ if (options === void 0) { options = {}; }
51
+ var _this = this;
52
+ Object.entries(options).forEach(function (_a) {
53
+ var key = _a[0], value = _a[1];
54
+ return (_this[key] = value);
55
+ });
56
+ }
57
+ Diff.prototype.toString = function () {
58
+ return JSON.stringify(this);
59
+ };
60
+ Diff.prototype.setValue = function (aKey, aValue) {
61
+ this[aKey] = aValue;
62
+ return this;
63
+ };
64
+ return Diff;
65
+ }());
66
+ function checkElementType(element) {
67
+ var arguments$1 = arguments;
68
+
69
+ var elementTypeNames = [];
70
+ for (var _i = 1; _i < arguments.length; _i++) {
71
+ elementTypeNames[_i - 1] = arguments$1[_i];
72
+ }
73
+ if (typeof element === "undefined" || element === null) {
74
+ return false;
75
+ }
76
+ return elementTypeNames.some(function (elementTypeName) {
77
+ var _a, _b;
78
+ // We need to check if the specified type is defined
79
+ // because otherwise instanceof throws an exception.
80
+ return typeof ((_b = (_a = element === null || element === void 0 ? void 0 : element.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) === null || _b === void 0 ? void 0 : _b[elementTypeName]) ===
81
+ "function" &&
82
+ element instanceof
83
+ element.ownerDocument.defaultView[elementTypeName];
84
+ });
85
+ }
86
+
87
+ function objToNode(objNode, insideSvg, options) {
88
+ var node;
89
+ if (objNode.nodeName === "#text") {
90
+ node = options.document.createTextNode(objNode.data);
91
+ }
92
+ else if (objNode.nodeName === "#comment") {
93
+ node = options.document.createComment(objNode.data);
94
+ }
95
+ else {
96
+ if (insideSvg) {
97
+ node = options.document.createElementNS("http://www.w3.org/2000/svg", objNode.nodeName);
98
+ if (objNode.nodeName === "foreignObject") {
99
+ insideSvg = false;
100
+ }
101
+ }
102
+ else if (objNode.nodeName.toLowerCase() === "svg") {
103
+ node = options.document.createElementNS("http://www.w3.org/2000/svg", "svg");
104
+ insideSvg = true;
105
+ }
106
+ else {
107
+ node = options.document.createElement(objNode.nodeName);
108
+ }
109
+ if (objNode.attributes) {
110
+ Object.entries(objNode.attributes).forEach(function (_a) {
111
+ var key = _a[0], value = _a[1];
112
+ return node.setAttribute(key, value);
113
+ });
114
+ }
115
+ if (objNode.childNodes) {
116
+ node = node;
117
+ objNode.childNodes.forEach(function (childNode) {
118
+ return node.appendChild(objToNode(childNode, insideSvg, options));
119
+ });
120
+ }
121
+ if (options.valueDiffing) {
122
+ if (objNode.value &&
123
+ checkElementType(node, "HTMLButtonElement", "HTMLDataElement", "HTMLInputElement", "HTMLLIElement", "HTMLMeterElement", "HTMLOptionElement", "HTMLProgressElement", "HTMLParamElement")) {
124
+ node.value = objNode.value;
125
+ }
126
+ if (objNode.checked && checkElementType(node, "HTMLInputElement")) {
127
+ node.checked = objNode.checked;
128
+ }
129
+ if (objNode.selected &&
130
+ checkElementType(node, "HTMLOptionElement")) {
131
+ node.selected = objNode.selected;
132
+ }
133
+ }
134
+ }
135
+ return node;
136
+ }
137
+
138
+ // ===== Apply a diff =====
139
+ var getFromRoute = function (node, route) {
140
+ route = route.slice();
141
+ while (route.length > 0) {
142
+ var c = route.splice(0, 1)[0];
143
+ node = node.childNodes[c];
144
+ }
145
+ return node;
146
+ };
147
+ function applyDiff(tree, diff, options) {
148
+ var action = diff[options._const.action];
149
+ var route = diff[options._const.route];
150
+ var node;
151
+ if (![options._const.addElement, options._const.addTextElement].includes(action)) {
152
+ // For adding nodes, we calculate the route later on. It's different because it includes the position of the newly added item.
153
+ node = getFromRoute(tree, route);
154
+ }
155
+ var newNode;
156
+ var reference;
157
+ var nodeArray;
158
+ // pre-diff hook
159
+ var info = {
160
+ diff: diff,
161
+ node: node
162
+ };
163
+ if (options.preDiffApply(info)) {
164
+ return true;
165
+ }
166
+ switch (action) {
167
+ case options._const.addAttribute:
168
+ if (!node || !checkElementType(node, "Element")) {
169
+ return false;
170
+ }
171
+ node.setAttribute(diff[options._const.name], diff[options._const.value]);
172
+ break;
173
+ case options._const.modifyAttribute:
174
+ if (!node || !checkElementType(node, "Element")) {
175
+ return false;
176
+ }
177
+ node.setAttribute(diff[options._const.name], diff[options._const.newValue]);
178
+ if (checkElementType(node, "HTMLInputElement") &&
179
+ diff[options._const.name] === "value") {
180
+ node.value = diff[options._const.newValue];
181
+ }
182
+ break;
183
+ case options._const.removeAttribute:
184
+ if (!node || !checkElementType(node, "Element")) {
185
+ return false;
186
+ }
187
+ node.removeAttribute(diff[options._const.name]);
188
+ break;
189
+ case options._const.modifyTextElement:
190
+ if (!node || !checkElementType(node, "Text")) {
191
+ return false;
192
+ }
193
+ options.textDiff(node, node.data, diff[options._const.oldValue], diff[options._const.newValue]);
194
+ if (checkElementType(node.parentNode, "HTMLTextAreaElement")) {
195
+ node.parentNode.value = diff[options._const.newValue];
196
+ }
197
+ break;
198
+ case options._const.modifyValue:
199
+ if (!node || typeof node.value === "undefined") {
200
+ return false;
201
+ }
202
+ node.value = diff[options._const.newValue];
203
+ break;
204
+ case options._const.modifyComment:
205
+ if (!node || !checkElementType(node, "Comment")) {
206
+ return false;
207
+ }
208
+ options.textDiff(node, node.data, diff[options._const.oldValue], diff[options._const.newValue]);
209
+ break;
210
+ case options._const.modifyChecked:
211
+ if (!node || typeof node.checked === "undefined") {
212
+ return false;
213
+ }
214
+ node.checked = diff[options._const.newValue];
215
+ break;
216
+ case options._const.modifySelected:
217
+ if (!node || typeof node.selected === "undefined") {
218
+ return false;
219
+ }
220
+ node.selected = diff[options._const.newValue];
221
+ break;
222
+ case options._const.replaceElement: {
223
+ var insideSvg = diff[options._const.newValue].nodeName.toLowerCase() === "svg" ||
224
+ node.parentNode.namespaceURI === "http://www.w3.org/2000/svg";
225
+ node.parentNode.replaceChild(objToNode(diff[options._const.newValue], insideSvg, options), node);
226
+ break;
227
+ }
228
+ case options._const.relocateGroup:
229
+ nodeArray = __spreadArray([], new Array(diff[options._const.groupLength]), true).map(function () {
230
+ return node.removeChild(node.childNodes[diff[options._const.from]]);
231
+ });
232
+ nodeArray.forEach(function (childNode, index) {
233
+ if (index === 0) {
234
+ reference =
235
+ node.childNodes[diff[options._const.to]];
236
+ }
237
+ node.insertBefore(childNode, reference || null);
238
+ });
239
+ break;
240
+ case options._const.removeElement:
241
+ node.parentNode.removeChild(node);
242
+ break;
243
+ case options._const.addElement: {
244
+ var parentRoute = route.slice();
245
+ var c = parentRoute.splice(parentRoute.length - 1, 1)[0];
246
+ node = getFromRoute(tree, parentRoute);
247
+ if (!checkElementType(node, "Element")) {
248
+ return false;
249
+ }
250
+ node.insertBefore(objToNode(diff[options._const.element], node.namespaceURI === "http://www.w3.org/2000/svg", options), node.childNodes[c] || null);
251
+ break;
252
+ }
253
+ case options._const.removeTextElement: {
254
+ if (!node || node.nodeType !== 3) {
255
+ return false;
256
+ }
257
+ var parentNode = node.parentNode;
258
+ parentNode.removeChild(node);
259
+ if (checkElementType(parentNode, "HTMLTextAreaElement")) {
260
+ parentNode.value = "";
261
+ }
262
+ break;
263
+ }
264
+ case options._const.addTextElement: {
265
+ var parentRoute = route.slice();
266
+ var c = parentRoute.splice(parentRoute.length - 1, 1)[0];
267
+ newNode = options.document.createTextNode(diff[options._const.value]);
268
+ node = getFromRoute(tree, parentRoute);
269
+ if (!node.childNodes) {
270
+ return false;
271
+ }
272
+ node.insertBefore(newNode, node.childNodes[c] || null);
273
+ if (checkElementType(node.parentNode, "HTMLTextAreaElement")) {
274
+ node.parentNode.value = diff[options._const.value];
275
+ }
276
+ break;
277
+ }
278
+ default:
279
+ console.log("unknown action");
280
+ }
281
+ // if a new node was created, we might be interested in its
282
+ // post diff hook
283
+ options.postDiffApply({
284
+ diff: info.diff,
285
+ node: info.node,
286
+ newNode: newNode
287
+ });
288
+ return true;
289
+ }
290
+ function applyDOM(tree, diffs, options) {
291
+ return diffs.every(function (diff) {
292
+ return applyDiff(tree, diff, options);
293
+ });
294
+ }
295
+
296
+ // ===== Undo a diff =====
297
+ function swap(obj, p1, p2) {
298
+ var tmp = obj[p1];
299
+ obj[p1] = obj[p2];
300
+ obj[p2] = tmp;
301
+ }
302
+ function undoDiff(tree, diff, options) {
303
+ switch (diff[options._const.action]) {
304
+ case options._const.addAttribute:
305
+ diff[options._const.action] = options._const.removeAttribute;
306
+ applyDiff(tree, diff, options);
307
+ break;
308
+ case options._const.modifyAttribute:
309
+ swap(diff, options._const.oldValue, options._const.newValue);
310
+ applyDiff(tree, diff, options);
311
+ break;
312
+ case options._const.removeAttribute:
313
+ diff[options._const.action] = options._const.addAttribute;
314
+ applyDiff(tree, diff, options);
315
+ break;
316
+ case options._const.modifyTextElement:
317
+ swap(diff, options._const.oldValue, options._const.newValue);
318
+ applyDiff(tree, diff, options);
319
+ break;
320
+ case options._const.modifyValue:
321
+ swap(diff, options._const.oldValue, options._const.newValue);
322
+ applyDiff(tree, diff, options);
323
+ break;
324
+ case options._const.modifyComment:
325
+ swap(diff, options._const.oldValue, options._const.newValue);
326
+ applyDiff(tree, diff, options);
327
+ break;
328
+ case options._const.modifyChecked:
329
+ swap(diff, options._const.oldValue, options._const.newValue);
330
+ applyDiff(tree, diff, options);
331
+ break;
332
+ case options._const.modifySelected:
333
+ swap(diff, options._const.oldValue, options._const.newValue);
334
+ applyDiff(tree, diff, options);
335
+ break;
336
+ case options._const.replaceElement:
337
+ swap(diff, options._const.oldValue, options._const.newValue);
338
+ applyDiff(tree, diff, options);
339
+ break;
340
+ case options._const.relocateGroup:
341
+ swap(diff, options._const.from, options._const.to);
342
+ applyDiff(tree, diff, options);
343
+ break;
344
+ case options._const.removeElement:
345
+ diff[options._const.action] = options._const.addElement;
346
+ applyDiff(tree, diff, options);
347
+ break;
348
+ case options._const.addElement:
349
+ diff[options._const.action] = options._const.removeElement;
350
+ applyDiff(tree, diff, options);
351
+ break;
352
+ case options._const.removeTextElement:
353
+ diff[options._const.action] = options._const.addTextElement;
354
+ applyDiff(tree, diff, options);
355
+ break;
356
+ case options._const.addTextElement:
357
+ diff[options._const.action] = options._const.removeTextElement;
358
+ applyDiff(tree, diff, options);
359
+ break;
360
+ default:
361
+ console.log("unknown action");
362
+ }
363
+ }
364
+ function undoDOM(tree, diffs, options) {
365
+ diffs = diffs.slice();
366
+ diffs.reverse();
367
+ diffs.forEach(function (diff) {
368
+ undoDiff(tree, diff, options);
369
+ });
370
+ }
371
+
372
+ var elementDescriptors = function (el) {
373
+ var output = [];
374
+ output.push(el.nodeName);
375
+ if (el.nodeName !== "#text" && el.nodeName !== "#comment") {
376
+ el = el;
377
+ if (el.attributes) {
378
+ if (el.attributes["class"]) {
379
+ output.push("".concat(el.nodeName, ".").concat(el.attributes["class"].replace(/ /g, ".")));
380
+ }
381
+ if (el.attributes.id) {
382
+ output.push("".concat(el.nodeName, "#").concat(el.attributes.id));
383
+ }
384
+ }
385
+ }
386
+ return output;
387
+ };
388
+ var findUniqueDescriptors = function (li) {
389
+ var uniqueDescriptors = {};
390
+ var duplicateDescriptors = {};
391
+ li.forEach(function (node) {
392
+ elementDescriptors(node).forEach(function (descriptor) {
393
+ var inUnique = descriptor in uniqueDescriptors;
394
+ var inDupes = descriptor in duplicateDescriptors;
395
+ if (!inUnique && !inDupes) {
396
+ uniqueDescriptors[descriptor] = true;
397
+ }
398
+ else if (inUnique) {
399
+ delete uniqueDescriptors[descriptor];
400
+ duplicateDescriptors[descriptor] = true;
401
+ }
402
+ });
403
+ });
404
+ return uniqueDescriptors;
405
+ };
406
+ var uniqueInBoth = function (l1, l2) {
407
+ var l1Unique = findUniqueDescriptors(l1);
408
+ var l2Unique = findUniqueDescriptors(l2);
409
+ var inBoth = {};
410
+ Object.keys(l1Unique).forEach(function (key) {
411
+ if (l2Unique[key]) {
412
+ inBoth[key] = true;
413
+ }
414
+ });
415
+ return inBoth;
416
+ };
417
+ var removeDone = function (tree) {
418
+ delete tree.outerDone;
419
+ delete tree.innerDone;
420
+ delete tree.valueDone;
421
+ if (tree.childNodes) {
422
+ return tree.childNodes.every(removeDone);
423
+ }
424
+ else {
425
+ return true;
426
+ }
427
+ };
428
+ var cleanNode = function (diffNode) {
429
+ if (Object.prototype.hasOwnProperty.call(diffNode, "data")) {
430
+ var textNode = {
431
+ nodeName: diffNode.nodeName === "#text" ? "#text" : "#comment",
432
+ data: diffNode.data
433
+ };
434
+ return textNode;
435
+ }
436
+ else {
437
+ var elementNode = {
438
+ nodeName: diffNode.nodeName
439
+ };
440
+ diffNode = diffNode;
441
+ if (Object.prototype.hasOwnProperty.call(diffNode, "attributes")) {
442
+ elementNode.attributes = __assign({}, diffNode.attributes);
443
+ }
444
+ if (Object.prototype.hasOwnProperty.call(diffNode, "checked")) {
445
+ elementNode.checked = diffNode.checked;
446
+ }
447
+ if (Object.prototype.hasOwnProperty.call(diffNode, "value")) {
448
+ elementNode.value = diffNode.value;
449
+ }
450
+ if (Object.prototype.hasOwnProperty.call(diffNode, "selected")) {
451
+ elementNode.selected = diffNode.selected;
452
+ }
453
+ if (Object.prototype.hasOwnProperty.call(diffNode, "childNodes")) {
454
+ elementNode.childNodes = diffNode.childNodes.map(function (diffChildNode) {
455
+ return cleanNode(diffChildNode);
456
+ });
457
+ }
458
+ return elementNode;
459
+ }
460
+ };
461
+ var isEqual = function (e1, e2) {
462
+ if (!["nodeName", "value", "checked", "selected", "data"].every(function (element) {
463
+ if (e1[element] !== e2[element]) {
464
+ return false;
465
+ }
466
+ return true;
467
+ })) {
468
+ return false;
469
+ }
470
+ if (Object.prototype.hasOwnProperty.call(e1, "data")) {
471
+ // Comment or Text
472
+ return true;
473
+ }
474
+ e1 = e1;
475
+ e2 = e2;
476
+ if (Boolean(e1.attributes) !== Boolean(e2.attributes)) {
477
+ return false;
478
+ }
479
+ if (Boolean(e1.childNodes) !== Boolean(e2.childNodes)) {
480
+ return false;
481
+ }
482
+ if (e1.attributes) {
483
+ var e1Attributes = Object.keys(e1.attributes);
484
+ var e2Attributes = Object.keys(e2.attributes);
485
+ if (e1Attributes.length !== e2Attributes.length) {
486
+ return false;
487
+ }
488
+ if (!e1Attributes.every(function (attribute) {
489
+ if (e1.attributes[attribute] !==
490
+ e2.attributes[attribute]) {
491
+ return false;
492
+ }
493
+ return true;
494
+ })) {
495
+ return false;
496
+ }
497
+ }
498
+ if (e1.childNodes) {
499
+ if (e1.childNodes.length !== e2.childNodes.length) {
500
+ return false;
501
+ }
502
+ if (!e1.childNodes.every(function (childNode, index) {
503
+ return isEqual(childNode, e2.childNodes[index]);
504
+ })) {
505
+ return false;
506
+ }
507
+ }
508
+ return true;
509
+ };
510
+ var roughlyEqual = function (e1, e2, uniqueDescriptors, sameSiblings, preventRecursion) {
511
+ if (preventRecursion === void 0) { preventRecursion = false; }
512
+ if (!e1 || !e2) {
513
+ return false;
514
+ }
515
+ if (e1.nodeName !== e2.nodeName) {
516
+ return false;
517
+ }
518
+ if (["#text", "#comment"].includes(e1.nodeName)) {
519
+ // Note that we initially don't care what the text content of a node is,
520
+ // the mere fact that it's the same tag and "has text" means it's roughly
521
+ // equal, and then we can find out the true text difference later.
522
+ return preventRecursion
523
+ ? true
524
+ : e1.data === e2.data;
525
+ }
526
+ e1 = e1;
527
+ e2 = e2;
528
+ if (e1.nodeName in uniqueDescriptors) {
529
+ return true;
530
+ }
531
+ if (e1.attributes && e2.attributes) {
532
+ if (e1.attributes.id) {
533
+ if (e1.attributes.id !== e2.attributes.id) {
534
+ return false;
535
+ }
536
+ else {
537
+ var idDescriptor = "".concat(e1.nodeName, "#").concat(e1.attributes.id);
538
+ if (idDescriptor in uniqueDescriptors) {
539
+ return true;
540
+ }
541
+ }
542
+ }
543
+ if (e1.attributes["class"] &&
544
+ e1.attributes["class"] === e2.attributes["class"]) {
545
+ var classDescriptor = "".concat(e1.nodeName, ".").concat(e1.attributes["class"].replace(/ /g, "."));
546
+ if (classDescriptor in uniqueDescriptors) {
547
+ return true;
548
+ }
549
+ }
550
+ }
551
+ if (sameSiblings) {
552
+ return true;
553
+ }
554
+ var nodeList1 = e1.childNodes ? e1.childNodes.slice().reverse() : [];
555
+ var nodeList2 = e2.childNodes ? e2.childNodes.slice().reverse() : [];
556
+ if (nodeList1.length !== nodeList2.length) {
557
+ return false;
558
+ }
559
+ if (preventRecursion) {
560
+ return nodeList1.every(function (element, index) {
561
+ return element.nodeName === nodeList2[index].nodeName;
562
+ });
563
+ }
564
+ else {
565
+ // note: we only allow one level of recursion at any depth. If 'preventRecursion'
566
+ // was not set, we must explicitly force it to true for child iterations.
567
+ var childUniqueDescriptors_1 = uniqueInBoth(nodeList1, nodeList2);
568
+ return nodeList1.every(function (element, index) {
569
+ return roughlyEqual(element, nodeList2[index], childUniqueDescriptors_1, true, true);
570
+ });
571
+ }
572
+ };
573
+ /**
574
+ * based on https://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Longest_common_substring#JavaScript
575
+ */
576
+ var findCommonSubsets = function (c1, c2, marked1, marked2) {
577
+ var lcsSize = 0;
578
+ var index = [];
579
+ var c1Length = c1.length;
580
+ var c2Length = c2.length;
581
+ var // set up the matching table
582
+ matches = __spreadArray([], new Array(c1Length + 1), true).map(function () { return []; });
583
+ var uniqueDescriptors = uniqueInBoth(c1, c2);
584
+ var // If all of the elements are the same tag, id and class, then we can
585
+ // consider them roughly the same even if they have a different number of
586
+ // children. This will reduce removing and re-adding similar elements.
587
+ subsetsSame = c1Length === c2Length;
588
+ if (subsetsSame) {
589
+ c1.some(function (element, i) {
590
+ var c1Desc = elementDescriptors(element);
591
+ var c2Desc = elementDescriptors(c2[i]);
592
+ if (c1Desc.length !== c2Desc.length) {
593
+ subsetsSame = false;
594
+ return true;
595
+ }
596
+ c1Desc.some(function (description, i) {
597
+ if (description !== c2Desc[i]) {
598
+ subsetsSame = false;
599
+ return true;
600
+ }
601
+ });
602
+ if (!subsetsSame) {
603
+ return true;
604
+ }
605
+ });
606
+ }
607
+ // fill the matches with distance values
608
+ for (var c1Index = 0; c1Index < c1Length; c1Index++) {
609
+ var c1Element = c1[c1Index];
610
+ for (var c2Index = 0; c2Index < c2Length; c2Index++) {
611
+ var c2Element = c2[c2Index];
612
+ if (!marked1[c1Index] &&
613
+ !marked2[c2Index] &&
614
+ roughlyEqual(c1Element, c2Element, uniqueDescriptors, subsetsSame)) {
615
+ matches[c1Index + 1][c2Index + 1] = matches[c1Index][c2Index]
616
+ ? matches[c1Index][c2Index] + 1
617
+ : 1;
618
+ if (matches[c1Index + 1][c2Index + 1] >= lcsSize) {
619
+ lcsSize = matches[c1Index + 1][c2Index + 1];
620
+ index = [c1Index + 1, c2Index + 1];
621
+ }
622
+ }
623
+ else {
624
+ matches[c1Index + 1][c2Index + 1] = 0;
625
+ }
626
+ }
627
+ }
628
+ if (lcsSize === 0) {
629
+ return false;
630
+ }
631
+ return {
632
+ oldValue: index[0] - lcsSize,
633
+ newValue: index[1] - lcsSize,
634
+ length: lcsSize
635
+ };
636
+ };
637
+ var makeBooleanArray = function (n, v) {
638
+ return __spreadArray([], new Array(n), true).map(function () { return v; });
639
+ };
640
+ /**
641
+ * Generate arrays that indicate which node belongs to which subset,
642
+ * or whether it's actually an orphan node, existing in only one
643
+ * of the two trees, rather than somewhere in both.
644
+ *
645
+ * So if t1 = <img><canvas><br>, t2 = <canvas><br><img>.
646
+ * The longest subset is "<canvas><br>" (length 2), so it will group 0.
647
+ * The second longest is "<img>" (length 1), so it will be group 1.
648
+ * gaps1 will therefore be [1,0,0] and gaps2 [0,0,1].
649
+ *
650
+ * If an element is not part of any group, it will stay being 'true', which
651
+ * is the initial value. For example:
652
+ * t1 = <img><p></p><br><canvas>, t2 = <b></b><br><canvas><img>
653
+ *
654
+ * The "<p></p>" and "<b></b>" do only show up in one of the two and will
655
+ * therefore be marked by "true". The remaining parts are parts of the
656
+ * groups 0 and 1:
657
+ * gaps1 = [1, true, 0, 0], gaps2 = [true, 0, 0, 1]
658
+ *
659
+ */
660
+ var getGapInformation = function (t1, t2, stable) {
661
+ var gaps1 = t1.childNodes
662
+ ? makeBooleanArray(t1.childNodes.length, true)
663
+ : [];
664
+ var gaps2 = t2.childNodes
665
+ ? makeBooleanArray(t2.childNodes.length, true)
666
+ : [];
667
+ var group = 0;
668
+ // give elements from the same subset the same group number
669
+ stable.forEach(function (subset) {
670
+ var endOld = subset.oldValue + subset.length;
671
+ var endNew = subset.newValue + subset.length;
672
+ for (var j = subset.oldValue; j < endOld; j += 1) {
673
+ gaps1[j] = group;
674
+ }
675
+ for (var j = subset.newValue; j < endNew; j += 1) {
676
+ gaps2[j] = group;
677
+ }
678
+ group += 1;
679
+ });
680
+ return {
681
+ gaps1: gaps1,
682
+ gaps2: gaps2
683
+ };
684
+ };
685
+ /**
686
+ * Find all matching subsets, based on immediate child differences only.
687
+ */
688
+ var markBoth = function (marked1, marked2, subset, i) {
689
+ marked1[subset.oldValue + i] = true;
690
+ marked2[subset.newValue + i] = true;
691
+ };
692
+ var markSubTrees = function (oldTree, newTree) {
693
+ // note: the child lists are views, and so update as we update old/newTree
694
+ var oldChildren = oldTree.childNodes ? oldTree.childNodes : [];
695
+ var newChildren = newTree.childNodes ? newTree.childNodes : [];
696
+ var marked1 = makeBooleanArray(oldChildren.length, false);
697
+ var marked2 = makeBooleanArray(newChildren.length, false);
698
+ var subsets = [];
699
+ var returnIndex = function () {
700
+ return arguments[1];
701
+ };
702
+ var foundAllSubsets = false;
703
+ var _loop_1 = function () {
704
+ var subset = findCommonSubsets(oldChildren, newChildren, marked1, marked2);
705
+ if (subset) {
706
+ subsets.push(subset);
707
+ var subsetArray = __spreadArray([], new Array(subset.length), true).map(returnIndex);
708
+ subsetArray.forEach(function (item) {
709
+ return markBoth(marked1, marked2, subset, item);
710
+ });
711
+ }
712
+ else {
713
+ foundAllSubsets = true;
714
+ }
715
+ };
716
+ while (!foundAllSubsets) {
717
+ _loop_1();
718
+ }
719
+ oldTree.subsets = subsets;
720
+ oldTree.subsetsAge = 100;
721
+ return subsets;
722
+ };
723
+ var DiffTracker = /** @class */ (function () {
724
+ function DiffTracker() {
725
+ this.list = [];
726
+ }
727
+ DiffTracker.prototype.add = function (diffs) {
728
+ var _a;
729
+ (_a = this.list).push.apply(_a, diffs);
730
+ };
731
+ DiffTracker.prototype.forEach = function (fn) {
732
+ this.list.forEach(function (li) { return fn(li); });
733
+ };
734
+ return DiffTracker;
735
+ }());
736
+
737
+ // ===== Apply a virtual diff =====
738
+ function getFromVirtualRoute(tree, route) {
739
+ var node = tree;
740
+ var parentNode;
741
+ var nodeIndex;
742
+ route = route.slice();
743
+ while (route.length > 0) {
744
+ nodeIndex = route.splice(0, 1)[0];
745
+ parentNode = node;
746
+ node = node.childNodes ? node.childNodes[nodeIndex] : undefined;
747
+ }
748
+ return {
749
+ node: node,
750
+ parentNode: parentNode,
751
+ nodeIndex: nodeIndex
752
+ };
753
+ }
754
+ function applyVirtualDiff(tree, diff, options) {
755
+ var _a;
756
+ var node, parentNode, nodeIndex;
757
+ if (![options._const.addElement, options._const.addTextElement].includes(diff[options._const.action])) {
758
+ // For adding nodes, we calculate the route later on. It's different because it includes the position of the newly added item.
759
+ var routeInfo = getFromVirtualRoute(tree, diff[options._const.route]);
760
+ node = routeInfo.node;
761
+ parentNode = routeInfo.parentNode;
762
+ nodeIndex = routeInfo.nodeIndex;
763
+ }
764
+ var newSubsets = [];
765
+ // pre-diff hook
766
+ var info = {
767
+ diff: diff,
768
+ node: node
769
+ };
770
+ if (options.preVirtualDiffApply(info)) {
771
+ return true;
772
+ }
773
+ var newNode;
774
+ var nodeArray;
775
+ var route;
776
+ switch (diff[options._const.action]) {
777
+ case options._const.addAttribute:
778
+ if (!node.attributes) {
779
+ node.attributes = {};
780
+ }
781
+ node.attributes[diff[options._const.name]] =
782
+ diff[options._const.value];
783
+ if (diff[options._const.name] === "checked") {
784
+ node.checked = true;
785
+ }
786
+ else if (diff[options._const.name] === "selected") {
787
+ node.selected = true;
788
+ }
789
+ else if (node.nodeName === "INPUT" &&
790
+ diff[options._const.name] === "value") {
791
+ node.value = diff[options._const.value];
792
+ }
793
+ break;
794
+ case options._const.modifyAttribute:
795
+ node.attributes[diff[options._const.name]] =
796
+ diff[options._const.newValue];
797
+ break;
798
+ case options._const.removeAttribute:
799
+ delete node.attributes[diff[options._const.name]];
800
+ if (Object.keys(node.attributes).length === 0) {
801
+ delete node.attributes;
802
+ }
803
+ if (diff[options._const.name] === "checked") {
804
+ node.checked = false;
805
+ }
806
+ else if (diff[options._const.name] === "selected") {
807
+ delete node.selected;
808
+ }
809
+ else if (node.nodeName === "INPUT" &&
810
+ diff[options._const.name] === "value") {
811
+ delete node.value;
812
+ }
813
+ break;
814
+ case options._const.modifyTextElement:
815
+ node.data = diff[options._const.newValue];
816
+ if (parentNode.nodeName === "TEXTAREA") {
817
+ parentNode.value = diff[options._const.newValue];
818
+ }
819
+ break;
820
+ case options._const.modifyValue:
821
+ node.value = diff[options._const.newValue];
822
+ break;
823
+ case options._const.modifyComment:
824
+ node.data = diff[options._const.newValue];
825
+ break;
826
+ case options._const.modifyChecked:
827
+ node.checked = diff[options._const.newValue];
828
+ break;
829
+ case options._const.modifySelected:
830
+ node.selected = diff[options._const.newValue];
831
+ break;
832
+ case options._const.replaceElement:
833
+ newNode = cleanNode(diff[options._const.newValue]);
834
+ parentNode.childNodes[nodeIndex] = newNode;
835
+ break;
836
+ case options._const.relocateGroup:
837
+ nodeArray = node.childNodes
838
+ .splice(diff[options._const.from], diff[options._const.groupLength])
839
+ .reverse();
840
+ nodeArray.forEach(function (movedNode) {
841
+ return node.childNodes.splice(diff[options._const.to], 0, movedNode);
842
+ });
843
+ if (node.subsets) {
844
+ node.subsets.forEach(function (map) {
845
+ if (diff[options._const.from] < diff[options._const.to] &&
846
+ map.oldValue <= diff[options._const.to] &&
847
+ map.oldValue > diff[options._const.from]) {
848
+ map.oldValue -= diff[options._const.groupLength];
849
+ var splitLength = map.oldValue + map.length - diff[options._const.to];
850
+ if (splitLength > 0) {
851
+ // new insertion splits map.
852
+ newSubsets.push({
853
+ oldValue: diff[options._const.to] +
854
+ diff[options._const.groupLength],
855
+ newValue: map.newValue + map.length - splitLength,
856
+ length: splitLength
857
+ });
858
+ map.length -= splitLength;
859
+ }
860
+ }
861
+ else if (diff[options._const.from] > diff[options._const.to] &&
862
+ map.oldValue > diff[options._const.to] &&
863
+ map.oldValue < diff[options._const.from]) {
864
+ map.oldValue += diff[options._const.groupLength];
865
+ var splitLength = map.oldValue + map.length - diff[options._const.to];
866
+ if (splitLength > 0) {
867
+ // new insertion splits map.
868
+ newSubsets.push({
869
+ oldValue: diff[options._const.to] +
870
+ diff[options._const.groupLength],
871
+ newValue: map.newValue + map.length - splitLength,
872
+ length: splitLength
873
+ });
874
+ map.length -= splitLength;
875
+ }
876
+ }
877
+ else if (map.oldValue === diff[options._const.from]) {
878
+ map.oldValue = diff[options._const.to];
879
+ }
880
+ });
881
+ }
882
+ break;
883
+ case options._const.removeElement:
884
+ parentNode.childNodes.splice(nodeIndex, 1);
885
+ if (parentNode.subsets) {
886
+ parentNode.subsets.forEach(function (map) {
887
+ if (map.oldValue > nodeIndex) {
888
+ map.oldValue -= 1;
889
+ }
890
+ else if (map.oldValue === nodeIndex) {
891
+ map["delete"] = true;
892
+ }
893
+ else if (map.oldValue < nodeIndex &&
894
+ map.oldValue + map.length > nodeIndex) {
895
+ if (map.oldValue + map.length - 1 === nodeIndex) {
896
+ map.length--;
897
+ }
898
+ else {
899
+ newSubsets.push({
900
+ newValue: map.newValue + nodeIndex - map.oldValue,
901
+ oldValue: nodeIndex,
902
+ length: map.length - nodeIndex + map.oldValue - 1
903
+ });
904
+ map.length = nodeIndex - map.oldValue;
905
+ }
906
+ }
907
+ });
908
+ }
909
+ node = parentNode;
910
+ break;
911
+ case options._const.addElement: {
912
+ route = diff[options._const.route].slice();
913
+ var c_1 = route.splice(route.length - 1, 1)[0];
914
+ node = (_a = getFromVirtualRoute(tree, route)) === null || _a === void 0 ? void 0 : _a.node;
915
+ newNode = cleanNode(diff[options._const.element]);
916
+ if (!node.childNodes) {
917
+ node.childNodes = [];
918
+ }
919
+ if (c_1 >= node.childNodes.length) {
920
+ node.childNodes.push(newNode);
921
+ }
922
+ else {
923
+ node.childNodes.splice(c_1, 0, newNode);
924
+ }
925
+ if (node.subsets) {
926
+ node.subsets.forEach(function (map) {
927
+ if (map.oldValue >= c_1) {
928
+ map.oldValue += 1;
929
+ }
930
+ else if (map.oldValue < c_1 &&
931
+ map.oldValue + map.length > c_1) {
932
+ var splitLength = map.oldValue + map.length - c_1;
933
+ newSubsets.push({
934
+ newValue: map.newValue + map.length - splitLength,
935
+ oldValue: c_1 + 1,
936
+ length: splitLength
937
+ });
938
+ map.length -= splitLength;
939
+ }
940
+ });
941
+ }
942
+ break;
943
+ }
944
+ case options._const.removeTextElement:
945
+ parentNode.childNodes.splice(nodeIndex, 1);
946
+ if (parentNode.nodeName === "TEXTAREA") {
947
+ delete parentNode.value;
948
+ }
949
+ if (parentNode.subsets) {
950
+ parentNode.subsets.forEach(function (map) {
951
+ if (map.oldValue > nodeIndex) {
952
+ map.oldValue -= 1;
953
+ }
954
+ else if (map.oldValue === nodeIndex) {
955
+ map["delete"] = true;
956
+ }
957
+ else if (map.oldValue < nodeIndex &&
958
+ map.oldValue + map.length > nodeIndex) {
959
+ if (map.oldValue + map.length - 1 === nodeIndex) {
960
+ map.length--;
961
+ }
962
+ else {
963
+ newSubsets.push({
964
+ newValue: map.newValue + nodeIndex - map.oldValue,
965
+ oldValue: nodeIndex,
966
+ length: map.length - nodeIndex + map.oldValue - 1
967
+ });
968
+ map.length = nodeIndex - map.oldValue;
969
+ }
970
+ }
971
+ });
972
+ }
973
+ node = parentNode;
974
+ break;
975
+ case options._const.addTextElement: {
976
+ route = diff[options._const.route].slice();
977
+ var c_2 = route.splice(route.length - 1, 1)[0];
978
+ newNode = {
979
+ nodeName: "#text",
980
+ data: diff[options._const.value]
981
+ };
982
+ node = getFromVirtualRoute(tree, route).node;
983
+ if (!node.childNodes) {
984
+ node.childNodes = [];
985
+ }
986
+ if (c_2 >= node.childNodes.length) {
987
+ node.childNodes.push(newNode);
988
+ }
989
+ else {
990
+ node.childNodes.splice(c_2, 0, newNode);
991
+ }
992
+ if (node.nodeName === "TEXTAREA") {
993
+ node.value = diff[options._const.newValue];
994
+ }
995
+ if (node.subsets) {
996
+ node.subsets.forEach(function (map) {
997
+ if (map.oldValue >= c_2) {
998
+ map.oldValue += 1;
999
+ }
1000
+ if (map.oldValue < c_2 && map.oldValue + map.length > c_2) {
1001
+ var splitLength = map.oldValue + map.length - c_2;
1002
+ newSubsets.push({
1003
+ newValue: map.newValue + map.length - splitLength,
1004
+ oldValue: c_2 + 1,
1005
+ length: splitLength
1006
+ });
1007
+ map.length -= splitLength;
1008
+ }
1009
+ });
1010
+ }
1011
+ break;
1012
+ }
1013
+ default:
1014
+ console.log("unknown action");
1015
+ }
1016
+ if (node.subsets) {
1017
+ node.subsets = node.subsets.filter(function (map) { return !map["delete"] && map.oldValue !== map.newValue; });
1018
+ if (newSubsets.length) {
1019
+ node.subsets = node.subsets.concat(newSubsets);
1020
+ }
1021
+ }
1022
+ options.postVirtualDiffApply({
1023
+ node: info.node,
1024
+ diff: info.diff,
1025
+ newNode: newNode
1026
+ });
1027
+ return;
1028
+ }
1029
+ function applyVirtual(tree, diffs, options) {
1030
+ diffs.forEach(function (diff) {
1031
+ applyVirtualDiff(tree, diff, options);
1032
+ });
1033
+ return true;
1034
+ }
1035
+
1036
+ function nodeToObj(aNode, options) {
1037
+ if (options === void 0) { options = { valueDiffing: true }; }
1038
+ var objNode = {
1039
+ nodeName: aNode.nodeName
1040
+ };
1041
+ if (checkElementType(aNode, "Text", "Comment")) {
1042
+ objNode.data = aNode.data;
1043
+ }
1044
+ else {
1045
+ if (aNode.attributes && aNode.attributes.length > 0) {
1046
+ objNode.attributes = {};
1047
+ var nodeArray = Array.prototype.slice.call(aNode.attributes);
1048
+ nodeArray.forEach(function (attribute) {
1049
+ return (objNode.attributes[attribute.name] = attribute.value);
1050
+ });
1051
+ }
1052
+ if (aNode.childNodes && aNode.childNodes.length > 0) {
1053
+ objNode.childNodes = [];
1054
+ var nodeArray = Array.prototype.slice.call(aNode.childNodes);
1055
+ nodeArray.forEach(function (childNode) {
1056
+ return objNode.childNodes.push(nodeToObj(childNode, options));
1057
+ });
1058
+ }
1059
+ if (options.valueDiffing) {
1060
+ if (checkElementType(aNode, "HTMLTextAreaElement")) {
1061
+ objNode.value = aNode.value;
1062
+ }
1063
+ if (checkElementType(aNode, "HTMLInputElement") &&
1064
+ ["radio", "checkbox"].includes(aNode.type.toLowerCase()) &&
1065
+ aNode.checked !== undefined) {
1066
+ objNode.checked = aNode.checked;
1067
+ }
1068
+ else if (checkElementType(aNode, "HTMLButtonElement", "HTMLDataElement", "HTMLInputElement", "HTMLLIElement", "HTMLMeterElement", "HTMLOptionElement", "HTMLProgressElement", "HTMLParamElement")) {
1069
+ objNode.value = aNode.value;
1070
+ }
1071
+ if (checkElementType(aNode, "HTMLOptionElement")) {
1072
+ objNode.selected = aNode.selected;
1073
+ }
1074
+ }
1075
+ }
1076
+ return objNode;
1077
+ }
1078
+
1079
+ // from html-parse-stringify (MIT)
1080
+ var tagRE = /<\s*\/*[a-zA-Z:_][a-zA-Z0-9:_\-.]*\s*(?:"[^"]*"['"]*|'[^']*'['"]*|[^'"/>])*\/*\s*>|<!--(?:.|\n|\r)*?-->/g;
1081
+ var attrRE = /\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;
1082
+ function unescape(string) {
1083
+ return string
1084
+ .replace(/&lt;/g, "<")
1085
+ .replace(/&gt;/g, ">")
1086
+ .replace(/&amp;/g, "&");
1087
+ }
1088
+ // create optimized lookup object for
1089
+ // void elements as listed here:
1090
+ // https://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
1091
+ var lookup = {
1092
+ area: true,
1093
+ base: true,
1094
+ br: true,
1095
+ col: true,
1096
+ embed: true,
1097
+ hr: true,
1098
+ img: true,
1099
+ input: true,
1100
+ keygen: true,
1101
+ link: true,
1102
+ menuItem: true,
1103
+ meta: true,
1104
+ param: true,
1105
+ source: true,
1106
+ track: true,
1107
+ wbr: true
1108
+ };
1109
+ var parseTag = function (tag, caseSensitive) {
1110
+ var res = {
1111
+ nodeName: "",
1112
+ attributes: {}
1113
+ };
1114
+ var voidElement = false;
1115
+ var type = "tag";
1116
+ var tagMatch = tag.match(/<\/?([^\s]+?)[/\s>]/);
1117
+ if (tagMatch) {
1118
+ res.nodeName =
1119
+ caseSensitive || tagMatch[1] === "svg"
1120
+ ? tagMatch[1]
1121
+ : tagMatch[1].toUpperCase();
1122
+ if (lookup[tagMatch[1]] || tag.charAt(tag.length - 2) === "/") {
1123
+ voidElement = true;
1124
+ }
1125
+ // handle comment tag
1126
+ if (res.nodeName.startsWith("!--")) {
1127
+ var endIndex = tag.indexOf("-->");
1128
+ return {
1129
+ type: "comment",
1130
+ node: {
1131
+ nodeName: "#comment",
1132
+ data: endIndex !== -1 ? tag.slice(4, endIndex) : ""
1133
+ },
1134
+ voidElement: voidElement
1135
+ };
1136
+ }
1137
+ }
1138
+ var reg = new RegExp(attrRE);
1139
+ var result = null;
1140
+ var done = false;
1141
+ while (!done) {
1142
+ result = reg.exec(tag);
1143
+ if (result === null) {
1144
+ done = true;
1145
+ }
1146
+ else if (result[0].trim()) {
1147
+ if (result[1]) {
1148
+ var attr = result[1].trim();
1149
+ var arr = [attr, ""];
1150
+ if (attr.indexOf("=") > -1)
1151
+ { arr = attr.split("="); }
1152
+ res.attributes[arr[0]] = arr[1];
1153
+ reg.lastIndex--;
1154
+ }
1155
+ else if (result[2])
1156
+ { res.attributes[result[2]] = result[3]
1157
+ .trim()
1158
+ .substring(1, result[3].length - 1); }
1159
+ }
1160
+ }
1161
+ return {
1162
+ type: type,
1163
+ node: res,
1164
+ voidElement: voidElement
1165
+ };
1166
+ };
1167
+ var stringToObj = function (html, options) {
1168
+ if (options === void 0) { options = {
1169
+ valueDiffing: true,
1170
+ caseSensitive: false
1171
+ }; }
1172
+ var result = [];
1173
+ var current;
1174
+ var level = -1;
1175
+ var arr = [];
1176
+ var inComponent = false, insideSvg = false;
1177
+ // handle text at top level
1178
+ if (html.indexOf("<") !== 0) {
1179
+ var end = html.indexOf("<");
1180
+ result.push({
1181
+ nodeName: "#text",
1182
+ data: end === -1 ? html : html.substring(0, end)
1183
+ });
1184
+ }
1185
+ html.replace(tagRE, function (tag, index) {
1186
+ var isOpen = tag.charAt(1) !== "/";
1187
+ var isComment = tag.startsWith("<!--");
1188
+ var start = index + tag.length;
1189
+ var nextChar = html.charAt(start);
1190
+ if (isComment) {
1191
+ var comment = parseTag(tag, options.caseSensitive).node;
1192
+ // if we're at root, push new base node
1193
+ if (level < 0) {
1194
+ result.push(comment);
1195
+ return "";
1196
+ }
1197
+ var parent_1 = arr[level];
1198
+ if (parent_1 && comment.nodeName) {
1199
+ if (!parent_1.node.childNodes) {
1200
+ parent_1.node.childNodes = [];
1201
+ }
1202
+ parent_1.node.childNodes.push(comment);
1203
+ }
1204
+ return "";
1205
+ }
1206
+ if (isOpen) {
1207
+ current = parseTag(tag, options.caseSensitive || insideSvg);
1208
+ if (current.node.nodeName === "svg") {
1209
+ insideSvg = true;
1210
+ }
1211
+ level++;
1212
+ if (!current.voidElement &&
1213
+ !inComponent &&
1214
+ nextChar &&
1215
+ nextChar !== "<") {
1216
+ if (!current.node.childNodes) {
1217
+ current.node.childNodes = [];
1218
+ }
1219
+ var data = unescape(html.slice(start, html.indexOf("<", start)));
1220
+ current.node.childNodes.push({
1221
+ nodeName: "#text",
1222
+ data: data
1223
+ });
1224
+ if (options.valueDiffing &&
1225
+ current.node.nodeName === "TEXTAREA") {
1226
+ current.node.value = data;
1227
+ }
1228
+ }
1229
+ // if we're at root, push new base node
1230
+ if (level === 0 && current.node.nodeName) {
1231
+ result.push(current.node);
1232
+ }
1233
+ var parent_2 = arr[level - 1];
1234
+ if (parent_2 && current.node.nodeName) {
1235
+ if (!parent_2.node.childNodes) {
1236
+ parent_2.node.childNodes = [];
1237
+ }
1238
+ parent_2.node.childNodes.push(current.node);
1239
+ }
1240
+ arr[level] = current;
1241
+ }
1242
+ if (!isOpen || current.voidElement) {
1243
+ if (level > -1 &&
1244
+ (current.voidElement ||
1245
+ (options.caseSensitive &&
1246
+ current.node.nodeName === tag.slice(2, -1)) ||
1247
+ (!options.caseSensitive &&
1248
+ current.node.nodeName.toUpperCase() ===
1249
+ tag.slice(2, -1).toUpperCase()))) {
1250
+ level--;
1251
+ // move current up a level to match the end tag
1252
+ if (level > -1) {
1253
+ if (current.node.nodeName === "svg") {
1254
+ insideSvg = false;
1255
+ }
1256
+ current = arr[level];
1257
+ }
1258
+ }
1259
+ if (nextChar !== "<" && nextChar) {
1260
+ // trailing text node
1261
+ // if we're at the root, push a base text node. otherwise add as
1262
+ // a child to the current node.
1263
+ var childNodes = level === -1 ? result : arr[level].node.childNodes || [];
1264
+ // calculate correct end of the data slice in case there's
1265
+ // no tag after the text node.
1266
+ var end = html.indexOf("<", start);
1267
+ var data = unescape(html.slice(start, end === -1 ? undefined : end));
1268
+ childNodes.push({
1269
+ nodeName: "#text",
1270
+ data: data
1271
+ });
1272
+ }
1273
+ }
1274
+ return "";
1275
+ });
1276
+ return result[0];
1277
+ };
1278
+
1279
+ // ===== Create a diff =====
1280
+ var DiffFinder = /** @class */ (function () {
1281
+ function DiffFinder(t1Node, t2Node, options) {
1282
+ this.options = options;
1283
+ this.t1 = (typeof Element !== "undefined" &&
1284
+ checkElementType(t1Node, "Element")
1285
+ ? nodeToObj(t1Node, this.options)
1286
+ : typeof t1Node === "string"
1287
+ ? stringToObj(t1Node, this.options)
1288
+ : JSON.parse(JSON.stringify(t1Node)));
1289
+ this.t2 = (typeof Element !== "undefined" &&
1290
+ checkElementType(t2Node, "Element")
1291
+ ? nodeToObj(t2Node, this.options)
1292
+ : typeof t2Node === "string"
1293
+ ? stringToObj(t2Node, this.options)
1294
+ : JSON.parse(JSON.stringify(t2Node)));
1295
+ this.diffcount = 0;
1296
+ this.foundAll = false;
1297
+ if (this.debug) {
1298
+ this.t1Orig =
1299
+ typeof Element !== "undefined" &&
1300
+ checkElementType(t1Node, "Element")
1301
+ ? nodeToObj(t1Node, this.options)
1302
+ : typeof t1Node === "string"
1303
+ ? stringToObj(t1Node, this.options)
1304
+ : JSON.parse(JSON.stringify(t1Node));
1305
+ this.t2Orig =
1306
+ typeof Element !== "undefined" &&
1307
+ checkElementType(t2Node, "Element")
1308
+ ? nodeToObj(t2Node, this.options)
1309
+ : typeof t2Node === "string"
1310
+ ? stringToObj(t2Node, this.options)
1311
+ : JSON.parse(JSON.stringify(t2Node));
1312
+ }
1313
+ this.tracker = new DiffTracker();
1314
+ }
1315
+ DiffFinder.prototype.init = function () {
1316
+ return this.findDiffs(this.t1, this.t2);
1317
+ };
1318
+ DiffFinder.prototype.findDiffs = function (t1, t2) {
1319
+ var diffs;
1320
+ do {
1321
+ if (this.options.debug) {
1322
+ this.diffcount += 1;
1323
+ if (this.diffcount > this.options.diffcap) {
1324
+ throw new Error("surpassed diffcap:".concat(JSON.stringify(this.t1Orig), " -> ").concat(JSON.stringify(this.t2Orig)));
1325
+ }
1326
+ }
1327
+ diffs = this.findNextDiff(t1, t2, []);
1328
+ if (diffs.length === 0) {
1329
+ // Last check if the elements really are the same now.
1330
+ // If not, remove all info about being done and start over.
1331
+ // Sometimes a node can be marked as done, but the creation of subsequent diffs means that it has to be changed again.
1332
+ if (!isEqual(t1, t2)) {
1333
+ if (this.foundAll) {
1334
+ console.error("Could not find remaining diffs!");
1335
+ }
1336
+ else {
1337
+ this.foundAll = true;
1338
+ removeDone(t1);
1339
+ diffs = this.findNextDiff(t1, t2, []);
1340
+ }
1341
+ }
1342
+ }
1343
+ if (diffs.length > 0) {
1344
+ this.foundAll = false;
1345
+ this.tracker.add(diffs);
1346
+ applyVirtual(t1, diffs, this.options);
1347
+ }
1348
+ } while (diffs.length > 0);
1349
+ return this.tracker.list;
1350
+ };
1351
+ DiffFinder.prototype.findNextDiff = function (t1, t2, route) {
1352
+ var diffs;
1353
+ var fdiffs;
1354
+ if (this.options.maxDepth && route.length > this.options.maxDepth) {
1355
+ return [];
1356
+ }
1357
+ // outer differences?
1358
+ if (!t1.outerDone) {
1359
+ diffs = this.findOuterDiff(t1, t2, route);
1360
+ if (this.options.filterOuterDiff) {
1361
+ fdiffs = this.options.filterOuterDiff(t1, t2, diffs);
1362
+ if (fdiffs)
1363
+ { diffs = fdiffs; }
1364
+ }
1365
+ if (diffs.length > 0) {
1366
+ t1.outerDone = true;
1367
+ return diffs;
1368
+ }
1369
+ else {
1370
+ t1.outerDone = true;
1371
+ }
1372
+ }
1373
+ if (Object.prototype.hasOwnProperty.call(t1, "data")) {
1374
+ // Comment or Text
1375
+ return [];
1376
+ }
1377
+ t1 = t1;
1378
+ t2 = t2;
1379
+ // inner differences?
1380
+ if (!t1.innerDone) {
1381
+ diffs = this.findInnerDiff(t1, t2, route);
1382
+ if (diffs.length > 0) {
1383
+ return diffs;
1384
+ }
1385
+ else {
1386
+ t1.innerDone = true;
1387
+ }
1388
+ }
1389
+ if (this.options.valueDiffing && !t1.valueDone) {
1390
+ // value differences?
1391
+ diffs = this.findValueDiff(t1, t2, route);
1392
+ if (diffs.length > 0) {
1393
+ t1.valueDone = true;
1394
+ return diffs;
1395
+ }
1396
+ else {
1397
+ t1.valueDone = true;
1398
+ }
1399
+ }
1400
+ // no differences
1401
+ return [];
1402
+ };
1403
+ DiffFinder.prototype.findOuterDiff = function (t1, t2, route) {
1404
+ var diffs = [];
1405
+ var attr;
1406
+ var attr1;
1407
+ var attr2;
1408
+ var attrLength;
1409
+ var pos;
1410
+ var i;
1411
+ if (t1.nodeName !== t2.nodeName) {
1412
+ if (!route.length) {
1413
+ throw new Error("Top level nodes have to be of the same kind.");
1414
+ }
1415
+ return [
1416
+ new Diff()
1417
+ .setValue(this.options._const.action, this.options._const.replaceElement)
1418
+ .setValue(this.options._const.oldValue, cleanNode(t1))
1419
+ .setValue(this.options._const.newValue, cleanNode(t2))
1420
+ .setValue(this.options._const.route, route) ];
1421
+ }
1422
+ if (route.length &&
1423
+ this.options.diffcap <
1424
+ Math.abs((t1.childNodes || []).length - (t2.childNodes || []).length)) {
1425
+ return [
1426
+ new Diff()
1427
+ .setValue(this.options._const.action, this.options._const.replaceElement)
1428
+ .setValue(this.options._const.oldValue, cleanNode(t1))
1429
+ .setValue(this.options._const.newValue, cleanNode(t2))
1430
+ .setValue(this.options._const.route, route) ];
1431
+ }
1432
+ if (Object.prototype.hasOwnProperty.call(t1, "data") &&
1433
+ t1.data !== t2.data) {
1434
+ // Comment or text node.
1435
+ if (t1.nodeName === "#text") {
1436
+ return [
1437
+ new Diff()
1438
+ .setValue(this.options._const.action, this.options._const.modifyTextElement)
1439
+ .setValue(this.options._const.route, route)
1440
+ .setValue(this.options._const.oldValue, t1.data)
1441
+ .setValue(this.options._const.newValue, t2.data) ];
1442
+ }
1443
+ else {
1444
+ return [
1445
+ new Diff()
1446
+ .setValue(this.options._const.action, this.options._const.modifyComment)
1447
+ .setValue(this.options._const.route, route)
1448
+ .setValue(this.options._const.oldValue, t1.data)
1449
+ .setValue(this.options._const.newValue, t2.data) ];
1450
+ }
1451
+ }
1452
+ t1 = t1;
1453
+ t2 = t2;
1454
+ attr1 = t1.attributes ? Object.keys(t1.attributes).sort() : [];
1455
+ attr2 = t2.attributes ? Object.keys(t2.attributes).sort() : [];
1456
+ attrLength = attr1.length;
1457
+ for (i = 0; i < attrLength; i++) {
1458
+ attr = attr1[i];
1459
+ pos = attr2.indexOf(attr);
1460
+ if (pos === -1) {
1461
+ diffs.push(new Diff()
1462
+ .setValue(this.options._const.action, this.options._const.removeAttribute)
1463
+ .setValue(this.options._const.route, route)
1464
+ .setValue(this.options._const.name, attr)
1465
+ .setValue(this.options._const.value, t1.attributes[attr]));
1466
+ }
1467
+ else {
1468
+ attr2.splice(pos, 1);
1469
+ if (t1.attributes[attr] !== t2.attributes[attr]) {
1470
+ diffs.push(new Diff()
1471
+ .setValue(this.options._const.action, this.options._const.modifyAttribute)
1472
+ .setValue(this.options._const.route, route)
1473
+ .setValue(this.options._const.name, attr)
1474
+ .setValue(this.options._const.oldValue, t1.attributes[attr])
1475
+ .setValue(this.options._const.newValue, t2.attributes[attr]));
1476
+ }
1477
+ }
1478
+ }
1479
+ attrLength = attr2.length;
1480
+ for (i = 0; i < attrLength; i++) {
1481
+ attr = attr2[i];
1482
+ diffs.push(new Diff()
1483
+ .setValue(this.options._const.action, this.options._const.addAttribute)
1484
+ .setValue(this.options._const.route, route)
1485
+ .setValue(this.options._const.name, attr)
1486
+ .setValue(this.options._const.value, t2.attributes[attr]));
1487
+ }
1488
+ return diffs;
1489
+ };
1490
+ DiffFinder.prototype.findInnerDiff = function (t1, t2, route) {
1491
+ var t1ChildNodes = t1.childNodes ? t1.childNodes.slice() : [];
1492
+ var t2ChildNodes = t2.childNodes ? t2.childNodes.slice() : [];
1493
+ var last = Math.max(t1ChildNodes.length, t2ChildNodes.length);
1494
+ var childNodesLengthDifference = Math.abs(t1ChildNodes.length - t2ChildNodes.length);
1495
+ var diffs = [];
1496
+ var index = 0;
1497
+ if (!this.options.maxChildCount || last < this.options.maxChildCount) {
1498
+ var cachedSubtrees = Boolean(t1.subsets && t1.subsetsAge--);
1499
+ var subtrees = cachedSubtrees
1500
+ ? t1.subsets
1501
+ : t1.childNodes && t2.childNodes
1502
+ ? markSubTrees(t1, t2)
1503
+ : [];
1504
+ if (subtrees.length > 0) {
1505
+ /* One or more groups have been identified among the childnodes of t1
1506
+ * and t2.
1507
+ */
1508
+ diffs = this.attemptGroupRelocation(t1, t2, subtrees, route, cachedSubtrees);
1509
+ if (diffs.length > 0) {
1510
+ return diffs;
1511
+ }
1512
+ }
1513
+ }
1514
+ /* 0 or 1 groups of similar child nodes have been found
1515
+ * for t1 and t2. 1 If there is 1, it could be a sign that the
1516
+ * contents are the same. When the number of groups is below 2,
1517
+ * t1 and t2 are made to have the same length and each of the
1518
+ * pairs of child nodes are diffed.
1519
+ */
1520
+ for (var i = 0; i < last; i += 1) {
1521
+ var e1 = t1ChildNodes[i];
1522
+ var e2 = t2ChildNodes[i];
1523
+ if (childNodesLengthDifference) {
1524
+ /* t1 and t2 have different amounts of childNodes. Add
1525
+ * and remove as necessary to obtain the same length */
1526
+ if (e1 && !e2) {
1527
+ if (e1.nodeName === "#text") {
1528
+ diffs.push(new Diff()
1529
+ .setValue(this.options._const.action, this.options._const.removeTextElement)
1530
+ .setValue(this.options._const.route, route.concat(index))
1531
+ .setValue(this.options._const.value, e1.data));
1532
+ index -= 1;
1533
+ }
1534
+ else {
1535
+ diffs.push(new Diff()
1536
+ .setValue(this.options._const.action, this.options._const.removeElement)
1537
+ .setValue(this.options._const.route, route.concat(index))
1538
+ .setValue(this.options._const.element, cleanNode(e1)));
1539
+ index -= 1;
1540
+ }
1541
+ }
1542
+ else if (e2 && !e1) {
1543
+ if (e2.nodeName === "#text") {
1544
+ diffs.push(new Diff()
1545
+ .setValue(this.options._const.action, this.options._const.addTextElement)
1546
+ .setValue(this.options._const.route, route.concat(index))
1547
+ .setValue(this.options._const.value, e2.data));
1548
+ }
1549
+ else {
1550
+ diffs.push(new Diff()
1551
+ .setValue(this.options._const.action, this.options._const.addElement)
1552
+ .setValue(this.options._const.route, route.concat(index))
1553
+ .setValue(this.options._const.element, cleanNode(e2)));
1554
+ }
1555
+ }
1556
+ }
1557
+ /* We are now guaranteed that childNodes e1 and e2 exist,
1558
+ * and that they can be diffed.
1559
+ */
1560
+ /* Diffs in child nodes should not affect the parent node,
1561
+ * so we let these diffs be submitted together with other
1562
+ * diffs.
1563
+ */
1564
+ if (e1 && e2) {
1565
+ if (!this.options.maxChildCount ||
1566
+ last < this.options.maxChildCount) {
1567
+ diffs = diffs.concat(this.findNextDiff(e1, e2, route.concat(index)));
1568
+ }
1569
+ else if (!isEqual(e1, e2)) {
1570
+ if (t1ChildNodes.length > t2ChildNodes.length) {
1571
+ if (e1.nodeName === "#text") {
1572
+ diffs.push(new Diff()
1573
+ .setValue(this.options._const.action, this.options._const.removeTextElement)
1574
+ .setValue(this.options._const.route, route.concat(index))
1575
+ .setValue(this.options._const.value, e1.data));
1576
+ }
1577
+ else {
1578
+ diffs.push(new Diff()
1579
+ .setValue(this.options._const.action, this.options._const.removeElement)
1580
+ .setValue(this.options._const.element, cleanNode(e1))
1581
+ .setValue(this.options._const.route, route.concat(index)));
1582
+ }
1583
+ t1ChildNodes.splice(i, 1);
1584
+ i -= 1;
1585
+ index -= 1;
1586
+ childNodesLengthDifference -= 1;
1587
+ }
1588
+ else if (t1ChildNodes.length < t2ChildNodes.length) {
1589
+ diffs = diffs.concat([
1590
+ new Diff()
1591
+ .setValue(this.options._const.action, this.options._const.addElement)
1592
+ .setValue(this.options._const.element, cleanNode(e2))
1593
+ .setValue(this.options._const.route, route.concat(index)) ]);
1594
+ t1ChildNodes.splice(i, 0, cleanNode(e2));
1595
+ childNodesLengthDifference -= 1;
1596
+ }
1597
+ else {
1598
+ diffs = diffs.concat([
1599
+ new Diff()
1600
+ .setValue(this.options._const.action, this.options._const.replaceElement)
1601
+ .setValue(this.options._const.oldValue, cleanNode(e1))
1602
+ .setValue(this.options._const.newValue, cleanNode(e2))
1603
+ .setValue(this.options._const.route, route.concat(index)) ]);
1604
+ }
1605
+ }
1606
+ }
1607
+ index += 1;
1608
+ }
1609
+ t1.innerDone = true;
1610
+ return diffs;
1611
+ };
1612
+ DiffFinder.prototype.attemptGroupRelocation = function (t1, t2, subtrees, route, cachedSubtrees) {
1613
+ /* Either t1.childNodes and t2.childNodes have the same length, or
1614
+ * there are at least two groups of similar elements can be found.
1615
+ * attempts are made at equalizing t1 with t2. First all initial
1616
+ * elements with no group affiliation (gaps=true) are removed (if
1617
+ * only in t1) or added (if only in t2). Then the creation of a group
1618
+ * relocation diff is attempted.
1619
+ */
1620
+ var gapInformation = getGapInformation(t1, t2, subtrees);
1621
+ var gaps1 = gapInformation.gaps1;
1622
+ var gaps2 = gapInformation.gaps2;
1623
+ var t1ChildNodes = t1.childNodes.slice();
1624
+ var t2ChildNodes = t2.childNodes.slice();
1625
+ var shortest = Math.min(gaps1.length, gaps2.length);
1626
+ var destinationDifferent;
1627
+ var toGroup;
1628
+ var group;
1629
+ var node;
1630
+ var similarNode;
1631
+ var diffs = [];
1632
+ for (var index2 = 0, index1 = 0; index2 < shortest; index1 += 1, index2 += 1) {
1633
+ if (cachedSubtrees &&
1634
+ (gaps1[index2] === true || gaps2[index2] === true)) ;
1635
+ else if (gaps1[index1] === true) {
1636
+ node = t1ChildNodes[index1];
1637
+ if (node.nodeName === "#text") {
1638
+ if (t2ChildNodes[index2].nodeName === "#text") {
1639
+ if (node.data !==
1640
+ t2ChildNodes[index2].data) {
1641
+ // Check whether a text node with the same value follows later on.
1642
+ var testI = index1;
1643
+ while (t1ChildNodes.length > testI + 1 &&
1644
+ t1ChildNodes[testI + 1].nodeName === "#text") {
1645
+ testI += 1;
1646
+ if (t2ChildNodes[index2]
1647
+ .data ===
1648
+ t1ChildNodes[testI]
1649
+ .data) {
1650
+ similarNode = true;
1651
+ break;
1652
+ }
1653
+ }
1654
+ if (!similarNode) {
1655
+ diffs.push(new Diff()
1656
+ .setValue(this.options._const.action, this.options._const
1657
+ .modifyTextElement)
1658
+ .setValue(this.options._const.route, route.concat(index1))
1659
+ .setValue(this.options._const.oldValue, node.data)
1660
+ .setValue(this.options._const.newValue, t2ChildNodes[index2].data));
1661
+ }
1662
+ }
1663
+ }
1664
+ else {
1665
+ diffs.push(new Diff()
1666
+ .setValue(this.options._const.action, this.options._const.removeTextElement)
1667
+ .setValue(this.options._const.route, route.concat(index1))
1668
+ .setValue(this.options._const.value, node.data));
1669
+ gaps1.splice(index1, 1);
1670
+ t1ChildNodes.splice(index1, 1);
1671
+ shortest = Math.min(gaps1.length, gaps2.length);
1672
+ index1 -= 1;
1673
+ index2 -= 1;
1674
+ }
1675
+ }
1676
+ else if (gaps2[index2] === true) {
1677
+ // both gaps1[index1] and gaps2[index2] are true.
1678
+ // We replace one element with another.
1679
+ diffs.push(new Diff()
1680
+ .setValue(this.options._const.action, this.options._const.replaceElement)
1681
+ .setValue(this.options._const.oldValue, cleanNode(node))
1682
+ .setValue(this.options._const.newValue, cleanNode(t2ChildNodes[index2]))
1683
+ .setValue(this.options._const.route, route.concat(index1)));
1684
+ // t1ChildNodes at position index1 is not up-to-date, but that does not matter as
1685
+ // index1 will increase +1
1686
+ }
1687
+ else {
1688
+ diffs.push(new Diff()
1689
+ .setValue(this.options._const.action, this.options._const.removeElement)
1690
+ .setValue(this.options._const.route, route.concat(index1))
1691
+ .setValue(this.options._const.element, cleanNode(node)));
1692
+ gaps1.splice(index1, 1);
1693
+ t1ChildNodes.splice(index1, 1);
1694
+ shortest = Math.min(gaps1.length, gaps2.length);
1695
+ index1 -= 1;
1696
+ index2 -= 1;
1697
+ }
1698
+ }
1699
+ else if (gaps2[index2] === true) {
1700
+ node = t2ChildNodes[index2];
1701
+ if (node.nodeName === "#text") {
1702
+ diffs.push(new Diff()
1703
+ .setValue(this.options._const.action, this.options._const.addTextElement)
1704
+ .setValue(this.options._const.route, route.concat(index1))
1705
+ .setValue(this.options._const.value, node.data));
1706
+ gaps1.splice(index1, 0, true);
1707
+ t1ChildNodes.splice(index1, 0, {
1708
+ nodeName: "#text",
1709
+ data: node.data
1710
+ });
1711
+ shortest = Math.min(gaps1.length, gaps2.length);
1712
+ //index1 += 1
1713
+ }
1714
+ else {
1715
+ diffs.push(new Diff()
1716
+ .setValue(this.options._const.action, this.options._const.addElement)
1717
+ .setValue(this.options._const.route, route.concat(index1))
1718
+ .setValue(this.options._const.element, cleanNode(node)));
1719
+ gaps1.splice(index1, 0, true);
1720
+ t1ChildNodes.splice(index1, 0, cleanNode(node));
1721
+ shortest = Math.min(gaps1.length, gaps2.length);
1722
+ //index1 += 1
1723
+ }
1724
+ }
1725
+ else if (gaps1[index1] !== gaps2[index2]) {
1726
+ if (diffs.length > 0) {
1727
+ return diffs;
1728
+ }
1729
+ // group relocation
1730
+ group = subtrees[gaps1[index1]];
1731
+ toGroup = Math.min(group.newValue, t1ChildNodes.length - group.length);
1732
+ if (toGroup !== group.oldValue && toGroup > -1) {
1733
+ // Check whether destination nodes are different than originating ones.
1734
+ destinationDifferent = false;
1735
+ for (var j = 0; j < group.length; j += 1) {
1736
+ if (!roughlyEqual(t1ChildNodes[toGroup + j], t1ChildNodes[group.oldValue + j], {}, false, true)) {
1737
+ destinationDifferent = true;
1738
+ }
1739
+ }
1740
+ if (destinationDifferent) {
1741
+ return [
1742
+ new Diff()
1743
+ .setValue(this.options._const.action, this.options._const.relocateGroup)
1744
+ .setValue(this.options._const.groupLength, group.length)
1745
+ .setValue(this.options._const.from, group.oldValue)
1746
+ .setValue(this.options._const.to, toGroup)
1747
+ .setValue(this.options._const.route, route) ];
1748
+ }
1749
+ }
1750
+ }
1751
+ }
1752
+ return diffs;
1753
+ };
1754
+ DiffFinder.prototype.findValueDiff = function (t1, t2, route) {
1755
+ // Differences of value. Only useful if the value/selection/checked value
1756
+ // differs from what is represented in the DOM. For example in the case
1757
+ // of filled out forms, etc.
1758
+ var diffs = [];
1759
+ if (t1.selected !== t2.selected) {
1760
+ diffs.push(new Diff()
1761
+ .setValue(this.options._const.action, this.options._const.modifySelected)
1762
+ .setValue(this.options._const.oldValue, t1.selected)
1763
+ .setValue(this.options._const.newValue, t2.selected)
1764
+ .setValue(this.options._const.route, route));
1765
+ }
1766
+ if ((t1.value || t2.value) &&
1767
+ t1.value !== t2.value &&
1768
+ t1.nodeName !== "OPTION") {
1769
+ diffs.push(new Diff()
1770
+ .setValue(this.options._const.action, this.options._const.modifyValue)
1771
+ .setValue(this.options._const.oldValue, t1.value || "")
1772
+ .setValue(this.options._const.newValue, t2.value || "")
1773
+ .setValue(this.options._const.route, route));
1774
+ }
1775
+ if (t1.checked !== t2.checked) {
1776
+ diffs.push(new Diff()
1777
+ .setValue(this.options._const.action, this.options._const.modifyChecked)
1778
+ .setValue(this.options._const.oldValue, t1.checked)
1779
+ .setValue(this.options._const.newValue, t2.checked)
1780
+ .setValue(this.options._const.route, route));
1781
+ }
1782
+ return diffs;
1783
+ };
1784
+ return DiffFinder;
1785
+ }());
1786
+
1787
+ var DEFAULT_OPTIONS = {
1788
+ debug: false,
1789
+ diffcap: 10,
1790
+ maxDepth: false,
1791
+ maxChildCount: 50,
1792
+ valueDiffing: true,
1793
+ // syntax: textDiff: function (node, currentValue, expectedValue, newValue)
1794
+ textDiff: function (node, currentValue, expectedValue, newValue) {
1795
+ node.data = newValue;
1796
+ return;
1797
+ },
1798
+ // empty functions were benchmarked as running faster than both
1799
+ // `f && f()` and `if (f) { f(); }`
1800
+ preVirtualDiffApply: function () { },
1801
+ postVirtualDiffApply: function () { },
1802
+ preDiffApply: function () { },
1803
+ postDiffApply: function () { },
1804
+ filterOuterDiff: null,
1805
+ compress: false,
1806
+ _const: false,
1807
+ document: typeof window !== "undefined" && window.document
1808
+ ? window.document
1809
+ : false,
1810
+ components: []
1811
+ };
1812
+ var DiffDOM = /** @class */ (function () {
1813
+ function DiffDOM(options) {
1814
+ if (options === void 0) { options = {}; }
1815
+ // IE11 doesn't have Object.assign and buble doesn't translate object spreaders
1816
+ // by default, so this is the safest way of doing it currently.
1817
+ Object.entries(DEFAULT_OPTIONS).forEach(function (_a) {
1818
+ var key = _a[0], value = _a[1];
1819
+ if (!Object.prototype.hasOwnProperty.call(options, key)) {
1820
+ options[key] = value;
1821
+ }
1822
+ });
1823
+ if (!options._const) {
1824
+ var varNames = [
1825
+ "addAttribute",
1826
+ "modifyAttribute",
1827
+ "removeAttribute",
1828
+ "modifyTextElement",
1829
+ "relocateGroup",
1830
+ "removeElement",
1831
+ "addElement",
1832
+ "removeTextElement",
1833
+ "addTextElement",
1834
+ "replaceElement",
1835
+ "modifyValue",
1836
+ "modifyChecked",
1837
+ "modifySelected",
1838
+ "modifyComment",
1839
+ "action",
1840
+ "route",
1841
+ "oldValue",
1842
+ "newValue",
1843
+ "element",
1844
+ "group",
1845
+ "groupLength",
1846
+ "from",
1847
+ "to",
1848
+ "name",
1849
+ "value",
1850
+ "data",
1851
+ "attributes",
1852
+ "nodeName",
1853
+ "childNodes",
1854
+ "checked",
1855
+ "selected" ];
1856
+ var constNames_1 = {};
1857
+ if (options.compress) {
1858
+ varNames.forEach(function (varName, index) { return (constNames_1[varName] = index); });
1859
+ }
1860
+ else {
1861
+ varNames.forEach(function (varName) { return (constNames_1[varName] = varName); });
1862
+ }
1863
+ options._const = constNames_1;
1864
+ }
1865
+ this.options = options;
1866
+ }
1867
+ DiffDOM.prototype.apply = function (tree, diffs) {
1868
+ return applyDOM(tree, diffs, this.options);
1869
+ };
1870
+ DiffDOM.prototype.undo = function (tree, diffs) {
1871
+ return undoDOM(tree, diffs, this.options);
1872
+ };
1873
+ DiffDOM.prototype.diff = function (t1Node, t2Node) {
1874
+ var finder = new DiffFinder(t1Node, t2Node, this.options);
1875
+ return finder.init();
1876
+ };
1877
+ return DiffDOM;
1878
+ }());
1879
+
1880
+ /**
1881
+ * Use TraceLogger to figure out function calls inside
1882
+ * JS objects by wrapping an object with a TraceLogger
1883
+ * instance.
1884
+ *
1885
+ * Pretty-prints the call trace (using unicode box code)
1886
+ * when tracelogger.toString() is called.
1887
+ */
1888
+ /**
1889
+ * Wrap an object by calling new TraceLogger(obj)
1890
+ *
1891
+ * If you're familiar with Python decorators, this
1892
+ * does roughly the same thing, adding pre/post
1893
+ * call hook logging calls so that you can see
1894
+ * what's going on.
1895
+ */
1896
+ var TraceLogger = /** @class */ (function () {
1897
+ function TraceLogger(obj) {
1898
+ if (obj === void 0) { obj = {}; }
1899
+ var _this = this;
1900
+ this.pad = "│ ";
1901
+ this.padding = "";
1902
+ this.tick = 1;
1903
+ this.messages = [];
1904
+ var wrapkey = function (obj, key) {
1905
+ // trace this function
1906
+ var oldfn = obj[key];
1907
+ obj[key] = function () {
1908
+ var arguments$1 = arguments;
1909
+
1910
+ var args = [];
1911
+ for (var _i = 0; _i < arguments.length; _i++) {
1912
+ args[_i] = arguments$1[_i];
1913
+ }
1914
+ _this.fin(key, Array.prototype.slice.call(args));
1915
+ var result = oldfn.apply(obj, args);
1916
+ _this.fout(key, result);
1917
+ return result;
1918
+ };
1919
+ };
1920
+ // can't use Object.keys for prototype walking
1921
+ for (var key in obj) {
1922
+ if (typeof obj[key] === "function") {
1923
+ wrapkey(obj, key);
1924
+ }
1925
+ }
1926
+ this.log("┌ TRACELOG START");
1927
+ }
1928
+ // called when entering a function
1929
+ TraceLogger.prototype.fin = function (fn, args) {
1930
+ this.padding += this.pad;
1931
+ this.log("\u251C\u2500> entering ".concat(fn), args);
1932
+ };
1933
+ // called when exiting a function
1934
+ TraceLogger.prototype.fout = function (fn, result) {
1935
+ this.log("│<──┘ generated return value", result);
1936
+ this.padding = this.padding.substring(0, this.padding.length - this.pad.length);
1937
+ };
1938
+ // log message formatting
1939
+ TraceLogger.prototype.format = function (s, tick) {
1940
+ var nf = function (t) {
1941
+ var tStr = "".concat(t);
1942
+ while (tStr.length < 4) {
1943
+ tStr = "0".concat(t);
1944
+ }
1945
+ return tStr;
1946
+ };
1947
+ return "".concat(nf(tick), "> ").concat(this.padding).concat(s);
1948
+ };
1949
+ // log a trace message
1950
+ TraceLogger.prototype.log = function () {
1951
+ var arguments$1 = arguments;
1952
+
1953
+ var args = [];
1954
+ for (var _i = 0; _i < arguments.length; _i++) {
1955
+ args[_i] = arguments$1[_i];
1956
+ }
1957
+ var stringCollapse = function (v) {
1958
+ if (!v) {
1959
+ return "<falsey>";
1960
+ }
1961
+ if (typeof v === "string") {
1962
+ return v;
1963
+ }
1964
+ if (checkElementType(v, "HTMLElement")) {
1965
+ return v.outerHTML || "<empty>";
1966
+ }
1967
+ if (v instanceof Array) {
1968
+ return "[".concat(v.map(stringCollapse).join(","), "]");
1969
+ }
1970
+ return v.toString() || v.valueOf() || "<unknown>";
1971
+ };
1972
+ var s = args.map(stringCollapse).join(", ");
1973
+ this.messages.push(this.format(s, this.tick++));
1974
+ };
1975
+ // turn the log into a structured string with
1976
+ // unicode box codes to make it a sensible trace.
1977
+ TraceLogger.prototype.toString = function () {
1978
+ var cap = "× ";
1979
+ var terminator = "└───";
1980
+ while (terminator.length <= this.padding.length + this.pad.length) {
1981
+ terminator += cap;
1982
+ }
1983
+ var _ = this.padding;
1984
+ this.padding = "";
1985
+ terminator = this.format(terminator, this.tick);
1986
+ this.padding = _;
1987
+ return "".concat(this.messages.join("\n"), "\n").concat(terminator);
1988
+ };
1989
+ return TraceLogger;
1990
+ }());
1991
+
1992
+ exports.DiffDOM = DiffDOM;
1993
+ exports.TraceLogger = TraceLogger;
1994
+ exports.nodeToObj = nodeToObj;
1995
+ exports.stringToObj = stringToObj;
1996
+ //# sourceMappingURL=index.js.map