Merge 042fd60faf into 1350740c98
This commit is contained in:
commit
28be4657da
6 changed files with 421 additions and 18 deletions
|
|
@ -157,29 +157,35 @@ describe('Diff2Html', () => {
|
||||||
"type": "delete",
|
"type": "delete",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"content": "+ TokenRevoked, MissingToken,",
|
"content": "\\ No newline at end of file",
|
||||||
"newNumber": 53,
|
"newNumber": 53,
|
||||||
"oldNumber": undefined,
|
"oldNumber": 55,
|
||||||
"type": "insert",
|
"type": "context",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"content": "+ IndexLock, RepositoryError, NotValidRepo, PullRequestNotMergeable, BranchError,",
|
"content": "+ TokenRevoked, MissingToken,",
|
||||||
"newNumber": 54,
|
"newNumber": 54,
|
||||||
"oldNumber": undefined,
|
"oldNumber": undefined,
|
||||||
"type": "insert",
|
"type": "insert",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"content": "+ PluginError, CodeParserError, EngineError = Value",
|
"content": "+ IndexLock, RepositoryError, NotValidRepo, PullRequestNotMergeable, BranchError,",
|
||||||
"newNumber": 55,
|
"newNumber": 55,
|
||||||
"oldNumber": undefined,
|
"oldNumber": undefined,
|
||||||
"type": "insert",
|
"type": "insert",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"content": "+}",
|
"content": "+ PluginError, CodeParserError, EngineError = Value",
|
||||||
"newNumber": 56,
|
"newNumber": 56,
|
||||||
"oldNumber": undefined,
|
"oldNumber": undefined,
|
||||||
"type": "insert",
|
"type": "insert",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"content": "+}",
|
||||||
|
"newNumber": 57,
|
||||||
|
"oldNumber": undefined,
|
||||||
|
"type": "insert",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
"newStartLine": 50,
|
"newStartLine": 50,
|
||||||
"oldStartLine": 50,
|
"oldStartLine": 50,
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,357 @@ describe('SideBySideRenderer', () => {
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle files without newlines at the end', () => {
|
||||||
|
const exampleJson: DiffFile[] = [
|
||||||
|
{
|
||||||
|
blocks: [
|
||||||
|
// Scenario 1: Old file missing newline, new file has newline
|
||||||
|
{
|
||||||
|
lines: [
|
||||||
|
{
|
||||||
|
content: '-oldLine1',
|
||||||
|
type: LineType.DELETE,
|
||||||
|
oldNumber: 1,
|
||||||
|
newNumber: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: '\\ No newline at end of file',
|
||||||
|
type: LineType.CONTEXT,
|
||||||
|
oldNumber: 1,
|
||||||
|
newNumber: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: '+newLine1',
|
||||||
|
type: LineType.INSERT,
|
||||||
|
oldNumber: undefined,
|
||||||
|
newNumber: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
oldStartLine: 1,
|
||||||
|
newStartLine: 1,
|
||||||
|
header: '@@ -1 +1 @@',
|
||||||
|
},
|
||||||
|
// Scenario 2: Old file has newline, new file missing newline
|
||||||
|
{
|
||||||
|
lines: [
|
||||||
|
{
|
||||||
|
content: '-oldLine2',
|
||||||
|
type: LineType.DELETE,
|
||||||
|
oldNumber: 2,
|
||||||
|
newNumber: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: '+newLine2',
|
||||||
|
type: LineType.INSERT,
|
||||||
|
oldNumber: undefined,
|
||||||
|
newNumber: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: '\\ No newline at end of file',
|
||||||
|
type: LineType.CONTEXT,
|
||||||
|
oldNumber: 2,
|
||||||
|
newNumber: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
oldStartLine: 2,
|
||||||
|
newStartLine: 2,
|
||||||
|
header: '@@ -2 +2 @@',
|
||||||
|
},
|
||||||
|
// Scenario 3: Both files missing newline
|
||||||
|
{
|
||||||
|
lines: [
|
||||||
|
{
|
||||||
|
content: '-oldLine3',
|
||||||
|
type: LineType.DELETE,
|
||||||
|
oldNumber: 3,
|
||||||
|
newNumber: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: '\\ No newline at end of file',
|
||||||
|
type: LineType.CONTEXT,
|
||||||
|
oldNumber: 3,
|
||||||
|
newNumber: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: '+newLine3',
|
||||||
|
type: LineType.INSERT,
|
||||||
|
oldNumber: undefined,
|
||||||
|
newNumber: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: '\\ No newline at end of file',
|
||||||
|
type: LineType.CONTEXT,
|
||||||
|
oldNumber: 3,
|
||||||
|
newNumber: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
oldStartLine: 3,
|
||||||
|
newStartLine: 3,
|
||||||
|
header: '@@ -3 +3 @@',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
deletedLines: 3,
|
||||||
|
addedLines: 3,
|
||||||
|
oldName: 'sample',
|
||||||
|
language: 'txt',
|
||||||
|
newName: 'sample',
|
||||||
|
isCombined: false,
|
||||||
|
isGitDiff: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const hoganUtils = new HoganJsUtils({});
|
||||||
|
const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {});
|
||||||
|
const html = sideBySideRenderer.render(exampleJson);
|
||||||
|
expect(html).toMatchInlineSnapshot(`
|
||||||
|
"<div class="d2h-wrapper d2h-light-color-scheme">
|
||||||
|
<div id="d2h-675094" class="d2h-file-wrapper" data-lang="txt">
|
||||||
|
<div class="d2h-file-header">
|
||||||
|
<span class="d2h-file-name-wrapper">
|
||||||
|
<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">
|
||||||
|
<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>
|
||||||
|
</svg> <span class="d2h-file-name">sample</span>
|
||||||
|
<span class="d2h-tag d2h-changed d2h-changed-tag">CHANGED</span></span>
|
||||||
|
<label class="d2h-file-collapse">
|
||||||
|
<input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">
|
||||||
|
Viewed
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="d2h-files-diff">
|
||||||
|
<div class="d2h-file-side-diff">
|
||||||
|
<div class="d2h-code-wrapper">
|
||||||
|
<table class="d2h-diff-table">
|
||||||
|
<tbody class="d2h-diff-tbody">
|
||||||
|
<tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-info"></td>
|
||||||
|
<td class="d2h-info">
|
||||||
|
<div class="d2h-code-side-line">@@ -1 +1 @@</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-del">
|
||||||
|
1
|
||||||
|
</td>
|
||||||
|
<td class="d2h-del">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">-</span>
|
||||||
|
<span class="d2h-code-line-ctn">oldLine1</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-cntx">
|
||||||
|
1
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">\\</span>
|
||||||
|
<span class="d2h-code-line-ctn"> No newline at end of file</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-code-side-emptyplaceholder d2h-cntx d2h-emptyplaceholder">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx d2h-emptyplaceholder">
|
||||||
|
<div class="d2h-code-side-line d2h-code-side-emptyplaceholder">
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-info"></td>
|
||||||
|
<td class="d2h-info">
|
||||||
|
<div class="d2h-code-side-line">@@ -2 +2 @@</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-del d2h-change">
|
||||||
|
2
|
||||||
|
</td>
|
||||||
|
<td class="d2h-del d2h-change">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">-</span>
|
||||||
|
<span class="d2h-code-line-ctn"><del>oldLine2</del></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-code-side-emptyplaceholder d2h-cntx d2h-emptyplaceholder">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx d2h-emptyplaceholder">
|
||||||
|
<div class="d2h-code-side-line d2h-code-side-emptyplaceholder">
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-info"></td>
|
||||||
|
<td class="d2h-info">
|
||||||
|
<div class="d2h-code-side-line">@@ -3 +3 @@</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-del">
|
||||||
|
3
|
||||||
|
</td>
|
||||||
|
<td class="d2h-del">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">-</span>
|
||||||
|
<span class="d2h-code-line-ctn">oldLine3</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-cntx">
|
||||||
|
3
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">\\</span>
|
||||||
|
<span class="d2h-code-line-ctn"> No newline at end of file</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-code-side-emptyplaceholder d2h-cntx d2h-emptyplaceholder">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx d2h-emptyplaceholder">
|
||||||
|
<div class="d2h-code-side-line d2h-code-side-emptyplaceholder">
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-code-side-emptyplaceholder d2h-cntx d2h-emptyplaceholder">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx d2h-emptyplaceholder">
|
||||||
|
<div class="d2h-code-side-line d2h-code-side-emptyplaceholder">
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d2h-file-side-diff">
|
||||||
|
<div class="d2h-code-wrapper">
|
||||||
|
<table class="d2h-diff-table">
|
||||||
|
<tbody class="d2h-diff-tbody">
|
||||||
|
<tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-info"></td>
|
||||||
|
<td class="d2h-info">
|
||||||
|
<div class="d2h-code-side-line"> </div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-code-side-emptyplaceholder d2h-cntx d2h-emptyplaceholder">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx d2h-emptyplaceholder">
|
||||||
|
<div class="d2h-code-side-line d2h-code-side-emptyplaceholder">
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-code-side-emptyplaceholder d2h-cntx d2h-emptyplaceholder">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx d2h-emptyplaceholder">
|
||||||
|
<div class="d2h-code-side-line d2h-code-side-emptyplaceholder">
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-ins">
|
||||||
|
1
|
||||||
|
</td>
|
||||||
|
<td class="d2h-ins">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">+</span>
|
||||||
|
<span class="d2h-code-line-ctn">newLine1</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-info"></td>
|
||||||
|
<td class="d2h-info">
|
||||||
|
<div class="d2h-code-side-line"> </div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-ins d2h-change">
|
||||||
|
2
|
||||||
|
</td>
|
||||||
|
<td class="d2h-ins d2h-change">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">+</span>
|
||||||
|
<span class="d2h-code-line-ctn"><ins>newLine2</ins></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-cntx">
|
||||||
|
2
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">\\</span>
|
||||||
|
<span class="d2h-code-line-ctn"> No newline at end of file</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-info"></td>
|
||||||
|
<td class="d2h-info">
|
||||||
|
<div class="d2h-code-side-line"> </div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-code-side-emptyplaceholder d2h-cntx d2h-emptyplaceholder">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx d2h-emptyplaceholder">
|
||||||
|
<div class="d2h-code-side-line d2h-code-side-emptyplaceholder">
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-code-side-emptyplaceholder d2h-cntx d2h-emptyplaceholder">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx d2h-emptyplaceholder">
|
||||||
|
<div class="d2h-code-side-line d2h-code-side-emptyplaceholder">
|
||||||
|
<span class="d2h-code-line-prefix"> </span>
|
||||||
|
<span class="d2h-code-line-ctn"><br></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-ins">
|
||||||
|
3
|
||||||
|
</td>
|
||||||
|
<td class="d2h-ins">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">+</span>
|
||||||
|
<span class="d2h-code-line-ctn">newLine3</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td class="d2h-code-side-linenumber d2h-cntx">
|
||||||
|
3
|
||||||
|
</td>
|
||||||
|
<td class="d2h-cntx">
|
||||||
|
<div class="d2h-code-side-line">
|
||||||
|
<span class="d2h-code-line-prefix">\\</span>
|
||||||
|
<span class="d2h-code-line-ctn"> No newline at end of file</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should work for too big file diff', () => {
|
it('should work for too big file diff', () => {
|
||||||
const exampleJson = [
|
const exampleJson = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -87,16 +87,15 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil
|
||||||
const binaryFiles = /^Binary files (.*) and (.*) differ/;
|
const binaryFiles = /^Binary files (.*) and (.*) differ/;
|
||||||
const binaryDiff = /^GIT binary patch/;
|
const binaryDiff = /^GIT binary patch/;
|
||||||
|
|
||||||
|
const noNewlineAtEndOfFile = /^\\ No newline at end of file/;
|
||||||
|
|
||||||
/* Combined Diff */
|
/* Combined Diff */
|
||||||
const combinedIndex = /^index ([\da-z]+),([\da-z]+)\.\.([\da-z]+)/;
|
const combinedIndex = /^index ([\da-z]+),([\da-z]+)\.\.([\da-z]+)/;
|
||||||
const combinedMode = /^mode (\d{6}),(\d{6})\.\.(\d{6})/;
|
const combinedMode = /^mode (\d{6}),(\d{6})\.\.(\d{6})/;
|
||||||
const combinedNewFile = /^new file mode (\d{6})/;
|
const combinedNewFile = /^new file mode (\d{6})/;
|
||||||
const combinedDeletedFile = /^deleted file mode (\d{6}),(\d{6})/;
|
const combinedDeletedFile = /^deleted file mode (\d{6}),(\d{6})/;
|
||||||
|
|
||||||
const diffLines = diffInput
|
const diffLines = diffInput.replace(/\r\n?/g, '\n').split('\n');
|
||||||
.replace(/\\ No newline at end of file/g, '')
|
|
||||||
.replace(/\r\n?/g, '\n')
|
|
||||||
.split('\n');
|
|
||||||
|
|
||||||
/* Add previous block(if exists) before start a new file */
|
/* Add previous block(if exists) before start a new file */
|
||||||
function saveBlock(): void {
|
function saveBlock(): void {
|
||||||
|
|
@ -471,6 +470,8 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil
|
||||||
} else if ((values = combinedDeletedFile.exec(line))) {
|
} else if ((values = combinedDeletedFile.exec(line))) {
|
||||||
currentFile.deletedFileMode = values[1];
|
currentFile.deletedFileMode = values[1];
|
||||||
currentFile.isDeleted = true;
|
currentFile.isDeleted = true;
|
||||||
|
} else if (line.match(noNewlineAtEndOfFile)) {
|
||||||
|
createLine(line);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,8 @@ export function toCSSClass(lineType: LineType): CSSLineClass {
|
||||||
return CSSLineClass.INSERTS;
|
return CSSLineClass.INSERTS;
|
||||||
case LineType.DELETE:
|
case LineType.DELETE:
|
||||||
return CSSLineClass.DELETES;
|
return CSSLineClass.DELETES;
|
||||||
|
case LineType.NO_NEW_LINE:
|
||||||
|
return CSSLineClass.CONTEXT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import {
|
||||||
DiffLineDeleted,
|
DiffLineDeleted,
|
||||||
DiffLineInserted,
|
DiffLineInserted,
|
||||||
DiffLineContent,
|
DiffLineContent,
|
||||||
|
DiffLineNoNewline,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
export interface SideBySideRendererConfig extends renderUtils.RenderConfig {
|
export interface SideBySideRendererConfig extends renderUtils.RenderConfig {
|
||||||
|
|
@ -114,20 +115,39 @@ export default class SideBySideRenderer {
|
||||||
} else if (contextLines.length) {
|
} else if (contextLines.length) {
|
||||||
contextLines.forEach(line => {
|
contextLines.forEach(line => {
|
||||||
const { prefix, content } = renderUtils.deconstructLine(line.content, file.isCombined);
|
const { prefix, content } = renderUtils.deconstructLine(line.content, file.isCombined);
|
||||||
const { left, right } = this.generateLineHtml(
|
let leftContext = undefined;
|
||||||
{
|
let rightContext = undefined;
|
||||||
|
if (line.type !== LineType.NO_NEW_LINE) {
|
||||||
|
leftContext = {
|
||||||
type: renderUtils.CSSLineClass.CONTEXT,
|
type: renderUtils.CSSLineClass.CONTEXT,
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
content: content,
|
content: content,
|
||||||
number: line.oldNumber,
|
number: line.oldNumber,
|
||||||
},
|
};
|
||||||
{
|
rightContext = {
|
||||||
type: renderUtils.CSSLineClass.CONTEXT,
|
type: renderUtils.CSSLineClass.CONTEXT,
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
content: content,
|
content: content,
|
||||||
number: line.newNumber,
|
number: line.newNumber,
|
||||||
},
|
};
|
||||||
);
|
} else if (line.type === LineType.NO_NEW_LINE) {
|
||||||
|
if (line.isLeft) {
|
||||||
|
leftContext = {
|
||||||
|
type: renderUtils.CSSLineClass.CONTEXT,
|
||||||
|
prefix: prefix,
|
||||||
|
content: content,
|
||||||
|
number: line.oldNumber,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
rightContext = {
|
||||||
|
type: renderUtils.CSSLineClass.CONTEXT,
|
||||||
|
prefix: prefix,
|
||||||
|
content: content,
|
||||||
|
number: line.newNumber,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { left, right } = this.generateLineHtml(leftContext, rightContext);
|
||||||
fileHtml.left += left;
|
fileHtml.left += left;
|
||||||
fileHtml.right += right;
|
fileHtml.right += right;
|
||||||
});
|
});
|
||||||
|
|
@ -155,6 +175,7 @@ export default class SideBySideRenderer {
|
||||||
|
|
||||||
let oldLines: (DiffLineDeleted & DiffLineContent)[] = [];
|
let oldLines: (DiffLineDeleted & DiffLineContent)[] = [];
|
||||||
let newLines: (DiffLineInserted & DiffLineContent)[] = [];
|
let newLines: (DiffLineInserted & DiffLineContent)[] = [];
|
||||||
|
let lastLineType: LineType = LineType.DELETE;
|
||||||
|
|
||||||
for (let i = 0; i < block.lines.length; i++) {
|
for (let i = 0; i < block.lines.length; i++) {
|
||||||
const diffLine = block.lines[i];
|
const diffLine = block.lines[i];
|
||||||
|
|
@ -169,7 +190,16 @@ export default class SideBySideRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diffLine.type === LineType.CONTEXT) {
|
if (diffLine.type === LineType.CONTEXT) {
|
||||||
blockLinesGroups.push([[diffLine], [], []]);
|
if (diffLine.content.trim() === '\\ No newline at end of file') {
|
||||||
|
const noNewLine: DiffLineNoNewline & DiffLineContent = {
|
||||||
|
...diffLine,
|
||||||
|
isLeft: lastLineType === LineType.DELETE,
|
||||||
|
type: LineType.NO_NEW_LINE,
|
||||||
|
};
|
||||||
|
blockLinesGroups.push([[noNewLine], [], []]);
|
||||||
|
} else {
|
||||||
|
blockLinesGroups.push([[diffLine], [], []]);
|
||||||
|
}
|
||||||
} else if (diffLine.type === LineType.INSERT && oldLines.length === 0) {
|
} else if (diffLine.type === LineType.INSERT && oldLines.length === 0) {
|
||||||
blockLinesGroups.push([[], [], [diffLine]]);
|
blockLinesGroups.push([[], [], [diffLine]]);
|
||||||
} else if (diffLine.type === LineType.INSERT && oldLines.length > 0) {
|
} else if (diffLine.type === LineType.INSERT && oldLines.length > 0) {
|
||||||
|
|
@ -177,6 +207,11 @@ export default class SideBySideRenderer {
|
||||||
} else if (diffLine.type === LineType.DELETE) {
|
} else if (diffLine.type === LineType.DELETE) {
|
||||||
oldLines.push(diffLine);
|
oldLines.push(diffLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track the last non-context line type to determine where "No newline" belongs
|
||||||
|
if (diffLine.type !== LineType.CONTEXT) {
|
||||||
|
lastLineType = diffLine.type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldLines.length || newLines.length) {
|
if (oldLines.length || newLines.length) {
|
||||||
|
|
@ -296,7 +331,7 @@ export default class SideBySideRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiffLineGroups = [
|
type DiffLineGroups = [
|
||||||
(DiffLineContext & DiffLineContent)[],
|
((DiffLineContext & DiffLineContent) | (DiffLineNoNewline & DiffLineContent))[],
|
||||||
(DiffLineDeleted & DiffLineContent)[],
|
(DiffLineDeleted & DiffLineContent)[],
|
||||||
(DiffLineInserted & DiffLineContent)[],
|
(DiffLineInserted & DiffLineContent)[],
|
||||||
][];
|
][];
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ export enum LineType {
|
||||||
INSERT = 'insert',
|
INSERT = 'insert',
|
||||||
DELETE = 'delete',
|
DELETE = 'delete',
|
||||||
CONTEXT = 'context',
|
CONTEXT = 'context',
|
||||||
|
NO_NEW_LINE = 'noNewLine',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DiffLineDeleted {
|
export interface DiffLineDeleted {
|
||||||
|
|
@ -27,6 +28,13 @@ export interface DiffLineContext {
|
||||||
newNumber: number;
|
newNumber: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DiffLineNoNewline {
|
||||||
|
type: LineType.NO_NEW_LINE;
|
||||||
|
oldNumber: number;
|
||||||
|
newNumber: number;
|
||||||
|
isLeft: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export type DiffLineContent = {
|
export type DiffLineContent = {
|
||||||
content: string;
|
content: string;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue