.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / diff / dist / diff.js
1 /*!
2
3  diff v4.0.1
4
5 Software License Agreement (BSD License)
6
7 Copyright (c) 2009-2015, Kevin Decker <kpdecker@gmail.com>
8
9 All rights reserved.
10
11 Redistribution and use of this software in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13
14 * Redistributions of source code must retain the above
15   copyright notice, this list of conditions and the
16   following disclaimer.
17
18 * Redistributions in binary form must reproduce the above
19   copyright notice, this list of conditions and the
20   following disclaimer in the documentation and/or other
21   materials provided with the distribution.
22
23 * Neither the name of Kevin Decker nor the names of its
24   contributors may be used to endorse or promote products
25   derived from this software without specific prior
26   written permission.
27
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
29 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
30 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
31 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
34 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
35 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 @license
37 */
38 (function (global, factory) {
39   typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
40   typeof define === 'function' && define.amd ? define(['exports'], factory) :
41   (global = global || self, factory(global.Diff = {}));
42 }(this, function (exports) { 'use strict';
43
44   function Diff() {}
45   Diff.prototype = {
46     diff: function diff(oldString, newString) {
47       var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
48       var callback = options.callback;
49
50       if (typeof options === 'function') {
51         callback = options;
52         options = {};
53       }
54
55       this.options = options;
56       var self = this;
57
58       function done(value) {
59         if (callback) {
60           setTimeout(function () {
61             callback(undefined, value);
62           }, 0);
63           return true;
64         } else {
65           return value;
66         }
67       } // Allow subclasses to massage the input prior to running
68
69
70       oldString = this.castInput(oldString);
71       newString = this.castInput(newString);
72       oldString = this.removeEmpty(this.tokenize(oldString));
73       newString = this.removeEmpty(this.tokenize(newString));
74       var newLen = newString.length,
75           oldLen = oldString.length;
76       var editLength = 1;
77       var maxEditLength = newLen + oldLen;
78       var bestPath = [{
79         newPos: -1,
80         components: []
81       }]; // Seed editLength = 0, i.e. the content starts with the same values
82
83       var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
84
85       if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
86         // Identity per the equality and tokenizer
87         return done([{
88           value: this.join(newString),
89           count: newString.length
90         }]);
91       } // Main worker method. checks all permutations of a given edit length for acceptance.
92
93
94       function execEditLength() {
95         for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
96           var basePath = void 0;
97
98           var addPath = bestPath[diagonalPath - 1],
99               removePath = bestPath[diagonalPath + 1],
100               _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
101
102           if (addPath) {
103             // No one else is going to attempt to use this value, clear it
104             bestPath[diagonalPath - 1] = undefined;
105           }
106
107           var canAdd = addPath && addPath.newPos + 1 < newLen,
108               canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen;
109
110           if (!canAdd && !canRemove) {
111             // If this path is a terminal then prune
112             bestPath[diagonalPath] = undefined;
113             continue;
114           } // Select the diagonal that we want to branch from. We select the prior
115           // path whose position in the new string is the farthest from the origin
116           // and does not pass the bounds of the diff graph
117
118
119           if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
120             basePath = clonePath(removePath);
121             self.pushComponent(basePath.components, undefined, true);
122           } else {
123             basePath = addPath; // No need to clone, we've pulled it from the list
124
125             basePath.newPos++;
126             self.pushComponent(basePath.components, true, undefined);
127           }
128
129           _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); // If we have hit the end of both strings, then we are done
130
131           if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) {
132             return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken));
133           } else {
134             // Otherwise track this path as a potential candidate and continue.
135             bestPath[diagonalPath] = basePath;
136           }
137         }
138
139         editLength++;
140       } // Performs the length of edit iteration. Is a bit fugly as this has to support the
141       // sync and async mode which is never fun. Loops over execEditLength until a value
142       // is produced.
143
144
145       if (callback) {
146         (function exec() {
147           setTimeout(function () {
148             // This should not happen, but we want to be safe.
149
150             /* istanbul ignore next */
151             if (editLength > maxEditLength) {
152               return callback();
153             }
154
155             if (!execEditLength()) {
156               exec();
157             }
158           }, 0);
159         })();
160       } else {
161         while (editLength <= maxEditLength) {
162           var ret = execEditLength();
163
164           if (ret) {
165             return ret;
166           }
167         }
168       }
169     },
170     pushComponent: function pushComponent(components, added, removed) {
171       var last = components[components.length - 1];
172
173       if (last && last.added === added && last.removed === removed) {
174         // We need to clone here as the component clone operation is just
175         // as shallow array clone
176         components[components.length - 1] = {
177           count: last.count + 1,
178           added: added,
179           removed: removed
180         };
181       } else {
182         components.push({
183           count: 1,
184           added: added,
185           removed: removed
186         });
187       }
188     },
189     extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) {
190       var newLen = newString.length,
191           oldLen = oldString.length,
192           newPos = basePath.newPos,
193           oldPos = newPos - diagonalPath,
194           commonCount = 0;
195
196       while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
197         newPos++;
198         oldPos++;
199         commonCount++;
200       }
201
202       if (commonCount) {
203         basePath.components.push({
204           count: commonCount
205         });
206       }
207
208       basePath.newPos = newPos;
209       return oldPos;
210     },
211     equals: function equals(left, right) {
212       if (this.options.comparator) {
213         return this.options.comparator(left, right);
214       } else {
215         return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase();
216       }
217     },
218     removeEmpty: function removeEmpty(array) {
219       var ret = [];
220
221       for (var i = 0; i < array.length; i++) {
222         if (array[i]) {
223           ret.push(array[i]);
224         }
225       }
226
227       return ret;
228     },
229     castInput: function castInput(value) {
230       return value;
231     },
232     tokenize: function tokenize(value) {
233       return value.split('');
234     },
235     join: function join(chars) {
236       return chars.join('');
237     }
238   };
239
240   function buildValues(diff, components, newString, oldString, useLongestToken) {
241     var componentPos = 0,
242         componentLen = components.length,
243         newPos = 0,
244         oldPos = 0;
245
246     for (; componentPos < componentLen; componentPos++) {
247       var component = components[componentPos];
248
249       if (!component.removed) {
250         if (!component.added && useLongestToken) {
251           var value = newString.slice(newPos, newPos + component.count);
252           value = value.map(function (value, i) {
253             var oldValue = oldString[oldPos + i];
254             return oldValue.length > value.length ? oldValue : value;
255           });
256           component.value = diff.join(value);
257         } else {
258           component.value = diff.join(newString.slice(newPos, newPos + component.count));
259         }
260
261         newPos += component.count; // Common case
262
263         if (!component.added) {
264           oldPos += component.count;
265         }
266       } else {
267         component.value = diff.join(oldString.slice(oldPos, oldPos + component.count));
268         oldPos += component.count; // Reverse add and remove so removes are output first to match common convention
269         // The diffing algorithm is tied to add then remove output and this is the simplest
270         // route to get the desired output with minimal overhead.
271
272         if (componentPos && components[componentPos - 1].added) {
273           var tmp = components[componentPos - 1];
274           components[componentPos - 1] = components[componentPos];
275           components[componentPos] = tmp;
276         }
277       }
278     } // Special case handle for when one terminal is ignored (i.e. whitespace).
279     // For this case we merge the terminal into the prior string and drop the change.
280     // This is only available for string mode.
281
282
283     var lastComponent = components[componentLen - 1];
284
285     if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) {
286       components[componentLen - 2].value += lastComponent.value;
287       components.pop();
288     }
289
290     return components;
291   }
292
293   function clonePath(path) {
294     return {
295       newPos: path.newPos,
296       components: path.components.slice(0)
297     };
298   }
299
300   var characterDiff = new Diff();
301   function diffChars(oldStr, newStr, options) {
302     return characterDiff.diff(oldStr, newStr, options);
303   }
304
305   function generateOptions(options, defaults) {
306     if (typeof options === 'function') {
307       defaults.callback = options;
308     } else if (options) {
309       for (var name in options) {
310         /* istanbul ignore else */
311         if (options.hasOwnProperty(name)) {
312           defaults[name] = options[name];
313         }
314       }
315     }
316
317     return defaults;
318   }
319
320   //
321   // Ranges and exceptions:
322   // Latin-1 Supplement, 0080–00FF
323   //  - U+00D7  × Multiplication sign
324   //  - U+00F7  ÷ Division sign
325   // Latin Extended-A, 0100–017F
326   // Latin Extended-B, 0180–024F
327   // IPA Extensions, 0250–02AF
328   // Spacing Modifier Letters, 02B0–02FF
329   //  - U+02C7  ˇ &#711;  Caron
330   //  - U+02D8  ˘ &#728;  Breve
331   //  - U+02D9  ˙ &#729;  Dot Above
332   //  - U+02DA  ˚ &#730;  Ring Above
333   //  - U+02DB  ˛ &#731;  Ogonek
334   //  - U+02DC  ˜ &#732;  Small Tilde
335   //  - U+02DD  ˝ &#733;  Double Acute Accent
336   // Latin Extended Additional, 1E00–1EFF
337
338   var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;
339   var reWhitespace = /\S/;
340   var wordDiff = new Diff();
341
342   wordDiff.equals = function (left, right) {
343     if (this.options.ignoreCase) {
344       left = left.toLowerCase();
345       right = right.toLowerCase();
346     }
347
348     return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right);
349   };
350
351   wordDiff.tokenize = function (value) {
352     var tokens = value.split(/(\s+|[()[\]{}'"]|\b)/); // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set.
353
354     for (var i = 0; i < tokens.length - 1; i++) {
355       // If we have an empty string in the next field and we have only word chars before and after, merge
356       if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) {
357         tokens[i] += tokens[i + 2];
358         tokens.splice(i + 1, 2);
359         i--;
360       }
361     }
362
363     return tokens;
364   };
365
366   function diffWords(oldStr, newStr, options) {
367     options = generateOptions(options, {
368       ignoreWhitespace: true
369     });
370     return wordDiff.diff(oldStr, newStr, options);
371   }
372   function diffWordsWithSpace(oldStr, newStr, options) {
373     return wordDiff.diff(oldStr, newStr, options);
374   }
375
376   var lineDiff = new Diff();
377
378   lineDiff.tokenize = function (value) {
379     var retLines = [],
380         linesAndNewlines = value.split(/(\n|\r\n)/); // Ignore the final empty token that occurs if the string ends with a new line
381
382     if (!linesAndNewlines[linesAndNewlines.length - 1]) {
383       linesAndNewlines.pop();
384     } // Merge the content and line separators into single tokens
385
386
387     for (var i = 0; i < linesAndNewlines.length; i++) {
388       var line = linesAndNewlines[i];
389
390       if (i % 2 && !this.options.newlineIsToken) {
391         retLines[retLines.length - 1] += line;
392       } else {
393         if (this.options.ignoreWhitespace) {
394           line = line.trim();
395         }
396
397         retLines.push(line);
398       }
399     }
400
401     return retLines;
402   };
403
404   function diffLines(oldStr, newStr, callback) {
405     return lineDiff.diff(oldStr, newStr, callback);
406   }
407   function diffTrimmedLines(oldStr, newStr, callback) {
408     var options = generateOptions(callback, {
409       ignoreWhitespace: true
410     });
411     return lineDiff.diff(oldStr, newStr, options);
412   }
413
414   var sentenceDiff = new Diff();
415
416   sentenceDiff.tokenize = function (value) {
417     return value.split(/(\S.+?[.!?])(?=\s+|$)/);
418   };
419
420   function diffSentences(oldStr, newStr, callback) {
421     return sentenceDiff.diff(oldStr, newStr, callback);
422   }
423
424   var cssDiff = new Diff();
425
426   cssDiff.tokenize = function (value) {
427     return value.split(/([{}:;,]|\s+)/);
428   };
429
430   function diffCss(oldStr, newStr, callback) {
431     return cssDiff.diff(oldStr, newStr, callback);
432   }
433
434   function _typeof(obj) {
435     if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
436       _typeof = function (obj) {
437         return typeof obj;
438       };
439     } else {
440       _typeof = function (obj) {
441         return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
442       };
443     }
444
445     return _typeof(obj);
446   }
447
448   function _toConsumableArray(arr) {
449     return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
450   }
451
452   function _arrayWithoutHoles(arr) {
453     if (Array.isArray(arr)) {
454       for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
455
456       return arr2;
457     }
458   }
459
460   function _iterableToArray(iter) {
461     if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
462   }
463
464   function _nonIterableSpread() {
465     throw new TypeError("Invalid attempt to spread non-iterable instance");
466   }
467
468   var objectPrototypeToString = Object.prototype.toString;
469   var jsonDiff = new Diff(); // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a
470   // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output:
471
472   jsonDiff.useLongestToken = true;
473   jsonDiff.tokenize = lineDiff.tokenize;
474
475   jsonDiff.castInput = function (value) {
476     var _this$options = this.options,
477         undefinedReplacement = _this$options.undefinedReplacement,
478         _this$options$stringi = _this$options.stringifyReplacer,
479         stringifyReplacer = _this$options$stringi === void 0 ? function (k, v) {
480       return typeof v === 'undefined' ? undefinedReplacement : v;
481     } : _this$options$stringi;
482     return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, '  ');
483   };
484
485   jsonDiff.equals = function (left, right) {
486     return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'));
487   };
488
489   function diffJson(oldObj, newObj, options) {
490     return jsonDiff.diff(oldObj, newObj, options);
491   } // This function handles the presence of circular references by bailing out when encountering an
492   // object that is already on the "stack" of items being processed. Accepts an optional replacer
493
494   function canonicalize(obj, stack, replacementStack, replacer, key) {
495     stack = stack || [];
496     replacementStack = replacementStack || [];
497
498     if (replacer) {
499       obj = replacer(key, obj);
500     }
501
502     var i;
503
504     for (i = 0; i < stack.length; i += 1) {
505       if (stack[i] === obj) {
506         return replacementStack[i];
507       }
508     }
509
510     var canonicalizedObj;
511
512     if ('[object Array]' === objectPrototypeToString.call(obj)) {
513       stack.push(obj);
514       canonicalizedObj = new Array(obj.length);
515       replacementStack.push(canonicalizedObj);
516
517       for (i = 0; i < obj.length; i += 1) {
518         canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key);
519       }
520
521       stack.pop();
522       replacementStack.pop();
523       return canonicalizedObj;
524     }
525
526     if (obj && obj.toJSON) {
527       obj = obj.toJSON();
528     }
529
530     if (_typeof(obj) === 'object' && obj !== null) {
531       stack.push(obj);
532       canonicalizedObj = {};
533       replacementStack.push(canonicalizedObj);
534
535       var sortedKeys = [],
536           _key;
537
538       for (_key in obj) {
539         /* istanbul ignore else */
540         if (obj.hasOwnProperty(_key)) {
541           sortedKeys.push(_key);
542         }
543       }
544
545       sortedKeys.sort();
546
547       for (i = 0; i < sortedKeys.length; i += 1) {
548         _key = sortedKeys[i];
549         canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key);
550       }
551
552       stack.pop();
553       replacementStack.pop();
554     } else {
555       canonicalizedObj = obj;
556     }
557
558     return canonicalizedObj;
559   }
560
561   var arrayDiff = new Diff();
562
563   arrayDiff.tokenize = function (value) {
564     return value.slice();
565   };
566
567   arrayDiff.join = arrayDiff.removeEmpty = function (value) {
568     return value;
569   };
570
571   function diffArrays(oldArr, newArr, callback) {
572     return arrayDiff.diff(oldArr, newArr, callback);
573   }
574
575   function parsePatch(uniDiff) {
576     var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
577     var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/),
578         delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [],
579         list = [],
580         i = 0;
581
582     function parseIndex() {
583       var index = {};
584       list.push(index); // Parse diff metadata
585
586       while (i < diffstr.length) {
587         var line = diffstr[i]; // File header found, end parsing diff metadata
588
589         if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) {
590           break;
591         } // Diff index
592
593
594         var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line);
595
596         if (header) {
597           index.index = header[1];
598         }
599
600         i++;
601       } // Parse file headers if they are defined. Unified diff requires them, but
602       // there's no technical issues to have an isolated hunk without file header
603
604
605       parseFileHeader(index);
606       parseFileHeader(index); // Parse hunks
607
608       index.hunks = [];
609
610       while (i < diffstr.length) {
611         var _line = diffstr[i];
612
613         if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) {
614           break;
615         } else if (/^@@/.test(_line)) {
616           index.hunks.push(parseHunk());
617         } else if (_line && options.strict) {
618           // Ignore unexpected content unless in strict mode
619           throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line));
620         } else {
621           i++;
622         }
623       }
624     } // Parses the --- and +++ headers, if none are found, no lines
625     // are consumed.
626
627
628     function parseFileHeader(index) {
629       var fileHeader = /^(---|\+\+\+)\s+(.*)$/.exec(diffstr[i]);
630
631       if (fileHeader) {
632         var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new';
633         var data = fileHeader[2].split('\t', 2);
634         var fileName = data[0].replace(/\\\\/g, '\\');
635
636         if (/^".*"$/.test(fileName)) {
637           fileName = fileName.substr(1, fileName.length - 2);
638         }
639
640         index[keyPrefix + 'FileName'] = fileName;
641         index[keyPrefix + 'Header'] = (data[1] || '').trim();
642         i++;
643       }
644     } // Parses a hunk
645     // This assumes that we are at the start of a hunk.
646
647
648     function parseHunk() {
649       var chunkHeaderIndex = i,
650           chunkHeaderLine = diffstr[i++],
651           chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
652       var hunk = {
653         oldStart: +chunkHeader[1],
654         oldLines: +chunkHeader[2] || 1,
655         newStart: +chunkHeader[3],
656         newLines: +chunkHeader[4] || 1,
657         lines: [],
658         linedelimiters: []
659       };
660       var addCount = 0,
661           removeCount = 0;
662
663       for (; i < diffstr.length; i++) {
664         // Lines starting with '---' could be mistaken for the "remove line" operation
665         // But they could be the header for the next file. Therefore prune such cases out.
666         if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) {
667           break;
668         }
669
670         var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0];
671
672         if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
673           hunk.lines.push(diffstr[i]);
674           hunk.linedelimiters.push(delimiters[i] || '\n');
675
676           if (operation === '+') {
677             addCount++;
678           } else if (operation === '-') {
679             removeCount++;
680           } else if (operation === ' ') {
681             addCount++;
682             removeCount++;
683           }
684         } else {
685           break;
686         }
687       } // Handle the empty block count case
688
689
690       if (!addCount && hunk.newLines === 1) {
691         hunk.newLines = 0;
692       }
693
694       if (!removeCount && hunk.oldLines === 1) {
695         hunk.oldLines = 0;
696       } // Perform optional sanity checking
697
698
699       if (options.strict) {
700         if (addCount !== hunk.newLines) {
701           throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
702         }
703
704         if (removeCount !== hunk.oldLines) {
705           throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
706         }
707       }
708
709       return hunk;
710     }
711
712     while (i < diffstr.length) {
713       parseIndex();
714     }
715
716     return list;
717   }
718
719   // Iterator that traverses in the range of [min, max], stepping
720   // by distance from a given start position. I.e. for [0, 4], with
721   // start of 2, this will iterate 2, 3, 1, 4, 0.
722   function distanceIterator (start, minLine, maxLine) {
723     var wantForward = true,
724         backwardExhausted = false,
725         forwardExhausted = false,
726         localOffset = 1;
727     return function iterator() {
728       if (wantForward && !forwardExhausted) {
729         if (backwardExhausted) {
730           localOffset++;
731         } else {
732           wantForward = false;
733         } // Check if trying to fit beyond text length, and if not, check it fits
734         // after offset location (or desired location on first iteration)
735
736
737         if (start + localOffset <= maxLine) {
738           return localOffset;
739         }
740
741         forwardExhausted = true;
742       }
743
744       if (!backwardExhausted) {
745         if (!forwardExhausted) {
746           wantForward = true;
747         } // Check if trying to fit before text beginning, and if not, check it fits
748         // before offset location
749
750
751         if (minLine <= start - localOffset) {
752           return -localOffset++;
753         }
754
755         backwardExhausted = true;
756         return iterator();
757       } // We tried to fit hunk before text beginning and beyond text length, then
758       // hunk can't fit on the text. Return undefined
759
760     };
761   }
762
763   function applyPatch(source, uniDiff) {
764     var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
765
766     if (typeof uniDiff === 'string') {
767       uniDiff = parsePatch(uniDiff);
768     }
769
770     if (Array.isArray(uniDiff)) {
771       if (uniDiff.length > 1) {
772         throw new Error('applyPatch only works with a single input.');
773       }
774
775       uniDiff = uniDiff[0];
776     } // Apply the diff to the input
777
778
779     var lines = source.split(/\r\n|[\n\v\f\r\x85]/),
780         delimiters = source.match(/\r\n|[\n\v\f\r\x85]/g) || [],
781         hunks = uniDiff.hunks,
782         compareLine = options.compareLine || function (lineNumber, line, operation, patchContent) {
783       return line === patchContent;
784     },
785         errorCount = 0,
786         fuzzFactor = options.fuzzFactor || 0,
787         minLine = 0,
788         offset = 0,
789         removeEOFNL,
790         addEOFNL;
791     /**
792      * Checks if the hunk exactly fits on the provided location
793      */
794
795
796     function hunkFits(hunk, toPos) {
797       for (var j = 0; j < hunk.lines.length; j++) {
798         var line = hunk.lines[j],
799             operation = line.length > 0 ? line[0] : ' ',
800             content = line.length > 0 ? line.substr(1) : line;
801
802         if (operation === ' ' || operation === '-') {
803           // Context sanity check
804           if (!compareLine(toPos + 1, lines[toPos], operation, content)) {
805             errorCount++;
806
807             if (errorCount > fuzzFactor) {
808               return false;
809             }
810           }
811
812           toPos++;
813         }
814       }
815
816       return true;
817     } // Search best fit offsets for each hunk based on the previous ones
818
819
820     for (var i = 0; i < hunks.length; i++) {
821       var hunk = hunks[i],
822           maxLine = lines.length - hunk.oldLines,
823           localOffset = 0,
824           toPos = offset + hunk.oldStart - 1;
825       var iterator = distanceIterator(toPos, minLine, maxLine);
826
827       for (; localOffset !== undefined; localOffset = iterator()) {
828         if (hunkFits(hunk, toPos + localOffset)) {
829           hunk.offset = offset += localOffset;
830           break;
831         }
832       }
833
834       if (localOffset === undefined) {
835         return false;
836       } // Set lower text limit to end of the current hunk, so next ones don't try
837       // to fit over already patched text
838
839
840       minLine = hunk.offset + hunk.oldStart + hunk.oldLines;
841     } // Apply patch hunks
842
843
844     var diffOffset = 0;
845
846     for (var _i = 0; _i < hunks.length; _i++) {
847       var _hunk = hunks[_i],
848           _toPos = _hunk.oldStart + _hunk.offset + diffOffset - 1;
849
850       diffOffset += _hunk.newLines - _hunk.oldLines;
851
852       if (_toPos < 0) {
853         // Creating a new file
854         _toPos = 0;
855       }
856
857       for (var j = 0; j < _hunk.lines.length; j++) {
858         var line = _hunk.lines[j],
859             operation = line.length > 0 ? line[0] : ' ',
860             content = line.length > 0 ? line.substr(1) : line,
861             delimiter = _hunk.linedelimiters[j];
862
863         if (operation === ' ') {
864           _toPos++;
865         } else if (operation === '-') {
866           lines.splice(_toPos, 1);
867           delimiters.splice(_toPos, 1);
868           /* istanbul ignore else */
869         } else if (operation === '+') {
870           lines.splice(_toPos, 0, content);
871           delimiters.splice(_toPos, 0, delimiter);
872           _toPos++;
873         } else if (operation === '\\') {
874           var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null;
875
876           if (previousOperation === '+') {
877             removeEOFNL = true;
878           } else if (previousOperation === '-') {
879             addEOFNL = true;
880           }
881         }
882       }
883     } // Handle EOFNL insertion/removal
884
885
886     if (removeEOFNL) {
887       while (!lines[lines.length - 1]) {
888         lines.pop();
889         delimiters.pop();
890       }
891     } else if (addEOFNL) {
892       lines.push('');
893       delimiters.push('\n');
894     }
895
896     for (var _k = 0; _k < lines.length - 1; _k++) {
897       lines[_k] = lines[_k] + delimiters[_k];
898     }
899
900     return lines.join('');
901   } // Wrapper that supports multiple file patches via callbacks.
902
903   function applyPatches(uniDiff, options) {
904     if (typeof uniDiff === 'string') {
905       uniDiff = parsePatch(uniDiff);
906     }
907
908     var currentIndex = 0;
909
910     function processIndex() {
911       var index = uniDiff[currentIndex++];
912
913       if (!index) {
914         return options.complete();
915       }
916
917       options.loadFile(index, function (err, data) {
918         if (err) {
919           return options.complete(err);
920         }
921
922         var updatedContent = applyPatch(data, index, options);
923         options.patched(index, updatedContent, function (err) {
924           if (err) {
925             return options.complete(err);
926           }
927
928           processIndex();
929         });
930       });
931     }
932
933     processIndex();
934   }
935
936   function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
937     if (!options) {
938       options = {};
939     }
940
941     if (typeof options.context === 'undefined') {
942       options.context = 4;
943     }
944
945     var diff = diffLines(oldStr, newStr, options);
946     diff.push({
947       value: '',
948       lines: []
949     }); // Append an empty value to make cleanup easier
950
951     function contextLines(lines) {
952       return lines.map(function (entry) {
953         return ' ' + entry;
954       });
955     }
956
957     var hunks = [];
958     var oldRangeStart = 0,
959         newRangeStart = 0,
960         curRange = [],
961         oldLine = 1,
962         newLine = 1;
963
964     var _loop = function _loop(i) {
965       var current = diff[i],
966           lines = current.lines || current.value.replace(/\n$/, '').split('\n');
967       current.lines = lines;
968
969       if (current.added || current.removed) {
970         var _curRange;
971
972         // If we have previous context, start with that
973         if (!oldRangeStart) {
974           var prev = diff[i - 1];
975           oldRangeStart = oldLine;
976           newRangeStart = newLine;
977
978           if (prev) {
979             curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : [];
980             oldRangeStart -= curRange.length;
981             newRangeStart -= curRange.length;
982           }
983         } // Output our changes
984
985
986         (_curRange = curRange).push.apply(_curRange, _toConsumableArray(lines.map(function (entry) {
987           return (current.added ? '+' : '-') + entry;
988         }))); // Track the updated file position
989
990
991         if (current.added) {
992           newLine += lines.length;
993         } else {
994           oldLine += lines.length;
995         }
996       } else {
997         // Identical context lines. Track line changes
998         if (oldRangeStart) {
999           // Close out any changes that have been output (or join overlapping)
1000           if (lines.length <= options.context * 2 && i < diff.length - 2) {
1001             var _curRange2;
1002
1003             // Overlapping
1004             (_curRange2 = curRange).push.apply(_curRange2, _toConsumableArray(contextLines(lines)));
1005           } else {
1006             var _curRange3;
1007
1008             // end the range and output
1009             var contextSize = Math.min(lines.length, options.context);
1010
1011             (_curRange3 = curRange).push.apply(_curRange3, _toConsumableArray(contextLines(lines.slice(0, contextSize))));
1012
1013             var hunk = {
1014               oldStart: oldRangeStart,
1015               oldLines: oldLine - oldRangeStart + contextSize,
1016               newStart: newRangeStart,
1017               newLines: newLine - newRangeStart + contextSize,
1018               lines: curRange
1019             };
1020
1021             if (i >= diff.length - 2 && lines.length <= options.context) {
1022               // EOF is inside this hunk
1023               var oldEOFNewline = /\n$/.test(oldStr);
1024               var newEOFNewline = /\n$/.test(newStr);
1025               var noNlBeforeAdds = lines.length == 0 && curRange.length > hunk.oldLines;
1026
1027               if (!oldEOFNewline && noNlBeforeAdds) {
1028                 // special case: old has no eol and no trailing context; no-nl can end up before adds
1029                 curRange.splice(hunk.oldLines, 0, '\\ No newline at end of file');
1030               }
1031
1032               if (!oldEOFNewline && !noNlBeforeAdds || !newEOFNewline) {
1033                 curRange.push('\\ No newline at end of file');
1034               }
1035             }
1036
1037             hunks.push(hunk);
1038             oldRangeStart = 0;
1039             newRangeStart = 0;
1040             curRange = [];
1041           }
1042         }
1043
1044         oldLine += lines.length;
1045         newLine += lines.length;
1046       }
1047     };
1048
1049     for (var i = 0; i < diff.length; i++) {
1050       _loop(i);
1051     }
1052
1053     return {
1054       oldFileName: oldFileName,
1055       newFileName: newFileName,
1056       oldHeader: oldHeader,
1057       newHeader: newHeader,
1058       hunks: hunks
1059     };
1060   }
1061   function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
1062     var diff = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
1063     var ret = [];
1064
1065     if (oldFileName == newFileName) {
1066       ret.push('Index: ' + oldFileName);
1067     }
1068
1069     ret.push('===================================================================');
1070     ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader));
1071     ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader));
1072
1073     for (var i = 0; i < diff.hunks.length; i++) {
1074       var hunk = diff.hunks[i];
1075       ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@');
1076       ret.push.apply(ret, hunk.lines);
1077     }
1078
1079     return ret.join('\n') + '\n';
1080   }
1081   function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) {
1082     return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options);
1083   }
1084
1085   function arrayEqual(a, b) {
1086     if (a.length !== b.length) {
1087       return false;
1088     }
1089
1090     return arrayStartsWith(a, b);
1091   }
1092   function arrayStartsWith(array, start) {
1093     if (start.length > array.length) {
1094       return false;
1095     }
1096
1097     for (var i = 0; i < start.length; i++) {
1098       if (start[i] !== array[i]) {
1099         return false;
1100       }
1101     }
1102
1103     return true;
1104   }
1105
1106   function calcLineCount(hunk) {
1107     var _calcOldNewLineCount = calcOldNewLineCount(hunk.lines),
1108         oldLines = _calcOldNewLineCount.oldLines,
1109         newLines = _calcOldNewLineCount.newLines;
1110
1111     if (oldLines !== undefined) {
1112       hunk.oldLines = oldLines;
1113     } else {
1114       delete hunk.oldLines;
1115     }
1116
1117     if (newLines !== undefined) {
1118       hunk.newLines = newLines;
1119     } else {
1120       delete hunk.newLines;
1121     }
1122   }
1123   function merge(mine, theirs, base) {
1124     mine = loadPatch(mine, base);
1125     theirs = loadPatch(theirs, base);
1126     var ret = {}; // For index we just let it pass through as it doesn't have any necessary meaning.
1127     // Leaving sanity checks on this to the API consumer that may know more about the
1128     // meaning in their own context.
1129
1130     if (mine.index || theirs.index) {
1131       ret.index = mine.index || theirs.index;
1132     }
1133
1134     if (mine.newFileName || theirs.newFileName) {
1135       if (!fileNameChanged(mine)) {
1136         // No header or no change in ours, use theirs (and ours if theirs does not exist)
1137         ret.oldFileName = theirs.oldFileName || mine.oldFileName;
1138         ret.newFileName = theirs.newFileName || mine.newFileName;
1139         ret.oldHeader = theirs.oldHeader || mine.oldHeader;
1140         ret.newHeader = theirs.newHeader || mine.newHeader;
1141       } else if (!fileNameChanged(theirs)) {
1142         // No header or no change in theirs, use ours
1143         ret.oldFileName = mine.oldFileName;
1144         ret.newFileName = mine.newFileName;
1145         ret.oldHeader = mine.oldHeader;
1146         ret.newHeader = mine.newHeader;
1147       } else {
1148         // Both changed... figure it out
1149         ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName);
1150         ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName);
1151         ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader);
1152         ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader);
1153       }
1154     }
1155
1156     ret.hunks = [];
1157     var mineIndex = 0,
1158         theirsIndex = 0,
1159         mineOffset = 0,
1160         theirsOffset = 0;
1161
1162     while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) {
1163       var mineCurrent = mine.hunks[mineIndex] || {
1164         oldStart: Infinity
1165       },
1166           theirsCurrent = theirs.hunks[theirsIndex] || {
1167         oldStart: Infinity
1168       };
1169
1170       if (hunkBefore(mineCurrent, theirsCurrent)) {
1171         // This patch does not overlap with any of the others, yay.
1172         ret.hunks.push(cloneHunk(mineCurrent, mineOffset));
1173         mineIndex++;
1174         theirsOffset += mineCurrent.newLines - mineCurrent.oldLines;
1175       } else if (hunkBefore(theirsCurrent, mineCurrent)) {
1176         // This patch does not overlap with any of the others, yay.
1177         ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset));
1178         theirsIndex++;
1179         mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines;
1180       } else {
1181         // Overlap, merge as best we can
1182         var mergedHunk = {
1183           oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart),
1184           oldLines: 0,
1185           newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset),
1186           newLines: 0,
1187           lines: []
1188         };
1189         mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines);
1190         theirsIndex++;
1191         mineIndex++;
1192         ret.hunks.push(mergedHunk);
1193       }
1194     }
1195
1196     return ret;
1197   }
1198
1199   function loadPatch(param, base) {
1200     if (typeof param === 'string') {
1201       if (/^@@/m.test(param) || /^Index:/m.test(param)) {
1202         return parsePatch(param)[0];
1203       }
1204
1205       if (!base) {
1206         throw new Error('Must provide a base reference or pass in a patch');
1207       }
1208
1209       return structuredPatch(undefined, undefined, base, param);
1210     }
1211
1212     return param;
1213   }
1214
1215   function fileNameChanged(patch) {
1216     return patch.newFileName && patch.newFileName !== patch.oldFileName;
1217   }
1218
1219   function selectField(index, mine, theirs) {
1220     if (mine === theirs) {
1221       return mine;
1222     } else {
1223       index.conflict = true;
1224       return {
1225         mine: mine,
1226         theirs: theirs
1227       };
1228     }
1229   }
1230
1231   function hunkBefore(test, check) {
1232     return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart;
1233   }
1234
1235   function cloneHunk(hunk, offset) {
1236     return {
1237       oldStart: hunk.oldStart,
1238       oldLines: hunk.oldLines,
1239       newStart: hunk.newStart + offset,
1240       newLines: hunk.newLines,
1241       lines: hunk.lines
1242     };
1243   }
1244
1245   function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) {
1246     // This will generally result in a conflicted hunk, but there are cases where the context
1247     // is the only overlap where we can successfully merge the content here.
1248     var mine = {
1249       offset: mineOffset,
1250       lines: mineLines,
1251       index: 0
1252     },
1253         their = {
1254       offset: theirOffset,
1255       lines: theirLines,
1256       index: 0
1257     }; // Handle any leading content
1258
1259     insertLeading(hunk, mine, their);
1260     insertLeading(hunk, their, mine); // Now in the overlap content. Scan through and select the best changes from each.
1261
1262     while (mine.index < mine.lines.length && their.index < their.lines.length) {
1263       var mineCurrent = mine.lines[mine.index],
1264           theirCurrent = their.lines[their.index];
1265
1266       if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) {
1267         // Both modified ...
1268         mutualChange(hunk, mine, their);
1269       } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') {
1270         var _hunk$lines;
1271
1272         // Mine inserted
1273         (_hunk$lines = hunk.lines).push.apply(_hunk$lines, _toConsumableArray(collectChange(mine)));
1274       } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') {
1275         var _hunk$lines2;
1276
1277         // Theirs inserted
1278         (_hunk$lines2 = hunk.lines).push.apply(_hunk$lines2, _toConsumableArray(collectChange(their)));
1279       } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') {
1280         // Mine removed or edited
1281         removal(hunk, mine, their);
1282       } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') {
1283         // Their removed or edited
1284         removal(hunk, their, mine, true);
1285       } else if (mineCurrent === theirCurrent) {
1286         // Context identity
1287         hunk.lines.push(mineCurrent);
1288         mine.index++;
1289         their.index++;
1290       } else {
1291         // Context mismatch
1292         conflict(hunk, collectChange(mine), collectChange(their));
1293       }
1294     } // Now push anything that may be remaining
1295
1296
1297     insertTrailing(hunk, mine);
1298     insertTrailing(hunk, their);
1299     calcLineCount(hunk);
1300   }
1301
1302   function mutualChange(hunk, mine, their) {
1303     var myChanges = collectChange(mine),
1304         theirChanges = collectChange(their);
1305
1306     if (allRemoves(myChanges) && allRemoves(theirChanges)) {
1307       // Special case for remove changes that are supersets of one another
1308       if (arrayStartsWith(myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) {
1309         var _hunk$lines3;
1310
1311         (_hunk$lines3 = hunk.lines).push.apply(_hunk$lines3, _toConsumableArray(myChanges));
1312
1313         return;
1314       } else if (arrayStartsWith(theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) {
1315         var _hunk$lines4;
1316
1317         (_hunk$lines4 = hunk.lines).push.apply(_hunk$lines4, _toConsumableArray(theirChanges));
1318
1319         return;
1320       }
1321     } else if (arrayEqual(myChanges, theirChanges)) {
1322       var _hunk$lines5;
1323
1324       (_hunk$lines5 = hunk.lines).push.apply(_hunk$lines5, _toConsumableArray(myChanges));
1325
1326       return;
1327     }
1328
1329     conflict(hunk, myChanges, theirChanges);
1330   }
1331
1332   function removal(hunk, mine, their, swap) {
1333     var myChanges = collectChange(mine),
1334         theirChanges = collectContext(their, myChanges);
1335
1336     if (theirChanges.merged) {
1337       var _hunk$lines6;
1338
1339       (_hunk$lines6 = hunk.lines).push.apply(_hunk$lines6, _toConsumableArray(theirChanges.merged));
1340     } else {
1341       conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges);
1342     }
1343   }
1344
1345   function conflict(hunk, mine, their) {
1346     hunk.conflict = true;
1347     hunk.lines.push({
1348       conflict: true,
1349       mine: mine,
1350       theirs: their
1351     });
1352   }
1353
1354   function insertLeading(hunk, insert, their) {
1355     while (insert.offset < their.offset && insert.index < insert.lines.length) {
1356       var line = insert.lines[insert.index++];
1357       hunk.lines.push(line);
1358       insert.offset++;
1359     }
1360   }
1361
1362   function insertTrailing(hunk, insert) {
1363     while (insert.index < insert.lines.length) {
1364       var line = insert.lines[insert.index++];
1365       hunk.lines.push(line);
1366     }
1367   }
1368
1369   function collectChange(state) {
1370     var ret = [],
1371         operation = state.lines[state.index][0];
1372
1373     while (state.index < state.lines.length) {
1374       var line = state.lines[state.index]; // Group additions that are immediately after subtractions and treat them as one "atomic" modify change.
1375
1376       if (operation === '-' && line[0] === '+') {
1377         operation = '+';
1378       }
1379
1380       if (operation === line[0]) {
1381         ret.push(line);
1382         state.index++;
1383       } else {
1384         break;
1385       }
1386     }
1387
1388     return ret;
1389   }
1390
1391   function collectContext(state, matchChanges) {
1392     var changes = [],
1393         merged = [],
1394         matchIndex = 0,
1395         contextChanges = false,
1396         conflicted = false;
1397
1398     while (matchIndex < matchChanges.length && state.index < state.lines.length) {
1399       var change = state.lines[state.index],
1400           match = matchChanges[matchIndex]; // Once we've hit our add, then we are done
1401
1402       if (match[0] === '+') {
1403         break;
1404       }
1405
1406       contextChanges = contextChanges || change[0] !== ' ';
1407       merged.push(match);
1408       matchIndex++; // Consume any additions in the other block as a conflict to attempt
1409       // to pull in the remaining context after this
1410
1411       if (change[0] === '+') {
1412         conflicted = true;
1413
1414         while (change[0] === '+') {
1415           changes.push(change);
1416           change = state.lines[++state.index];
1417         }
1418       }
1419
1420       if (match.substr(1) === change.substr(1)) {
1421         changes.push(change);
1422         state.index++;
1423       } else {
1424         conflicted = true;
1425       }
1426     }
1427
1428     if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) {
1429       conflicted = true;
1430     }
1431
1432     if (conflicted) {
1433       return changes;
1434     }
1435
1436     while (matchIndex < matchChanges.length) {
1437       merged.push(matchChanges[matchIndex++]);
1438     }
1439
1440     return {
1441       merged: merged,
1442       changes: changes
1443     };
1444   }
1445
1446   function allRemoves(changes) {
1447     return changes.reduce(function (prev, change) {
1448       return prev && change[0] === '-';
1449     }, true);
1450   }
1451
1452   function skipRemoveSuperset(state, removeChanges, delta) {
1453     for (var i = 0; i < delta; i++) {
1454       var changeContent = removeChanges[removeChanges.length - delta + i].substr(1);
1455
1456       if (state.lines[state.index + i] !== ' ' + changeContent) {
1457         return false;
1458       }
1459     }
1460
1461     state.index += delta;
1462     return true;
1463   }
1464
1465   function calcOldNewLineCount(lines) {
1466     var oldLines = 0;
1467     var newLines = 0;
1468     lines.forEach(function (line) {
1469       if (typeof line !== 'string') {
1470         var myCount = calcOldNewLineCount(line.mine);
1471         var theirCount = calcOldNewLineCount(line.theirs);
1472
1473         if (oldLines !== undefined) {
1474           if (myCount.oldLines === theirCount.oldLines) {
1475             oldLines += myCount.oldLines;
1476           } else {
1477             oldLines = undefined;
1478           }
1479         }
1480
1481         if (newLines !== undefined) {
1482           if (myCount.newLines === theirCount.newLines) {
1483             newLines += myCount.newLines;
1484           } else {
1485             newLines = undefined;
1486           }
1487         }
1488       } else {
1489         if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) {
1490           newLines++;
1491         }
1492
1493         if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) {
1494           oldLines++;
1495         }
1496       }
1497     });
1498     return {
1499       oldLines: oldLines,
1500       newLines: newLines
1501     };
1502   }
1503
1504   // See: http://code.google.com/p/google-diff-match-patch/wiki/API
1505   function convertChangesToDMP(changes) {
1506     var ret = [],
1507         change,
1508         operation;
1509
1510     for (var i = 0; i < changes.length; i++) {
1511       change = changes[i];
1512
1513       if (change.added) {
1514         operation = 1;
1515       } else if (change.removed) {
1516         operation = -1;
1517       } else {
1518         operation = 0;
1519       }
1520
1521       ret.push([operation, change.value]);
1522     }
1523
1524     return ret;
1525   }
1526
1527   function convertChangesToXML(changes) {
1528     var ret = [];
1529
1530     for (var i = 0; i < changes.length; i++) {
1531       var change = changes[i];
1532
1533       if (change.added) {
1534         ret.push('<ins>');
1535       } else if (change.removed) {
1536         ret.push('<del>');
1537       }
1538
1539       ret.push(escapeHTML(change.value));
1540
1541       if (change.added) {
1542         ret.push('</ins>');
1543       } else if (change.removed) {
1544         ret.push('</del>');
1545       }
1546     }
1547
1548     return ret.join('');
1549   }
1550
1551   function escapeHTML(s) {
1552     var n = s;
1553     n = n.replace(/&/g, '&amp;');
1554     n = n.replace(/</g, '&lt;');
1555     n = n.replace(/>/g, '&gt;');
1556     n = n.replace(/"/g, '&quot;');
1557     return n;
1558   }
1559
1560   /* See LICENSE file for terms of use */
1561
1562   exports.Diff = Diff;
1563   exports.diffChars = diffChars;
1564   exports.diffWords = diffWords;
1565   exports.diffWordsWithSpace = diffWordsWithSpace;
1566   exports.diffLines = diffLines;
1567   exports.diffTrimmedLines = diffTrimmedLines;
1568   exports.diffSentences = diffSentences;
1569   exports.diffCss = diffCss;
1570   exports.diffJson = diffJson;
1571   exports.diffArrays = diffArrays;
1572   exports.structuredPatch = structuredPatch;
1573   exports.createTwoFilesPatch = createTwoFilesPatch;
1574   exports.createPatch = createPatch;
1575   exports.applyPatch = applyPatch;
1576   exports.applyPatches = applyPatches;
1577   exports.parsePatch = parsePatch;
1578   exports.merge = merge;
1579   exports.convertChangesToDMP = convertChangesToDMP;
1580   exports.convertChangesToXML = convertChangesToXML;
1581   exports.canonicalize = canonicalize;
1582
1583   Object.defineProperty(exports, '__esModule', { value: true });
1584
1585 }));