UNPKG

157 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('./empty')) :
3 typeof define === 'function' && define.amd ? define(['exports', './empty'], factory) :
4 (factory((global.jsondiffpatch = {}),global.chalk));
5}(this, (function (exports,chalk) { 'use strict';
6
7chalk = chalk && chalk.hasOwnProperty('default') ? chalk['default'] : chalk;
8
9var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
10 return typeof obj;
11} : function (obj) {
12 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
13};
14
15
16
17
18
19
20
21
22
23
24
25var classCallCheck = function (instance, Constructor) {
26 if (!(instance instanceof Constructor)) {
27 throw new TypeError("Cannot call a class as a function");
28 }
29};
30
31var createClass = function () {
32 function defineProperties(target, props) {
33 for (var i = 0; i < props.length; i++) {
34 var descriptor = props[i];
35 descriptor.enumerable = descriptor.enumerable || false;
36 descriptor.configurable = true;
37 if ("value" in descriptor) descriptor.writable = true;
38 Object.defineProperty(target, descriptor.key, descriptor);
39 }
40 }
41
42 return function (Constructor, protoProps, staticProps) {
43 if (protoProps) defineProperties(Constructor.prototype, protoProps);
44 if (staticProps) defineProperties(Constructor, staticProps);
45 return Constructor;
46 };
47}();
48
49
50
51
52
53
54
55var get = function get(object, property, receiver) {
56 if (object === null) object = Function.prototype;
57 var desc = Object.getOwnPropertyDescriptor(object, property);
58
59 if (desc === undefined) {
60 var parent = Object.getPrototypeOf(object);
61
62 if (parent === null) {
63 return undefined;
64 } else {
65 return get(parent, property, receiver);
66 }
67 } else if ("value" in desc) {
68 return desc.value;
69 } else {
70 var getter = desc.get;
71
72 if (getter === undefined) {
73 return undefined;
74 }
75
76 return getter.call(receiver);
77 }
78};
79
80var inherits = function (subClass, superClass) {
81 if (typeof superClass !== "function" && superClass !== null) {
82 throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
83 }
84
85 subClass.prototype = Object.create(superClass && superClass.prototype, {
86 constructor: {
87 value: subClass,
88 enumerable: false,
89 writable: true,
90 configurable: true
91 }
92 });
93 if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
94};
95
96
97
98
99
100
101
102
103
104
105
106var possibleConstructorReturn = function (self, call) {
107 if (!self) {
108 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
109 }
110
111 return call && (typeof call === "object" || typeof call === "function") ? call : self;
112};
113
114
115
116
117
118var slicedToArray = function () {
119 function sliceIterator(arr, i) {
120 var _arr = [];
121 var _n = true;
122 var _d = false;
123 var _e = undefined;
124
125 try {
126 for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
127 _arr.push(_s.value);
128
129 if (i && _arr.length === i) break;
130 }
131 } catch (err) {
132 _d = true;
133 _e = err;
134 } finally {
135 try {
136 if (!_n && _i["return"]) _i["return"]();
137 } finally {
138 if (_d) throw _e;
139 }
140 }
141
142 return _arr;
143 }
144
145 return function (arr, i) {
146 if (Array.isArray(arr)) {
147 return arr;
148 } else if (Symbol.iterator in Object(arr)) {
149 return sliceIterator(arr, i);
150 } else {
151 throw new TypeError("Invalid attempt to destructure non-iterable instance");
152 }
153 };
154}();
155
156
157
158
159
160
161
162
163
164
165
166
167
168var toConsumableArray = function (arr) {
169 if (Array.isArray(arr)) {
170 for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
171
172 return arr2;
173 } else {
174 return Array.from(arr);
175 }
176};
177
178var Processor = function () {
179 function Processor(options) {
180 classCallCheck(this, Processor);
181
182 this.selfOptions = options || {};
183 this.pipes = {};
184 }
185
186 createClass(Processor, [{
187 key: 'options',
188 value: function options(_options) {
189 if (_options) {
190 this.selfOptions = _options;
191 }
192 return this.selfOptions;
193 }
194 }, {
195 key: 'pipe',
196 value: function pipe(name, pipeArg) {
197 var pipe = pipeArg;
198 if (typeof name === 'string') {
199 if (typeof pipe === 'undefined') {
200 return this.pipes[name];
201 } else {
202 this.pipes[name] = pipe;
203 }
204 }
205 if (name && name.name) {
206 pipe = name;
207 if (pipe.processor === this) {
208 return pipe;
209 }
210 this.pipes[pipe.name] = pipe;
211 }
212 pipe.processor = this;
213 return pipe;
214 }
215 }, {
216 key: 'process',
217 value: function process(input, pipe) {
218 var context = input;
219 context.options = this.options();
220 var nextPipe = pipe || input.pipe || 'default';
221 var lastPipe = void 0;
222 var lastContext = void 0;
223 while (nextPipe) {
224 if (typeof context.nextAfterChildren !== 'undefined') {
225 // children processed and coming back to parent
226 context.next = context.nextAfterChildren;
227 context.nextAfterChildren = null;
228 }
229
230 if (typeof nextPipe === 'string') {
231 nextPipe = this.pipe(nextPipe);
232 }
233 nextPipe.process(context);
234 lastContext = context;
235 lastPipe = nextPipe;
236 nextPipe = null;
237 if (context) {
238 if (context.next) {
239 context = context.next;
240 nextPipe = lastContext.nextPipe || context.pipe || lastPipe;
241 }
242 }
243 }
244 return context.hasResult ? context.result : undefined;
245 }
246 }]);
247 return Processor;
248}();
249
250var Pipe = function () {
251 function Pipe(name) {
252 classCallCheck(this, Pipe);
253
254 this.name = name;
255 this.filters = [];
256 }
257
258 createClass(Pipe, [{
259 key: 'process',
260 value: function process(input) {
261 if (!this.processor) {
262 throw new Error('add this pipe to a processor before using it');
263 }
264 var debug = this.debug;
265 var length = this.filters.length;
266 var context = input;
267 for (var index = 0; index < length; index++) {
268 var filter = this.filters[index];
269 if (debug) {
270 this.log('filter: ' + filter.filterName);
271 }
272 filter(context);
273 if ((typeof context === 'undefined' ? 'undefined' : _typeof(context)) === 'object' && context.exiting) {
274 context.exiting = false;
275 break;
276 }
277 }
278 if (!context.next && this.resultCheck) {
279 this.resultCheck(context);
280 }
281 }
282 }, {
283 key: 'log',
284 value: function log(msg) {
285 console.log('[jsondiffpatch] ' + this.name + ' pipe, ' + msg);
286 }
287 }, {
288 key: 'append',
289 value: function append() {
290 var _filters;
291
292 (_filters = this.filters).push.apply(_filters, arguments);
293 return this;
294 }
295 }, {
296 key: 'prepend',
297 value: function prepend() {
298 var _filters2;
299
300 (_filters2 = this.filters).unshift.apply(_filters2, arguments);
301 return this;
302 }
303 }, {
304 key: 'indexOf',
305 value: function indexOf(filterName) {
306 if (!filterName) {
307 throw new Error('a filter name is required');
308 }
309 for (var index = 0; index < this.filters.length; index++) {
310 var filter = this.filters[index];
311 if (filter.filterName === filterName) {
312 return index;
313 }
314 }
315 throw new Error('filter not found: ' + filterName);
316 }
317 }, {
318 key: 'list',
319 value: function list() {
320 return this.filters.map(function (f) {
321 return f.filterName;
322 });
323 }
324 }, {
325 key: 'after',
326 value: function after(filterName) {
327 var index = this.indexOf(filterName);
328 var params = Array.prototype.slice.call(arguments, 1);
329 if (!params.length) {
330 throw new Error('a filter is required');
331 }
332 params.unshift(index + 1, 0);
333 Array.prototype.splice.apply(this.filters, params);
334 return this;
335 }
336 }, {
337 key: 'before',
338 value: function before(filterName) {
339 var index = this.indexOf(filterName);
340 var params = Array.prototype.slice.call(arguments, 1);
341 if (!params.length) {
342 throw new Error('a filter is required');
343 }
344 params.unshift(index, 0);
345 Array.prototype.splice.apply(this.filters, params);
346 return this;
347 }
348 }, {
349 key: 'replace',
350 value: function replace(filterName) {
351 var index = this.indexOf(filterName);
352 var params = Array.prototype.slice.call(arguments, 1);
353 if (!params.length) {
354 throw new Error('a filter is required');
355 }
356 params.unshift(index, 1);
357 Array.prototype.splice.apply(this.filters, params);
358 return this;
359 }
360 }, {
361 key: 'remove',
362 value: function remove(filterName) {
363 var index = this.indexOf(filterName);
364 this.filters.splice(index, 1);
365 return this;
366 }
367 }, {
368 key: 'clear',
369 value: function clear() {
370 this.filters.length = 0;
371 return this;
372 }
373 }, {
374 key: 'shouldHaveResult',
375 value: function shouldHaveResult(should) {
376 if (should === false) {
377 this.resultCheck = null;
378 return;
379 }
380 if (this.resultCheck) {
381 return;
382 }
383 var pipe = this;
384 this.resultCheck = function (context) {
385 if (!context.hasResult) {
386 console.log(context);
387 var error = new Error(pipe.name + ' failed');
388 error.noResult = true;
389 throw error;
390 }
391 };
392 return this;
393 }
394 }]);
395 return Pipe;
396}();
397
398var Context = function () {
399 function Context() {
400 classCallCheck(this, Context);
401 }
402
403 createClass(Context, [{
404 key: 'setResult',
405 value: function setResult(result) {
406 this.result = result;
407 this.hasResult = true;
408 return this;
409 }
410 }, {
411 key: 'exit',
412 value: function exit() {
413 this.exiting = true;
414 return this;
415 }
416 }, {
417 key: 'switchTo',
418 value: function switchTo(next, pipe) {
419 if (typeof next === 'string' || next instanceof Pipe) {
420 this.nextPipe = next;
421 } else {
422 this.next = next;
423 if (pipe) {
424 this.nextPipe = pipe;
425 }
426 }
427 return this;
428 }
429 }, {
430 key: 'push',
431 value: function push(child, name) {
432 child.parent = this;
433 if (typeof name !== 'undefined') {
434 child.childName = name;
435 }
436 child.root = this.root || this;
437 child.options = child.options || this.options;
438 if (!this.children) {
439 this.children = [child];
440 this.nextAfterChildren = this.next || null;
441 this.next = child;
442 } else {
443 this.children[this.children.length - 1].next = child;
444 this.children.push(child);
445 }
446 child.next = this;
447 return this;
448 }
449 }]);
450 return Context;
451}();
452
453var isArray = typeof Array.isArray === 'function' ? Array.isArray : function (a) {
454 return a instanceof Array;
455};
456
457function cloneRegExp(re) {
458 var regexMatch = /^\/(.*)\/([gimyu]*)$/.exec(re.toString());
459 return new RegExp(regexMatch[1], regexMatch[2]);
460}
461
462function clone(arg) {
463 if ((typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) !== 'object') {
464 return arg;
465 }
466 if (arg === null) {
467 return null;
468 }
469 if (isArray(arg)) {
470 return arg.map(clone);
471 }
472 if (arg instanceof Date) {
473 return new Date(arg.getTime());
474 }
475 if (arg instanceof RegExp) {
476 return cloneRegExp(arg);
477 }
478 var cloned = {};
479 for (var name in arg) {
480 if (Object.prototype.hasOwnProperty.call(arg, name)) {
481 cloned[name] = clone(arg[name]);
482 }
483 }
484 return cloned;
485}
486
487var DiffContext = function (_Context) {
488 inherits(DiffContext, _Context);
489
490 function DiffContext(left, right) {
491 classCallCheck(this, DiffContext);
492
493 var _this = possibleConstructorReturn(this, (DiffContext.__proto__ || Object.getPrototypeOf(DiffContext)).call(this));
494
495 _this.left = left;
496 _this.right = right;
497 _this.pipe = 'diff';
498 return _this;
499 }
500
501 createClass(DiffContext, [{
502 key: 'setResult',
503 value: function setResult(result) {
504 if (this.options.cloneDiffValues && (typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object') {
505 var clone$$1 = typeof this.options.cloneDiffValues === 'function' ? this.options.cloneDiffValues : clone;
506 if (_typeof(result[0]) === 'object') {
507 result[0] = clone$$1(result[0]);
508 }
509 if (_typeof(result[1]) === 'object') {
510 result[1] = clone$$1(result[1]);
511 }
512 }
513 return Context.prototype.setResult.apply(this, arguments);
514 }
515 }]);
516 return DiffContext;
517}(Context);
518
519var PatchContext = function (_Context) {
520 inherits(PatchContext, _Context);
521
522 function PatchContext(left, delta) {
523 classCallCheck(this, PatchContext);
524
525 var _this = possibleConstructorReturn(this, (PatchContext.__proto__ || Object.getPrototypeOf(PatchContext)).call(this));
526
527 _this.left = left;
528 _this.delta = delta;
529 _this.pipe = 'patch';
530 return _this;
531 }
532
533 return PatchContext;
534}(Context);
535
536var ReverseContext = function (_Context) {
537 inherits(ReverseContext, _Context);
538
539 function ReverseContext(delta) {
540 classCallCheck(this, ReverseContext);
541
542 var _this = possibleConstructorReturn(this, (ReverseContext.__proto__ || Object.getPrototypeOf(ReverseContext)).call(this));
543
544 _this.delta = delta;
545 _this.pipe = 'reverse';
546 return _this;
547 }
548
549 return ReverseContext;
550}(Context);
551
552var isArray$1 = typeof Array.isArray === 'function' ? Array.isArray : function (a) {
553 return a instanceof Array;
554};
555
556var diffFilter = function trivialMatchesDiffFilter(context) {
557 if (context.left === context.right) {
558 context.setResult(undefined).exit();
559 return;
560 }
561 if (typeof context.left === 'undefined') {
562 if (typeof context.right === 'function') {
563 throw new Error('functions are not supported');
564 }
565 context.setResult([context.right]).exit();
566 return;
567 }
568 if (typeof context.right === 'undefined') {
569 context.setResult([context.left, 0, 0]).exit();
570 return;
571 }
572 if (typeof context.left === 'function' || typeof context.right === 'function') {
573 throw new Error('functions are not supported');
574 }
575 context.leftType = context.left === null ? 'null' : _typeof(context.left);
576 context.rightType = context.right === null ? 'null' : _typeof(context.right);
577 if (context.leftType !== context.rightType) {
578 context.setResult([context.left, context.right]).exit();
579 return;
580 }
581 if (context.leftType === 'boolean' || context.leftType === 'number') {
582 context.setResult([context.left, context.right]).exit();
583 return;
584 }
585 if (context.leftType === 'object') {
586 context.leftIsArray = isArray$1(context.left);
587 }
588 if (context.rightType === 'object') {
589 context.rightIsArray = isArray$1(context.right);
590 }
591 if (context.leftIsArray !== context.rightIsArray) {
592 context.setResult([context.left, context.right]).exit();
593 return;
594 }
595
596 if (context.left instanceof RegExp) {
597 if (context.right instanceof RegExp) {
598 context.setResult([context.left.toString(), context.right.toString()]).exit();
599 } else {
600 context.setResult([context.left, context.right]).exit();
601 }
602 }
603};
604diffFilter.filterName = 'trivial';
605
606var patchFilter = function trivialMatchesPatchFilter(context) {
607 if (typeof context.delta === 'undefined') {
608 context.setResult(context.left).exit();
609 return;
610 }
611 context.nested = !isArray$1(context.delta);
612 if (context.nested) {
613 return;
614 }
615 if (context.delta.length === 1) {
616 context.setResult(context.delta[0]).exit();
617 return;
618 }
619 if (context.delta.length === 2) {
620 if (context.left instanceof RegExp) {
621 var regexArgs = /^\/(.*)\/([gimyu]+)$/.exec(context.delta[1]);
622 if (regexArgs) {
623 context.setResult(new RegExp(regexArgs[1], regexArgs[2])).exit();
624 return;
625 }
626 }
627 context.setResult(context.delta[1]).exit();
628 return;
629 }
630 if (context.delta.length === 3 && context.delta[2] === 0) {
631 context.setResult(undefined).exit();
632 }
633};
634patchFilter.filterName = 'trivial';
635
636var reverseFilter = function trivialReferseFilter(context) {
637 if (typeof context.delta === 'undefined') {
638 context.setResult(context.delta).exit();
639 return;
640 }
641 context.nested = !isArray$1(context.delta);
642 if (context.nested) {
643 return;
644 }
645 if (context.delta.length === 1) {
646 context.setResult([context.delta[0], 0, 0]).exit();
647 return;
648 }
649 if (context.delta.length === 2) {
650 context.setResult([context.delta[1], context.delta[0]]).exit();
651 return;
652 }
653 if (context.delta.length === 3 && context.delta[2] === 0) {
654 context.setResult([context.delta[0]]).exit();
655 }
656};
657reverseFilter.filterName = 'trivial';
658
659function collectChildrenDiffFilter(context) {
660 if (!context || !context.children) {
661 return;
662 }
663 var length = context.children.length;
664 var child = void 0;
665 var result = context.result;
666 for (var index = 0; index < length; index++) {
667 child = context.children[index];
668 if (typeof child.result === 'undefined') {
669 continue;
670 }
671 result = result || {};
672 result[child.childName] = child.result;
673 }
674 if (result && context.leftIsArray) {
675 result._t = 'a';
676 }
677 context.setResult(result).exit();
678}
679collectChildrenDiffFilter.filterName = 'collectChildren';
680
681function objectsDiffFilter(context) {
682 if (context.leftIsArray || context.leftType !== 'object') {
683 return;
684 }
685
686 var name = void 0;
687 var child = void 0;
688 var propertyFilter = context.options.propertyFilter;
689 for (name in context.left) {
690 if (!Object.prototype.hasOwnProperty.call(context.left, name)) {
691 continue;
692 }
693 if (propertyFilter && !propertyFilter(name, context)) {
694 continue;
695 }
696 child = new DiffContext(context.left[name], context.right[name]);
697 context.push(child, name);
698 }
699 for (name in context.right) {
700 if (!Object.prototype.hasOwnProperty.call(context.right, name)) {
701 continue;
702 }
703 if (propertyFilter && !propertyFilter(name, context)) {
704 continue;
705 }
706 if (typeof context.left[name] === 'undefined') {
707 child = new DiffContext(undefined, context.right[name]);
708 context.push(child, name);
709 }
710 }
711
712 if (!context.children || context.children.length === 0) {
713 context.setResult(undefined).exit();
714 return;
715 }
716 context.exit();
717}
718objectsDiffFilter.filterName = 'objects';
719
720var patchFilter$1 = function nestedPatchFilter(context) {
721 if (!context.nested) {
722 return;
723 }
724 if (context.delta._t) {
725 return;
726 }
727 var name = void 0;
728 var child = void 0;
729 for (name in context.delta) {
730 child = new PatchContext(context.left[name], context.delta[name]);
731 context.push(child, name);
732 }
733 context.exit();
734};
735patchFilter$1.filterName = 'objects';
736
737var collectChildrenPatchFilter = function collectChildrenPatchFilter(context) {
738 if (!context || !context.children) {
739 return;
740 }
741 if (context.delta._t) {
742 return;
743 }
744 var length = context.children.length;
745 var child = void 0;
746 for (var index = 0; index < length; index++) {
747 child = context.children[index];
748 if (Object.prototype.hasOwnProperty.call(context.left, child.childName) && child.result === undefined) {
749 delete context.left[child.childName];
750 } else if (context.left[child.childName] !== child.result) {
751 context.left[child.childName] = child.result;
752 }
753 }
754 context.setResult(context.left).exit();
755};
756collectChildrenPatchFilter.filterName = 'collectChildren';
757
758var reverseFilter$1 = function nestedReverseFilter(context) {
759 if (!context.nested) {
760 return;
761 }
762 if (context.delta._t) {
763 return;
764 }
765 var name = void 0;
766 var child = void 0;
767 for (name in context.delta) {
768 child = new ReverseContext(context.delta[name]);
769 context.push(child, name);
770 }
771 context.exit();
772};
773reverseFilter$1.filterName = 'objects';
774
775function collectChildrenReverseFilter(context) {
776 if (!context || !context.children) {
777 return;
778 }
779 if (context.delta._t) {
780 return;
781 }
782 var length = context.children.length;
783 var child = void 0;
784 var delta = {};
785 for (var index = 0; index < length; index++) {
786 child = context.children[index];
787 if (delta[child.childName] !== child.result) {
788 delta[child.childName] = child.result;
789 }
790 }
791 context.setResult(delta).exit();
792}
793collectChildrenReverseFilter.filterName = 'collectChildren';
794
795/*
796
797LCS implementation that supports arrays or strings
798
799reference: http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
800
801*/
802
803var defaultMatch = function defaultMatch(array1, array2, index1, index2) {
804 return array1[index1] === array2[index2];
805};
806
807var lengthMatrix = function lengthMatrix(array1, array2, match, context) {
808 var len1 = array1.length;
809 var len2 = array2.length;
810 var x = void 0,
811 y = void 0;
812
813 // initialize empty matrix of len1+1 x len2+1
814 var matrix = [len1 + 1];
815 for (x = 0; x < len1 + 1; x++) {
816 matrix[x] = [len2 + 1];
817 for (y = 0; y < len2 + 1; y++) {
818 matrix[x][y] = 0;
819 }
820 }
821 matrix.match = match;
822 // save sequence lengths for each coordinate
823 for (x = 1; x < len1 + 1; x++) {
824 for (y = 1; y < len2 + 1; y++) {
825 if (match(array1, array2, x - 1, y - 1, context)) {
826 matrix[x][y] = matrix[x - 1][y - 1] + 1;
827 } else {
828 matrix[x][y] = Math.max(matrix[x - 1][y], matrix[x][y - 1]);
829 }
830 }
831 }
832 return matrix;
833};
834
835var backtrack = function backtrack(matrix, array1, array2, index1, index2, context) {
836 if (index1 === 0 || index2 === 0) {
837 return {
838 sequence: [],
839 indices1: [],
840 indices2: []
841 };
842 }
843
844 if (matrix.match(array1, array2, index1 - 1, index2 - 1, context)) {
845 var subsequence = backtrack(matrix, array1, array2, index1 - 1, index2 - 1, context);
846 subsequence.sequence.push(array1[index1 - 1]);
847 subsequence.indices1.push(index1 - 1);
848 subsequence.indices2.push(index2 - 1);
849 return subsequence;
850 }
851
852 if (matrix[index1][index2 - 1] > matrix[index1 - 1][index2]) {
853 return backtrack(matrix, array1, array2, index1, index2 - 1, context);
854 } else {
855 return backtrack(matrix, array1, array2, index1 - 1, index2, context);
856 }
857};
858
859var get$1 = function get(array1, array2, match, context) {
860 var innerContext = context || {};
861 var matrix = lengthMatrix(array1, array2, match || defaultMatch, innerContext);
862 var result = backtrack(matrix, array1, array2, array1.length, array2.length, innerContext);
863 if (typeof array1 === 'string' && typeof array2 === 'string') {
864 result.sequence = result.sequence.join('');
865 }
866 return result;
867};
868
869var lcs = {
870 get: get$1
871};
872
873var ARRAY_MOVE = 3;
874
875var isArray$2 = typeof Array.isArray === 'function' ? Array.isArray : function (a) {
876 return a instanceof Array;
877};
878
879var arrayIndexOf = typeof Array.prototype.indexOf === 'function' ? function (array, item) {
880 return array.indexOf(item);
881} : function (array, item) {
882 var length = array.length;
883 for (var i = 0; i < length; i++) {
884 if (array[i] === item) {
885 return i;
886 }
887 }
888 return -1;
889};
890
891function arraysHaveMatchByRef(array1, array2, len1, len2) {
892 for (var index1 = 0; index1 < len1; index1++) {
893 var val1 = array1[index1];
894 for (var index2 = 0; index2 < len2; index2++) {
895 var val2 = array2[index2];
896 if (index1 !== index2 && val1 === val2) {
897 return true;
898 }
899 }
900 }
901}
902
903function matchItems(array1, array2, index1, index2, context) {
904 var value1 = array1[index1];
905 var value2 = array2[index2];
906 if (value1 === value2) {
907 return true;
908 }
909 if ((typeof value1 === 'undefined' ? 'undefined' : _typeof(value1)) !== 'object' || (typeof value2 === 'undefined' ? 'undefined' : _typeof(value2)) !== 'object') {
910 return false;
911 }
912 var objectHash = context.objectHash;
913 if (!objectHash) {
914 // no way to match objects was provided, try match by position
915 return context.matchByPosition && index1 === index2;
916 }
917 var hash1 = void 0;
918 var hash2 = void 0;
919 if (typeof index1 === 'number') {
920 context.hashCache1 = context.hashCache1 || [];
921 hash1 = context.hashCache1[index1];
922 if (typeof hash1 === 'undefined') {
923 context.hashCache1[index1] = hash1 = objectHash(value1, index1);
924 }
925 } else {
926 hash1 = objectHash(value1);
927 }
928 if (typeof hash1 === 'undefined') {
929 return false;
930 }
931 if (typeof index2 === 'number') {
932 context.hashCache2 = context.hashCache2 || [];
933 hash2 = context.hashCache2[index2];
934 if (typeof hash2 === 'undefined') {
935 context.hashCache2[index2] = hash2 = objectHash(value2, index2);
936 }
937 } else {
938 hash2 = objectHash(value2);
939 }
940 if (typeof hash2 === 'undefined') {
941 return false;
942 }
943 return hash1 === hash2;
944}
945
946var diffFilter$1 = function arraysDiffFilter(context) {
947 if (!context.leftIsArray) {
948 return;
949 }
950
951 var matchContext = {
952 objectHash: context.options && context.options.objectHash,
953 matchByPosition: context.options && context.options.matchByPosition
954 };
955 var commonHead = 0;
956 var commonTail = 0;
957 var index = void 0;
958 var index1 = void 0;
959 var index2 = void 0;
960 var array1 = context.left;
961 var array2 = context.right;
962 var len1 = array1.length;
963 var len2 = array2.length;
964
965 var child = void 0;
966
967 if (len1 > 0 && len2 > 0 && !matchContext.objectHash && typeof matchContext.matchByPosition !== 'boolean') {
968 matchContext.matchByPosition = !arraysHaveMatchByRef(array1, array2, len1, len2);
969 }
970
971 // separate common head
972 while (commonHead < len1 && commonHead < len2 && matchItems(array1, array2, commonHead, commonHead, matchContext)) {
973 index = commonHead;
974 child = new DiffContext(context.left[index], context.right[index]);
975 context.push(child, index);
976 commonHead++;
977 }
978 // separate common tail
979 while (commonTail + commonHead < len1 && commonTail + commonHead < len2 && matchItems(array1, array2, len1 - 1 - commonTail, len2 - 1 - commonTail, matchContext)) {
980 index1 = len1 - 1 - commonTail;
981 index2 = len2 - 1 - commonTail;
982 child = new DiffContext(context.left[index1], context.right[index2]);
983 context.push(child, index2);
984 commonTail++;
985 }
986 var result = void 0;
987 if (commonHead + commonTail === len1) {
988 if (len1 === len2) {
989 // arrays are identical
990 context.setResult(undefined).exit();
991 return;
992 }
993 // trivial case, a block (1 or more consecutive items) was added
994 result = result || {
995 _t: 'a'
996 };
997 for (index = commonHead; index < len2 - commonTail; index++) {
998 result[index] = [array2[index]];
999 }
1000 context.setResult(result).exit();
1001 return;
1002 }
1003 if (commonHead + commonTail === len2) {
1004 // trivial case, a block (1 or more consecutive items) was removed
1005 result = result || {
1006 _t: 'a'
1007 };
1008 for (index = commonHead; index < len1 - commonTail; index++) {
1009 result['_' + index] = [array1[index], 0, 0];
1010 }
1011 context.setResult(result).exit();
1012 return;
1013 }
1014 // reset hash cache
1015 delete matchContext.hashCache1;
1016 delete matchContext.hashCache2;
1017
1018 // diff is not trivial, find the LCS (Longest Common Subsequence)
1019 var trimmed1 = array1.slice(commonHead, len1 - commonTail);
1020 var trimmed2 = array2.slice(commonHead, len2 - commonTail);
1021 var seq = lcs.get(trimmed1, trimmed2, matchItems, matchContext);
1022 var removedItems = [];
1023 result = result || {
1024 _t: 'a'
1025 };
1026 for (index = commonHead; index < len1 - commonTail; index++) {
1027 if (arrayIndexOf(seq.indices1, index - commonHead) < 0) {
1028 // removed
1029 result['_' + index] = [array1[index], 0, 0];
1030 removedItems.push(index);
1031 }
1032 }
1033
1034 var detectMove = true;
1035 if (context.options && context.options.arrays && context.options.arrays.detectMove === false) {
1036 detectMove = false;
1037 }
1038 var includeValueOnMove = false;
1039 if (context.options && context.options.arrays && context.options.arrays.includeValueOnMove) {
1040 includeValueOnMove = true;
1041 }
1042
1043 var removedItemsLength = removedItems.length;
1044 for (index = commonHead; index < len2 - commonTail; index++) {
1045 var indexOnArray2 = arrayIndexOf(seq.indices2, index - commonHead);
1046 if (indexOnArray2 < 0) {
1047 // added, try to match with a removed item and register as position move
1048 var isMove = false;
1049 if (detectMove && removedItemsLength > 0) {
1050 for (var removeItemIndex1 = 0; removeItemIndex1 < removedItemsLength; removeItemIndex1++) {
1051 index1 = removedItems[removeItemIndex1];
1052 if (matchItems(trimmed1, trimmed2, index1 - commonHead, index - commonHead, matchContext)) {
1053 // store position move as: [originalValue, newPosition, ARRAY_MOVE]
1054 result['_' + index1].splice(1, 2, index, ARRAY_MOVE);
1055 if (!includeValueOnMove) {
1056 // don't include moved value on diff, to save bytes
1057 result['_' + index1][0] = '';
1058 }
1059
1060 index2 = index;
1061 child = new DiffContext(context.left[index1], context.right[index2]);
1062 context.push(child, index2);
1063 removedItems.splice(removeItemIndex1, 1);
1064 isMove = true;
1065 break;
1066 }
1067 }
1068 }
1069 if (!isMove) {
1070 // added
1071 result[index] = [array2[index]];
1072 }
1073 } else {
1074 // match, do inner diff
1075 index1 = seq.indices1[indexOnArray2] + commonHead;
1076 index2 = seq.indices2[indexOnArray2] + commonHead;
1077 child = new DiffContext(context.left[index1], context.right[index2]);
1078 context.push(child, index2);
1079 }
1080 }
1081
1082 context.setResult(result).exit();
1083};
1084diffFilter$1.filterName = 'arrays';
1085
1086var compare = {
1087 numerically: function numerically(a, b) {
1088 return a - b;
1089 },
1090 numericallyBy: function numericallyBy(name) {
1091 return function (a, b) {
1092 return a[name] - b[name];
1093 };
1094 }
1095};
1096
1097var patchFilter$2 = function nestedPatchFilter(context) {
1098 if (!context.nested) {
1099 return;
1100 }
1101 if (context.delta._t !== 'a') {
1102 return;
1103 }
1104 var index = void 0;
1105 var index1 = void 0;
1106
1107 var delta = context.delta;
1108 var array = context.left;
1109
1110 // first, separate removals, insertions and modifications
1111 var toRemove = [];
1112 var toInsert = [];
1113 var toModify = [];
1114 for (index in delta) {
1115 if (index !== '_t') {
1116 if (index[0] === '_') {
1117 // removed item from original array
1118 if (delta[index][2] === 0 || delta[index][2] === ARRAY_MOVE) {
1119 toRemove.push(parseInt(index.slice(1), 10));
1120 } else {
1121 throw new Error('only removal or move can be applied at original array indices,' + (' invalid diff type: ' + delta[index][2]));
1122 }
1123 } else {
1124 if (delta[index].length === 1) {
1125 // added item at new array
1126 toInsert.push({
1127 index: parseInt(index, 10),
1128 value: delta[index][0]
1129 });
1130 } else {
1131 // modified item at new array
1132 toModify.push({
1133 index: parseInt(index, 10),
1134 delta: delta[index]
1135 });
1136 }
1137 }
1138 }
1139 }
1140
1141 // remove items, in reverse order to avoid sawing our own floor
1142 toRemove = toRemove.sort(compare.numerically);
1143 for (index = toRemove.length - 1; index >= 0; index--) {
1144 index1 = toRemove[index];
1145 var indexDiff = delta['_' + index1];
1146 var removedValue = array.splice(index1, 1)[0];
1147 if (indexDiff[2] === ARRAY_MOVE) {
1148 // reinsert later
1149 toInsert.push({
1150 index: indexDiff[1],
1151 value: removedValue
1152 });
1153 }
1154 }
1155
1156 // insert items, in reverse order to avoid moving our own floor
1157 toInsert = toInsert.sort(compare.numericallyBy('index'));
1158 var toInsertLength = toInsert.length;
1159 for (index = 0; index < toInsertLength; index++) {
1160 var insertion = toInsert[index];
1161 array.splice(insertion.index, 0, insertion.value);
1162 }
1163
1164 // apply modifications
1165 var toModifyLength = toModify.length;
1166 var child = void 0;
1167 if (toModifyLength > 0) {
1168 for (index = 0; index < toModifyLength; index++) {
1169 var modification = toModify[index];
1170 child = new PatchContext(context.left[modification.index], modification.delta);
1171 context.push(child, modification.index);
1172 }
1173 }
1174
1175 if (!context.children) {
1176 context.setResult(context.left).exit();
1177 return;
1178 }
1179 context.exit();
1180};
1181patchFilter$2.filterName = 'arrays';
1182
1183var collectChildrenPatchFilter$1 = function collectChildrenPatchFilter(context) {
1184 if (!context || !context.children) {
1185 return;
1186 }
1187 if (context.delta._t !== 'a') {
1188 return;
1189 }
1190 var length = context.children.length;
1191 var child = void 0;
1192 for (var index = 0; index < length; index++) {
1193 child = context.children[index];
1194 context.left[child.childName] = child.result;
1195 }
1196 context.setResult(context.left).exit();
1197};
1198collectChildrenPatchFilter$1.filterName = 'arraysCollectChildren';
1199
1200var reverseFilter$2 = function arraysReverseFilter(context) {
1201 if (!context.nested) {
1202 if (context.delta[2] === ARRAY_MOVE) {
1203 context.newName = '_' + context.delta[1];
1204 context.setResult([context.delta[0], parseInt(context.childName.substr(1), 10), ARRAY_MOVE]).exit();
1205 }
1206 return;
1207 }
1208 if (context.delta._t !== 'a') {
1209 return;
1210 }
1211 var name = void 0;
1212 var child = void 0;
1213 for (name in context.delta) {
1214 if (name === '_t') {
1215 continue;
1216 }
1217 child = new ReverseContext(context.delta[name]);
1218 context.push(child, name);
1219 }
1220 context.exit();
1221};
1222reverseFilter$2.filterName = 'arrays';
1223
1224var reverseArrayDeltaIndex = function reverseArrayDeltaIndex(delta, index, itemDelta) {
1225 if (typeof index === 'string' && index[0] === '_') {
1226 return parseInt(index.substr(1), 10);
1227 } else if (isArray$2(itemDelta) && itemDelta[2] === 0) {
1228 return '_' + index;
1229 }
1230
1231 var reverseIndex = +index;
1232 for (var deltaIndex in delta) {
1233 var deltaItem = delta[deltaIndex];
1234 if (isArray$2(deltaItem)) {
1235 if (deltaItem[2] === ARRAY_MOVE) {
1236 var moveFromIndex = parseInt(deltaIndex.substr(1), 10);
1237 var moveToIndex = deltaItem[1];
1238 if (moveToIndex === +index) {
1239 return moveFromIndex;
1240 }
1241 if (moveFromIndex <= reverseIndex && moveToIndex > reverseIndex) {
1242 reverseIndex++;
1243 } else if (moveFromIndex >= reverseIndex && moveToIndex < reverseIndex) {
1244 reverseIndex--;
1245 }
1246 } else if (deltaItem[2] === 0) {
1247 var deleteIndex = parseInt(deltaIndex.substr(1), 10);
1248 if (deleteIndex <= reverseIndex) {
1249 reverseIndex++;
1250 }
1251 } else if (deltaItem.length === 1 && deltaIndex <= reverseIndex) {
1252 reverseIndex--;
1253 }
1254 }
1255 }
1256
1257 return reverseIndex;
1258};
1259
1260function collectChildrenReverseFilter$1(context) {
1261 if (!context || !context.children) {
1262 return;
1263 }
1264 if (context.delta._t !== 'a') {
1265 return;
1266 }
1267 var length = context.children.length;
1268 var child = void 0;
1269 var delta = {
1270 _t: 'a'
1271 };
1272
1273 for (var index = 0; index < length; index++) {
1274 child = context.children[index];
1275 var name = child.newName;
1276 if (typeof name === 'undefined') {
1277 name = reverseArrayDeltaIndex(context.delta, child.childName, child.result);
1278 }
1279 if (delta[name] !== child.result) {
1280 delta[name] = child.result;
1281 }
1282 }
1283 context.setResult(delta).exit();
1284}
1285collectChildrenReverseFilter$1.filterName = 'arraysCollectChildren';
1286
1287var diffFilter$2 = function datesDiffFilter(context) {
1288 if (context.left instanceof Date) {
1289 if (context.right instanceof Date) {
1290 if (context.left.getTime() !== context.right.getTime()) {
1291 context.setResult([context.left, context.right]);
1292 } else {
1293 context.setResult(undefined);
1294 }
1295 } else {
1296 context.setResult([context.left, context.right]);
1297 }
1298 context.exit();
1299 } else if (context.right instanceof Date) {
1300 context.setResult([context.left, context.right]).exit();
1301 }
1302};
1303diffFilter$2.filterName = 'dates';
1304
1305function createCommonjsModule(fn, module) {
1306 return module = { exports: {} }, fn(module, module.exports), module.exports;
1307}
1308
1309var diffMatchPatch = createCommonjsModule(function (module) {
1310function diff_match_patch() {
1311
1312 // Defaults.
1313 // Redefine these in your program to override the defaults.
1314
1315 // Number of seconds to map a diff before giving up (0 for infinity).
1316 this.Diff_Timeout = 1.0;
1317 // Cost of an empty edit operation in terms of edit characters.
1318 this.Diff_EditCost = 4;
1319 // At what point is no match declared (0.0 = perfection, 1.0 = very loose).
1320 this.Match_Threshold = 0.5;
1321 // How far to search for a match (0 = exact location, 1000+ = broad match).
1322 // A match this many characters away from the expected location will add
1323 // 1.0 to the score (0.0 is a perfect match).
1324 this.Match_Distance = 1000;
1325 // When deleting a large block of text (over ~64 characters), how close do
1326 // the contents have to be to match the expected contents. (0.0 = perfection,
1327 // 1.0 = very loose). Note that Match_Threshold controls how closely the
1328 // end points of a delete need to match.
1329 this.Patch_DeleteThreshold = 0.5;
1330 // Chunk size for context length.
1331 this.Patch_Margin = 4;
1332
1333 // The number of bits in an int.
1334 this.Match_MaxBits = 32;
1335}
1336
1337
1338// DIFF FUNCTIONS
1339
1340
1341/**
1342 * The data structure representing a diff is an array of tuples:
1343 * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
1344 * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
1345 */
1346var DIFF_DELETE = -1;
1347var DIFF_INSERT = 1;
1348var DIFF_EQUAL = 0;
1349
1350/** @typedef {{0: number, 1: string}} */
1351diff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines,
1352 opt_deadline) {
1353 // Set a deadline by which time the diff must be complete.
1354 if (typeof opt_deadline == 'undefined') {
1355 if (this.Diff_Timeout <= 0) {
1356 opt_deadline = Number.MAX_VALUE;
1357 } else {
1358 opt_deadline = (new Date).getTime() + this.Diff_Timeout * 1000;
1359 }
1360 }
1361 var deadline = opt_deadline;
1362
1363 // Check for null inputs.
1364 if (text1 == null || text2 == null) {
1365 throw new Error('Null input. (diff_main)');
1366 }
1367
1368 // Check for equality (speedup).
1369 if (text1 == text2) {
1370 if (text1) {
1371 return [[DIFF_EQUAL, text1]];
1372 }
1373 return [];
1374 }
1375
1376 if (typeof opt_checklines == 'undefined') {
1377 opt_checklines = true;
1378 }
1379 var checklines = opt_checklines;
1380
1381 // Trim off common prefix (speedup).
1382 var commonlength = this.diff_commonPrefix(text1, text2);
1383 var commonprefix = text1.substring(0, commonlength);
1384 text1 = text1.substring(commonlength);
1385 text2 = text2.substring(commonlength);
1386
1387 // Trim off common suffix (speedup).
1388 commonlength = this.diff_commonSuffix(text1, text2);
1389 var commonsuffix = text1.substring(text1.length - commonlength);
1390 text1 = text1.substring(0, text1.length - commonlength);
1391 text2 = text2.substring(0, text2.length - commonlength);
1392
1393 // Compute the diff on the middle block.
1394 var diffs = this.diff_compute_(text1, text2, checklines, deadline);
1395
1396 // Restore the prefix and suffix.
1397 if (commonprefix) {
1398 diffs.unshift([DIFF_EQUAL, commonprefix]);
1399 }
1400 if (commonsuffix) {
1401 diffs.push([DIFF_EQUAL, commonsuffix]);
1402 }
1403 this.diff_cleanupMerge(diffs);
1404 return diffs;
1405};
1406
1407
1408/**
1409 * Find the differences between two texts. Assumes that the texts do not
1410 * have any common prefix or suffix.
1411 * @param {string} text1 Old string to be diffed.
1412 * @param {string} text2 New string to be diffed.
1413 * @param {boolean} checklines Speedup flag. If false, then don't run a
1414 * line-level diff first to identify the changed areas.
1415 * If true, then run a faster, slightly less optimal diff.
1416 * @param {number} deadline Time when the diff should be complete by.
1417 * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.
1418 * @private
1419 */
1420diff_match_patch.prototype.diff_compute_ = function(text1, text2, checklines,
1421 deadline) {
1422 var diffs;
1423
1424 if (!text1) {
1425 // Just add some text (speedup).
1426 return [[DIFF_INSERT, text2]];
1427 }
1428
1429 if (!text2) {
1430 // Just delete some text (speedup).
1431 return [[DIFF_DELETE, text1]];
1432 }
1433
1434 var longtext = text1.length > text2.length ? text1 : text2;
1435 var shorttext = text1.length > text2.length ? text2 : text1;
1436 var i = longtext.indexOf(shorttext);
1437 if (i != -1) {
1438 // Shorter text is inside the longer text (speedup).
1439 diffs = [[DIFF_INSERT, longtext.substring(0, i)],
1440 [DIFF_EQUAL, shorttext],
1441 [DIFF_INSERT, longtext.substring(i + shorttext.length)]];
1442 // Swap insertions for deletions if diff is reversed.
1443 if (text1.length > text2.length) {
1444 diffs[0][0] = diffs[2][0] = DIFF_DELETE;
1445 }
1446 return diffs;
1447 }
1448
1449 if (shorttext.length == 1) {
1450 // Single character string.
1451 // After the previous speedup, the character can't be an equality.
1452 return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
1453 }
1454
1455 // Check to see if the problem can be split in two.
1456 var hm = this.diff_halfMatch_(text1, text2);
1457 if (hm) {
1458 // A half-match was found, sort out the return data.
1459 var text1_a = hm[0];
1460 var text1_b = hm[1];
1461 var text2_a = hm[2];
1462 var text2_b = hm[3];
1463 var mid_common = hm[4];
1464 // Send both pairs off for separate processing.
1465 var diffs_a = this.diff_main(text1_a, text2_a, checklines, deadline);
1466 var diffs_b = this.diff_main(text1_b, text2_b, checklines, deadline);
1467 // Merge the results.
1468 return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b);
1469 }
1470
1471 if (checklines && text1.length > 100 && text2.length > 100) {
1472 return this.diff_lineMode_(text1, text2, deadline);
1473 }
1474
1475 return this.diff_bisect_(text1, text2, deadline);
1476};
1477
1478
1479/**
1480 * Do a quick line-level diff on both strings, then rediff the parts for
1481 * greater accuracy.
1482 * This speedup can produce non-minimal diffs.
1483 * @param {string} text1 Old string to be diffed.
1484 * @param {string} text2 New string to be diffed.
1485 * @param {number} deadline Time when the diff should be complete by.
1486 * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.
1487 * @private
1488 */
1489diff_match_patch.prototype.diff_lineMode_ = function(text1, text2, deadline) {
1490 // Scan the text on a line-by-line basis first.
1491 var a = this.diff_linesToChars_(text1, text2);
1492 text1 = a.chars1;
1493 text2 = a.chars2;
1494 var linearray = a.lineArray;
1495
1496 var diffs = this.diff_main(text1, text2, false, deadline);
1497
1498 // Convert the diff back to original text.
1499 this.diff_charsToLines_(diffs, linearray);
1500 // Eliminate freak matches (e.g. blank lines)
1501 this.diff_cleanupSemantic(diffs);
1502
1503 // Rediff any replacement blocks, this time character-by-character.
1504 // Add a dummy entry at the end.
1505 diffs.push([DIFF_EQUAL, '']);
1506 var pointer = 0;
1507 var count_delete = 0;
1508 var count_insert = 0;
1509 var text_delete = '';
1510 var text_insert = '';
1511 while (pointer < diffs.length) {
1512 switch (diffs[pointer][0]) {
1513 case DIFF_INSERT:
1514 count_insert++;
1515 text_insert += diffs[pointer][1];
1516 break;
1517 case DIFF_DELETE:
1518 count_delete++;
1519 text_delete += diffs[pointer][1];
1520 break;
1521 case DIFF_EQUAL:
1522 // Upon reaching an equality, check for prior redundancies.
1523 if (count_delete >= 1 && count_insert >= 1) {
1524 // Delete the offending records and add the merged ones.
1525 diffs.splice(pointer - count_delete - count_insert,
1526 count_delete + count_insert);
1527 pointer = pointer - count_delete - count_insert;
1528 var a = this.diff_main(text_delete, text_insert, false, deadline);
1529 for (var j = a.length - 1; j >= 0; j--) {
1530 diffs.splice(pointer, 0, a[j]);
1531 }
1532 pointer = pointer + a.length;
1533 }
1534 count_insert = 0;
1535 count_delete = 0;
1536 text_delete = '';
1537 text_insert = '';
1538 break;
1539 }
1540 pointer++;
1541 }
1542 diffs.pop(); // Remove the dummy entry at the end.
1543
1544 return diffs;
1545};
1546
1547
1548/**
1549 * Find the 'middle snake' of a diff, split the problem in two
1550 * and return the recursively constructed diff.
1551 * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
1552 * @param {string} text1 Old string to be diffed.
1553 * @param {string} text2 New string to be diffed.
1554 * @param {number} deadline Time at which to bail if not yet complete.
1555 * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.
1556 * @private
1557 */
1558diff_match_patch.prototype.diff_bisect_ = function(text1, text2, deadline) {
1559 // Cache the text lengths to prevent multiple calls.
1560 var text1_length = text1.length;
1561 var text2_length = text2.length;
1562 var max_d = Math.ceil((text1_length + text2_length) / 2);
1563 var v_offset = max_d;
1564 var v_length = 2 * max_d;
1565 var v1 = new Array(v_length);
1566 var v2 = new Array(v_length);
1567 // Setting all elements to -1 is faster in Chrome & Firefox than mixing
1568 // integers and undefined.
1569 for (var x = 0; x < v_length; x++) {
1570 v1[x] = -1;
1571 v2[x] = -1;
1572 }
1573 v1[v_offset + 1] = 0;
1574 v2[v_offset + 1] = 0;
1575 var delta = text1_length - text2_length;
1576 // If the total number of characters is odd, then the front path will collide
1577 // with the reverse path.
1578 var front = (delta % 2 != 0);
1579 // Offsets for start and end of k loop.
1580 // Prevents mapping of space beyond the grid.
1581 var k1start = 0;
1582 var k1end = 0;
1583 var k2start = 0;
1584 var k2end = 0;
1585 for (var d = 0; d < max_d; d++) {
1586 // Bail out if deadline is reached.
1587 if ((new Date()).getTime() > deadline) {
1588 break;
1589 }
1590
1591 // Walk the front path one step.
1592 for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
1593 var k1_offset = v_offset + k1;
1594 var x1;
1595 if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) {
1596 x1 = v1[k1_offset + 1];
1597 } else {
1598 x1 = v1[k1_offset - 1] + 1;
1599 }
1600 var y1 = x1 - k1;
1601 while (x1 < text1_length && y1 < text2_length &&
1602 text1.charAt(x1) == text2.charAt(y1)) {
1603 x1++;
1604 y1++;
1605 }
1606 v1[k1_offset] = x1;
1607 if (x1 > text1_length) {
1608 // Ran off the right of the graph.
1609 k1end += 2;
1610 } else if (y1 > text2_length) {
1611 // Ran off the bottom of the graph.
1612 k1start += 2;
1613 } else if (front) {
1614 var k2_offset = v_offset + delta - k1;
1615 if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) {
1616 // Mirror x2 onto top-left coordinate system.
1617 var x2 = text1_length - v2[k2_offset];
1618 if (x1 >= x2) {
1619 // Overlap detected.
1620 return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);
1621 }
1622 }
1623 }
1624 }
1625
1626 // Walk the reverse path one step.
1627 for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
1628 var k2_offset = v_offset + k2;
1629 var x2;
1630 if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) {
1631 x2 = v2[k2_offset + 1];
1632 } else {
1633 x2 = v2[k2_offset - 1] + 1;
1634 }
1635 var y2 = x2 - k2;
1636 while (x2 < text1_length && y2 < text2_length &&
1637 text1.charAt(text1_length - x2 - 1) ==
1638 text2.charAt(text2_length - y2 - 1)) {
1639 x2++;
1640 y2++;
1641 }
1642 v2[k2_offset] = x2;
1643 if (x2 > text1_length) {
1644 // Ran off the left of the graph.
1645 k2end += 2;
1646 } else if (y2 > text2_length) {
1647 // Ran off the top of the graph.
1648 k2start += 2;
1649 } else if (!front) {
1650 var k1_offset = v_offset + delta - k2;
1651 if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) {
1652 var x1 = v1[k1_offset];
1653 var y1 = v_offset + x1 - k1_offset;
1654 // Mirror x2 onto top-left coordinate system.
1655 x2 = text1_length - x2;
1656 if (x1 >= x2) {
1657 // Overlap detected.
1658 return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);
1659 }
1660 }
1661 }
1662 }
1663 }
1664 // Diff took too long and hit the deadline or
1665 // number of diffs equals number of characters, no commonality at all.
1666 return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
1667};
1668
1669
1670/**
1671 * Given the location of the 'middle snake', split the diff in two parts
1672 * and recurse.
1673 * @param {string} text1 Old string to be diffed.
1674 * @param {string} text2 New string to be diffed.
1675 * @param {number} x Index of split point in text1.
1676 * @param {number} y Index of split point in text2.
1677 * @param {number} deadline Time at which to bail if not yet complete.
1678 * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.
1679 * @private
1680 */
1681diff_match_patch.prototype.diff_bisectSplit_ = function(text1, text2, x, y,
1682 deadline) {
1683 var text1a = text1.substring(0, x);
1684 var text2a = text2.substring(0, y);
1685 var text1b = text1.substring(x);
1686 var text2b = text2.substring(y);
1687
1688 // Compute both diffs serially.
1689 var diffs = this.diff_main(text1a, text2a, false, deadline);
1690 var diffsb = this.diff_main(text1b, text2b, false, deadline);
1691
1692 return diffs.concat(diffsb);
1693};
1694
1695
1696/**
1697 * Split two texts into an array of strings. Reduce the texts to a string of
1698 * hashes where each Unicode character represents one line.
1699 * @param {string} text1 First string.
1700 * @param {string} text2 Second string.
1701 * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
1702 * An object containing the encoded text1, the encoded text2 and
1703 * the array of unique strings.
1704 * The zeroth element of the array of unique strings is intentionally blank.
1705 * @private
1706 */
1707diff_match_patch.prototype.diff_linesToChars_ = function(text1, text2) {
1708 var lineArray = []; // e.g. lineArray[4] == 'Hello\n'
1709 var lineHash = {}; // e.g. lineHash['Hello\n'] == 4
1710
1711 // '\x00' is a valid character, but various debuggers don't like it.
1712 // So we'll insert a junk entry to avoid generating a null character.
1713 lineArray[0] = '';
1714
1715 /**
1716 * Split a text into an array of strings. Reduce the texts to a string of
1717 * hashes where each Unicode character represents one line.
1718 * Modifies linearray and linehash through being a closure.
1719 * @param {string} text String to encode.
1720 * @return {string} Encoded string.
1721 * @private
1722 */
1723 function diff_linesToCharsMunge_(text) {
1724 var chars = '';
1725 // Walk the text, pulling out a substring for each line.
1726 // text.split('\n') would would temporarily double our memory footprint.
1727 // Modifying text would create many large strings to garbage collect.
1728 var lineStart = 0;
1729 var lineEnd = -1;
1730 // Keeping our own length variable is faster than looking it up.
1731 var lineArrayLength = lineArray.length;
1732 while (lineEnd < text.length - 1) {
1733 lineEnd = text.indexOf('\n', lineStart);
1734 if (lineEnd == -1) {
1735 lineEnd = text.length - 1;
1736 }
1737 var line = text.substring(lineStart, lineEnd + 1);
1738 lineStart = lineEnd + 1;
1739
1740 if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :
1741 (lineHash[line] !== undefined)) {
1742 chars += String.fromCharCode(lineHash[line]);
1743 } else {
1744 chars += String.fromCharCode(lineArrayLength);
1745 lineHash[line] = lineArrayLength;
1746 lineArray[lineArrayLength++] = line;
1747 }
1748 }
1749 return chars;
1750 }
1751
1752 var chars1 = diff_linesToCharsMunge_(text1);
1753 var chars2 = diff_linesToCharsMunge_(text2);
1754 return {chars1: chars1, chars2: chars2, lineArray: lineArray};
1755};
1756
1757
1758/**
1759 * Rehydrate the text in a diff from a string of line hashes to real lines of
1760 * text.
1761 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
1762 * @param {!Array.<string>} lineArray Array of unique strings.
1763 * @private
1764 */
1765diff_match_patch.prototype.diff_charsToLines_ = function(diffs, lineArray) {
1766 for (var x = 0; x < diffs.length; x++) {
1767 var chars = diffs[x][1];
1768 var text = [];
1769 for (var y = 0; y < chars.length; y++) {
1770 text[y] = lineArray[chars.charCodeAt(y)];
1771 }
1772 diffs[x][1] = text.join('');
1773 }
1774};
1775
1776
1777/**
1778 * Determine the common prefix of two strings.
1779 * @param {string} text1 First string.
1780 * @param {string} text2 Second string.
1781 * @return {number} The number of characters common to the start of each
1782 * string.
1783 */
1784diff_match_patch.prototype.diff_commonPrefix = function(text1, text2) {
1785 // Quick check for common null cases.
1786 if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {
1787 return 0;
1788 }
1789 // Binary search.
1790 // Performance analysis: http://neil.fraser.name/news/2007/10/09/
1791 var pointermin = 0;
1792 var pointermax = Math.min(text1.length, text2.length);
1793 var pointermid = pointermax;
1794 var pointerstart = 0;
1795 while (pointermin < pointermid) {
1796 if (text1.substring(pointerstart, pointermid) ==
1797 text2.substring(pointerstart, pointermid)) {
1798 pointermin = pointermid;
1799 pointerstart = pointermin;
1800 } else {
1801 pointermax = pointermid;
1802 }
1803 pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
1804 }
1805 return pointermid;
1806};
1807
1808
1809/**
1810 * Determine the common suffix of two strings.
1811 * @param {string} text1 First string.
1812 * @param {string} text2 Second string.
1813 * @return {number} The number of characters common to the end of each string.
1814 */
1815diff_match_patch.prototype.diff_commonSuffix = function(text1, text2) {
1816 // Quick check for common null cases.
1817 if (!text1 || !text2 ||
1818 text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {
1819 return 0;
1820 }
1821 // Binary search.
1822 // Performance analysis: http://neil.fraser.name/news/2007/10/09/
1823 var pointermin = 0;
1824 var pointermax = Math.min(text1.length, text2.length);
1825 var pointermid = pointermax;
1826 var pointerend = 0;
1827 while (pointermin < pointermid) {
1828 if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==
1829 text2.substring(text2.length - pointermid, text2.length - pointerend)) {
1830 pointermin = pointermid;
1831 pointerend = pointermin;
1832 } else {
1833 pointermax = pointermid;
1834 }
1835 pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
1836 }
1837 return pointermid;
1838};
1839
1840
1841/**
1842 * Determine if the suffix of one string is the prefix of another.
1843 * @param {string} text1 First string.
1844 * @param {string} text2 Second string.
1845 * @return {number} The number of characters common to the end of the first
1846 * string and the start of the second string.
1847 * @private
1848 */
1849diff_match_patch.prototype.diff_commonOverlap_ = function(text1, text2) {
1850 // Cache the text lengths to prevent multiple calls.
1851 var text1_length = text1.length;
1852 var text2_length = text2.length;
1853 // Eliminate the null case.
1854 if (text1_length == 0 || text2_length == 0) {
1855 return 0;
1856 }
1857 // Truncate the longer string.
1858 if (text1_length > text2_length) {
1859 text1 = text1.substring(text1_length - text2_length);
1860 } else if (text1_length < text2_length) {
1861 text2 = text2.substring(0, text1_length);
1862 }
1863 var text_length = Math.min(text1_length, text2_length);
1864 // Quick check for the worst case.
1865 if (text1 == text2) {
1866 return text_length;
1867 }
1868
1869 // Start by looking for a single character match
1870 // and increase length until no match is found.
1871 // Performance analysis: http://neil.fraser.name/news/2010/11/04/
1872 var best = 0;
1873 var length = 1;
1874 while (true) {
1875 var pattern = text1.substring(text_length - length);
1876 var found = text2.indexOf(pattern);
1877 if (found == -1) {
1878 return best;
1879 }
1880 length += found;
1881 if (found == 0 || text1.substring(text_length - length) ==
1882 text2.substring(0, length)) {
1883 best = length;
1884 length++;
1885 }
1886 }
1887};
1888
1889
1890/**
1891 * Do the two texts share a substring which is at least half the length of the
1892 * longer text?
1893 * This speedup can produce non-minimal diffs.
1894 * @param {string} text1 First string.
1895 * @param {string} text2 Second string.
1896 * @return {Array.<string>} Five element Array, containing the prefix of
1897 * text1, the suffix of text1, the prefix of text2, the suffix of
1898 * text2 and the common middle. Or null if there was no match.
1899 * @private
1900 */
1901diff_match_patch.prototype.diff_halfMatch_ = function(text1, text2) {
1902 if (this.Diff_Timeout <= 0) {
1903 // Don't risk returning a non-optimal diff if we have unlimited time.
1904 return null;
1905 }
1906 var longtext = text1.length > text2.length ? text1 : text2;
1907 var shorttext = text1.length > text2.length ? text2 : text1;
1908 if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {
1909 return null; // Pointless.
1910 }
1911 var dmp = this; // 'this' becomes 'window' in a closure.
1912
1913 /**
1914 * Does a substring of shorttext exist within longtext such that the substring
1915 * is at least half the length of longtext?
1916 * Closure, but does not reference any external variables.
1917 * @param {string} longtext Longer string.
1918 * @param {string} shorttext Shorter string.
1919 * @param {number} i Start index of quarter length substring within longtext.
1920 * @return {Array.<string>} Five element Array, containing the prefix of
1921 * longtext, the suffix of longtext, the prefix of shorttext, the suffix
1922 * of shorttext and the common middle. Or null if there was no match.
1923 * @private
1924 */
1925 function diff_halfMatchI_(longtext, shorttext, i) {
1926 // Start with a 1/4 length substring at position i as a seed.
1927 var seed = longtext.substring(i, i + Math.floor(longtext.length / 4));
1928 var j = -1;
1929 var best_common = '';
1930 var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;
1931 while ((j = shorttext.indexOf(seed, j + 1)) != -1) {
1932 var prefixLength = dmp.diff_commonPrefix(longtext.substring(i),
1933 shorttext.substring(j));
1934 var suffixLength = dmp.diff_commonSuffix(longtext.substring(0, i),
1935 shorttext.substring(0, j));
1936 if (best_common.length < suffixLength + prefixLength) {
1937 best_common = shorttext.substring(j - suffixLength, j) +
1938 shorttext.substring(j, j + prefixLength);
1939 best_longtext_a = longtext.substring(0, i - suffixLength);
1940 best_longtext_b = longtext.substring(i + prefixLength);
1941 best_shorttext_a = shorttext.substring(0, j - suffixLength);
1942 best_shorttext_b = shorttext.substring(j + prefixLength);
1943 }
1944 }
1945 if (best_common.length * 2 >= longtext.length) {
1946 return [best_longtext_a, best_longtext_b,
1947 best_shorttext_a, best_shorttext_b, best_common];
1948 } else {
1949 return null;
1950 }
1951 }
1952
1953 // First check if the second quarter is the seed for a half-match.
1954 var hm1 = diff_halfMatchI_(longtext, shorttext,
1955 Math.ceil(longtext.length / 4));
1956 // Check again based on the third quarter.
1957 var hm2 = diff_halfMatchI_(longtext, shorttext,
1958 Math.ceil(longtext.length / 2));
1959 var hm;
1960 if (!hm1 && !hm2) {
1961 return null;
1962 } else if (!hm2) {
1963 hm = hm1;
1964 } else if (!hm1) {
1965 hm = hm2;
1966 } else {
1967 // Both matched. Select the longest.
1968 hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
1969 }
1970
1971 // A half-match was found, sort out the return data.
1972 var text1_a, text1_b, text2_a, text2_b;
1973 if (text1.length > text2.length) {
1974 text1_a = hm[0];
1975 text1_b = hm[1];
1976 text2_a = hm[2];
1977 text2_b = hm[3];
1978 } else {
1979 text2_a = hm[0];
1980 text2_b = hm[1];
1981 text1_a = hm[2];
1982 text1_b = hm[3];
1983 }
1984 var mid_common = hm[4];
1985 return [text1_a, text1_b, text2_a, text2_b, mid_common];
1986};
1987
1988
1989/**
1990 * Reduce the number of edits by eliminating semantically trivial equalities.
1991 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
1992 */
1993diff_match_patch.prototype.diff_cleanupSemantic = function(diffs) {
1994 var changes = false;
1995 var equalities = []; // Stack of indices where equalities are found.
1996 var equalitiesLength = 0; // Keeping our own length var is faster in JS.
1997 /** @type {?string} */
1998 var lastequality = null;
1999 // Always equal to diffs[equalities[equalitiesLength - 1]][1]
2000 var pointer = 0; // Index of current position.
2001 // Number of characters that changed prior to the equality.
2002 var length_insertions1 = 0;
2003 var length_deletions1 = 0;
2004 // Number of characters that changed after the equality.
2005 var length_insertions2 = 0;
2006 var length_deletions2 = 0;
2007 while (pointer < diffs.length) {
2008 if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found.
2009 equalities[equalitiesLength++] = pointer;
2010 length_insertions1 = length_insertions2;
2011 length_deletions1 = length_deletions2;
2012 length_insertions2 = 0;
2013 length_deletions2 = 0;
2014 lastequality = diffs[pointer][1];
2015 } else { // An insertion or deletion.
2016 if (diffs[pointer][0] == DIFF_INSERT) {
2017 length_insertions2 += diffs[pointer][1].length;
2018 } else {
2019 length_deletions2 += diffs[pointer][1].length;
2020 }
2021 // Eliminate an equality that is smaller or equal to the edits on both
2022 // sides of it.
2023 if (lastequality && (lastequality.length <=
2024 Math.max(length_insertions1, length_deletions1)) &&
2025 (lastequality.length <= Math.max(length_insertions2,
2026 length_deletions2))) {
2027 // Duplicate record.
2028 diffs.splice(equalities[equalitiesLength - 1], 0,
2029 [DIFF_DELETE, lastequality]);
2030 // Change second copy to insert.
2031 diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
2032 // Throw away the equality we just deleted.
2033 equalitiesLength--;
2034 // Throw away the previous equality (it needs to be reevaluated).
2035 equalitiesLength--;
2036 pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
2037 length_insertions1 = 0; // Reset the counters.
2038 length_deletions1 = 0;
2039 length_insertions2 = 0;
2040 length_deletions2 = 0;
2041 lastequality = null;
2042 changes = true;
2043 }
2044 }
2045 pointer++;
2046 }
2047
2048 // Normalize the diff.
2049 if (changes) {
2050 this.diff_cleanupMerge(diffs);
2051 }
2052 this.diff_cleanupSemanticLossless(diffs);
2053
2054 // Find any overlaps between deletions and insertions.
2055 // e.g: <del>abcxxx</del><ins>xxxdef</ins>
2056 // -> <del>abc</del>xxx<ins>def</ins>
2057 // e.g: <del>xxxabc</del><ins>defxxx</ins>
2058 // -> <ins>def</ins>xxx<del>abc</del>
2059 // Only extract an overlap if it is as big as the edit ahead or behind it.
2060 pointer = 1;
2061 while (pointer < diffs.length) {
2062 if (diffs[pointer - 1][0] == DIFF_DELETE &&
2063 diffs[pointer][0] == DIFF_INSERT) {
2064 var deletion = diffs[pointer - 1][1];
2065 var insertion = diffs[pointer][1];
2066 var overlap_length1 = this.diff_commonOverlap_(deletion, insertion);
2067 var overlap_length2 = this.diff_commonOverlap_(insertion, deletion);
2068 if (overlap_length1 >= overlap_length2) {
2069 if (overlap_length1 >= deletion.length / 2 ||
2070 overlap_length1 >= insertion.length / 2) {
2071 // Overlap found. Insert an equality and trim the surrounding edits.
2072 diffs.splice(pointer, 0,
2073 [DIFF_EQUAL, insertion.substring(0, overlap_length1)]);
2074 diffs[pointer - 1][1] =
2075 deletion.substring(0, deletion.length - overlap_length1);
2076 diffs[pointer + 1][1] = insertion.substring(overlap_length1);
2077 pointer++;
2078 }
2079 } else {
2080 if (overlap_length2 >= deletion.length / 2 ||
2081 overlap_length2 >= insertion.length / 2) {
2082 // Reverse overlap found.
2083 // Insert an equality and swap and trim the surrounding edits.
2084 diffs.splice(pointer, 0,
2085 [DIFF_EQUAL, deletion.substring(0, overlap_length2)]);
2086 diffs[pointer - 1][0] = DIFF_INSERT;
2087 diffs[pointer - 1][1] =
2088 insertion.substring(0, insertion.length - overlap_length2);
2089 diffs[pointer + 1][0] = DIFF_DELETE;
2090 diffs[pointer + 1][1] =
2091 deletion.substring(overlap_length2);
2092 pointer++;
2093 }
2094 }
2095 pointer++;
2096 }
2097 pointer++;
2098 }
2099};
2100
2101
2102/**
2103 * Look for single edits surrounded on both sides by equalities
2104 * which can be shifted sideways to align the edit to a word boundary.
2105 * e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.
2106 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2107 */
2108diff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) {
2109 /**
2110 * Given two strings, compute a score representing whether the internal
2111 * boundary falls on logical boundaries.
2112 * Scores range from 6 (best) to 0 (worst).
2113 * Closure, but does not reference any external variables.
2114 * @param {string} one First string.
2115 * @param {string} two Second string.
2116 * @return {number} The score.
2117 * @private
2118 */
2119 function diff_cleanupSemanticScore_(one, two) {
2120 if (!one || !two) {
2121 // Edges are the best.
2122 return 6;
2123 }
2124
2125 // Each port of this function behaves slightly differently due to
2126 // subtle differences in each language's definition of things like
2127 // 'whitespace'. Since this function's purpose is largely cosmetic,
2128 // the choice has been made to use each language's native features
2129 // rather than force total conformity.
2130 var char1 = one.charAt(one.length - 1);
2131 var char2 = two.charAt(0);
2132 var nonAlphaNumeric1 = char1.match(diff_match_patch.nonAlphaNumericRegex_);
2133 var nonAlphaNumeric2 = char2.match(diff_match_patch.nonAlphaNumericRegex_);
2134 var whitespace1 = nonAlphaNumeric1 &&
2135 char1.match(diff_match_patch.whitespaceRegex_);
2136 var whitespace2 = nonAlphaNumeric2 &&
2137 char2.match(diff_match_patch.whitespaceRegex_);
2138 var lineBreak1 = whitespace1 &&
2139 char1.match(diff_match_patch.linebreakRegex_);
2140 var lineBreak2 = whitespace2 &&
2141 char2.match(diff_match_patch.linebreakRegex_);
2142 var blankLine1 = lineBreak1 &&
2143 one.match(diff_match_patch.blanklineEndRegex_);
2144 var blankLine2 = lineBreak2 &&
2145 two.match(diff_match_patch.blanklineStartRegex_);
2146
2147 if (blankLine1 || blankLine2) {
2148 // Five points for blank lines.
2149 return 5;
2150 } else if (lineBreak1 || lineBreak2) {
2151 // Four points for line breaks.
2152 return 4;
2153 } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {
2154 // Three points for end of sentences.
2155 return 3;
2156 } else if (whitespace1 || whitespace2) {
2157 // Two points for whitespace.
2158 return 2;
2159 } else if (nonAlphaNumeric1 || nonAlphaNumeric2) {
2160 // One point for non-alphanumeric.
2161 return 1;
2162 }
2163 return 0;
2164 }
2165
2166 var pointer = 1;
2167 // Intentionally ignore the first and last element (don't need checking).
2168 while (pointer < diffs.length - 1) {
2169 if (diffs[pointer - 1][0] == DIFF_EQUAL &&
2170 diffs[pointer + 1][0] == DIFF_EQUAL) {
2171 // This is a single edit surrounded by equalities.
2172 var equality1 = diffs[pointer - 1][1];
2173 var edit = diffs[pointer][1];
2174 var equality2 = diffs[pointer + 1][1];
2175
2176 // First, shift the edit as far left as possible.
2177 var commonOffset = this.diff_commonSuffix(equality1, edit);
2178 if (commonOffset) {
2179 var commonString = edit.substring(edit.length - commonOffset);
2180 equality1 = equality1.substring(0, equality1.length - commonOffset);
2181 edit = commonString + edit.substring(0, edit.length - commonOffset);
2182 equality2 = commonString + equality2;
2183 }
2184
2185 // Second, step character by character right, looking for the best fit.
2186 var bestEquality1 = equality1;
2187 var bestEdit = edit;
2188 var bestEquality2 = equality2;
2189 var bestScore = diff_cleanupSemanticScore_(equality1, edit) +
2190 diff_cleanupSemanticScore_(edit, equality2);
2191 while (edit.charAt(0) === equality2.charAt(0)) {
2192 equality1 += edit.charAt(0);
2193 edit = edit.substring(1) + equality2.charAt(0);
2194 equality2 = equality2.substring(1);
2195 var score = diff_cleanupSemanticScore_(equality1, edit) +
2196 diff_cleanupSemanticScore_(edit, equality2);
2197 // The >= encourages trailing rather than leading whitespace on edits.
2198 if (score >= bestScore) {
2199 bestScore = score;
2200 bestEquality1 = equality1;
2201 bestEdit = edit;
2202 bestEquality2 = equality2;
2203 }
2204 }
2205
2206 if (diffs[pointer - 1][1] != bestEquality1) {
2207 // We have an improvement, save it back to the diff.
2208 if (bestEquality1) {
2209 diffs[pointer - 1][1] = bestEquality1;
2210 } else {
2211 diffs.splice(pointer - 1, 1);
2212 pointer--;
2213 }
2214 diffs[pointer][1] = bestEdit;
2215 if (bestEquality2) {
2216 diffs[pointer + 1][1] = bestEquality2;
2217 } else {
2218 diffs.splice(pointer + 1, 1);
2219 pointer--;
2220 }
2221 }
2222 }
2223 pointer++;
2224 }
2225};
2226
2227// Define some regex patterns for matching boundaries.
2228diff_match_patch.nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/;
2229diff_match_patch.whitespaceRegex_ = /\s/;
2230diff_match_patch.linebreakRegex_ = /[\r\n]/;
2231diff_match_patch.blanklineEndRegex_ = /\n\r?\n$/;
2232diff_match_patch.blanklineStartRegex_ = /^\r?\n\r?\n/;
2233
2234/**
2235 * Reduce the number of edits by eliminating operationally trivial equalities.
2236 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2237 */
2238diff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) {
2239 var changes = false;
2240 var equalities = []; // Stack of indices where equalities are found.
2241 var equalitiesLength = 0; // Keeping our own length var is faster in JS.
2242 /** @type {?string} */
2243 var lastequality = null;
2244 // Always equal to diffs[equalities[equalitiesLength - 1]][1]
2245 var pointer = 0; // Index of current position.
2246 // Is there an insertion operation before the last equality.
2247 var pre_ins = false;
2248 // Is there a deletion operation before the last equality.
2249 var pre_del = false;
2250 // Is there an insertion operation after the last equality.
2251 var post_ins = false;
2252 // Is there a deletion operation after the last equality.
2253 var post_del = false;
2254 while (pointer < diffs.length) {
2255 if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found.
2256 if (diffs[pointer][1].length < this.Diff_EditCost &&
2257 (post_ins || post_del)) {
2258 // Candidate found.
2259 equalities[equalitiesLength++] = pointer;
2260 pre_ins = post_ins;
2261 pre_del = post_del;
2262 lastequality = diffs[pointer][1];
2263 } else {
2264 // Not a candidate, and can never become one.
2265 equalitiesLength = 0;
2266 lastequality = null;
2267 }
2268 post_ins = post_del = false;
2269 } else { // An insertion or deletion.
2270 if (diffs[pointer][0] == DIFF_DELETE) {
2271 post_del = true;
2272 } else {
2273 post_ins = true;
2274 }
2275 /*
2276 * Five types to be split:
2277 * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
2278 * <ins>A</ins>X<ins>C</ins><del>D</del>
2279 * <ins>A</ins><del>B</del>X<ins>C</ins>
2280 * <ins>A</del>X<ins>C</ins><del>D</del>
2281 * <ins>A</ins><del>B</del>X<del>C</del>
2282 */
2283 if (lastequality && ((pre_ins && pre_del && post_ins && post_del) ||
2284 ((lastequality.length < this.Diff_EditCost / 2) &&
2285 (pre_ins + pre_del + post_ins + post_del) == 3))) {
2286 // Duplicate record.
2287 diffs.splice(equalities[equalitiesLength - 1], 0,
2288 [DIFF_DELETE, lastequality]);
2289 // Change second copy to insert.
2290 diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
2291 equalitiesLength--; // Throw away the equality we just deleted;
2292 lastequality = null;
2293 if (pre_ins && pre_del) {
2294 // No changes made which could affect previous entry, keep going.
2295 post_ins = post_del = true;
2296 equalitiesLength = 0;
2297 } else {
2298 equalitiesLength--; // Throw away the previous equality.
2299 pointer = equalitiesLength > 0 ?
2300 equalities[equalitiesLength - 1] : -1;
2301 post_ins = post_del = false;
2302 }
2303 changes = true;
2304 }
2305 }
2306 pointer++;
2307 }
2308
2309 if (changes) {
2310 this.diff_cleanupMerge(diffs);
2311 }
2312};
2313
2314
2315/**
2316 * Reorder and merge like edit sections. Merge equalities.
2317 * Any edit section can move as long as it doesn't cross an equality.
2318 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2319 */
2320diff_match_patch.prototype.diff_cleanupMerge = function(diffs) {
2321 diffs.push([DIFF_EQUAL, '']); // Add a dummy entry at the end.
2322 var pointer = 0;
2323 var count_delete = 0;
2324 var count_insert = 0;
2325 var text_delete = '';
2326 var text_insert = '';
2327 var commonlength;
2328 while (pointer < diffs.length) {
2329 switch (diffs[pointer][0]) {
2330 case DIFF_INSERT:
2331 count_insert++;
2332 text_insert += diffs[pointer][1];
2333 pointer++;
2334 break;
2335 case DIFF_DELETE:
2336 count_delete++;
2337 text_delete += diffs[pointer][1];
2338 pointer++;
2339 break;
2340 case DIFF_EQUAL:
2341 // Upon reaching an equality, check for prior redundancies.
2342 if (count_delete + count_insert > 1) {
2343 if (count_delete !== 0 && count_insert !== 0) {
2344 // Factor out any common prefixies.
2345 commonlength = this.diff_commonPrefix(text_insert, text_delete);
2346 if (commonlength !== 0) {
2347 if ((pointer - count_delete - count_insert) > 0 &&
2348 diffs[pointer - count_delete - count_insert - 1][0] ==
2349 DIFF_EQUAL) {
2350 diffs[pointer - count_delete - count_insert - 1][1] +=
2351 text_insert.substring(0, commonlength);
2352 } else {
2353 diffs.splice(0, 0, [DIFF_EQUAL,
2354 text_insert.substring(0, commonlength)]);
2355 pointer++;
2356 }
2357 text_insert = text_insert.substring(commonlength);
2358 text_delete = text_delete.substring(commonlength);
2359 }
2360 // Factor out any common suffixies.
2361 commonlength = this.diff_commonSuffix(text_insert, text_delete);
2362 if (commonlength !== 0) {
2363 diffs[pointer][1] = text_insert.substring(text_insert.length -
2364 commonlength) + diffs[pointer][1];
2365 text_insert = text_insert.substring(0, text_insert.length -
2366 commonlength);
2367 text_delete = text_delete.substring(0, text_delete.length -
2368 commonlength);
2369 }
2370 }
2371 // Delete the offending records and add the merged ones.
2372 if (count_delete === 0) {
2373 diffs.splice(pointer - count_insert,
2374 count_delete + count_insert, [DIFF_INSERT, text_insert]);
2375 } else if (count_insert === 0) {
2376 diffs.splice(pointer - count_delete,
2377 count_delete + count_insert, [DIFF_DELETE, text_delete]);
2378 } else {
2379 diffs.splice(pointer - count_delete - count_insert,
2380 count_delete + count_insert, [DIFF_DELETE, text_delete],
2381 [DIFF_INSERT, text_insert]);
2382 }
2383 pointer = pointer - count_delete - count_insert +
2384 (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1;
2385 } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) {
2386 // Merge this equality with the previous one.
2387 diffs[pointer - 1][1] += diffs[pointer][1];
2388 diffs.splice(pointer, 1);
2389 } else {
2390 pointer++;
2391 }
2392 count_insert = 0;
2393 count_delete = 0;
2394 text_delete = '';
2395 text_insert = '';
2396 break;
2397 }
2398 }
2399 if (diffs[diffs.length - 1][1] === '') {
2400 diffs.pop(); // Remove the dummy entry at the end.
2401 }
2402
2403 // Second pass: look for single edits surrounded on both sides by equalities
2404 // which can be shifted sideways to eliminate an equality.
2405 // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
2406 var changes = false;
2407 pointer = 1;
2408 // Intentionally ignore the first and last element (don't need checking).
2409 while (pointer < diffs.length - 1) {
2410 if (diffs[pointer - 1][0] == DIFF_EQUAL &&
2411 diffs[pointer + 1][0] == DIFF_EQUAL) {
2412 // This is a single edit surrounded by equalities.
2413 if (diffs[pointer][1].substring(diffs[pointer][1].length -
2414 diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) {
2415 // Shift the edit over the previous equality.
2416 diffs[pointer][1] = diffs[pointer - 1][1] +
2417 diffs[pointer][1].substring(0, diffs[pointer][1].length -
2418 diffs[pointer - 1][1].length);
2419 diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
2420 diffs.splice(pointer - 1, 1);
2421 changes = true;
2422 } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==
2423 diffs[pointer + 1][1]) {
2424 // Shift the edit over the next equality.
2425 diffs[pointer - 1][1] += diffs[pointer + 1][1];
2426 diffs[pointer][1] =
2427 diffs[pointer][1].substring(diffs[pointer + 1][1].length) +
2428 diffs[pointer + 1][1];
2429 diffs.splice(pointer + 1, 1);
2430 changes = true;
2431 }
2432 }
2433 pointer++;
2434 }
2435 // If shifts were made, the diff needs reordering and another shift sweep.
2436 if (changes) {
2437 this.diff_cleanupMerge(diffs);
2438 }
2439};
2440
2441
2442/**
2443 * loc is a location in text1, compute and return the equivalent location in
2444 * text2.
2445 * e.g. 'The cat' vs 'The big cat', 1->1, 5->8
2446 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2447 * @param {number} loc Location within text1.
2448 * @return {number} Location within text2.
2449 */
2450diff_match_patch.prototype.diff_xIndex = function(diffs, loc) {
2451 var chars1 = 0;
2452 var chars2 = 0;
2453 var last_chars1 = 0;
2454 var last_chars2 = 0;
2455 var x;
2456 for (x = 0; x < diffs.length; x++) {
2457 if (diffs[x][0] !== DIFF_INSERT) { // Equality or deletion.
2458 chars1 += diffs[x][1].length;
2459 }
2460 if (diffs[x][0] !== DIFF_DELETE) { // Equality or insertion.
2461 chars2 += diffs[x][1].length;
2462 }
2463 if (chars1 > loc) { // Overshot the location.
2464 break;
2465 }
2466 last_chars1 = chars1;
2467 last_chars2 = chars2;
2468 }
2469 // Was the location was deleted?
2470 if (diffs.length != x && diffs[x][0] === DIFF_DELETE) {
2471 return last_chars2;
2472 }
2473 // Add the remaining character length.
2474 return last_chars2 + (loc - last_chars1);
2475};
2476
2477
2478/**
2479 * Convert a diff array into a pretty HTML report.
2480 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2481 * @return {string} HTML representation.
2482 */
2483diff_match_patch.prototype.diff_prettyHtml = function(diffs) {
2484 var html = [];
2485 var pattern_amp = /&/g;
2486 var pattern_lt = /</g;
2487 var pattern_gt = />/g;
2488 var pattern_para = /\n/g;
2489 for (var x = 0; x < diffs.length; x++) {
2490 var op = diffs[x][0]; // Operation (insert, delete, equal)
2491 var data = diffs[x][1]; // Text of change.
2492 var text = data.replace(pattern_amp, '&amp;').replace(pattern_lt, '&lt;')
2493 .replace(pattern_gt, '&gt;').replace(pattern_para, '&para;<br>');
2494 switch (op) {
2495 case DIFF_INSERT:
2496 html[x] = '<ins style="background:#e6ffe6;">' + text + '</ins>';
2497 break;
2498 case DIFF_DELETE:
2499 html[x] = '<del style="background:#ffe6e6;">' + text + '</del>';
2500 break;
2501 case DIFF_EQUAL:
2502 html[x] = '<span>' + text + '</span>';
2503 break;
2504 }
2505 }
2506 return html.join('');
2507};
2508
2509
2510/**
2511 * Compute and return the source text (all equalities and deletions).
2512 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2513 * @return {string} Source text.
2514 */
2515diff_match_patch.prototype.diff_text1 = function(diffs) {
2516 var text = [];
2517 for (var x = 0; x < diffs.length; x++) {
2518 if (diffs[x][0] !== DIFF_INSERT) {
2519 text[x] = diffs[x][1];
2520 }
2521 }
2522 return text.join('');
2523};
2524
2525
2526/**
2527 * Compute and return the destination text (all equalities and insertions).
2528 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2529 * @return {string} Destination text.
2530 */
2531diff_match_patch.prototype.diff_text2 = function(diffs) {
2532 var text = [];
2533 for (var x = 0; x < diffs.length; x++) {
2534 if (diffs[x][0] !== DIFF_DELETE) {
2535 text[x] = diffs[x][1];
2536 }
2537 }
2538 return text.join('');
2539};
2540
2541
2542/**
2543 * Compute the Levenshtein distance; the number of inserted, deleted or
2544 * substituted characters.
2545 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2546 * @return {number} Number of changes.
2547 */
2548diff_match_patch.prototype.diff_levenshtein = function(diffs) {
2549 var levenshtein = 0;
2550 var insertions = 0;
2551 var deletions = 0;
2552 for (var x = 0; x < diffs.length; x++) {
2553 var op = diffs[x][0];
2554 var data = diffs[x][1];
2555 switch (op) {
2556 case DIFF_INSERT:
2557 insertions += data.length;
2558 break;
2559 case DIFF_DELETE:
2560 deletions += data.length;
2561 break;
2562 case DIFF_EQUAL:
2563 // A deletion and an insertion is one substitution.
2564 levenshtein += Math.max(insertions, deletions);
2565 insertions = 0;
2566 deletions = 0;
2567 break;
2568 }
2569 }
2570 levenshtein += Math.max(insertions, deletions);
2571 return levenshtein;
2572};
2573
2574
2575/**
2576 * Crush the diff into an encoded string which describes the operations
2577 * required to transform text1 into text2.
2578 * E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'.
2579 * Operations are tab-separated. Inserted text is escaped using %xx notation.
2580 * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
2581 * @return {string} Delta text.
2582 */
2583diff_match_patch.prototype.diff_toDelta = function(diffs) {
2584 var text = [];
2585 for (var x = 0; x < diffs.length; x++) {
2586 switch (diffs[x][0]) {
2587 case DIFF_INSERT:
2588 text[x] = '+' + encodeURI(diffs[x][1]);
2589 break;
2590 case DIFF_DELETE:
2591 text[x] = '-' + diffs[x][1].length;
2592 break;
2593 case DIFF_EQUAL:
2594 text[x] = '=' + diffs[x][1].length;
2595 break;
2596 }
2597 }
2598 return text.join('\t').replace(/%20/g, ' ');
2599};
2600
2601
2602/**
2603 * Given the original text1, and an encoded string which describes the
2604 * operations required to transform text1 into text2, compute the full diff.
2605 * @param {string} text1 Source string for the diff.
2606 * @param {string} delta Delta text.
2607 * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.
2608 * @throws {!Error} If invalid input.
2609 */
2610diff_match_patch.prototype.diff_fromDelta = function(text1, delta) {
2611 var diffs = [];
2612 var diffsLength = 0; // Keeping our own length var is faster in JS.
2613 var pointer = 0; // Cursor in text1
2614 var tokens = delta.split(/\t/g);
2615 for (var x = 0; x < tokens.length; x++) {
2616 // Each token begins with a one character parameter which specifies the
2617 // operation of this token (delete, insert, equality).
2618 var param = tokens[x].substring(1);
2619 switch (tokens[x].charAt(0)) {
2620 case '+':
2621 try {
2622 diffs[diffsLength++] = [DIFF_INSERT, decodeURI(param)];
2623 } catch (ex) {
2624 // Malformed URI sequence.
2625 throw new Error('Illegal escape in diff_fromDelta: ' + param);
2626 }
2627 break;
2628 case '-':
2629 // Fall through.
2630 case '=':
2631 var n = parseInt(param, 10);
2632 if (isNaN(n) || n < 0) {
2633 throw new Error('Invalid number in diff_fromDelta: ' + param);
2634 }
2635 var text = text1.substring(pointer, pointer += n);
2636 if (tokens[x].charAt(0) == '=') {
2637 diffs[diffsLength++] = [DIFF_EQUAL, text];
2638 } else {
2639 diffs[diffsLength++] = [DIFF_DELETE, text];
2640 }
2641 break;
2642 default:
2643 // Blank tokens are ok (from a trailing \t).
2644 // Anything else is an error.
2645 if (tokens[x]) {
2646 throw new Error('Invalid diff operation in diff_fromDelta: ' +
2647 tokens[x]);
2648 }
2649 }
2650 }
2651 if (pointer != text1.length) {
2652 throw new Error('Delta length (' + pointer +
2653 ') does not equal source text length (' + text1.length + ').');
2654 }
2655 return diffs;
2656};
2657
2658
2659// MATCH FUNCTIONS
2660
2661
2662/**
2663 * Locate the best instance of 'pattern' in 'text' near 'loc'.
2664 * @param {string} text The text to search.
2665 * @param {string} pattern The pattern to search for.
2666 * @param {number} loc The location to search around.
2667 * @return {number} Best match index or -1.
2668 */
2669diff_match_patch.prototype.match_main = function(text, pattern, loc) {
2670 // Check for null inputs.
2671 if (text == null || pattern == null || loc == null) {
2672 throw new Error('Null input. (match_main)');
2673 }
2674
2675 loc = Math.max(0, Math.min(loc, text.length));
2676 if (text == pattern) {
2677 // Shortcut (potentially not guaranteed by the algorithm)
2678 return 0;
2679 } else if (!text.length) {
2680 // Nothing to match.
2681 return -1;
2682 } else if (text.substring(loc, loc + pattern.length) == pattern) {
2683 // Perfect match at the perfect spot! (Includes case of null pattern)
2684 return loc;
2685 } else {
2686 // Do a fuzzy compare.
2687 return this.match_bitap_(text, pattern, loc);
2688 }
2689};
2690
2691
2692/**
2693 * Locate the best instance of 'pattern' in 'text' near 'loc' using the
2694 * Bitap algorithm.
2695 * @param {string} text The text to search.
2696 * @param {string} pattern The pattern to search for.
2697 * @param {number} loc The location to search around.
2698 * @return {number} Best match index or -1.
2699 * @private
2700 */
2701diff_match_patch.prototype.match_bitap_ = function(text, pattern, loc) {
2702 if (pattern.length > this.Match_MaxBits) {
2703 throw new Error('Pattern too long for this browser.');
2704 }
2705
2706 // Initialise the alphabet.
2707 var s = this.match_alphabet_(pattern);
2708
2709 var dmp = this; // 'this' becomes 'window' in a closure.
2710
2711 /**
2712 * Compute and return the score for a match with e errors and x location.
2713 * Accesses loc and pattern through being a closure.
2714 * @param {number} e Number of errors in match.
2715 * @param {number} x Location of match.
2716 * @return {number} Overall score for match (0.0 = good, 1.0 = bad).
2717 * @private
2718 */
2719 function match_bitapScore_(e, x) {
2720 var accuracy = e / pattern.length;
2721 var proximity = Math.abs(loc - x);
2722 if (!dmp.Match_Distance) {
2723 // Dodge divide by zero error.
2724 return proximity ? 1.0 : accuracy;
2725 }
2726 return accuracy + (proximity / dmp.Match_Distance);
2727 }
2728
2729 // Highest score beyond which we give up.
2730 var score_threshold = this.Match_Threshold;
2731 // Is there a nearby exact match? (speedup)
2732 var best_loc = text.indexOf(pattern, loc);
2733 if (best_loc != -1) {
2734 score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold);
2735 // What about in the other direction? (speedup)
2736 best_loc = text.lastIndexOf(pattern, loc + pattern.length);
2737 if (best_loc != -1) {
2738 score_threshold =
2739 Math.min(match_bitapScore_(0, best_loc), score_threshold);
2740 }
2741 }
2742
2743 // Initialise the bit arrays.
2744 var matchmask = 1 << (pattern.length - 1);
2745 best_loc = -1;
2746
2747 var bin_min, bin_mid;
2748 var bin_max = pattern.length + text.length;
2749 var last_rd;
2750 for (var d = 0; d < pattern.length; d++) {
2751 // Scan for the best match; each iteration allows for one more error.
2752 // Run a binary search to determine how far from 'loc' we can stray at this
2753 // error level.
2754 bin_min = 0;
2755 bin_mid = bin_max;
2756 while (bin_min < bin_mid) {
2757 if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) {
2758 bin_min = bin_mid;
2759 } else {
2760 bin_max = bin_mid;
2761 }
2762 bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min);
2763 }
2764 // Use the result from this iteration as the maximum for the next.
2765 bin_max = bin_mid;
2766 var start = Math.max(1, loc - bin_mid + 1);
2767 var finish = Math.min(loc + bin_mid, text.length) + pattern.length;
2768
2769 var rd = Array(finish + 2);
2770 rd[finish + 1] = (1 << d) - 1;
2771 for (var j = finish; j >= start; j--) {
2772 // The alphabet (s) is a sparse hash, so the following line generates
2773 // warnings.
2774 var charMatch = s[text.charAt(j - 1)];
2775 if (d === 0) { // First pass: exact match.
2776 rd[j] = ((rd[j + 1] << 1) | 1) & charMatch;
2777 } else { // Subsequent passes: fuzzy match.
2778 rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) |
2779 (((last_rd[j + 1] | last_rd[j]) << 1) | 1) |
2780 last_rd[j + 1];
2781 }
2782 if (rd[j] & matchmask) {
2783 var score = match_bitapScore_(d, j - 1);
2784 // This match will almost certainly be better than any existing match.
2785 // But check anyway.
2786 if (score <= score_threshold) {
2787 // Told you so.
2788 score_threshold = score;
2789 best_loc = j - 1;
2790 if (best_loc > loc) {
2791 // When passing loc, don't exceed our current distance from loc.
2792 start = Math.max(1, 2 * loc - best_loc);
2793 } else {
2794 // Already passed loc, downhill from here on in.
2795 break;
2796 }
2797 }
2798 }
2799 }
2800 // No hope for a (better) match at greater error levels.
2801 if (match_bitapScore_(d + 1, loc) > score_threshold) {
2802 break;
2803 }
2804 last_rd = rd;
2805 }
2806 return best_loc;
2807};
2808
2809
2810/**
2811 * Initialise the alphabet for the Bitap algorithm.
2812 * @param {string} pattern The text to encode.
2813 * @return {!Object} Hash of character locations.
2814 * @private
2815 */
2816diff_match_patch.prototype.match_alphabet_ = function(pattern) {
2817 var s = {};
2818 for (var i = 0; i < pattern.length; i++) {
2819 s[pattern.charAt(i)] = 0;
2820 }
2821 for (var i = 0; i < pattern.length; i++) {
2822 s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1);
2823 }
2824 return s;
2825};
2826
2827
2828// PATCH FUNCTIONS
2829
2830
2831/**
2832 * Increase the context until it is unique,
2833 * but don't let the pattern expand beyond Match_MaxBits.
2834 * @param {!diff_match_patch.patch_obj} patch The patch to grow.
2835 * @param {string} text Source text.
2836 * @private
2837 */
2838diff_match_patch.prototype.patch_addContext_ = function(patch, text) {
2839 if (text.length == 0) {
2840 return;
2841 }
2842 var pattern = text.substring(patch.start2, patch.start2 + patch.length1);
2843 var padding = 0;
2844
2845 // Look for the first and last matches of pattern in text. If two different
2846 // matches are found, increase the pattern length.
2847 while (text.indexOf(pattern) != text.lastIndexOf(pattern) &&
2848 pattern.length < this.Match_MaxBits - this.Patch_Margin -
2849 this.Patch_Margin) {
2850 padding += this.Patch_Margin;
2851 pattern = text.substring(patch.start2 - padding,
2852 patch.start2 + patch.length1 + padding);
2853 }
2854 // Add one chunk for good luck.
2855 padding += this.Patch_Margin;
2856
2857 // Add the prefix.
2858 var prefix = text.substring(patch.start2 - padding, patch.start2);
2859 if (prefix) {
2860 patch.diffs.unshift([DIFF_EQUAL, prefix]);
2861 }
2862 // Add the suffix.
2863 var suffix = text.substring(patch.start2 + patch.length1,
2864 patch.start2 + patch.length1 + padding);
2865 if (suffix) {
2866 patch.diffs.push([DIFF_EQUAL, suffix]);
2867 }
2868
2869 // Roll back the start points.
2870 patch.start1 -= prefix.length;
2871 patch.start2 -= prefix.length;
2872 // Extend the lengths.
2873 patch.length1 += prefix.length + suffix.length;
2874 patch.length2 += prefix.length + suffix.length;
2875};
2876
2877
2878/**
2879 * Compute a list of patches to turn text1 into text2.
2880 * Use diffs if provided, otherwise compute it ourselves.
2881 * There are four ways to call this function, depending on what data is
2882 * available to the caller:
2883 * Method 1:
2884 * a = text1, b = text2
2885 * Method 2:
2886 * a = diffs
2887 * Method 3 (optimal):
2888 * a = text1, b = diffs
2889 * Method 4 (deprecated, use method 3):
2890 * a = text1, b = text2, c = diffs
2891 *
2892 * @param {string|!Array.<!diff_match_patch.Diff>} a text1 (methods 1,3,4) or
2893 * Array of diff tuples for text1 to text2 (method 2).
2894 * @param {string|!Array.<!diff_match_patch.Diff>} opt_b text2 (methods 1,4) or
2895 * Array of diff tuples for text1 to text2 (method 3) or undefined (method 2).
2896 * @param {string|!Array.<!diff_match_patch.Diff>} opt_c Array of diff tuples
2897 * for text1 to text2 (method 4) or undefined (methods 1,2,3).
2898 * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.
2899 */
2900diff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) {
2901 var text1, diffs;
2902 if (typeof a == 'string' && typeof opt_b == 'string' &&
2903 typeof opt_c == 'undefined') {
2904 // Method 1: text1, text2
2905 // Compute diffs from text1 and text2.
2906 text1 = /** @type {string} */(a);
2907 diffs = this.diff_main(text1, /** @type {string} */(opt_b), true);
2908 if (diffs.length > 2) {
2909 this.diff_cleanupSemantic(diffs);
2910 this.diff_cleanupEfficiency(diffs);
2911 }
2912 } else if (a && typeof a == 'object' && typeof opt_b == 'undefined' &&
2913 typeof opt_c == 'undefined') {
2914 // Method 2: diffs
2915 // Compute text1 from diffs.
2916 diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(a);
2917 text1 = this.diff_text1(diffs);
2918 } else if (typeof a == 'string' && opt_b && typeof opt_b == 'object' &&
2919 typeof opt_c == 'undefined') {
2920 // Method 3: text1, diffs
2921 text1 = /** @type {string} */(a);
2922 diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_b);
2923 } else if (typeof a == 'string' && typeof opt_b == 'string' &&
2924 opt_c && typeof opt_c == 'object') {
2925 // Method 4: text1, text2, diffs
2926 // text2 is not used.
2927 text1 = /** @type {string} */(a);
2928 diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_c);
2929 } else {
2930 throw new Error('Unknown call format to patch_make.');
2931 }
2932
2933 if (diffs.length === 0) {
2934 return []; // Get rid of the null case.
2935 }
2936 var patches = [];
2937 var patch = new diff_match_patch.patch_obj();
2938 var patchDiffLength = 0; // Keeping our own length var is faster in JS.
2939 var char_count1 = 0; // Number of characters into the text1 string.
2940 var char_count2 = 0; // Number of characters into the text2 string.
2941 // Start with text1 (prepatch_text) and apply the diffs until we arrive at
2942 // text2 (postpatch_text). We recreate the patches one by one to determine
2943 // context info.
2944 var prepatch_text = text1;
2945 var postpatch_text = text1;
2946 for (var x = 0; x < diffs.length; x++) {
2947 var diff_type = diffs[x][0];
2948 var diff_text = diffs[x][1];
2949
2950 if (!patchDiffLength && diff_type !== DIFF_EQUAL) {
2951 // A new patch starts here.
2952 patch.start1 = char_count1;
2953 patch.start2 = char_count2;
2954 }
2955
2956 switch (diff_type) {
2957 case DIFF_INSERT:
2958 patch.diffs[patchDiffLength++] = diffs[x];
2959 patch.length2 += diff_text.length;
2960 postpatch_text = postpatch_text.substring(0, char_count2) + diff_text +
2961 postpatch_text.substring(char_count2);
2962 break;
2963 case DIFF_DELETE:
2964 patch.length1 += diff_text.length;
2965 patch.diffs[patchDiffLength++] = diffs[x];
2966 postpatch_text = postpatch_text.substring(0, char_count2) +
2967 postpatch_text.substring(char_count2 +
2968 diff_text.length);
2969 break;
2970 case DIFF_EQUAL:
2971 if (diff_text.length <= 2 * this.Patch_Margin &&
2972 patchDiffLength && diffs.length != x + 1) {
2973 // Small equality inside a patch.
2974 patch.diffs[patchDiffLength++] = diffs[x];
2975 patch.length1 += diff_text.length;
2976 patch.length2 += diff_text.length;
2977 } else if (diff_text.length >= 2 * this.Patch_Margin) {
2978 // Time for a new patch.
2979 if (patchDiffLength) {
2980 this.patch_addContext_(patch, prepatch_text);
2981 patches.push(patch);
2982 patch = new diff_match_patch.patch_obj();
2983 patchDiffLength = 0;
2984 // Unlike Unidiff, our patch lists have a rolling context.
2985 // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff
2986 // Update prepatch text & pos to reflect the application of the
2987 // just completed patch.
2988 prepatch_text = postpatch_text;
2989 char_count1 = char_count2;
2990 }
2991 }
2992 break;
2993 }
2994
2995 // Update the current character count.
2996 if (diff_type !== DIFF_INSERT) {
2997 char_count1 += diff_text.length;
2998 }
2999 if (diff_type !== DIFF_DELETE) {
3000 char_count2 += diff_text.length;
3001 }
3002 }
3003 // Pick up the leftover patch if not empty.
3004 if (patchDiffLength) {
3005 this.patch_addContext_(patch, prepatch_text);
3006 patches.push(patch);
3007 }
3008
3009 return patches;
3010};
3011
3012
3013/**
3014 * Given an array of patches, return another array that is identical.
3015 * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.
3016 * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.
3017 */
3018diff_match_patch.prototype.patch_deepCopy = function(patches) {
3019 // Making deep copies is hard in JavaScript.
3020 var patchesCopy = [];
3021 for (var x = 0; x < patches.length; x++) {
3022 var patch = patches[x];
3023 var patchCopy = new diff_match_patch.patch_obj();
3024 patchCopy.diffs = [];
3025 for (var y = 0; y < patch.diffs.length; y++) {
3026 patchCopy.diffs[y] = patch.diffs[y].slice();
3027 }
3028 patchCopy.start1 = patch.start1;
3029 patchCopy.start2 = patch.start2;
3030 patchCopy.length1 = patch.length1;
3031 patchCopy.length2 = patch.length2;
3032 patchesCopy[x] = patchCopy;
3033 }
3034 return patchesCopy;
3035};
3036
3037
3038/**
3039 * Merge a set of patches onto the text. Return a patched text, as well
3040 * as a list of true/false values indicating which patches were applied.
3041 * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.
3042 * @param {string} text Old text.
3043 * @return {!Array.<string|!Array.<boolean>>} Two element Array, containing the
3044 * new text and an array of boolean values.
3045 */
3046diff_match_patch.prototype.patch_apply = function(patches, text) {
3047 if (patches.length == 0) {
3048 return [text, []];
3049 }
3050
3051 // Deep copy the patches so that no changes are made to originals.
3052 patches = this.patch_deepCopy(patches);
3053
3054 var nullPadding = this.patch_addPadding(patches);
3055 text = nullPadding + text + nullPadding;
3056
3057 this.patch_splitMax(patches);
3058 // delta keeps track of the offset between the expected and actual location
3059 // of the previous patch. If there are patches expected at positions 10 and
3060 // 20, but the first patch was found at 12, delta is 2 and the second patch
3061 // has an effective expected position of 22.
3062 var delta = 0;
3063 var results = [];
3064 for (var x = 0; x < patches.length; x++) {
3065 var expected_loc = patches[x].start2 + delta;
3066 var text1 = this.diff_text1(patches[x].diffs);
3067 var start_loc;
3068 var end_loc = -1;
3069 if (text1.length > this.Match_MaxBits) {
3070 // patch_splitMax will only provide an oversized pattern in the case of
3071 // a monster delete.
3072 start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits),
3073 expected_loc);
3074 if (start_loc != -1) {
3075 end_loc = this.match_main(text,
3076 text1.substring(text1.length - this.Match_MaxBits),
3077 expected_loc + text1.length - this.Match_MaxBits);
3078 if (end_loc == -1 || start_loc >= end_loc) {
3079 // Can't find valid trailing context. Drop this patch.
3080 start_loc = -1;
3081 }
3082 }
3083 } else {
3084 start_loc = this.match_main(text, text1, expected_loc);
3085 }
3086 if (start_loc == -1) {
3087 // No match found. :(
3088 results[x] = false;
3089 // Subtract the delta for this failed patch from subsequent patches.
3090 delta -= patches[x].length2 - patches[x].length1;
3091 } else {
3092 // Found a match. :)
3093 results[x] = true;
3094 delta = start_loc - expected_loc;
3095 var text2;
3096 if (end_loc == -1) {
3097 text2 = text.substring(start_loc, start_loc + text1.length);
3098 } else {
3099 text2 = text.substring(start_loc, end_loc + this.Match_MaxBits);
3100 }
3101 if (text1 == text2) {
3102 // Perfect match, just shove the replacement text in.
3103 text = text.substring(0, start_loc) +
3104 this.diff_text2(patches[x].diffs) +
3105 text.substring(start_loc + text1.length);
3106 } else {
3107 // Imperfect match. Run a diff to get a framework of equivalent
3108 // indices.
3109 var diffs = this.diff_main(text1, text2, false);
3110 if (text1.length > this.Match_MaxBits &&
3111 this.diff_levenshtein(diffs) / text1.length >
3112 this.Patch_DeleteThreshold) {
3113 // The end points match, but the content is unacceptably bad.
3114 results[x] = false;
3115 } else {
3116 this.diff_cleanupSemanticLossless(diffs);
3117 var index1 = 0;
3118 var index2;
3119 for (var y = 0; y < patches[x].diffs.length; y++) {
3120 var mod = patches[x].diffs[y];
3121 if (mod[0] !== DIFF_EQUAL) {
3122 index2 = this.diff_xIndex(diffs, index1);
3123 }
3124 if (mod[0] === DIFF_INSERT) { // Insertion
3125 text = text.substring(0, start_loc + index2) + mod[1] +
3126 text.substring(start_loc + index2);
3127 } else if (mod[0] === DIFF_DELETE) { // Deletion
3128 text = text.substring(0, start_loc + index2) +
3129 text.substring(start_loc + this.diff_xIndex(diffs,
3130 index1 + mod[1].length));
3131 }
3132 if (mod[0] !== DIFF_DELETE) {
3133 index1 += mod[1].length;
3134 }
3135 }
3136 }
3137 }
3138 }
3139 }
3140 // Strip the padding off.
3141 text = text.substring(nullPadding.length, text.length - nullPadding.length);
3142 return [text, results];
3143};
3144
3145
3146/**
3147 * Add some padding on text start and end so that edges can match something.
3148 * Intended to be called only from within patch_apply.
3149 * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.
3150 * @return {string} The padding string added to each side.
3151 */
3152diff_match_patch.prototype.patch_addPadding = function(patches) {
3153 var paddingLength = this.Patch_Margin;
3154 var nullPadding = '';
3155 for (var x = 1; x <= paddingLength; x++) {
3156 nullPadding += String.fromCharCode(x);
3157 }
3158
3159 // Bump all the patches forward.
3160 for (var x = 0; x < patches.length; x++) {
3161 patches[x].start1 += paddingLength;
3162 patches[x].start2 += paddingLength;
3163 }
3164
3165 // Add some padding on start of first diff.
3166 var patch = patches[0];
3167 var diffs = patch.diffs;
3168 if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) {
3169 // Add nullPadding equality.
3170 diffs.unshift([DIFF_EQUAL, nullPadding]);
3171 patch.start1 -= paddingLength; // Should be 0.
3172 patch.start2 -= paddingLength; // Should be 0.
3173 patch.length1 += paddingLength;
3174 patch.length2 += paddingLength;
3175 } else if (paddingLength > diffs[0][1].length) {
3176 // Grow first equality.
3177 var extraLength = paddingLength - diffs[0][1].length;
3178 diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1];
3179 patch.start1 -= extraLength;
3180 patch.start2 -= extraLength;
3181 patch.length1 += extraLength;
3182 patch.length2 += extraLength;
3183 }
3184
3185 // Add some padding on end of last diff.
3186 patch = patches[patches.length - 1];
3187 diffs = patch.diffs;
3188 if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) {
3189 // Add nullPadding equality.
3190 diffs.push([DIFF_EQUAL, nullPadding]);
3191 patch.length1 += paddingLength;
3192 patch.length2 += paddingLength;
3193 } else if (paddingLength > diffs[diffs.length - 1][1].length) {
3194 // Grow last equality.
3195 var extraLength = paddingLength - diffs[diffs.length - 1][1].length;
3196 diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength);
3197 patch.length1 += extraLength;
3198 patch.length2 += extraLength;
3199 }
3200
3201 return nullPadding;
3202};
3203
3204
3205/**
3206 * Look through the patches and break up any which are longer than the maximum
3207 * limit of the match algorithm.
3208 * Intended to be called only from within patch_apply.
3209 * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.
3210 */
3211diff_match_patch.prototype.patch_splitMax = function(patches) {
3212 var patch_size = this.Match_MaxBits;
3213 for (var x = 0; x < patches.length; x++) {
3214 if (patches[x].length1 <= patch_size) {
3215 continue;
3216 }
3217 var bigpatch = patches[x];
3218 // Remove the big old patch.
3219 patches.splice(x--, 1);
3220 var start1 = bigpatch.start1;
3221 var start2 = bigpatch.start2;
3222 var precontext = '';
3223 while (bigpatch.diffs.length !== 0) {
3224 // Create one of several smaller patches.
3225 var patch = new diff_match_patch.patch_obj();
3226 var empty = true;
3227 patch.start1 = start1 - precontext.length;
3228 patch.start2 = start2 - precontext.length;
3229 if (precontext !== '') {
3230 patch.length1 = patch.length2 = precontext.length;
3231 patch.diffs.push([DIFF_EQUAL, precontext]);
3232 }
3233 while (bigpatch.diffs.length !== 0 &&
3234 patch.length1 < patch_size - this.Patch_Margin) {
3235 var diff_type = bigpatch.diffs[0][0];
3236 var diff_text = bigpatch.diffs[0][1];
3237 if (diff_type === DIFF_INSERT) {
3238 // Insertions are harmless.
3239 patch.length2 += diff_text.length;
3240 start2 += diff_text.length;
3241 patch.diffs.push(bigpatch.diffs.shift());
3242 empty = false;
3243 } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 &&
3244 patch.diffs[0][0] == DIFF_EQUAL &&
3245 diff_text.length > 2 * patch_size) {
3246 // This is a large deletion. Let it pass in one chunk.
3247 patch.length1 += diff_text.length;
3248 start1 += diff_text.length;
3249 empty = false;
3250 patch.diffs.push([diff_type, diff_text]);
3251 bigpatch.diffs.shift();
3252 } else {
3253 // Deletion or equality. Only take as much as we can stomach.
3254 diff_text = diff_text.substring(0,
3255 patch_size - patch.length1 - this.Patch_Margin);
3256 patch.length1 += diff_text.length;
3257 start1 += diff_text.length;
3258 if (diff_type === DIFF_EQUAL) {
3259 patch.length2 += diff_text.length;
3260 start2 += diff_text.length;
3261 } else {
3262 empty = false;
3263 }
3264 patch.diffs.push([diff_type, diff_text]);
3265 if (diff_text == bigpatch.diffs[0][1]) {
3266 bigpatch.diffs.shift();
3267 } else {
3268 bigpatch.diffs[0][1] =
3269 bigpatch.diffs[0][1].substring(diff_text.length);
3270 }
3271 }
3272 }
3273 // Compute the head context for the next patch.
3274 precontext = this.diff_text2(patch.diffs);
3275 precontext =
3276 precontext.substring(precontext.length - this.Patch_Margin);
3277 // Append the end context for this patch.
3278 var postcontext = this.diff_text1(bigpatch.diffs)
3279 .substring(0, this.Patch_Margin);
3280 if (postcontext !== '') {
3281 patch.length1 += postcontext.length;
3282 patch.length2 += postcontext.length;
3283 if (patch.diffs.length !== 0 &&
3284 patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) {
3285 patch.diffs[patch.diffs.length - 1][1] += postcontext;
3286 } else {
3287 patch.diffs.push([DIFF_EQUAL, postcontext]);
3288 }
3289 }
3290 if (!empty) {
3291 patches.splice(++x, 0, patch);
3292 }
3293 }
3294 }
3295};
3296
3297
3298/**
3299 * Take a list of patches and return a textual representation.
3300 * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.
3301 * @return {string} Text representation of patches.
3302 */
3303diff_match_patch.prototype.patch_toText = function(patches) {
3304 var text = [];
3305 for (var x = 0; x < patches.length; x++) {
3306 text[x] = patches[x];
3307 }
3308 return text.join('');
3309};
3310
3311
3312/**
3313 * Parse a textual representation of patches and return a list of Patch objects.
3314 * @param {string} textline Text representation of patches.
3315 * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.
3316 * @throws {!Error} If invalid input.
3317 */
3318diff_match_patch.prototype.patch_fromText = function(textline) {
3319 var patches = [];
3320 if (!textline) {
3321 return patches;
3322 }
3323 var text = textline.split('\n');
3324 var textPointer = 0;
3325 var patchHeader = /^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;
3326 while (textPointer < text.length) {
3327 var m = text[textPointer].match(patchHeader);
3328 if (!m) {
3329 throw new Error('Invalid patch string: ' + text[textPointer]);
3330 }
3331 var patch = new diff_match_patch.patch_obj();
3332 patches.push(patch);
3333 patch.start1 = parseInt(m[1], 10);
3334 if (m[2] === '') {
3335 patch.start1--;
3336 patch.length1 = 1;
3337 } else if (m[2] == '0') {
3338 patch.length1 = 0;
3339 } else {
3340 patch.start1--;
3341 patch.length1 = parseInt(m[2], 10);
3342 }
3343
3344 patch.start2 = parseInt(m[3], 10);
3345 if (m[4] === '') {
3346 patch.start2--;
3347 patch.length2 = 1;
3348 } else if (m[4] == '0') {
3349 patch.length2 = 0;
3350 } else {
3351 patch.start2--;
3352 patch.length2 = parseInt(m[4], 10);
3353 }
3354 textPointer++;
3355
3356 while (textPointer < text.length) {
3357 var sign = text[textPointer].charAt(0);
3358 try {
3359 var line = decodeURI(text[textPointer].substring(1));
3360 } catch (ex) {
3361 // Malformed URI sequence.
3362 throw new Error('Illegal escape in patch_fromText: ' + line);
3363 }
3364 if (sign == '-') {
3365 // Deletion.
3366 patch.diffs.push([DIFF_DELETE, line]);
3367 } else if (sign == '+') {
3368 // Insertion.
3369 patch.diffs.push([DIFF_INSERT, line]);
3370 } else if (sign == ' ') {
3371 // Minor equality.
3372 patch.diffs.push([DIFF_EQUAL, line]);
3373 } else if (sign == '@') {
3374 // Start of next patch.
3375 break;
3376 } else if (sign === '') {
3377 // Blank line? Whatever.
3378 } else {
3379 // WTF?
3380 throw new Error('Invalid patch mode "' + sign + '" in: ' + line);
3381 }
3382 textPointer++;
3383 }
3384 }
3385 return patches;
3386};
3387
3388
3389/**
3390 * Class representing one patch operation.
3391 * @constructor
3392 */
3393diff_match_patch.patch_obj = function() {
3394 /** @type {!Array.<!diff_match_patch.Diff>} */
3395 this.diffs = [];
3396 /** @type {?number} */
3397 this.start1 = null;
3398 /** @type {?number} */
3399 this.start2 = null;
3400 /** @type {number} */
3401 this.length1 = 0;
3402 /** @type {number} */
3403 this.length2 = 0;
3404};
3405
3406
3407/**
3408 * Emmulate GNU diff's format.
3409 * Header: @@ -382,8 +481,9 @@
3410 * Indicies are printed as 1-based, not 0-based.
3411 * @return {string} The GNU diff string.
3412 */
3413diff_match_patch.patch_obj.prototype.toString = function() {
3414 var coords1, coords2;
3415 if (this.length1 === 0) {
3416 coords1 = this.start1 + ',0';
3417 } else if (this.length1 == 1) {
3418 coords1 = this.start1 + 1;
3419 } else {
3420 coords1 = (this.start1 + 1) + ',' + this.length1;
3421 }
3422 if (this.length2 === 0) {
3423 coords2 = this.start2 + ',0';
3424 } else if (this.length2 == 1) {
3425 coords2 = this.start2 + 1;
3426 } else {
3427 coords2 = (this.start2 + 1) + ',' + this.length2;
3428 }
3429 var text = ['@@ -' + coords1 + ' +' + coords2 + ' @@\n'];
3430 var op;
3431 // Escape the body of the patch with %xx notation.
3432 for (var x = 0; x < this.diffs.length; x++) {
3433 switch (this.diffs[x][0]) {
3434 case DIFF_INSERT:
3435 op = '+';
3436 break;
3437 case DIFF_DELETE:
3438 op = '-';
3439 break;
3440 case DIFF_EQUAL:
3441 op = ' ';
3442 break;
3443 }
3444 text[x + 1] = op + encodeURI(this.diffs[x][1]) + '\n';
3445 }
3446 return text.join('').replace(/%20/g, ' ');
3447};
3448
3449
3450// The following export code was added by @ForbesLindesay
3451module.exports = diff_match_patch;
3452module.exports['diff_match_patch'] = diff_match_patch;
3453module.exports['DIFF_DELETE'] = DIFF_DELETE;
3454module.exports['DIFF_INSERT'] = DIFF_INSERT;
3455module.exports['DIFF_EQUAL'] = DIFF_EQUAL;
3456});
3457
3458/* global diff_match_patch */
3459var TEXT_DIFF = 2;
3460var DEFAULT_MIN_LENGTH = 60;
3461var cachedDiffPatch = null;
3462
3463var getDiffMatchPatch = function getDiffMatchPatch(required) {
3464 /* jshint camelcase: false */
3465
3466 if (!cachedDiffPatch) {
3467 var instance = void 0;
3468 /* eslint-disable camelcase, new-cap */
3469 if (typeof diff_match_patch !== 'undefined') {
3470 // already loaded, probably a browser
3471 instance = typeof diff_match_patch === 'function' ? new diff_match_patch() : new diff_match_patch.diff_match_patch();
3472 } else if (diffMatchPatch) {
3473 try {
3474 instance = diffMatchPatch && new diffMatchPatch();
3475 } catch (err) {
3476 instance = null;
3477 }
3478 }
3479 /* eslint-enable camelcase, new-cap */
3480 if (!instance) {
3481 if (!required) {
3482 return null;
3483 }
3484 var error = new Error('text diff_match_patch library not found');
3485 // eslint-disable-next-line camelcase
3486 error.diff_match_patch_not_found = true;
3487 throw error;
3488 }
3489 cachedDiffPatch = {
3490 diff: function diff(txt1, txt2) {
3491 return instance.patch_toText(instance.patch_make(txt1, txt2));
3492 },
3493 patch: function patch(txt1, _patch) {
3494 var results = instance.patch_apply(instance.patch_fromText(_patch), txt1);
3495 for (var i = 0; i < results[1].length; i++) {
3496 if (!results[1][i]) {
3497 var _error = new Error('text patch failed');
3498 _error.textPatchFailed = true;
3499 }
3500 }
3501 return results[0];
3502 }
3503 };
3504 }
3505 return cachedDiffPatch;
3506};
3507
3508var diffFilter$3 = function textsDiffFilter(context) {
3509 if (context.leftType !== 'string') {
3510 return;
3511 }
3512 var minLength = context.options && context.options.textDiff && context.options.textDiff.minLength || DEFAULT_MIN_LENGTH;
3513 if (context.left.length < minLength || context.right.length < minLength) {
3514 context.setResult([context.left, context.right]).exit();
3515 return;
3516 }
3517 // large text, try to use a text-diff algorithm
3518 var diffMatchPatch$$1 = getDiffMatchPatch();
3519 if (!diffMatchPatch$$1) {
3520 // diff-match-patch library not available,
3521 // fallback to regular string replace
3522 context.setResult([context.left, context.right]).exit();
3523 return;
3524 }
3525 var diff = diffMatchPatch$$1.diff;
3526 context.setResult([diff(context.left, context.right), 0, TEXT_DIFF]).exit();
3527};
3528diffFilter$3.filterName = 'texts';
3529
3530var patchFilter$3 = function textsPatchFilter(context) {
3531 if (context.nested) {
3532 return;
3533 }
3534 if (context.delta[2] !== TEXT_DIFF) {
3535 return;
3536 }
3537
3538 // text-diff, use a text-patch algorithm
3539 var patch = getDiffMatchPatch(true).patch;
3540 context.setResult(patch(context.left, context.delta[0])).exit();
3541};
3542patchFilter$3.filterName = 'texts';
3543
3544var textDeltaReverse = function textDeltaReverse(delta) {
3545 var i = void 0;
3546 var l = void 0;
3547 var lines = void 0;
3548 var line = void 0;
3549 var lineTmp = void 0;
3550 var header = null;
3551 var headerRegex = /^@@ +-(\d+),(\d+) +\+(\d+),(\d+) +@@$/;
3552 var lineHeader = void 0;
3553 lines = delta.split('\n');
3554 for (i = 0, l = lines.length; i < l; i++) {
3555 line = lines[i];
3556 var lineStart = line.slice(0, 1);
3557 if (lineStart === '@') {
3558 header = headerRegex.exec(line);
3559 lineHeader = i;
3560
3561 // fix header
3562 lines[lineHeader] = '@@ -' + header[3] + ',' + header[4] + ' +' + header[1] + ',' + header[2] + ' @@';
3563 } else if (lineStart === '+') {
3564 lines[i] = '-' + lines[i].slice(1);
3565 if (lines[i - 1].slice(0, 1) === '+') {
3566 // swap lines to keep default order (-+)
3567 lineTmp = lines[i];
3568 lines[i] = lines[i - 1];
3569 lines[i - 1] = lineTmp;
3570 }
3571 } else if (lineStart === '-') {
3572 lines[i] = '+' + lines[i].slice(1);
3573 }
3574 }
3575 return lines.join('\n');
3576};
3577
3578var reverseFilter$3 = function textsReverseFilter(context) {
3579 if (context.nested) {
3580 return;
3581 }
3582 if (context.delta[2] !== TEXT_DIFF) {
3583 return;
3584 }
3585
3586 // text-diff, use a text-diff algorithm
3587 context.setResult([textDeltaReverse(context.delta[0]), 0, TEXT_DIFF]).exit();
3588};
3589reverseFilter$3.filterName = 'texts';
3590
3591var DiffPatcher = function () {
3592 function DiffPatcher(options) {
3593 classCallCheck(this, DiffPatcher);
3594
3595 this.processor = new Processor(options);
3596 this.processor.pipe(new Pipe('diff').append(collectChildrenDiffFilter, diffFilter, diffFilter$2, diffFilter$3, objectsDiffFilter, diffFilter$1).shouldHaveResult());
3597 this.processor.pipe(new Pipe('patch').append(collectChildrenPatchFilter, collectChildrenPatchFilter$1, patchFilter, patchFilter$3, patchFilter$1, patchFilter$2).shouldHaveResult());
3598 this.processor.pipe(new Pipe('reverse').append(collectChildrenReverseFilter, collectChildrenReverseFilter$1, reverseFilter, reverseFilter$3, reverseFilter$1, reverseFilter$2).shouldHaveResult());
3599 }
3600
3601 createClass(DiffPatcher, [{
3602 key: 'options',
3603 value: function options() {
3604 var _processor;
3605
3606 return (_processor = this.processor).options.apply(_processor, arguments);
3607 }
3608 }, {
3609 key: 'diff',
3610 value: function diff(left, right) {
3611 return this.processor.process(new DiffContext(left, right));
3612 }
3613 }, {
3614 key: 'patch',
3615 value: function patch(left, delta) {
3616 return this.processor.process(new PatchContext(left, delta));
3617 }
3618 }, {
3619 key: 'reverse',
3620 value: function reverse(delta) {
3621 return this.processor.process(new ReverseContext(delta));
3622 }
3623 }, {
3624 key: 'unpatch',
3625 value: function unpatch(right, delta) {
3626 return this.patch(right, this.reverse(delta));
3627 }
3628 }, {
3629 key: 'clone',
3630 value: function clone$$1(value) {
3631 return clone(value);
3632 }
3633 }]);
3634 return DiffPatcher;
3635}();
3636
3637var isArray$3 = typeof Array.isArray === 'function' ? Array.isArray : function (a) {
3638 return a instanceof Array;
3639};
3640
3641var getObjectKeys = typeof Object.keys === 'function' ? function (obj) {
3642 return Object.keys(obj);
3643} : function (obj) {
3644 var names = [];
3645 for (var property in obj) {
3646 if (Object.prototype.hasOwnProperty.call(obj, property)) {
3647 names.push(property);
3648 }
3649 }
3650 return names;
3651};
3652
3653var trimUnderscore = function trimUnderscore(str) {
3654 if (str.substr(0, 1) === '_') {
3655 return str.slice(1);
3656 }
3657 return str;
3658};
3659
3660var arrayKeyToSortNumber = function arrayKeyToSortNumber(key) {
3661 if (key === '_t') {
3662 return -1;
3663 } else {
3664 if (key.substr(0, 1) === '_') {
3665 return parseInt(key.slice(1), 10);
3666 } else {
3667 return parseInt(key, 10) + 0.1;
3668 }
3669 }
3670};
3671
3672var arrayKeyComparer = function arrayKeyComparer(key1, key2) {
3673 return arrayKeyToSortNumber(key1) - arrayKeyToSortNumber(key2);
3674};
3675
3676var BaseFormatter = function () {
3677 function BaseFormatter() {
3678 classCallCheck(this, BaseFormatter);
3679 }
3680
3681 createClass(BaseFormatter, [{
3682 key: 'format',
3683 value: function format(delta, left) {
3684 var context = {};
3685 this.prepareContext(context);
3686 this.recurse(context, delta, left);
3687 return this.finalize(context);
3688 }
3689 }, {
3690 key: 'prepareContext',
3691 value: function prepareContext(context) {
3692 context.buffer = [];
3693 context.out = function () {
3694 var _buffer;
3695
3696 (_buffer = this.buffer).push.apply(_buffer, arguments);
3697 };
3698 }
3699 }, {
3700 key: 'typeFormattterNotFound',
3701 value: function typeFormattterNotFound(context, deltaType) {
3702 throw new Error('cannot format delta type: ' + deltaType);
3703 }
3704 }, {
3705 key: 'typeFormattterErrorFormatter',
3706 value: function typeFormattterErrorFormatter(context, err) {
3707 return err.toString();
3708 }
3709 }, {
3710 key: 'finalize',
3711 value: function finalize(_ref) {
3712 var buffer = _ref.buffer;
3713
3714 if (isArray$3(buffer)) {
3715 return buffer.join('');
3716 }
3717 }
3718 }, {
3719 key: 'recurse',
3720 value: function recurse(context, delta, left, key, leftKey, movedFrom, isLast) {
3721 var useMoveOriginHere = delta && movedFrom;
3722 var leftValue = useMoveOriginHere ? movedFrom.value : left;
3723
3724 if (typeof delta === 'undefined' && typeof key === 'undefined') {
3725 return undefined;
3726 }
3727
3728 var type = this.getDeltaType(delta, movedFrom);
3729 var nodeType = type === 'node' ? delta._t === 'a' ? 'array' : 'object' : '';
3730
3731 if (typeof key !== 'undefined') {
3732 this.nodeBegin(context, key, leftKey, type, nodeType, isLast);
3733 } else {
3734 this.rootBegin(context, type, nodeType);
3735 }
3736
3737 var typeFormattter = void 0;
3738 try {
3739 typeFormattter = this['format_' + type] || this.typeFormattterNotFound(context, type);
3740 typeFormattter.call(this, context, delta, leftValue, key, leftKey, movedFrom);
3741 } catch (err) {
3742 this.typeFormattterErrorFormatter(context, err, delta, leftValue, key, leftKey, movedFrom);
3743 if (typeof console !== 'undefined' && console.error) {
3744 console.error(err.stack);
3745 }
3746 }
3747
3748 if (typeof key !== 'undefined') {
3749 this.nodeEnd(context, key, leftKey, type, nodeType, isLast);
3750 } else {
3751 this.rootEnd(context, type, nodeType);
3752 }
3753 }
3754 }, {
3755 key: 'formatDeltaChildren',
3756 value: function formatDeltaChildren(context, delta, left) {
3757 var self = this;
3758 this.forEachDeltaKey(delta, left, function (key, leftKey, movedFrom, isLast) {
3759 self.recurse(context, delta[key], left ? left[leftKey] : undefined, key, leftKey, movedFrom, isLast);
3760 });
3761 }
3762 }, {
3763 key: 'forEachDeltaKey',
3764 value: function forEachDeltaKey(delta, left, fn) {
3765 var keys = getObjectKeys(delta);
3766 var arrayKeys = delta._t === 'a';
3767 var moveDestinations = {};
3768 var name = void 0;
3769 if (typeof left !== 'undefined') {
3770 for (name in left) {
3771 if (Object.prototype.hasOwnProperty.call(left, name)) {
3772 if (typeof delta[name] === 'undefined' && (!arrayKeys || typeof delta['_' + name] === 'undefined')) {
3773 keys.push(name);
3774 }
3775 }
3776 }
3777 }
3778 // look for move destinations
3779 for (name in delta) {
3780 if (Object.prototype.hasOwnProperty.call(delta, name)) {
3781 var value = delta[name];
3782 if (isArray$3(value) && value[2] === 3) {
3783 moveDestinations[value[1].toString()] = {
3784 key: name,
3785 value: left && left[parseInt(name.substr(1))]
3786 };
3787 if (this.includeMoveDestinations !== false) {
3788 if (typeof left === 'undefined' && typeof delta[value[1]] === 'undefined') {
3789 keys.push(value[1].toString());
3790 }
3791 }
3792 }
3793 }
3794 }
3795 if (arrayKeys) {
3796 keys.sort(arrayKeyComparer);
3797 } else {
3798 keys.sort();
3799 }
3800 for (var index = 0, length = keys.length; index < length; index++) {
3801 var key = keys[index];
3802 if (arrayKeys && key === '_t') {
3803 continue;
3804 }
3805 var leftKey = arrayKeys ? typeof key === 'number' ? key : parseInt(trimUnderscore(key), 10) : key;
3806 var isLast = index === length - 1;
3807 fn(key, leftKey, moveDestinations[leftKey], isLast);
3808 }
3809 }
3810 }, {
3811 key: 'getDeltaType',
3812 value: function getDeltaType(delta, movedFrom) {
3813 if (typeof delta === 'undefined') {
3814 if (typeof movedFrom !== 'undefined') {
3815 return 'movedestination';
3816 }
3817 return 'unchanged';
3818 }
3819 if (isArray$3(delta)) {
3820 if (delta.length === 1) {
3821 return 'added';
3822 }
3823 if (delta.length === 2) {
3824 return 'modified';
3825 }
3826 if (delta.length === 3 && delta[2] === 0) {
3827 return 'deleted';
3828 }
3829 if (delta.length === 3 && delta[2] === 2) {
3830 return 'textdiff';
3831 }
3832 if (delta.length === 3 && delta[2] === 3) {
3833 return 'moved';
3834 }
3835 } else if ((typeof delta === 'undefined' ? 'undefined' : _typeof(delta)) === 'object') {
3836 return 'node';
3837 }
3838 return 'unknown';
3839 }
3840 }, {
3841 key: 'parseTextDiff',
3842 value: function parseTextDiff(value) {
3843 var output = [];
3844 var lines = value.split('\n@@ ');
3845 for (var i = 0, l = lines.length; i < l; i++) {
3846 var line = lines[i];
3847 var lineOutput = {
3848 pieces: []
3849 };
3850 var location = /^(?:@@ )?[-+]?(\d+),(\d+)/.exec(line).slice(1);
3851 lineOutput.location = {
3852 line: location[0],
3853 chr: location[1]
3854 };
3855 var pieces = line.split('\n').slice(1);
3856 for (var pieceIndex = 0, piecesLength = pieces.length; pieceIndex < piecesLength; pieceIndex++) {
3857 var piece = pieces[pieceIndex];
3858 if (!piece.length) {
3859 continue;
3860 }
3861 var pieceOutput = {
3862 type: 'context'
3863 };
3864 if (piece.substr(0, 1) === '+') {
3865 pieceOutput.type = 'added';
3866 } else if (piece.substr(0, 1) === '-') {
3867 pieceOutput.type = 'deleted';
3868 }
3869 pieceOutput.text = piece.slice(1);
3870 lineOutput.pieces.push(pieceOutput);
3871 }
3872 output.push(lineOutput);
3873 }
3874 return output;
3875 }
3876 }]);
3877 return BaseFormatter;
3878}();
3879
3880
3881
3882var base = Object.freeze({
3883 default: BaseFormatter
3884});
3885
3886var HtmlFormatter = function (_BaseFormatter) {
3887 inherits(HtmlFormatter, _BaseFormatter);
3888
3889 function HtmlFormatter() {
3890 classCallCheck(this, HtmlFormatter);
3891 return possibleConstructorReturn(this, (HtmlFormatter.__proto__ || Object.getPrototypeOf(HtmlFormatter)).apply(this, arguments));
3892 }
3893
3894 createClass(HtmlFormatter, [{
3895 key: 'typeFormattterErrorFormatter',
3896 value: function typeFormattterErrorFormatter(context, err) {
3897 context.out('<pre class="jsondiffpatch-error">' + err + '</pre>');
3898 }
3899 }, {
3900 key: 'formatValue',
3901 value: function formatValue(context, value) {
3902 context.out('<pre>' + htmlEscape(JSON.stringify(value, null, 2)) + '</pre>');
3903 }
3904 }, {
3905 key: 'formatTextDiffString',
3906 value: function formatTextDiffString(context, value) {
3907 var lines = this.parseTextDiff(value);
3908 context.out('<ul class="jsondiffpatch-textdiff">');
3909 for (var i = 0, l = lines.length; i < l; i++) {
3910 var line = lines[i];
3911 context.out('<li><div class="jsondiffpatch-textdiff-location">' + ('<span class="jsondiffpatch-textdiff-line-number">' + line.location.line + '</span><span class="jsondiffpatch-textdiff-char">' + line.location.chr + '</span></div><div class="jsondiffpatch-textdiff-line">'));
3912 var pieces = line.pieces;
3913 for (var pieceIndex = 0, piecesLength = pieces.length; pieceIndex < piecesLength; pieceIndex++) {
3914 /* global decodeURI */
3915 var piece = pieces[pieceIndex];
3916 context.out('<span class="jsondiffpatch-textdiff-' + piece.type + '">' + htmlEscape(decodeURI(piece.text)) + '</span>');
3917 }
3918 context.out('</div></li>');
3919 }
3920 context.out('</ul>');
3921 }
3922 }, {
3923 key: 'rootBegin',
3924 value: function rootBegin(context, type, nodeType) {
3925 var nodeClass = 'jsondiffpatch-' + type + (nodeType ? ' jsondiffpatch-child-node-type-' + nodeType : '');
3926 context.out('<div class="jsondiffpatch-delta ' + nodeClass + '">');
3927 }
3928 }, {
3929 key: 'rootEnd',
3930 value: function rootEnd(context) {
3931 context.out('</div>' + (context.hasArrows ? '<script type="text/javascript">setTimeout(' + (adjustArrows.toString() + ',10);</script>') : ''));
3932 }
3933 }, {
3934 key: 'nodeBegin',
3935 value: function nodeBegin(context, key, leftKey, type, nodeType) {
3936 var nodeClass = 'jsondiffpatch-' + type + (nodeType ? ' jsondiffpatch-child-node-type-' + nodeType : '');
3937 context.out('<li class="' + nodeClass + '" data-key="' + leftKey + '">' + ('<div class="jsondiffpatch-property-name">' + leftKey + '</div>'));
3938 }
3939 }, {
3940 key: 'nodeEnd',
3941 value: function nodeEnd(context) {
3942 context.out('</li>');
3943 }
3944
3945 /* jshint camelcase: false */
3946 /* eslint-disable camelcase */
3947
3948 }, {
3949 key: 'format_unchanged',
3950 value: function format_unchanged(context, delta, left) {
3951 if (typeof left === 'undefined') {
3952 return;
3953 }
3954 context.out('<div class="jsondiffpatch-value">');
3955 this.formatValue(context, left);
3956 context.out('</div>');
3957 }
3958 }, {
3959 key: 'format_movedestination',
3960 value: function format_movedestination(context, delta, left) {
3961 if (typeof left === 'undefined') {
3962 return;
3963 }
3964 context.out('<div class="jsondiffpatch-value">');
3965 this.formatValue(context, left);
3966 context.out('</div>');
3967 }
3968 }, {
3969 key: 'format_node',
3970 value: function format_node(context, delta, left) {
3971 // recurse
3972 var nodeType = delta._t === 'a' ? 'array' : 'object';
3973 context.out('<ul class="jsondiffpatch-node jsondiffpatch-node-type-' + nodeType + '">');
3974 this.formatDeltaChildren(context, delta, left);
3975 context.out('</ul>');
3976 }
3977 }, {
3978 key: 'format_added',
3979 value: function format_added(context, delta) {
3980 context.out('<div class="jsondiffpatch-value">');
3981 this.formatValue(context, delta[0]);
3982 context.out('</div>');
3983 }
3984 }, {
3985 key: 'format_modified',
3986 value: function format_modified(context, delta) {
3987 context.out('<div class="jsondiffpatch-value jsondiffpatch-left-value">');
3988 this.formatValue(context, delta[0]);
3989 context.out('</div>' + '<div class="jsondiffpatch-value jsondiffpatch-right-value">');
3990 this.formatValue(context, delta[1]);
3991 context.out('</div>');
3992 }
3993 }, {
3994 key: 'format_deleted',
3995 value: function format_deleted(context, delta) {
3996 context.out('<div class="jsondiffpatch-value">');
3997 this.formatValue(context, delta[0]);
3998 context.out('</div>');
3999 }
4000 }, {
4001 key: 'format_moved',
4002 value: function format_moved(context, delta) {
4003 context.out('<div class="jsondiffpatch-value">');
4004 this.formatValue(context, delta[0]);
4005 context.out('</div><div class="jsondiffpatch-moved-destination">' + delta[1] + '</div>');
4006
4007 // draw an SVG arrow from here to move destination
4008 context.out(
4009 /* jshint multistr: true */
4010 '<div class="jsondiffpatch-arrow" ' + 'style="position: relative; left: -34px;">\n <svg width="30" height="60" ' + 'style="position: absolute; display: none;">\n <defs>\n <marker id="markerArrow" markerWidth="8" markerHeight="8"\n refx="2" refy="4"\n orient="auto" markerUnits="userSpaceOnUse">\n <path d="M1,1 L1,7 L7,4 L1,1" style="fill: #339;" />\n </marker>\n </defs>\n <path d="M30,0 Q-10,25 26,50"\n style="stroke: #88f; stroke-width: 2px; fill: none; ' + 'stroke-opacity: 0.5; marker-end: url(#markerArrow);"\n ></path>\n </svg>\n </div>');
4011 context.hasArrows = true;
4012 }
4013 }, {
4014 key: 'format_textdiff',
4015 value: function format_textdiff(context, delta) {
4016 context.out('<div class="jsondiffpatch-value">');
4017 this.formatTextDiffString(context, delta[0]);
4018 context.out('</div>');
4019 }
4020 }]);
4021 return HtmlFormatter;
4022}(BaseFormatter);
4023
4024function htmlEscape(text) {
4025 var html = text;
4026 var replacements = [[/&/g, '&amp;'], [/</g, '&lt;'], [/>/g, '&gt;'], [/'/g, '&apos;'], [/"/g, '&quot;']];
4027 for (var i = 0; i < replacements.length; i++) {
4028 html = html.replace(replacements[i][0], replacements[i][1]);
4029 }
4030 return html;
4031}
4032
4033var adjustArrows = function jsondiffpatchHtmlFormatterAdjustArrows(nodeArg) {
4034 var node = nodeArg || document;
4035 var getElementText = function getElementText(_ref) {
4036 var textContent = _ref.textContent,
4037 innerText = _ref.innerText;
4038 return textContent || innerText;
4039 };
4040 var eachByQuery = function eachByQuery(el, query, fn) {
4041 var elems = el.querySelectorAll(query);
4042 for (var i = 0, l = elems.length; i < l; i++) {
4043 fn(elems[i]);
4044 }
4045 };
4046 var eachChildren = function eachChildren(_ref2, fn) {
4047 var children = _ref2.children;
4048
4049 for (var i = 0, l = children.length; i < l; i++) {
4050 fn(children[i], i);
4051 }
4052 };
4053 eachByQuery(node, '.jsondiffpatch-arrow', function (_ref3) {
4054 var parentNode = _ref3.parentNode,
4055 children = _ref3.children,
4056 style = _ref3.style;
4057
4058 var arrowParent = parentNode;
4059 var svg = children[0];
4060 var path = svg.children[1];
4061 svg.style.display = 'none';
4062 var destination = getElementText(arrowParent.querySelector('.jsondiffpatch-moved-destination'));
4063 var container = arrowParent.parentNode;
4064 var destinationElem = void 0;
4065 eachChildren(container, function (child) {
4066 if (child.getAttribute('data-key') === destination) {
4067 destinationElem = child;
4068 }
4069 });
4070 if (!destinationElem) {
4071 return;
4072 }
4073 try {
4074 var distance = destinationElem.offsetTop - arrowParent.offsetTop;
4075 svg.setAttribute('height', Math.abs(distance) + 6);
4076 style.top = -8 + (distance > 0 ? 0 : distance) + 'px';
4077 var curve = distance > 0 ? 'M30,0 Q-10,' + Math.round(distance / 2) + ' 26,' + (distance - 4) : 'M30,' + -distance + ' Q-10,' + Math.round(-distance / 2) + ' 26,4';
4078 path.setAttribute('d', curve);
4079 svg.style.display = '';
4080 } catch (err) {}
4081 });
4082};
4083
4084/* jshint camelcase: true */
4085/* eslint-enable camelcase */
4086
4087var showUnchanged = function showUnchanged(show, node, delay) {
4088 var el = node || document.body;
4089 var prefix = 'jsondiffpatch-unchanged-';
4090 var classes = {
4091 showing: prefix + 'showing',
4092 hiding: prefix + 'hiding',
4093 visible: prefix + 'visible',
4094 hidden: prefix + 'hidden'
4095 };
4096 var list = el.classList;
4097 if (!list) {
4098 return;
4099 }
4100 if (!delay) {
4101 list.remove(classes.showing);
4102 list.remove(classes.hiding);
4103 list.remove(classes.visible);
4104 list.remove(classes.hidden);
4105 if (show === false) {
4106 list.add(classes.hidden);
4107 }
4108 return;
4109 }
4110 if (show === false) {
4111 list.remove(classes.showing);
4112 list.add(classes.visible);
4113 setTimeout(function () {
4114 list.add(classes.hiding);
4115 }, 10);
4116 } else {
4117 list.remove(classes.hiding);
4118 list.add(classes.showing);
4119 list.remove(classes.hidden);
4120 }
4121 var intervalId = setInterval(function () {
4122 adjustArrows(el);
4123 }, 100);
4124 setTimeout(function () {
4125 list.remove(classes.showing);
4126 list.remove(classes.hiding);
4127 if (show === false) {
4128 list.add(classes.hidden);
4129 list.remove(classes.visible);
4130 } else {
4131 list.add(classes.visible);
4132 list.remove(classes.hidden);
4133 }
4134 setTimeout(function () {
4135 list.remove(classes.visible);
4136 clearInterval(intervalId);
4137 }, delay + 400);
4138 }, delay);
4139};
4140
4141var hideUnchanged = function hideUnchanged(node, delay) {
4142 return showUnchanged(false, node, delay);
4143};
4144
4145var defaultInstance = void 0;
4146
4147function format(delta, left) {
4148 if (!defaultInstance) {
4149 defaultInstance = new HtmlFormatter();
4150 }
4151 return defaultInstance.format(delta, left);
4152}
4153
4154
4155
4156var html = Object.freeze({
4157 showUnchanged: showUnchanged,
4158 hideUnchanged: hideUnchanged,
4159 default: HtmlFormatter,
4160 format: format
4161});
4162
4163var AnnotatedFormatter = function (_BaseFormatter) {
4164 inherits(AnnotatedFormatter, _BaseFormatter);
4165
4166 function AnnotatedFormatter() {
4167 classCallCheck(this, AnnotatedFormatter);
4168
4169 var _this = possibleConstructorReturn(this, (AnnotatedFormatter.__proto__ || Object.getPrototypeOf(AnnotatedFormatter)).call(this));
4170
4171 _this.includeMoveDestinations = false;
4172 return _this;
4173 }
4174
4175 createClass(AnnotatedFormatter, [{
4176 key: 'prepareContext',
4177 value: function prepareContext(context) {
4178 get(AnnotatedFormatter.prototype.__proto__ || Object.getPrototypeOf(AnnotatedFormatter.prototype), 'prepareContext', this).call(this, context);
4179 context.indent = function (levels) {
4180 this.indentLevel = (this.indentLevel || 0) + (typeof levels === 'undefined' ? 1 : levels);
4181 this.indentPad = new Array(this.indentLevel + 1).join('&nbsp;&nbsp;');
4182 };
4183 context.row = function (json, htmlNote) {
4184 context.out('<tr><td style="white-space: nowrap;">' + '<pre class="jsondiffpatch-annotated-indent"' + ' style="display: inline-block">');
4185 context.out(context.indentPad);
4186 context.out('</pre><pre style="display: inline-block">');
4187 context.out(json);
4188 context.out('</pre></td><td class="jsondiffpatch-delta-note"><div>');
4189 context.out(htmlNote);
4190 context.out('</div></td></tr>');
4191 };
4192 }
4193 }, {
4194 key: 'typeFormattterErrorFormatter',
4195 value: function typeFormattterErrorFormatter(context, err) {
4196 context.row('', '<pre class="jsondiffpatch-error">' + err + '</pre>');
4197 }
4198 }, {
4199 key: 'formatTextDiffString',
4200 value: function formatTextDiffString(context, value) {
4201 var lines = this.parseTextDiff(value);
4202 context.out('<ul class="jsondiffpatch-textdiff">');
4203 for (var i = 0, l = lines.length; i < l; i++) {
4204 var line = lines[i];
4205 context.out('<li><div class="jsondiffpatch-textdiff-location">' + ('<span class="jsondiffpatch-textdiff-line-number">' + line.location.line + '</span><span class="jsondiffpatch-textdiff-char">' + line.location.chr + '</span></div><div class="jsondiffpatch-textdiff-line">'));
4206 var pieces = line.pieces;
4207 for (var pieceIndex = 0, piecesLength = pieces.length; pieceIndex < piecesLength; pieceIndex++) {
4208 var piece = pieces[pieceIndex];
4209 context.out('<span class="jsondiffpatch-textdiff-' + piece.type + '">' + piece.text + '</span>');
4210 }
4211 context.out('</div></li>');
4212 }
4213 context.out('</ul>');
4214 }
4215 }, {
4216 key: 'rootBegin',
4217 value: function rootBegin(context, type, nodeType) {
4218 context.out('<table class="jsondiffpatch-annotated-delta">');
4219 if (type === 'node') {
4220 context.row('{');
4221 context.indent();
4222 }
4223 if (nodeType === 'array') {
4224 context.row('"_t": "a",', 'Array delta (member names indicate array indices)');
4225 }
4226 }
4227 }, {
4228 key: 'rootEnd',
4229 value: function rootEnd(context, type) {
4230 if (type === 'node') {
4231 context.indent(-1);
4232 context.row('}');
4233 }
4234 context.out('</table>');
4235 }
4236 }, {
4237 key: 'nodeBegin',
4238 value: function nodeBegin(context, key, leftKey, type, nodeType) {
4239 context.row('&quot;' + key + '&quot;: {');
4240 if (type === 'node') {
4241 context.indent();
4242 }
4243 if (nodeType === 'array') {
4244 context.row('"_t": "a",', 'Array delta (member names indicate array indices)');
4245 }
4246 }
4247 }, {
4248 key: 'nodeEnd',
4249 value: function nodeEnd(context, key, leftKey, type, nodeType, isLast) {
4250 if (type === 'node') {
4251 context.indent(-1);
4252 }
4253 context.row('}' + (isLast ? '' : ','));
4254 }
4255
4256 /* jshint camelcase: false */
4257
4258 /* eslint-disable camelcase */
4259
4260 }, {
4261 key: 'format_unchanged',
4262 value: function format_unchanged() {}
4263 }, {
4264 key: 'format_movedestination',
4265 value: function format_movedestination() {}
4266 }, {
4267 key: 'format_node',
4268 value: function format_node(context, delta, left) {
4269 // recurse
4270 this.formatDeltaChildren(context, delta, left);
4271 }
4272 }]);
4273 return AnnotatedFormatter;
4274}(BaseFormatter);
4275
4276/* eslint-enable camelcase */
4277
4278var wrapPropertyName = function wrapPropertyName(name) {
4279 return '<pre style="display:inline-block">&quot;' + name + '&quot;</pre>';
4280};
4281
4282var deltaAnnotations = {
4283 added: function added(delta, left, key, leftKey) {
4284 var formatLegend = ' <pre>([newValue])</pre>';
4285 if (typeof leftKey === 'undefined') {
4286 return 'new value' + formatLegend;
4287 }
4288 if (typeof leftKey === 'number') {
4289 return 'insert at index ' + leftKey + formatLegend;
4290 }
4291 return 'add property ' + wrapPropertyName(leftKey) + formatLegend;
4292 },
4293 modified: function modified(delta, left, key, leftKey) {
4294 var formatLegend = ' <pre>([previousValue, newValue])</pre>';
4295 if (typeof leftKey === 'undefined') {
4296 return 'modify value' + formatLegend;
4297 }
4298 if (typeof leftKey === 'number') {
4299 return 'modify at index ' + leftKey + formatLegend;
4300 }
4301 return 'modify property ' + wrapPropertyName(leftKey) + formatLegend;
4302 },
4303 deleted: function deleted(delta, left, key, leftKey) {
4304 var formatLegend = ' <pre>([previousValue, 0, 0])</pre>';
4305 if (typeof leftKey === 'undefined') {
4306 return 'delete value' + formatLegend;
4307 }
4308 if (typeof leftKey === 'number') {
4309 return 'remove index ' + leftKey + formatLegend;
4310 }
4311 return 'delete property ' + wrapPropertyName(leftKey) + formatLegend;
4312 },
4313 moved: function moved(delta, left, key, leftKey) {
4314 return 'move from <span title="(position to remove at original state)">' + ('index ' + leftKey + '</span> to <span title="(position to insert at final') + (' state)">index ' + delta[1] + '</span>');
4315 },
4316 textdiff: function textdiff(delta, left, key, leftKey) {
4317 var location = typeof leftKey === 'undefined' ? '' : typeof leftKey === 'number' ? ' at index ' + leftKey : ' at property ' + wrapPropertyName(leftKey);
4318 return 'text diff' + location + ', format is <a href="https://code.google.com/' + 'p/google-diff-match-patch/wiki/Unidiff">a variation of Unidiff</a>';
4319 }
4320};
4321
4322var formatAnyChange = function formatAnyChange(context, delta) {
4323 var deltaType = this.getDeltaType(delta);
4324 var annotator = deltaAnnotations[deltaType];
4325 var htmlNote = annotator && annotator.apply(annotator, Array.prototype.slice.call(arguments, 1));
4326 var json = JSON.stringify(delta, null, 2);
4327 if (deltaType === 'textdiff') {
4328 // split text diffs lines
4329 json = json.split('\\n').join('\\n"+\n "');
4330 }
4331 context.indent();
4332 context.row(json, htmlNote);
4333 context.indent(-1);
4334};
4335
4336/* eslint-disable camelcase */
4337AnnotatedFormatter.prototype.format_added = formatAnyChange;
4338AnnotatedFormatter.prototype.format_modified = formatAnyChange;
4339AnnotatedFormatter.prototype.format_deleted = formatAnyChange;
4340AnnotatedFormatter.prototype.format_moved = formatAnyChange;
4341AnnotatedFormatter.prototype.format_textdiff = formatAnyChange;
4342var defaultInstance$1 = void 0;
4343
4344function format$1(delta, left) {
4345 if (!defaultInstance$1) {
4346 defaultInstance$1 = new AnnotatedFormatter();
4347 }
4348 return defaultInstance$1.format(delta, left);
4349}
4350
4351
4352
4353var annotated = Object.freeze({
4354 default: AnnotatedFormatter,
4355 format: format$1
4356});
4357
4358var OPERATIONS = {
4359 add: 'add',
4360 remove: 'remove',
4361 replace: 'replace',
4362 move: 'move'
4363};
4364
4365var JSONFormatter = function (_BaseFormatter) {
4366 inherits(JSONFormatter, _BaseFormatter);
4367
4368 function JSONFormatter() {
4369 classCallCheck(this, JSONFormatter);
4370
4371 var _this = possibleConstructorReturn(this, (JSONFormatter.__proto__ || Object.getPrototypeOf(JSONFormatter)).call(this));
4372
4373 _this.includeMoveDestinations = true;
4374 return _this;
4375 }
4376
4377 createClass(JSONFormatter, [{
4378 key: 'prepareContext',
4379 value: function prepareContext(context) {
4380 get(JSONFormatter.prototype.__proto__ || Object.getPrototypeOf(JSONFormatter.prototype), 'prepareContext', this).call(this, context);
4381 context.result = [];
4382 context.path = [];
4383 context.pushCurrentOp = function (obj) {
4384 var op = obj.op,
4385 value = obj.value;
4386
4387 var val = {
4388 op: op,
4389 path: this.currentPath()
4390 };
4391 if (typeof value !== 'undefined') {
4392 val.value = value;
4393 }
4394 this.result.push(val);
4395 };
4396
4397 context.pushMoveOp = function (to) {
4398 var from = this.currentPath();
4399 this.result.push({
4400 op: OPERATIONS.move,
4401 from: from,
4402 path: this.toPath(to)
4403 });
4404 };
4405
4406 context.currentPath = function () {
4407 return '/' + this.path.join('/');
4408 };
4409
4410 context.toPath = function (toPath) {
4411 var to = this.path.slice();
4412 to[to.length - 1] = toPath;
4413 return '/' + to.join('/');
4414 };
4415 }
4416 }, {
4417 key: 'typeFormattterErrorFormatter',
4418 value: function typeFormattterErrorFormatter(context, err) {
4419 context.out('[ERROR] ' + err);
4420 }
4421 }, {
4422 key: 'rootBegin',
4423 value: function rootBegin() {}
4424 }, {
4425 key: 'rootEnd',
4426 value: function rootEnd() {}
4427 }, {
4428 key: 'nodeBegin',
4429 value: function nodeBegin(_ref, key, leftKey) {
4430 var path = _ref.path;
4431
4432 path.push(leftKey);
4433 }
4434 }, {
4435 key: 'nodeEnd',
4436 value: function nodeEnd(_ref2) {
4437 var path = _ref2.path;
4438
4439 path.pop();
4440 }
4441
4442 /* jshint camelcase: false */
4443 /* eslint-disable camelcase */
4444
4445 }, {
4446 key: 'format_unchanged',
4447 value: function format_unchanged() {}
4448 }, {
4449 key: 'format_movedestination',
4450 value: function format_movedestination() {}
4451 }, {
4452 key: 'format_node',
4453 value: function format_node(context, delta, left) {
4454 this.formatDeltaChildren(context, delta, left);
4455 }
4456 }, {
4457 key: 'format_added',
4458 value: function format_added(context, delta) {
4459 context.pushCurrentOp({ op: OPERATIONS.add, value: delta[0] });
4460 }
4461 }, {
4462 key: 'format_modified',
4463 value: function format_modified(context, delta) {
4464 context.pushCurrentOp({ op: OPERATIONS.replace, value: delta[1] });
4465 }
4466 }, {
4467 key: 'format_deleted',
4468 value: function format_deleted(context) {
4469 context.pushCurrentOp({ op: OPERATIONS.remove });
4470 }
4471 }, {
4472 key: 'format_moved',
4473 value: function format_moved(context, delta) {
4474 var to = delta[1];
4475 context.pushMoveOp(to);
4476 }
4477 }, {
4478 key: 'format_textdiff',
4479 value: function format_textdiff() {
4480 throw new Error('Not implemented');
4481 }
4482 }, {
4483 key: 'format',
4484 value: function format(delta, left) {
4485 var context = {};
4486 this.prepareContext(context);
4487 this.recurse(context, delta, left);
4488 return context.result;
4489 }
4490 }]);
4491 return JSONFormatter;
4492}(BaseFormatter);
4493
4494var last = function last(arr) {
4495 return arr[arr.length - 1];
4496};
4497
4498var sortBy = function sortBy(arr, pred) {
4499 arr.sort(pred);
4500 return arr;
4501};
4502
4503var compareByIndexDesc = function compareByIndexDesc(indexA, indexB) {
4504 var lastA = parseInt(indexA, 10);
4505 var lastB = parseInt(indexB, 10);
4506 if (!(isNaN(lastA) || isNaN(lastB))) {
4507 return lastB - lastA;
4508 } else {
4509 return 0;
4510 }
4511};
4512
4513var opsByDescendingOrder = function opsByDescendingOrder(removeOps) {
4514 return sortBy(removeOps, function (a, b) {
4515 var splitA = a.path.split('/');
4516 var splitB = b.path.split('/');
4517 if (splitA.length !== splitB.length) {
4518 return splitA.length - splitB.length;
4519 } else {
4520 return compareByIndexDesc(last(splitA), last(splitB));
4521 }
4522 });
4523};
4524
4525var partitionOps = function partitionOps(arr, fns) {
4526 var initArr = Array(fns.length + 1).fill().map(function () {
4527 return [];
4528 });
4529 return arr.map(function (item) {
4530 var position = fns.map(function (fn) {
4531 return fn(item);
4532 }).indexOf(true);
4533 if (position < 0) {
4534 position = fns.length;
4535 }
4536 return { item: item, position: position };
4537 }).reduce(function (acc, item) {
4538 acc[item.position].push(item.item);
4539 return acc;
4540 }, initArr);
4541};
4542var isMoveOp = function isMoveOp(_ref3) {
4543 var op = _ref3.op;
4544 return op === 'move';
4545};
4546var isRemoveOp = function isRemoveOp(_ref4) {
4547 var op = _ref4.op;
4548 return op === 'remove';
4549};
4550
4551var reorderOps = function reorderOps(diff) {
4552 var _partitionOps = partitionOps(diff, [isMoveOp, isRemoveOp]),
4553 _partitionOps2 = slicedToArray(_partitionOps, 3),
4554 moveOps = _partitionOps2[0],
4555 removedOps = _partitionOps2[1],
4556 restOps = _partitionOps2[2];
4557
4558 var removeOpsReverse = opsByDescendingOrder(removedOps);
4559 return [].concat(toConsumableArray(removeOpsReverse), toConsumableArray(moveOps), toConsumableArray(restOps));
4560};
4561
4562var defaultInstance$2 = void 0;
4563
4564var format$2 = function format(delta, left) {
4565 if (!defaultInstance$2) {
4566 defaultInstance$2 = new JSONFormatter();
4567 }
4568 return reorderOps(defaultInstance$2.format(delta, left));
4569};
4570
4571var log = function log(delta, left) {
4572 console.log(format$2(delta, left));
4573};
4574
4575
4576
4577var jsonpatch = Object.freeze({
4578 default: JSONFormatter,
4579 partitionOps: partitionOps,
4580 format: format$2,
4581 log: log
4582});
4583
4584function chalkColor(name) {
4585 return chalk && chalk[name] || function () {
4586 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
4587 args[_key] = arguments[_key];
4588 }
4589
4590 return args;
4591 };
4592}
4593
4594var colors = {
4595 added: chalkColor('green'),
4596 deleted: chalkColor('red'),
4597 movedestination: chalkColor('gray'),
4598 moved: chalkColor('yellow'),
4599 unchanged: chalkColor('gray'),
4600 error: chalkColor('white.bgRed'),
4601 textDiffLine: chalkColor('gray')
4602};
4603
4604var ConsoleFormatter = function (_BaseFormatter) {
4605 inherits(ConsoleFormatter, _BaseFormatter);
4606
4607 function ConsoleFormatter() {
4608 classCallCheck(this, ConsoleFormatter);
4609
4610 var _this = possibleConstructorReturn(this, (ConsoleFormatter.__proto__ || Object.getPrototypeOf(ConsoleFormatter)).call(this));
4611
4612 _this.includeMoveDestinations = false;
4613 return _this;
4614 }
4615
4616 createClass(ConsoleFormatter, [{
4617 key: 'prepareContext',
4618 value: function prepareContext(context) {
4619 get(ConsoleFormatter.prototype.__proto__ || Object.getPrototypeOf(ConsoleFormatter.prototype), 'prepareContext', this).call(this, context);
4620 context.indent = function (levels) {
4621 this.indentLevel = (this.indentLevel || 0) + (typeof levels === 'undefined' ? 1 : levels);
4622 this.indentPad = new Array(this.indentLevel + 1).join(' ');
4623 this.outLine();
4624 };
4625 context.outLine = function () {
4626 this.buffer.push('\n' + (this.indentPad || ''));
4627 };
4628 context.out = function () {
4629 for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
4630 args[_key2] = arguments[_key2];
4631 }
4632
4633 for (var i = 0, l = args.length; i < l; i++) {
4634 var lines = args[i].split('\n');
4635 var text = lines.join('\n' + (this.indentPad || ''));
4636 if (this.color && this.color[0]) {
4637 text = this.color[0](text);
4638 }
4639 this.buffer.push(text);
4640 }
4641 };
4642 context.pushColor = function (color) {
4643 this.color = this.color || [];
4644 this.color.unshift(color);
4645 };
4646 context.popColor = function () {
4647 this.color = this.color || [];
4648 this.color.shift();
4649 };
4650 }
4651 }, {
4652 key: 'typeFormattterErrorFormatter',
4653 value: function typeFormattterErrorFormatter(context, err) {
4654 context.pushColor(colors.error);
4655 context.out('[ERROR]' + err);
4656 context.popColor();
4657 }
4658 }, {
4659 key: 'formatValue',
4660 value: function formatValue(context, value) {
4661 context.out(JSON.stringify(value, null, 2));
4662 }
4663 }, {
4664 key: 'formatTextDiffString',
4665 value: function formatTextDiffString(context, value) {
4666 var lines = this.parseTextDiff(value);
4667 context.indent();
4668 for (var i = 0, l = lines.length; i < l; i++) {
4669 var line = lines[i];
4670 context.pushColor(colors.textDiffLine);
4671 context.out(line.location.line + ',' + line.location.chr + ' ');
4672 context.popColor();
4673 var pieces = line.pieces;
4674 for (var pieceIndex = 0, piecesLength = pieces.length; pieceIndex < piecesLength; pieceIndex++) {
4675 var piece = pieces[pieceIndex];
4676 context.pushColor(colors[piece.type]);
4677 context.out(piece.text);
4678 context.popColor();
4679 }
4680 if (i < l - 1) {
4681 context.outLine();
4682 }
4683 }
4684 context.indent(-1);
4685 }
4686 }, {
4687 key: 'rootBegin',
4688 value: function rootBegin(context, type, nodeType) {
4689 context.pushColor(colors[type]);
4690 if (type === 'node') {
4691 context.out(nodeType === 'array' ? '[' : '{');
4692 context.indent();
4693 }
4694 }
4695 }, {
4696 key: 'rootEnd',
4697 value: function rootEnd(context, type, nodeType) {
4698 if (type === 'node') {
4699 context.indent(-1);
4700 context.out(nodeType === 'array' ? ']' : '}');
4701 }
4702 context.popColor();
4703 }
4704 }, {
4705 key: 'nodeBegin',
4706 value: function nodeBegin(context, key, leftKey, type, nodeType) {
4707 context.pushColor(colors[type]);
4708 context.out(leftKey + ': ');
4709 if (type === 'node') {
4710 context.out(nodeType === 'array' ? '[' : '{');
4711 context.indent();
4712 }
4713 }
4714 }, {
4715 key: 'nodeEnd',
4716 value: function nodeEnd(context, key, leftKey, type, nodeType, isLast) {
4717 if (type === 'node') {
4718 context.indent(-1);
4719 context.out(nodeType === 'array' ? ']' : '}' + (isLast ? '' : ','));
4720 }
4721 if (!isLast) {
4722 context.outLine();
4723 }
4724 context.popColor();
4725 }
4726
4727 /* jshint camelcase: false */
4728 /* eslint-disable camelcase */
4729
4730 }, {
4731 key: 'format_unchanged',
4732 value: function format_unchanged(context, delta, left) {
4733 if (typeof left === 'undefined') {
4734 return;
4735 }
4736 this.formatValue(context, left);
4737 }
4738 }, {
4739 key: 'format_movedestination',
4740 value: function format_movedestination(context, delta, left) {
4741 if (typeof left === 'undefined') {
4742 return;
4743 }
4744 this.formatValue(context, left);
4745 }
4746 }, {
4747 key: 'format_node',
4748 value: function format_node(context, delta, left) {
4749 // recurse
4750 this.formatDeltaChildren(context, delta, left);
4751 }
4752 }, {
4753 key: 'format_added',
4754 value: function format_added(context, delta) {
4755 this.formatValue(context, delta[0]);
4756 }
4757 }, {
4758 key: 'format_modified',
4759 value: function format_modified(context, delta) {
4760 context.pushColor(colors.deleted);
4761 this.formatValue(context, delta[0]);
4762 context.popColor();
4763 context.out(' => ');
4764 context.pushColor(colors.added);
4765 this.formatValue(context, delta[1]);
4766 context.popColor();
4767 }
4768 }, {
4769 key: 'format_deleted',
4770 value: function format_deleted(context, delta) {
4771 this.formatValue(context, delta[0]);
4772 }
4773 }, {
4774 key: 'format_moved',
4775 value: function format_moved(context, delta) {
4776 context.out('==> ' + delta[1]);
4777 }
4778 }, {
4779 key: 'format_textdiff',
4780 value: function format_textdiff(context, delta) {
4781 this.formatTextDiffString(context, delta[0]);
4782 }
4783 }]);
4784 return ConsoleFormatter;
4785}(BaseFormatter);
4786
4787var defaultInstance$3 = void 0;
4788
4789var format$3 = function format(delta, left) {
4790 if (!defaultInstance$3) {
4791 defaultInstance$3 = new ConsoleFormatter();
4792 }
4793 return defaultInstance$3.format(delta, left);
4794};
4795
4796function log$1(delta, left) {
4797 console.log(format$3(delta, left));
4798}
4799
4800
4801
4802var console$1 = Object.freeze({
4803 default: ConsoleFormatter,
4804 format: format$3,
4805 log: log$1
4806});
4807
4808
4809
4810var index = Object.freeze({
4811 base: base,
4812 html: html,
4813 annotated: annotated,
4814 jsonpatch: jsonpatch,
4815 console: console$1
4816});
4817
4818// use as 2nd parameter for JSON.parse to revive Date instances
4819function dateReviver(key, value) {
4820 var parts = void 0;
4821 if (typeof value === 'string') {
4822 // eslint-disable-next-line max-len
4823 parts = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d*))?(Z|([+-])(\d{2}):(\d{2}))$/.exec(value);
4824 if (parts) {
4825 return new Date(Date.UTC(+parts[1], +parts[2] - 1, +parts[3], +parts[4], +parts[5], +parts[6], +(parts[7] || 0)));
4826 }
4827 }
4828 return value;
4829}
4830
4831function create(options) {
4832 return new DiffPatcher(options);
4833}
4834
4835var defaultInstance$4 = void 0;
4836
4837function diff() {
4838 if (!defaultInstance$4) {
4839 defaultInstance$4 = new DiffPatcher();
4840 }
4841 return defaultInstance$4.diff.apply(defaultInstance$4, arguments);
4842}
4843
4844function patch() {
4845 if (!defaultInstance$4) {
4846 defaultInstance$4 = new DiffPatcher();
4847 }
4848 return defaultInstance$4.patch.apply(defaultInstance$4, arguments);
4849}
4850
4851function unpatch() {
4852 if (!defaultInstance$4) {
4853 defaultInstance$4 = new DiffPatcher();
4854 }
4855 return defaultInstance$4.unpatch.apply(defaultInstance$4, arguments);
4856}
4857
4858function reverse() {
4859 if (!defaultInstance$4) {
4860 defaultInstance$4 = new DiffPatcher();
4861 }
4862 return defaultInstance$4.reverse.apply(defaultInstance$4, arguments);
4863}
4864
4865function clone$1() {
4866 if (!defaultInstance$4) {
4867 defaultInstance$4 = new DiffPatcher();
4868 }
4869 return defaultInstance$4.clone.apply(defaultInstance$4, arguments);
4870}
4871
4872exports.DiffPatcher = DiffPatcher;
4873exports.formatters = index;
4874exports.console = console$1;
4875exports.create = create;
4876exports.dateReviver = dateReviver;
4877exports.diff = diff;
4878exports.patch = patch;
4879exports.unpatch = unpatch;
4880exports.reverse = reverse;
4881exports.clone = clone$1;
4882
4883Object.defineProperty(exports, '__esModule', { value: true });
4884
4885})));