/* * Javascript Diff Algorithm * By John Resig (http://ejohn.org/) * Modified by Chu Alan "sprite" * * Released under the MIT license. * * More Info: * http://ejohn.org/projects/javascript-diff-algorithm/ * * Usage: QUnit.diff(expected, actual) * * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick brown fox jumped jumps over" */ QUnit.diff = (function() { var hasOwn = Object.prototype.hasOwnProperty; /*jshint eqeqeq:false, eqnull:true */ function diff( o, n ) { var i, ns = {}, os = {}; for ( i = 0; i < n.length; i++ ) { if ( !hasOwn.call( ns, n[ i ] ) ) { ns[ n[ i ] ] = { rows: [], o: null }; } ns[ n[ i ] ].rows.push( i ); } for ( i = 0; i < o.length; i++ ) { if ( !hasOwn.call( os, o[ i ] ) ) { os[ o[ i ] ] = { rows: [], n: null }; } os[ o[ i ] ].rows.push( i ); } for ( i in ns ) { if ( hasOwn.call( ns, i ) ) { if ( ns[ i ].rows.length === 1 && hasOwn.call( os, i ) && os[ i ].rows.length === 1 ) { n[ ns[ i ].rows[ 0 ] ] = { text: n[ ns[ i ].rows[ 0 ] ], row: os[ i ].rows[ 0 ] }; o[ os[ i ].rows[ 0 ] ] = { text: o[ os[ i ].rows[ 0 ] ], row: ns[ i ].rows[ 0 ] }; } } } for ( i = 0; i < n.length - 1; i++ ) { if ( n[ i ].text != null && n[ i + 1 ].text == null && n[ i ].row + 1 < o.length && o[ n[ i ].row + 1 ].text == null && n[ i + 1 ] == o[ n[ i ].row + 1 ] ) { n[ i + 1 ] = { text: n[ i + 1 ], row: n[ i ].row + 1 }; o[ n[ i ].row + 1 ] = { text: o[ n[ i ].row + 1 ], row: i + 1 }; } } for ( i = n.length - 1; i > 0; i-- ) { if ( n[ i ].text != null && n[ i - 1 ].text == null && n[ i ].row > 0 && o[ n[ i ].row - 1 ].text == null && n[ i - 1 ] == o[ n[ i ].row - 1 ] ) { n[ i - 1 ] = { text: n[ i - 1 ], row: n[ i ].row - 1 }; o[ n[ i ].row - 1 ] = { text: o[ n[ i ].row - 1 ], row: i - 1 }; } } return { o: o, n: n }; } return function( o, n ) { o = o.replace( /\s+$/, "" ); n = n.replace( /\s+$/, "" ); var i, pre, str = "", out = diff( o === "" ? [] : o.split( /\s+/ ), n === "" ? [] : n.split( /\s+/ ) ), oSpace = o.match( /\s+/g ), nSpace = n.match( /\s+/g ); if ( oSpace == null ) { oSpace = [ " " ]; } else { oSpace.push( " " ); } if ( nSpace == null ) { nSpace = [ " " ]; } else { nSpace.push( " " ); } if ( out.n.length === 0 ) { for ( i = 0; i < out.o.length; i++ ) { str += "" + out.o[ i ] + oSpace[ i ] + ""; } } else { if ( out.n[ 0 ].text == null ) { for ( n = 0; n < out.o.length && out.o[ n ].text == null; n++ ) { str += "" + out.o[ n ] + oSpace[ n ] + ""; } } for ( i = 0; i < out.n.length; i++ ) { if ( out.n[ i ].text == null ) { str += "" + out.n[ i ] + nSpace[ i ] + ""; } else { // `pre` initialized at top of scope pre = ""; for ( n = out.n[ i ].row + 1; n < out.o.length && out.o[ n ].text == null; n++ ) { pre += "" + out.o[ n ] + oSpace[ n ] + ""; } str += " " + out.n[ i ].text + nSpace[ i ] + pre; } } } return str; }; }());