| 
					
				 | 
			
			
				@@ -0,0 +1,776 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Author: @jhchen - https://github.com/jhchen 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Modified by: @lucascalion - 23/07/2019 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This library modifies the diff-patch-match library by Neil Fraser 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * by removing the patch and match functionality and certain advanced 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * options in the diff function. The original license is as follows: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * === 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Diff Match and Patch 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Copyright 2006 Google Inc. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * http://code.google.com/p/google-diff-match-patch/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Licensed under the Apache License, Version 2.0 (the "License"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * you may not use this file except in compliance with the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * You may obtain a copy of the License at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   http://www.apache.org/licenses/LICENSE-2.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Unless required by applicable law or agreed to in writing, software 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * distributed under the License is distributed on an "AS IS" BASIS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * See the License for the specific language governing permissions and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * limitations under the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * The data structure representing a diff is an array of tuples: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * which means: delete 'Hello', add 'Goodbye' and keep ' world.' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const DIFF_DELETE = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const DIFF_INSERT = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const DIFF_EQUAL = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Find the differences between two texts.  Simplifies the problem by stripping 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * any common prefix or suffix off the texts before diffing. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text1 Old string to be diffed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text2 New string to be diffed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {Int|Object} [cursor_pos] Edit position in text1 or object with more info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @return {Array} Array of diff tuples. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff_main(text1, text2, cursor_pos, _fix_unicode) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Check for equality 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (text1 === text2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (text1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return [[DIFF_EQUAL, text1]]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (cursor_pos != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const editdiff = find_cursor_edit_diff(text1, text2, cursor_pos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (editdiff) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return editdiff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Trim off common prefix (speedup). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let commonlength = diff_commonPrefix(text1, text2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const commonprefix = text1.substring(0, commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  text1 = text1.substring(commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  text2 = text2.substring(commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Trim off common suffix (speedup). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  commonlength = diff_commonSuffix(text1, text2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const commonsuffix = text1.substring(text1.length - commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  text1 = text1.substring(0, text1.length - commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  text2 = text2.substring(0, text2.length - commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Compute the diff on the middle block. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const diffs = diff_compute_(text1, text2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Restore the prefix and suffix. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (commonprefix) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    diffs.unshift([DIFF_EQUAL, commonprefix]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (commonsuffix) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    diffs.push([DIFF_EQUAL, commonsuffix]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  diff_cleanupMerge(diffs, _fix_unicode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return diffs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Find the differences between two texts.  Assumes that the texts do not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * have any common prefix or suffix. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text1 Old string to be diffed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text2 New string to be diffed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @return {Array} Array of diff tuples. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff_compute_(text1, text2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let diffs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!text1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Just add some text (speedup). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return [[DIFF_INSERT, text2]]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!text2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Just delete some text (speedup). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return [[DIFF_DELETE, text1]]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const longtext = text1.length > text2.length ? text1 : text2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const shorttext = text1.length > text2.length ? text2 : text1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const i = longtext.indexOf(shorttext); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (i !== -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Shorter text is inside the longer text (speedup). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    diffs = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      [DIFF_INSERT, longtext.substring(0, i)], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      [DIFF_EQUAL, shorttext], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      [DIFF_INSERT, longtext.substring(i + shorttext.length)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Swap insertions for deletions if diff is reversed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (text1.length > text2.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      diffs[0][0] = diffs[2][0] = DIFF_DELETE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return diffs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (shorttext.length === 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Single character string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // After the previous speedup, the character can't be an equality. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Check to see if the problem can be split in two. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  var hm = diff_halfMatch_(text1, text2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (hm) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // A half-match was found, sort out the return data. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var text1_a = hm[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var text1_b = hm[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var text2_a = hm[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var text2_b = hm[3]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var mid_common = hm[4]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Send both pairs off for separate processing. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var diffs_a = diff_main(text1_a, text2_a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var diffs_b = diff_main(text1_b, text2_b); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Merge the results. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return diff_bisect_(text1, text2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Find the 'middle snake' of a diff, split the problem in two 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * and return the recursively constructed diff. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text1 Old string to be diffed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text2 New string to be diffed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @return {Array} Array of diff tuples. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @private 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff_bisect_(text1, text2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Cache the text lengths to prevent multiple calls. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const text1_length = text1.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const text2_length = text2.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const max_d = Math.ceil((text1_length + text2_length) / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const v_offset = max_d; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const v_length = 2 * max_d; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const v1 = new Array(v_length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const v2 = new Array(v_length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Setting all elements to -1 is faster in Chrome & Firefox than mixing 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // integers and undefined. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (var x = 0; x < v_length; x++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    v1[x] = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    v2[x] = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  v1[v_offset + 1] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  v2[v_offset + 1] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const delta = text1_length - text2_length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // If the total number of characters is odd, then the front path will collide 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // with the reverse path. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const front = (delta % 2 !== 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Offsets for start and end of k loop. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Prevents mapping of space beyond the grid. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let k1start = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let k1end = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let k2start = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let k2end = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (let d = 0; d < max_d; d++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Walk the front path one step. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let k1 = -d + k1start; k1 <= d - k1end; k1 += 2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const k1_offset = v_offset + k1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let x1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (k1 === -d || (k1 !== d && v1[k1_offset - 1] < v1[k1_offset + 1])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x1 = v1[k1_offset + 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x1 = v1[k1_offset - 1] + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let y1 = x1 - k1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      while ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x1 < text1_length && y1 < text2_length && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        text1.charAt(x1) === text2.charAt(y1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x1++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        y1++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      v1[k1_offset] = x1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (x1 > text1_length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Ran off the right of the graph. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        k1end += 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (y1 > text2_length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Ran off the bottom of the graph. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        k1start += 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (front) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const k2_offset = v_offset + delta - k1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] !== -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // Mirror x2 onto top-left coordinate system. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const x2 = text1_length - v2[k2_offset]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (x1 >= x2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Overlap detfrontected. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return diff_bisectSplit_(text1, text2, x1, y1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Walk the reverse path one step. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let k2 = -d + k2start; k2 <= d - k2end; k2 += 2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const k2_offset = v_offset + k2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let x2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (k2 === -d || (k2 !== d && v2[k2_offset - 1] < v2[k2_offset + 1])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x2 = v2[k2_offset + 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x2 = v2[k2_offset - 1] + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let y2 = x2 - k2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      while ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x2 < text1_length && y2 < text2_length && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        text1.charAt(text1_length - x2 - 1) === text2.charAt(text2_length - y2 - 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x2++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        y2++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      v2[k2_offset] = x2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (x2 > text1_length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Ran off the left of the graph. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        k2end += 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (y2 > text2_length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Ran off the top of the graph. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        k2start += 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (!front) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const k1_offset = v_offset + delta - k2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] !== -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const x1 = v1[k1_offset]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const y1 = v_offset + x1 - k1_offset; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // Mirror x2 onto top-left coordinate system. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          x2 = text1_length - x2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (x1 >= x2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Overlap detected. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return diff_bisectSplit_(text1, text2, x1, y1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Diff took too long and hit the deadline or 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // number of diffs equals number of characters, no commonality at all. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Given the location of the 'middle snake', split the diff in two parts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * and recurse. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text1 Old string to be diffed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text2 New string to be diffed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {number} x Index of split point in text1. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {number} y Index of split point in text2. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @return {Array} Array of diff tuples. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff_bisectSplit_(text1, text2, x, y) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const text1a = text1.substring(0, x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const text2a = text2.substring(0, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const text1b = text1.substring(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const text2b = text2.substring(y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Compute both diffs serially. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const diffs = diff_main(text1a, text2a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const diffsb = diff_main(text1b, text2b); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return diffs.concat(diffsb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Determine the common prefix of two strings. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text1 First string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text2 Second string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @return {number} The number of characters common to the start of each 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff_commonPrefix(text1, text2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Quick check for common null cases. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Binary search. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Performance analysis: http://neil.fraser.name/news/2007/10/09/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointermin = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointermax = Math.min(text1.length, text2.length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointermid = pointermax; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointerstart = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  while (pointermin < pointermid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      text1.substring(pointerstart, pointermid) == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      text2.substring(pointerstart, pointermid) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      pointermin = pointermid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      pointerstart = pointermin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      pointermax = pointermid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (is_surrogate_pair_start(text1.charCodeAt(pointermid - 1))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pointermid--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return pointermid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Determine the common suffix of two strings. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text1 First string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text2 Second string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @return {number} The number of characters common to the end of each string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff_commonSuffix(text1, text2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Quick check for common null cases. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!text1 || !text2 || text1.slice(-1) !== text2.slice(-1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Binary search. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Performance analysis: http://neil.fraser.name/news/2007/10/09/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointermin = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointermax = Math.min(text1.length, text2.length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointermid = pointermax; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointerend = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  while (pointermin < pointermid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      text1.substring(text1.length - pointermid, text1.length - pointerend) == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      text2.substring(text2.length - pointermid, text2.length - pointerend) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      pointermin = pointermid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      pointerend = pointermin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      pointermax = pointermid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (is_surrogate_pair_end(text1.charCodeAt(text1.length - pointermid))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pointermid--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return pointermid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Do the two texts share a substring which is at least half the length of the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * longer text? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This speedup can produce non-minimal diffs. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text1 First string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {string} text2 Second string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @return {Array.<string>} Five element Array, containing the prefix of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     text1, the suffix of text1, the prefix of text2, the suffix of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     text2 and the common middle.  Or null if there was no match. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff_halfMatch_(text1, text2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const longtext = text1.length > text2.length ? text1 : text2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const shorttext = text1.length > text2.length ? text2 : text1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (longtext.length < 4 || shorttext.length * 2 < longtext.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return null;  // Pointless. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Does a substring of shorttext exist within longtext such that the substring 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * is at least half the length of longtext? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Closure, but does not reference any external variables. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @param {string} longtext Longer string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @param {string} shorttext Shorter string. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @param {number} i Start index of quarter length substring within longtext. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @return {Array.<string>} Five element Array, containing the prefix of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   *     longtext, the suffix of longtext, the prefix of shorttext, the suffix 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   *     of shorttext and the common middle.  Or null if there was no match. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @private 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  function diff_halfMatchI_(longtext, shorttext, i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Start with a 1/4 length substring at position i as a seed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const seed = longtext.substring(i, i + Math.floor(longtext.length / 4)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let j = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let best_common = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while ((j = shorttext.indexOf(seed, j + 1)) !== -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const prefixLength = diff_commonPrefix( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        longtext.substring(i), shorttext.substring(j)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const suffixLength = diff_commonSuffix( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        longtext.substring(0, i), shorttext.substring(0, j)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (best_common.length < suffixLength + prefixLength) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        best_common = shorttext.substring( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          j - suffixLength, j) + shorttext.substring(j, j + prefixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        best_longtext_a = longtext.substring(0, i - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        best_longtext_b = longtext.substring(i + prefixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        best_shorttext_a = shorttext.substring(0, j - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        best_shorttext_b = shorttext.substring(j + prefixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (best_common.length * 2 >= longtext.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        best_longtext_a, best_longtext_b, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        best_shorttext_a, best_shorttext_b, best_common 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // First check if the second quarter is the seed for a half-match. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const hm1 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 4)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Check again based on the third quarter. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const hm2 = diff_halfMatchI_(longtext, shorttext, Math.ceil(longtext.length / 2)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let hm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!hm1 && !hm2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else if (!hm2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    hm = hm1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else if (!hm1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    hm = hm2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Both matched.  Select the longest. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    hm = hm1[4].length > hm2[4].length ? hm1 : hm2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // A half-match was found, sort out the return data. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let text1_a, text1_b, text2_a, text2_b; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (text1.length > text2.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text1_a = hm[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text1_b = hm[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text2_a = hm[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text2_b = hm[3]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text2_a = hm[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text2_b = hm[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text1_a = hm[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text1_b = hm[3]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const mid_common = hm[4]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return [text1_a, text1_b, text2_a, text2_b, mid_common]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Reorder and merge like edit sections.  Merge equalities. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Any edit section can move as long as it doesn't cross an equality. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {Array} diffs Array of diff tuples. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {boolean} fix_unicode Whether to normalize to a unicode-correct diff 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff_cleanupMerge(diffs, fix_unicode) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  diffs.push([DIFF_EQUAL, '']);  // Add a dummy entry at the end. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let pointer = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let count_delete = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let count_insert = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let text_delete = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let text_insert = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let commonlength; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let previous_equality; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  while (pointer < diffs.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (pointer < diffs.length - 1 && !diffs[pointer][1]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      diffs.splice(pointer, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    switch (diffs[pointer][0]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      case DIFF_INSERT: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        count_insert++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        text_insert += diffs[pointer][1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointer++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      case DIFF_DELETE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        count_delete++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        text_delete += diffs[pointer][1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointer++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      case DIFF_EQUAL: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        previous_equality = pointer - count_insert - count_delete - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (fix_unicode) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // prevent splitting of unicode surrogate pairs.  when fix_unicode is true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // we assume that the old and new text in the diff are complete and correct 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // unicode-encoded JS strings, but the tuple boundaries may fall between 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // surrogate pairs.  we fix this by shaving off stray surrogates from the end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // of the previous equality and the beginning of this equality.  this may create 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // empty equalities or a common prefix or suffix.  for example, if AB and AC are 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // emojis, `[[0, 'A'], [-1, 'BA'], [0, 'C']]` would turn into deleting 'ABAC' and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // inserting 'AC', and then the common suffix 'AC' will be eliminated.  in this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // particular case, both equalities go away, we absorb any previous inequalities, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // and we keep scanning for the next equality before rewriting the tuples. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (previous_equality >= 0 && ends_with_pair_start(diffs[previous_equality][1])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const stray = diffs[previous_equality][1].slice(-1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            diffs[previous_equality][1] = diffs[previous_equality][1].slice(0, -1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            text_delete = stray + text_delete; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            text_insert = stray + text_insert; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!diffs[previous_equality][1]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              // emptied out previous equality, so delete it and include previous delete/insert 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              diffs.splice(previous_equality, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              pointer--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              var k = previous_equality - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              if (diffs[k] && diffs[k][0] === DIFF_INSERT) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                count_insert++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                text_insert = diffs[k][1] + text_insert; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                k--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              if (diffs[k] && diffs[k][0] === DIFF_DELETE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                count_delete++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                text_delete = diffs[k][1] + text_delete; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                k--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              previous_equality = k; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (starts_with_pair_end(diffs[pointer][1])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const stray = diffs[pointer][1].charAt(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            diffs[pointer][1] = diffs[pointer][1].slice(1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            text_delete += stray; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            text_insert += stray; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (pointer < diffs.length - 1 && !diffs[pointer][1]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // for empty equality not at end, wait for next equality 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          diffs.splice(pointer, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (text_delete.length > 0 || text_insert.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // note that diff_commonPrefix and diff_commonSuffix are unicode-aware 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (text_delete.length > 0 && text_insert.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Factor out any common prefixes. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            commonlength = diff_commonPrefix(text_insert, text_delete); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (commonlength !== 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              if (previous_equality >= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                diffs[previous_equality][1] += text_insert.substring(0, commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                diffs.splice(0, 0, [DIFF_EQUAL, text_insert.substring(0, commonlength)]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                pointer++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              text_insert = text_insert.substring(commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              text_delete = text_delete.substring(commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Factor out any common suffixes. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            commonlength = diff_commonSuffix(text_insert, text_delete); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (commonlength !== 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              diffs[pointer][1] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                text_insert.substring(text_insert.length - commonlength) + diffs[pointer][1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              text_insert = text_insert.substring(0, text_insert.length - commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              text_delete = text_delete.substring(0, text_delete.length - commonlength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // Delete the offending records and add the merged ones. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const n = count_insert + count_delete; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (text_delete.length === 0 && text_insert.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            diffs.splice(pointer - n, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            pointer = pointer - n; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } else if (text_delete.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            diffs.splice(pointer - n, n, [DIFF_INSERT, text_insert]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            pointer = pointer - n + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } else if (text_insert.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            diffs.splice(pointer - n, n, [DIFF_DELETE, text_delete]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            pointer = pointer - n + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            diffs.splice(pointer - n, n, [DIFF_DELETE, text_delete], [DIFF_INSERT, text_insert]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            pointer = pointer - n + 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // Merge this equality with the previous one. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          diffs[pointer - 1][1] += diffs[pointer][1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          diffs.splice(pointer, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          pointer++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        count_insert = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        count_delete = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        text_delete = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        text_insert = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (diffs[diffs.length - 1][1] === '') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    diffs.pop();  // Remove the dummy entry at the end. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Second pass: look for single edits surrounded on both sides by equalities 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // which can be shifted sideways to eliminate an equality. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  let changes = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  pointer = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Intentionally ignore the first and last element (don't need checking). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  while (pointer < diffs.length - 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (diffs[pointer - 1][0] === DIFF_EQUAL && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      diffs[pointer + 1][0] === DIFF_EQUAL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // This is a single edit surrounded by equalities. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (diffs[pointer][1].substring(diffs[pointer][1].length - 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        diffs[pointer - 1][1].length) === diffs[pointer - 1][1]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Shift the edit over the previous equality. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        diffs[pointer][1] = diffs[pointer - 1][1] + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          diffs[pointer][1].substring(0, diffs[pointer][1].length - 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            diffs[pointer - 1][1].length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        diffs.splice(pointer - 1, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        changes = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        diffs[pointer + 1][1]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Shift the edit over the next equality. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        diffs[pointer - 1][1] += diffs[pointer + 1][1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        diffs[pointer][1] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          diffs[pointer][1].substring(diffs[pointer + 1][1].length) + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          diffs[pointer + 1][1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        diffs.splice(pointer + 1, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        changes = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pointer++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // If shifts were made, the diff needs reordering and another shift sweep. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (changes) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    diff_cleanupMerge(diffs, fix_unicode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function is_surrogate_pair_start(charCode) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return charCode >= 0xD800 && charCode <= 0xDBFF; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function is_surrogate_pair_end(charCode) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return charCode >= 0xDC00 && charCode <= 0xDFFF; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function starts_with_pair_end(str) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return is_surrogate_pair_end(str.charCodeAt(0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function ends_with_pair_start(str) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return is_surrogate_pair_start(str.charCodeAt(str.length - 1)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function remove_empty_tuples(tuples) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const ret = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (let i = 0; i < tuples.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (tuples[i][1].length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ret.push(tuples[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function make_edit_splice(before, oldMiddle, newMiddle, after) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (ends_with_pair_start(before) || starts_with_pair_end(after)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return remove_empty_tuples([ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    [DIFF_EQUAL, before], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    [DIFF_DELETE, oldMiddle], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    [DIFF_INSERT, newMiddle], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    [DIFF_EQUAL, after] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function find_cursor_edit_diff(oldText, newText, cursor_pos) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // note: this runs after equality check has ruled out exact equality 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const oldRange = typeof cursor_pos === 'number' ? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { index: cursor_pos, length: 0 } : cursor_pos.oldRange; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const newRange = typeof cursor_pos === 'number' ? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    null : cursor_pos.newRange; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // take into account the old and new selection to generate the best diff 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // possible for a text edit.  for example, a text change from "xxx" to "xx" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // could be a delete or forwards-delete of any one of the x's, or the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // result of selecting two of the x's and typing "x". 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const oldLength = oldText.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const newLength = newText.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (oldRange.length === 0 && (newRange === null || newRange.length === 0)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // see if we have an insert or delete before or after cursor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const oldCursor = oldRange.index; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const oldBefore = oldText.slice(0, oldCursor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const oldAfter = oldText.slice(oldCursor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const maybeNewCursor = newRange ? newRange.index : null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    editBefore: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // is this an insert or delete right before oldCursor? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newCursor = oldCursor + newLength - oldLength; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (maybeNewCursor !== null && maybeNewCursor !== newCursor) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break editBefore; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (newCursor < 0 || newCursor > newLength) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break editBefore; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newBefore = newText.slice(0, newCursor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newAfter = newText.slice(newCursor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (newAfter !== oldAfter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break editBefore; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const prefixLength = Math.min(oldCursor, newCursor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const oldPrefix = oldBefore.slice(0, prefixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newPrefix = newBefore.slice(0, prefixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (oldPrefix !== newPrefix) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break editBefore; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const oldMiddle = oldBefore.slice(prefixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newMiddle = newBefore.slice(prefixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return make_edit_splice(oldPrefix, oldMiddle, newMiddle, oldAfter); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    editAfter: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // is this an insert or delete right after oldCursor? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (maybeNewCursor !== null && maybeNewCursor !== oldCursor) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break editAfter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const cursor = oldCursor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newBefore = newText.slice(0, cursor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newAfter = newText.slice(cursor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (newBefore !== oldBefore) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break editAfter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const suffixLength = Math.min(oldLength - cursor, newLength - cursor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const oldSuffix = oldAfter.slice(oldAfter.length - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newSuffix = newAfter.slice(newAfter.length - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (oldSuffix !== newSuffix) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break editAfter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const oldMiddle = oldAfter.slice(0, oldAfter.length - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newMiddle = newAfter.slice(0, newAfter.length - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return make_edit_splice(oldBefore, oldMiddle, newMiddle, oldSuffix); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (oldRange.length > 0 && newRange && newRange.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    replaceRange: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // see if diff could be a splice of the old selection range 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const oldPrefix = oldText.slice(0, oldRange.index); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const oldSuffix = oldText.slice(oldRange.index + oldRange.length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const prefixLength = oldPrefix.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const suffixLength = oldSuffix.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (newLength < prefixLength + suffixLength) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break replaceRange; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newPrefix = newText.slice(0, prefixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newSuffix = newText.slice(newLength - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (oldPrefix !== newPrefix || oldSuffix !== newSuffix) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break replaceRange; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const oldMiddle = oldText.slice(prefixLength, oldLength - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const newMiddle = newText.slice(prefixLength, newLength - suffixLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return make_edit_splice(oldPrefix, oldMiddle, newMiddle, oldSuffix); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function diff(text1, text2, cursor_pos) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // only pass fix_unicode=true at the top level, not when diff_main is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // recursively invoked 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return diff_main(text1, text2, cursor_pos, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+diff.INSERT = DIFF_INSERT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+diff.DELETE = DIFF_DELETE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+diff.EQUAL = DIFF_EQUAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+export default diff; 
			 |