@@ -412,21 +412,19 @@ function canonicalizeForDiff(text) {
412412 . replace ( / [ ‘ ’ ‚ ‛ ] / g, "'" )
413413 . replace ( / [ \u2013 \u2014 ] / g, '-' ) // en/em dash -> hyphen
414414 . replace ( / \u00a0 / g, ' ' ) // non-breaking space
415- . replace ( / \n + / g, ' ' ) // collapse newlines
415+ // .replace(/\n+/g, ' ') // collapse newlines
416416 . replace ( / [ \t ] + / g, ' ' ) // collapse spaces/tabs
417417 . trim ( )
418- . toLowerCase ( ) ;
418+ // .toLowerCase();
419419}
420420
421- // Prepare text for visual diff (light cleanup, keep original casing)
421+ // Prepare text for visual diff display
422422function prepareDisplayText ( text ) {
423423 if ( ! text ) return '' ;
424424 return String ( text )
425425 . replace ( / \r \n / g, '\n' )
426- . replace ( / \u00a0 / g, ' ' )
427- . replace ( / [ \t ] { 2 , } / g, ' ' )
428- . replace ( / \n { 3 , } / g, '\n\n' )
429- . trim ( ) ;
426+ . replace ( / \r / g, '\n' )
427+ . replace ( / \u00a0 / g, ' ' ) ;
430428}
431429
432430function computeDiffSimilarities ( diff , lenA , lenB ) {
@@ -1675,6 +1673,8 @@ function generateStableDisplayDiff(licenseText, selectionText) {
16751673 const originalTimeout = dmp . Diff_Timeout ;
16761674 const displayA = prepareDisplayText ( licenseText ) ;
16771675 const displayB = prepareDisplayText ( selectionText ) ;
1676+
1677+ // Keep canonical only for "do we have overlap" checks; do NOT use it as a display-diff source.
16781678 const canonA = canonicalizeForDiff ( displayA ) ;
16791679 const canonB = canonicalizeForDiff ( displayB ) ;
16801680
@@ -1700,17 +1700,20 @@ function generateStableDisplayDiff(licenseText, selectionText) {
17001700 const attemptDiff = ( ) => {
17011701 const timeouts = [ Math . max ( originalTimeout || 0 , 1 ) , 4 , 0 ] ;
17021702 const attempts = [
1703- { a : displayA , b : displayB , mode : 'chars ' } ,
1704- { a : displayA , b : displayB , mode : 'lines ' } ,
1703+ // { a: displayA, b: displayB, mode: 'lines ' },
1704+ // { a: displayA, b: displayB, mode: 'chars ' },
17051705 { a : canonA , b : canonB , mode : 'chars' } ,
17061706 { a : canonA , b : canonB , mode : 'lines' }
17071707 ] ;
1708+
17081709 for ( const { a, b, mode } of attempts ) {
17091710 for ( const timeout of timeouts ) {
17101711 try {
17111712 const diff = runDisplayDiff ( a , b , timeout , mode ) ;
17121713 if ( isDegenerate ( diff , a . length , b . length ) ) continue ;
1713- if ( ! hasEqual ( diff ) || ! hasMeaningfulOverlap ( diff , a . length , b . length ) ) continue ;
1714+ if ( ! hasEqual ( diff ) ) continue ;
1715+ if ( ! hasMeaningfulOverlap ( diff , canonA . length , canonB . length ) ) continue ;
1716+
17141717 return diff ;
17151718 } catch ( err ) {
17161719 console . warn ( `[LicenseMatch][DisplayDiff] mode=${ mode } timeout=${ timeout } failed` , err ) ;
@@ -1774,40 +1777,17 @@ function renderDiffHtml(diff) {
17741777 . replace ( / & / g, '&' )
17751778 . replace ( / < / g, '<' )
17761779 . replace ( / > / g, '>' )
1777- . replace ( / \t / g, ' ' ) ;
1778- const listLinePattern = / ^ \s * (?: \( ? \d + \) | \d + [ . ) ] | [ a - z A - Z ] [ . ) ] | [ - * • ] ) \s + / ;
1779- const shouldForceBreak = ( text , newlineIdx , runLength ) => {
1780- if ( runLength !== 1 ) return false ;
1781- const nextSlice = text . slice ( newlineIdx + 1 ) ;
1782- const nextLine = nextSlice . split ( '\n' , 1 ) [ 0 ] || '' ;
1783- return listLinePattern . test ( nextLine ) ;
1784- } ;
1785- const formatDiffText = ( text ) => {
1786- if ( ! text ) return '' ;
1787- let out = '' ;
1788- let lastIndex = 0 ;
1789- text . replace ( / \n + / g, ( match , idx ) => {
1790- if ( idx > lastIndex ) out += escapeHtmlFragment ( text . slice ( lastIndex , idx ) ) ;
1791- out += match . length === 1
1792- ? ( shouldForceBreak ( text , idx , match . length ) ? '<br>' : ' ' )
1793- : '<br>' . repeat ( match . length ) ;
1794- lastIndex = idx + match . length ;
1795- return match ;
1796- } ) ;
1797- if ( lastIndex < text . length ) out += escapeHtmlFragment ( text . slice ( lastIndex ) ) ;
1798- return out ;
1799- } ;
1780+ . replace ( / \t / g, ' ' ) ;
1781+
1782+ const formatDiffText = ( text ) => escapeHtmlFragment ( text ) ;
1783+
18001784 const renderBody = ( op , chunk ) => {
1801- if ( ! chunk ) return '' ;
1802- const formatted = formatDiffText ( chunk ) ;
1803- const whitespaceOnly = ! / \S / . test ( chunk ) ;
1804- if ( op === 1 && ! whitespaceOnly ) return `<ins>${ formatted } </ins>` ;
1805- if ( op === - 1 && ! whitespaceOnly ) return `<del>${ formatted } </del>` ;
1806- if ( op === 0 && ! whitespaceOnly ) return `<span>${ formatted } </span>` ;
1807- return `<span></span>` ;
1785+ const formatted = formatDiffText ( chunk ?? '' ) ;
1786+ if ( op === 1 ) return `<ins>${ formatted } </ins>` ;
1787+ if ( op === - 1 ) return `<del>${ formatted } </del>` ;
1788+ return `<span>${ formatted } </span>` ;
18081789 } ;
1809- const viewable = sanitized ; // include deletions again
1810- if ( ! viewable . length ) throw new Error ( 'Empty diff after filtering viewable segments' ) ;
1811- const html = viewable . map ( ( [ op , data ] ) => renderBody ( op , data ) ) . join ( '' ) ;
1812- return `<div class="ldiff-output" id="outputdiv">${ html } </div>` ;
1790+
1791+ const html = sanitized . map ( ( [ op , data ] ) => renderBody ( op , data ) ) . join ( '' ) ;
1792+ return `<pre class="ldiff-output" id="outputdiv">${ html } </pre>` ;
18131793}
0 commit comments