UNPKG

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