/**
 * Diff Match and Patch
 * Copyright 2018 The diff-match-patch Authors.
 * https://github.com/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.
 */ fileoverview author fraser google /**
 * CHANGES by pedrottimark to diff_match_patch_uncompressed.ts file:
 *
 * 1. Delete anything not needed to use diff_cleanupSemantic method
 * 2. Convert from prototype properties to var declarations
 * 3. Convert Diff to class from constructor and prototype
 * 4. Add type annotations for arguments and return values
 * 5. Add exports
 */ /**
 * 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.'
 */ var DIFF_DELETE = - 1 ; var DIFF_INSERT = 1 ; var DIFF_EQUAL = 0 ; param { number } op param { string } text constructor class Diff { 0 : number ; 1 : string ; constructor ( op , text ) { this [ 0 ] = op ; this [ 1 ] = text ; } } param { string } text1 param { string } text2 return { number } var diff_commonPrefix = function ( text1 , text2 ) : number { if ( ! text1 || ! text2 || text1 . charAt ( 0 ) != text2 . charAt ( 0 ) ) { return 0 ; } var pointermin = 0 ; var pointermax = Math . min ( text1 . length , text2 . length ) ; var pointermid = pointermax ; var 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 ) ; } return pointermid ; } ; param { string } text1 param { string } text2 return { number } var diff_commonSuffix = function ( text1 , text2 ) : number { if ( ! text1 || ! text2 || text1 . charAt ( text1 . length - 1 ) != text2 . charAt ( text2 . length - 1 ) ) { return 0 ; } var pointermin = 0 ; var pointermax = Math . min ( text1 . length , text2 . length ) ; var pointermid = pointermax ; var 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 ) ; } return pointermid ; } ; param { string } text1 param { string } text2 return { number } private var diff_commonOverlap_ = function ( text1 , text2 ) : number { var text1_length = text1 . length ; var text2_length = text2 . length ; if ( text1_length == 0 || text2_length == 0 ) { return 0 ; } if ( text1_length > text2_length ) { text1 = text1 . substring ( text1_length - text2_length ) ; } else if ( text1_length < text2_length ) { text2 = text2 . substring ( 0 , text1_length ) ; } var text_length = Math . min ( text1_length , text2_length ) ; if ( text1 == text2 ) { return text_length ; } var best = 0 ; var length = 1 ; while ( true ) { var pattern = text1 . substring ( text_length - length ) ; var found = text2 . indexOf ( pattern ) ; if ( found == - 1 ) { return best ; } length += found ; if ( found == 0 || text1 . substring ( text_length - length ) == text2 . substring ( 0 , length ) ) { best = length ; length ++ ; } } } ; param { ! Array . < ! diff_match_patch . Diff > } diffs var diff_cleanupSemantic = function ( diffs ) { var changes = false ; var equalities = [ ] ; var equalitiesLength = 0 ; type { ? string } var lastEquality = null ; var pointer = 0 ; var length_insertions1 = 0 ; var length_deletions1 = 0 ; var length_insertions2 = 0 ; var length_deletions2 = 0 ; while ( pointer < diffs . length ) { if ( diffs [ pointer ] [ 0 ] == DIFF_EQUAL ) { equalities [ equalitiesLength ++ ] = pointer ; length_insertions1 = length_insertions2 ; length_deletions1 = length_deletions2 ; length_insertions2 = 0 ; length_deletions2 = 0 ; lastEquality = diffs [ pointer ] [ 1 ] ; } else { if ( diffs [ pointer ] [ 0 ] == DIFF_INSERT ) { length_insertions2 += diffs [ pointer ] [ 1 ] . length ; } else { length_deletions2 += diffs [ pointer ] [ 1 ] . length ; } if ( lastEquality && lastEquality . length <= Math . max ( length_insertions1 , length_deletions1 ) && lastEquality . length <= Math . max ( length_insertions2 , length_deletions2 ) ) { diffs . splice ( equalities [ equalitiesLength - 1 ] , 0 , new Diff ( DIFF_DELETE , lastEquality ) ) ; diffs [ equalities [ equalitiesLength - 1 ] + 1 ] [ 0 ] = DIFF_INSERT ; equalitiesLength -- ; equalitiesLength -- ; pointer = equalitiesLength > 0 ? equalities [ equalitiesLength - 1 ] : - 1 ; length_insertions1 = 0 ; length_deletions1 = 0 ; length_insertions2 = 0 ; length_deletions2 = 0 ; lastEquality = null ; changes = true ; } } pointer ++ ; } if ( changes ) { diff_cleanupMerge ( diffs ) ; } diff_cleanupSemanticLossless ( diffs ) ; pointer = 1 ; while ( pointer < diffs . length ) { if ( diffs [ pointer - 1 ] [ 0 ] == DIFF_DELETE && diffs [ pointer ] [ 0 ] == DIFF_INSERT ) { var deletion = diffs [ pointer - 1 ] [ 1 ] ; var insertion = diffs [ pointer ] [ 1 ] ; var overlap_length1 = diff_commonOverlap_ ( deletion , insertion ) ; var overlap_length2 = diff_commonOverlap_ ( insertion , deletion ) ; if ( overlap_length1 >= overlap_length2 ) { if ( overlap_length1 >= deletion . length / 2 || overlap_length1 >= insertion . length / 2 ) { diffs . splice ( pointer , 0 , new Diff ( DIFF_EQUAL , insertion . substring ( 0 , overlap_length1 ) ) ) ; diffs [ pointer - 1 ] [ 1 ] = deletion . substring ( 0 , deletion . length - overlap_length1 ) ; diffs [ pointer + 1 ] [ 1 ] = insertion . substring ( overlap_length1 ) ; pointer ++ ; } } else { if ( overlap_length2 >= deletion . length / 2 || overlap_length2 >= insertion . length / 2 ) { diffs . splice ( pointer , 0 , new Diff ( DIFF_EQUAL , deletion . substring ( 0 , overlap_length2 ) ) ) ; diffs [ pointer - 1 ] [ 0 ] = DIFF_INSERT ; diffs [ pointer - 1 ] [ 1 ] = insertion . substring ( 0 , insertion . length - overlap_length2 ) ; diffs [ pointer + 1 ] [ 0 ] = DIFF_DELETE ; diffs [ pointer + 1 ] [ 1 ] = deletion . substring ( overlap_length2 ) ; pointer ++ ; } } pointer ++ ; } pointer ++ ; } } ; param { ! Array . < ! diff_match_patch . Diff > } diffs var diff_cleanupSemanticLossless = function ( diffs ) { param { string } one param { string } two return { number } private function diff_cleanupSemanticScore_ ( one , two ) { if ( ! one || ! two ) { return 6 ; } var char1 = one . charAt ( one . length - 1 ) ; var char2 = two . charAt ( 0 ) ; var nonAlphaNumeric1 = char1 . match ( nonAlphaNumericRegex_ ) ; var nonAlphaNumeric2 = char2 . match ( nonAlphaNumericRegex_ ) ; var whitespace1 = nonAlphaNumeric1 && char1 . match ( whitespaceRegex_ ) ; var whitespace2 = nonAlphaNumeric2 && char2 . match ( whitespaceRegex_ ) ; var lineBreak1 = whitespace1 && char1 . match ( linebreakRegex_ ) ; var lineBreak2 = whitespace2 && char2 . match ( linebreakRegex_ ) ; var blankLine1 = lineBreak1 && one . match ( blanklineEndRegex_ ) ; var blankLine2 = lineBreak2 && two . match ( blanklineStartRegex_ ) ; if ( blankLine1 || blankLine2 ) { return 5 ; } else if ( lineBreak1 || lineBreak2 ) { return 4 ; } else if ( nonAlphaNumeric1 && ! whitespace1 && whitespace2 ) { return 3 ; } else if ( whitespace1 || whitespace2 ) { return 2 ; } else if ( nonAlphaNumeric1 || nonAlphaNumeric2 ) { return 1 ; } return 0 ; } var pointer = 1 ; while ( pointer < diffs . length - 1 ) { if ( diffs [ pointer - 1 ] [ 0 ] == DIFF_EQUAL && diffs [ pointer + 1 ] [ 0 ] == DIFF_EQUAL ) { var equality1 = diffs [ pointer - 1 ] [ 1 ] ; var edit = diffs [ pointer ] [ 1 ] ; var equality2 = diffs [ pointer + 1 ] [ 1 ] ; var commonOffset = diff_commonSuffix ( equality1 , edit ) ; if ( commonOffset ) { var commonString = edit . substring ( edit . length - commonOffset ) ; equality1 = equality1 . substring ( 0 , equality1 . length - commonOffset ) ; edit = commonString + edit . substring ( 0 , edit . length - commonOffset ) ; equality2 = commonString + equality2 ; } var bestEquality1 = equality1 ; var bestEdit = edit ; var bestEquality2 = equality2 ; var bestScore = diff_cleanupSemanticScore_ ( equality1 , edit ) + diff_cleanupSemanticScore_ ( edit , equality2 ) ; while ( edit . charAt ( 0 ) === equality2 . charAt ( 0 ) ) { equality1 += edit . charAt ( 0 ) ; edit = edit . substring ( 1 ) + equality2 . charAt ( 0 ) ; equality2 = equality2 . substring ( 1 ) ; var score = diff_cleanupSemanticScore_ ( equality1 , edit ) + diff_cleanupSemanticScore_ ( edit , equality2 ) ; if ( score >= bestScore ) { bestScore = score ; bestEquality1 = equality1 ; bestEdit = edit ; bestEquality2 = equality2 ; } } if ( diffs [ pointer - 1 ] [ 1 ] != bestEquality1 ) { if ( bestEquality1 ) { diffs [ pointer - 1 ] [ 1 ] = bestEquality1 ; } else { diffs . splice ( pointer - 1 , 1 ) ; pointer -- ; } diffs [ pointer ] [ 1 ] = bestEdit ; if ( bestEquality2 ) { diffs [ pointer + 1 ] [ 1 ] = bestEquality2 ; } else { diffs . splice ( pointer + 1 , 1 ) ; pointer -- ; } } } pointer ++ ; } } ; var nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/ ; var whitespaceRegex_ = /\s/ ; var linebreakRegex_ = /[\r\n]/ ; var blanklineEndRegex_ = /\n\r?\n$/ ; var blanklineStartRegex_ = /^\r?\n\r?\n/ ; param { ! Array . < ! diff_match_patch . Diff > } diffs var diff_cleanupMerge = function ( diffs ) { diffs . push ( new Diff ( DIFF_EQUAL , '' ) ) ; var pointer = 0 ; var count_delete = 0 ; var count_insert = 0 ; var text_delete = '' ; var text_insert = '' ; var commonlength ; while ( pointer < diffs . length ) { 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 : if ( count_delete + count_insert > 1 ) { if ( count_delete !== 0 && count_insert !== 0 ) { commonlength = diff_commonPrefix ( text_insert , text_delete ) ; if ( commonlength !== 0 ) { if ( pointer - count_delete - count_insert > 0 && diffs [ pointer - count_delete - count_insert - 1 ] [ 0 ] == DIFF_EQUAL ) { diffs [ pointer - count_delete - count_insert - 1 ] [ 1 ] += text_insert . substring ( 0 , commonlength ) ; } else { diffs . splice ( 0 , 0 , new Diff ( DIFF_EQUAL , text_insert . substring ( 0 , commonlength ) ) ) ; pointer ++ ; } text_insert = text_insert . substring ( commonlength ) ; text_delete = text_delete . substring ( commonlength ) ; } 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 ) ; } } pointer -= count_delete + count_insert ; diffs . splice ( pointer , count_delete + count_insert ) ; if ( text_delete . length ) { diffs . splice ( pointer , 0 , new Diff ( DIFF_DELETE , text_delete ) ) ; pointer ++ ; } if ( text_insert . length ) { diffs . splice ( pointer , 0 , new Diff ( DIFF_INSERT , text_insert ) ) ; pointer ++ ; } pointer ++ ; } else if ( pointer !== 0 && diffs [ pointer - 1 ] [ 0 ] == DIFF_EQUAL ) { 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 ( ) ; } var changes = false ; pointer = 1 ; while ( pointer < diffs . length - 1 ) { if ( diffs [ pointer - 1 ] [ 0 ] == DIFF_EQUAL && diffs [ pointer + 1 ] [ 0 ] == DIFF_EQUAL ) { if ( diffs [ pointer ] [ 1 ] . substring ( diffs [ pointer ] [ 1 ] . length - diffs [ pointer - 1 ] [ 1 ] . length ) == diffs [ pointer - 1 ] [ 1 ] ) { 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 ] ) { 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 ( changes ) { diff_cleanupMerge ( diffs ) ; } } ; export { Diff , DIFF_EQUAL , DIFF_DELETE , DIFF_INSERT , diff_cleanupSemantic as cleanupSemantic , } ;