Skip to content

Commit 38a9d8f

Browse files
authored
Merge pull request #365 from huggingface/diff-max-lines
feature: bypass parsing/rendering of file diff if specific threshold is crossed
2 parents e55d145 + a65a3b9 commit 38a9d8f

File tree

9 files changed

+398
-6
lines changed

9 files changed

+398
-6
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ The HTML output accepts a Javascript object with configuration. Possible options
149149
- `outputFormat`: the format of the output data: `'line-by-line'` or `'side-by-side'`, default is `'line-by-line'`
150150
- `drawFileList`: show a file list before the diff: `true` or `false`, default is `true`
151151
- `diffStyle`: show differences level in each line: `word` or `char`, default is `word`
152+
- `diffMaxChanges`: number of changed lines after which a file diff is deemed as too big and not displayed, default is
153+
`undefined`
154+
- `diffTooBigMessage`: function allowing to customize the message in case of file diff too big (if `diffMaxChanges` is
155+
set)
152156
- `matching`: matching level: `'lines'` for matching lines, `'words'` for matching lines and words or `'none'`, default
153157
is `none`
154158
- `matchWordsThreshold`: similarity threshold for word matching, default is `0.25`

src/__tests__/diff-parser-tests.ts

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,5 +1975,231 @@ describe('DiffParser', () => {
19751975
]
19761976
`);
19771977
});
1978+
1979+
it('should work when `diffMaxChanges` is set and excedeed', () => {
1980+
const diff =
1981+
'diff --git a/src/core/init.js b/src/core/init.js\n' +
1982+
'index e49196a..50f310c 100644\n' +
1983+
'--- a/src/core/init.js\n' +
1984+
'+++ b/src/core/init.js\n' +
1985+
'@@ -101,7 +101,7 @@ var rootjQuery,\n' +
1986+
' // HANDLE: $(function)\n' +
1987+
' // Shortcut for document ready\n' +
1988+
' } else if ( jQuery.isFunction( selector ) ) {\n' +
1989+
'- return typeof rootjQuery.ready !== "undefined" ?\n' +
1990+
'+ return rootjQuery.ready !== undefined ?\n' +
1991+
' rootjQuery.ready( selector ) :\n' +
1992+
' // Execute immediately if ready is not present\n' +
1993+
' selector( jQuery );\n' +
1994+
'diff --git a/src/event.js b/src/event.js\n' +
1995+
'index 7336f4d..6183f70 100644\n' +
1996+
'--- a/src/event.js\n' +
1997+
'+++ b/src/event.js\n' +
1998+
'@@ -1,6 +1,5 @@\n' +
1999+
' define([\n' +
2000+
' "./core",\n' +
2001+
'- "./var/strundefined",\n' +
2002+
' "./var/rnotwhite",\n' +
2003+
' "./var/hasOwn",\n' +
2004+
' "./var/slice",\n';
2005+
const result = parse(diff, { diffMaxChanges: 1 });
2006+
expect(result).toMatchInlineSnapshot(`
2007+
Array [
2008+
Object {
2009+
"addedLines": 0,
2010+
"blocks": Array [
2011+
Object {
2012+
"header": "Diff too big to be displayed",
2013+
"lines": Array [],
2014+
"newStartLine": 0,
2015+
"oldStartLine": 0,
2016+
"oldStartLine2": null,
2017+
},
2018+
],
2019+
"checksumAfter": "50f310c",
2020+
"checksumBefore": "e49196a",
2021+
"deletedLines": 0,
2022+
"isCombined": false,
2023+
"isGitDiff": true,
2024+
"isTooBig": true,
2025+
"language": "js",
2026+
"mode": "100644",
2027+
"newName": "src/core/init.js",
2028+
"oldName": "src/core/init.js",
2029+
},
2030+
Object {
2031+
"addedLines": 0,
2032+
"blocks": Array [
2033+
Object {
2034+
"header": "@@ -1,6 +1,5 @@",
2035+
"lines": Array [
2036+
Object {
2037+
"content": " define([",
2038+
"newNumber": 1,
2039+
"oldNumber": 1,
2040+
"type": "context",
2041+
},
2042+
Object {
2043+
"content": " \\"./core\\",",
2044+
"newNumber": 2,
2045+
"oldNumber": 2,
2046+
"type": "context",
2047+
},
2048+
Object {
2049+
"content": "- \\"./var/strundefined\\",",
2050+
"newNumber": undefined,
2051+
"oldNumber": 3,
2052+
"type": "delete",
2053+
},
2054+
Object {
2055+
"content": " \\"./var/rnotwhite\\",",
2056+
"newNumber": 3,
2057+
"oldNumber": 4,
2058+
"type": "context",
2059+
},
2060+
Object {
2061+
"content": " \\"./var/hasOwn\\",",
2062+
"newNumber": 4,
2063+
"oldNumber": 5,
2064+
"type": "context",
2065+
},
2066+
Object {
2067+
"content": " \\"./var/slice\\",",
2068+
"newNumber": 5,
2069+
"oldNumber": 6,
2070+
"type": "context",
2071+
},
2072+
],
2073+
"newStartLine": 1,
2074+
"oldStartLine": 1,
2075+
"oldStartLine2": null,
2076+
},
2077+
],
2078+
"checksumAfter": "6183f70",
2079+
"checksumBefore": "7336f4d",
2080+
"deletedLines": 1,
2081+
"isCombined": false,
2082+
"isGitDiff": true,
2083+
"language": "js",
2084+
"mode": "100644",
2085+
"newName": "src/event.js",
2086+
"oldName": "src/event.js",
2087+
},
2088+
]
2089+
`);
2090+
});
2091+
2092+
it('should work when `diffMaxChanges` is set and excedeed, and `diffTooBigMessage` is set', () => {
2093+
const diff =
2094+
'diff --git a/src/core/init.js b/src/core/init.js\n' +
2095+
'index e49196a..50f310c 100644\n' +
2096+
'--- a/src/core/init.js\n' +
2097+
'+++ b/src/core/init.js\n' +
2098+
'@@ -101,7 +101,7 @@ var rootjQuery,\n' +
2099+
' // HANDLE: $(function)\n' +
2100+
' // Shortcut for document ready\n' +
2101+
' } else if ( jQuery.isFunction( selector ) ) {\n' +
2102+
'- return typeof rootjQuery.ready !== "undefined" ?\n' +
2103+
'+ return rootjQuery.ready !== undefined ?\n' +
2104+
' rootjQuery.ready( selector ) :\n' +
2105+
' // Execute immediately if ready is not present\n' +
2106+
' selector( jQuery );\n' +
2107+
'diff --git a/src/event.js b/src/event.js\n' +
2108+
'index 7336f4d..6183f70 100644\n' +
2109+
'--- a/src/event.js\n' +
2110+
'+++ b/src/event.js\n' +
2111+
'@@ -1,6 +1,5 @@\n' +
2112+
' define([\n' +
2113+
' "./core",\n' +
2114+
'- "./var/strundefined",\n' +
2115+
' "./var/rnotwhite",\n' +
2116+
' "./var/hasOwn",\n' +
2117+
' "./var/slice",\n';
2118+
const result = parse(diff, { diffMaxChanges: 1, diffTooBigMessage: (i: number) => `Custom ${i}` });
2119+
expect(result).toMatchInlineSnapshot(`
2120+
Array [
2121+
Object {
2122+
"addedLines": 0,
2123+
"blocks": Array [
2124+
Object {
2125+
"header": "Custom 0",
2126+
"lines": Array [],
2127+
"newStartLine": 0,
2128+
"oldStartLine": 0,
2129+
"oldStartLine2": null,
2130+
},
2131+
],
2132+
"checksumAfter": "50f310c",
2133+
"checksumBefore": "e49196a",
2134+
"deletedLines": 0,
2135+
"isCombined": false,
2136+
"isGitDiff": true,
2137+
"isTooBig": true,
2138+
"language": "js",
2139+
"mode": "100644",
2140+
"newName": "src/core/init.js",
2141+
"oldName": "src/core/init.js",
2142+
},
2143+
Object {
2144+
"addedLines": 0,
2145+
"blocks": Array [
2146+
Object {
2147+
"header": "@@ -1,6 +1,5 @@",
2148+
"lines": Array [
2149+
Object {
2150+
"content": " define([",
2151+
"newNumber": 1,
2152+
"oldNumber": 1,
2153+
"type": "context",
2154+
},
2155+
Object {
2156+
"content": " \\"./core\\",",
2157+
"newNumber": 2,
2158+
"oldNumber": 2,
2159+
"type": "context",
2160+
},
2161+
Object {
2162+
"content": "- \\"./var/strundefined\\",",
2163+
"newNumber": undefined,
2164+
"oldNumber": 3,
2165+
"type": "delete",
2166+
},
2167+
Object {
2168+
"content": " \\"./var/rnotwhite\\",",
2169+
"newNumber": 3,
2170+
"oldNumber": 4,
2171+
"type": "context",
2172+
},
2173+
Object {
2174+
"content": " \\"./var/hasOwn\\",",
2175+
"newNumber": 4,
2176+
"oldNumber": 5,
2177+
"type": "context",
2178+
},
2179+
Object {
2180+
"content": " \\"./var/slice\\",",
2181+
"newNumber": 5,
2182+
"oldNumber": 6,
2183+
"type": "context",
2184+
},
2185+
],
2186+
"newStartLine": 1,
2187+
"oldStartLine": 1,
2188+
"oldStartLine2": null,
2189+
},
2190+
],
2191+
"checksumAfter": "6183f70",
2192+
"checksumBefore": "7336f4d",
2193+
"deletedLines": 1,
2194+
"isCombined": false,
2195+
"isGitDiff": true,
2196+
"language": "js",
2197+
"mode": "100644",
2198+
"newName": "src/event.js",
2199+
"oldName": "src/event.js",
2200+
},
2201+
]
2202+
`);
2203+
});
19782204
});
19792205
});

src/__tests__/line-by-line-tests.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,65 @@ describe('LineByLineRenderer', () => {
505505
</div>"
506506
`);
507507
});
508+
509+
it('should work for too big file diff', () => {
510+
const exampleJson = [
511+
{
512+
blocks: [
513+
{
514+
header: '<a href="http://example.com">Custom link to render</a>',
515+
lines: [],
516+
newStartLine: 0,
517+
oldStartLine: 0,
518+
oldStartLine2: undefined,
519+
},
520+
],
521+
deletedLines: 0,
522+
addedLines: 0,
523+
oldName: 'sample',
524+
language: 'js',
525+
newName: 'sample',
526+
isCombined: false,
527+
isGitDiff: false,
528+
isTooBig: true,
529+
},
530+
];
531+
532+
const hoganUtils = new HoganJsUtils({});
533+
const lineByLineRenderer = new LineByLineRenderer(hoganUtils);
534+
const html = lineByLineRenderer.render(exampleJson);
535+
expect(html).toMatchInlineSnapshot(`
536+
"<div class=\\"d2h-wrapper\\">
537+
<div id=\\"d2h-675094\\" class=\\"d2h-file-wrapper\\" data-lang=\\"js\\">
538+
<div class=\\"d2h-file-header\\">
539+
<span class=\\"d2h-file-name-wrapper\\">
540+
<svg aria-hidden=\\"true\\" class=\\"d2h-icon\\" height=\\"16\\" version=\\"1.1\\" viewBox=\\"0 0 12 16\\" width=\\"12\\">
541+
<path d=\\"M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z\\"></path>
542+
</svg> <span class=\\"d2h-file-name\\">sample</span>
543+
<span class=\\"d2h-tag d2h-changed d2h-changed-tag\\">CHANGED</span></span>
544+
<label class=\\"d2h-file-collapse\\">
545+
<input class=\\"d2h-file-collapse-input\\" type=\\"checkbox\\" name=\\"viewed\\" value=\\"viewed\\">
546+
Viewed
547+
</label>
548+
</div>
549+
<div class=\\"d2h-file-diff\\">
550+
<div class=\\"d2h-code-wrapper\\">
551+
<table class=\\"d2h-diff-table\\">
552+
<tbody class=\\"d2h-diff-tbody\\">
553+
<tr>
554+
<td class=\\"d2h-code-linenumber d2h-info\\"></td>
555+
<td class=\\"d2h-info\\">
556+
<div class=\\"d2h-code-line d2h-info\\"><a href=\\"http://example.com\\">Custom link to render</a></div>
557+
</td>
558+
</tr>
559+
</tbody>
560+
</table>
561+
</div>
562+
</div>
563+
</div>
564+
</div>"
565+
`);
566+
});
508567
});
509568

510569
describe('_generateFileHtml', () => {

src/__tests__/side-by-side-printer-tests.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,81 @@ describe('SideBySideRenderer', () => {
406406
</div>"
407407
`);
408408
});
409+
410+
it('should work for too big file diff', () => {
411+
const exampleJson = [
412+
{
413+
blocks: [
414+
{
415+
header: '<a href="http://example.com">Custom link to render</a>',
416+
lines: [],
417+
newStartLine: 0,
418+
oldStartLine: 0,
419+
oldStartLine2: undefined,
420+
},
421+
],
422+
deletedLines: 0,
423+
addedLines: 0,
424+
oldName: 'sample',
425+
language: 'js',
426+
newName: 'sample',
427+
isCombined: false,
428+
isGitDiff: false,
429+
isTooBig: true,
430+
},
431+
];
432+
433+
const hoganUtils = new HoganJsUtils({});
434+
const sideBySideRenderer = new SideBySideRenderer(hoganUtils);
435+
const html = sideBySideRenderer.render(exampleJson);
436+
expect(html).toMatchInlineSnapshot(`
437+
"<div class=\\"d2h-wrapper\\">
438+
<div id=\\"d2h-675094\\" class=\\"d2h-file-wrapper\\" data-lang=\\"js\\">
439+
<div class=\\"d2h-file-header\\">
440+
<span class=\\"d2h-file-name-wrapper\\">
441+
<svg aria-hidden=\\"true\\" class=\\"d2h-icon\\" height=\\"16\\" version=\\"1.1\\" viewBox=\\"0 0 12 16\\" width=\\"12\\">
442+
<path d=\\"M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z\\"></path>
443+
</svg> <span class=\\"d2h-file-name\\">sample</span>
444+
<span class=\\"d2h-tag d2h-changed d2h-changed-tag\\">CHANGED</span></span>
445+
<label class=\\"d2h-file-collapse\\">
446+
<input class=\\"d2h-file-collapse-input\\" type=\\"checkbox\\" name=\\"viewed\\" value=\\"viewed\\">
447+
Viewed
448+
</label>
449+
</div>
450+
<div class=\\"d2h-files-diff\\">
451+
<div class=\\"d2h-file-side-diff\\">
452+
<div class=\\"d2h-code-wrapper\\">
453+
<table class=\\"d2h-diff-table\\">
454+
<tbody class=\\"d2h-diff-tbody\\">
455+
<tr>
456+
<td class=\\"d2h-code-side-linenumber d2h-info\\"></td>
457+
<td class=\\"d2h-info\\">
458+
<div class=\\"d2h-code-side-line d2h-info\\"><a href=\\"http://example.com\\">Custom link to render</a></div>
459+
</td>
460+
</tr>
461+
</tbody>
462+
</table>
463+
</div>
464+
</div>
465+
<div class=\\"d2h-file-side-diff\\">
466+
<div class=\\"d2h-code-wrapper\\">
467+
<table class=\\"d2h-diff-table\\">
468+
<tbody class=\\"d2h-diff-tbody\\">
469+
<tr>
470+
<td class=\\"d2h-code-side-linenumber d2h-info\\"></td>
471+
<td class=\\"d2h-info\\">
472+
<div class=\\"d2h-code-side-line d2h-info\\"></div>
473+
</td>
474+
</tr>
475+
</tbody>
476+
</table>
477+
</div>
478+
</div>
479+
</div>
480+
</div>
481+
</div>"
482+
`);
483+
});
409484
});
410485

411486
describe('processLines', () => {

0 commit comments

Comments
 (0)