mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-09-11 12:25:42 +03:00
Merge pull request #42 from gitbutlerapp/sc-render-removals
Better rendering of removed files
This commit is contained in:
commit
d2fdecc752
@ -1,165 +1,165 @@
|
||||
import { Operation, type DiffArray, charDiff } from './diff';
|
||||
|
||||
export interface Token {
|
||||
text: string;
|
||||
className: string;
|
||||
text: string;
|
||||
className: string;
|
||||
}
|
||||
|
||||
export interface Row {
|
||||
originalLineNumber: number;
|
||||
currentLineNumber: number;
|
||||
tokens: Token[];
|
||||
type: RowType;
|
||||
size: number;
|
||||
originalLineNumber: number;
|
||||
currentLineNumber: number;
|
||||
tokens: Token[];
|
||||
type: RowType;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export const enum RowType {
|
||||
Deletion = 'deletion',
|
||||
Addition = 'addition',
|
||||
Equal = 'equal',
|
||||
Spacer = 'spacer'
|
||||
Deletion = 'deletion',
|
||||
Addition = 'addition',
|
||||
Equal = 'equal',
|
||||
Spacer = 'spacer'
|
||||
}
|
||||
|
||||
export function buildDiffRows(
|
||||
diff: DiffArray,
|
||||
opts = { paddingLines: 10000 }
|
||||
diff: DiffArray,
|
||||
opts = { paddingLines: 10000 }
|
||||
): {
|
||||
originalLines: readonly string[];
|
||||
currentLines: readonly string[];
|
||||
rows: readonly Row[];
|
||||
originalLines: readonly string[];
|
||||
currentLines: readonly string[];
|
||||
rows: readonly Row[];
|
||||
} {
|
||||
const { paddingLines } = opts;
|
||||
const { paddingLines } = opts;
|
||||
|
||||
let currentLineNumber = 0;
|
||||
let originalLineNumber = 0;
|
||||
let currentLineNumber = 0;
|
||||
let originalLineNumber = 0;
|
||||
|
||||
const originalLines: string[] = [];
|
||||
const currentLines: string[] = [];
|
||||
const rows: Row[] = [];
|
||||
const originalLines: string[] = [];
|
||||
const currentLines: string[] = [];
|
||||
const rows: Row[] = [];
|
||||
|
||||
for (let i = 0; i < diff.length; ++i) {
|
||||
const token = diff[i];
|
||||
switch (token[0]) {
|
||||
case Operation.Equal:
|
||||
rows.push(...createEqualRows(token[1], i === 0, i === diff.length - 1));
|
||||
originalLines.push(...token[1]);
|
||||
currentLines.push(...token[1]);
|
||||
break;
|
||||
case Operation.Insert:
|
||||
for (const line of token[1]) {
|
||||
rows.push(createRow(line, RowType.Addition));
|
||||
}
|
||||
currentLines.push(...token[1]);
|
||||
break;
|
||||
case Operation.Delete:
|
||||
originalLines.push(...token[1]);
|
||||
if (diff[i + 1] && diff[i + 1][0] === Operation.Insert) {
|
||||
i++;
|
||||
rows.push(...createModifyRows(token[1].join('\n'), diff[i][1].join('\n')));
|
||||
currentLines.push(...diff[i][1]);
|
||||
} else {
|
||||
for (const line of token[1]) {
|
||||
rows.push(createRow(line, RowType.Deletion));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < diff.length; ++i) {
|
||||
const token = diff[i];
|
||||
switch (token[0]) {
|
||||
case Operation.Equal:
|
||||
rows.push(...createEqualRows(token[1], i === 0, i === diff.length - 1));
|
||||
originalLines.push(...token[1]);
|
||||
currentLines.push(...token[1]);
|
||||
break;
|
||||
case Operation.Insert:
|
||||
for (const line of token[1]) {
|
||||
rows.push(createRow(line, RowType.Addition));
|
||||
}
|
||||
currentLines.push(...token[1]);
|
||||
break;
|
||||
case Operation.Delete:
|
||||
originalLines.push(...token[1]);
|
||||
if (diff[i + 1] && diff[i + 1][0] === Operation.Insert) {
|
||||
i++;
|
||||
rows.push(...createModifyRows(token[1].join('\n'), diff[i][1].join('\n')));
|
||||
currentLines.push(...diff[i][1]);
|
||||
} else {
|
||||
for (const line of token[1]) {
|
||||
rows.push(createRow(line, RowType.Deletion));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { originalLines, currentLines, rows };
|
||||
return { originalLines, currentLines, rows };
|
||||
|
||||
function createEqualRows(lines: string[], atStart: boolean, atEnd: boolean): Row[] {
|
||||
const equalRows = [];
|
||||
if (!atStart) {
|
||||
for (let i = 0; i < paddingLines && i < lines.length; i++) {
|
||||
equalRows.push(createRow(lines[i], RowType.Equal));
|
||||
}
|
||||
if (lines.length > paddingLines * 2 + 1 && !atEnd) {
|
||||
equalRows.push(
|
||||
createRow(
|
||||
`skipping ${lines.length - paddingLines * 2} matching lines`,
|
||||
RowType.Spacer,
|
||||
lines.length - paddingLines * 2
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!atEnd) {
|
||||
const start = Math.max(lines.length - paddingLines - 1, atStart ? 0 : paddingLines);
|
||||
let skip = lines.length - paddingLines - 1;
|
||||
if (!atStart) {
|
||||
skip -= paddingLines;
|
||||
}
|
||||
if (skip > 0) {
|
||||
originalLineNumber += skip;
|
||||
currentLineNumber += skip;
|
||||
}
|
||||
function createEqualRows(lines: string[], atStart: boolean, atEnd: boolean): Row[] {
|
||||
const equalRows = [];
|
||||
if (!atStart) {
|
||||
for (let i = 0; i < paddingLines && i < lines.length; i++) {
|
||||
equalRows.push(createRow(lines[i], RowType.Equal));
|
||||
}
|
||||
if (lines.length > paddingLines * 2 + 1 && !atEnd) {
|
||||
equalRows.push(
|
||||
createRow(
|
||||
`skipping ${lines.length - paddingLines * 2} matching lines`,
|
||||
RowType.Spacer,
|
||||
lines.length - paddingLines * 2
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!atEnd) {
|
||||
const start = Math.max(lines.length - paddingLines - 1, atStart ? 0 : paddingLines);
|
||||
let skip = lines.length - paddingLines - 1;
|
||||
if (!atStart) {
|
||||
skip -= paddingLines;
|
||||
}
|
||||
if (skip > 0) {
|
||||
originalLineNumber += skip;
|
||||
currentLineNumber += skip;
|
||||
}
|
||||
|
||||
for (let i = start; i < lines.length; i++) {
|
||||
equalRows.push(createRow(lines[i], RowType.Equal));
|
||||
}
|
||||
}
|
||||
return equalRows;
|
||||
}
|
||||
for (let i = start; i < lines.length; i++) {
|
||||
equalRows.push(createRow(lines[i], RowType.Equal));
|
||||
}
|
||||
}
|
||||
return equalRows;
|
||||
}
|
||||
|
||||
function createModifyRows(before: string, after: string): Row[] {
|
||||
const internalDiff = charDiff(before, after, true /* cleanup diff */);
|
||||
const deletionRows = [createRow('', RowType.Deletion)];
|
||||
const insertionRows = [createRow('', RowType.Addition)];
|
||||
function createModifyRows(before: string, after: string): Row[] {
|
||||
const internalDiff = charDiff(before, after, true /* cleanup diff */);
|
||||
const deletionRows = [createRow('', RowType.Deletion)];
|
||||
const insertionRows = [createRow('', RowType.Addition)];
|
||||
|
||||
for (const token of internalDiff) {
|
||||
const text = token[1];
|
||||
const type = token[0];
|
||||
const className = type === Operation.Equal ? '' : 'inner-diff';
|
||||
const lines = text.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (i > 0 && type !== Operation.Insert) {
|
||||
deletionRows.push(createRow('', RowType.Deletion));
|
||||
}
|
||||
if (i > 0 && type !== Operation.Delete) {
|
||||
insertionRows.push(createRow('', RowType.Addition));
|
||||
}
|
||||
if (!lines[i]) {
|
||||
continue;
|
||||
}
|
||||
if (type !== Operation.Insert) {
|
||||
deletionRows[deletionRows.length - 1].tokens.push({ text: lines[i], className });
|
||||
}
|
||||
if (type !== Operation.Delete) {
|
||||
insertionRows[insertionRows.length - 1].tokens.push({ text: lines[i], className });
|
||||
}
|
||||
}
|
||||
}
|
||||
return deletionRows.concat(insertionRows);
|
||||
}
|
||||
for (const token of internalDiff) {
|
||||
const text = token[1];
|
||||
const type = token[0];
|
||||
const className = type === Operation.Equal ? '' : 'inner-diff';
|
||||
const lines = text.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (i > 0 && type !== Operation.Insert) {
|
||||
deletionRows.push(createRow('', RowType.Deletion));
|
||||
}
|
||||
if (i > 0 && type !== Operation.Delete) {
|
||||
insertionRows.push(createRow('', RowType.Addition));
|
||||
}
|
||||
if (!lines[i]) {
|
||||
continue;
|
||||
}
|
||||
if (type !== Operation.Insert) {
|
||||
deletionRows[deletionRows.length - 1].tokens.push({ text: lines[i], className });
|
||||
}
|
||||
if (type !== Operation.Delete) {
|
||||
insertionRows[insertionRows.length - 1].tokens.push({ text: lines[i], className });
|
||||
}
|
||||
}
|
||||
}
|
||||
return deletionRows.concat(insertionRows);
|
||||
}
|
||||
|
||||
function createRow(text: string, type: RowType, size = 1): Row {
|
||||
if (type === RowType.Addition) {
|
||||
currentLineNumber++;
|
||||
}
|
||||
if (type === RowType.Deletion) {
|
||||
originalLineNumber++;
|
||||
}
|
||||
if (type === RowType.Equal) {
|
||||
originalLineNumber++;
|
||||
currentLineNumber++;
|
||||
}
|
||||
function createRow(text: string, type: RowType, size = 1): Row {
|
||||
if (type === RowType.Addition) {
|
||||
currentLineNumber++;
|
||||
}
|
||||
if (type === RowType.Deletion) {
|
||||
originalLineNumber++;
|
||||
}
|
||||
if (type === RowType.Equal) {
|
||||
originalLineNumber++;
|
||||
currentLineNumber++;
|
||||
}
|
||||
|
||||
return {
|
||||
originalLineNumber,
|
||||
currentLineNumber,
|
||||
tokens: text ? [{ text, className: 'inner-diff' }] : [],
|
||||
type,
|
||||
size
|
||||
};
|
||||
}
|
||||
return {
|
||||
originalLineNumber,
|
||||
currentLineNumber,
|
||||
tokens: text ? [{ text, className: 'inner-diff' }] : [],
|
||||
type,
|
||||
size
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function documentMap(lines: readonly string[]): Map<number, number> {
|
||||
const map = new Map<number, number>();
|
||||
for (let pos = 0, lineNo = 0; lineNo < lines.length; lineNo++) {
|
||||
map.set(lineNo + 1, pos);
|
||||
pos += lines[lineNo].length + 1;
|
||||
}
|
||||
return map;
|
||||
const map = new Map<number, number>();
|
||||
for (let pos = 0, lineNo = 0; lineNo < lines.length; lineNo++) {
|
||||
map.set(lineNo + 1, pos);
|
||||
pos += lines[lineNo].length + 1;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
let middleDiff = '';
|
||||
let currentOffset = 0;
|
||||
|
||||
let htmlTagRegex = /(<([^>]+)>)/gi;
|
||||
|
||||
$: if (diff) {
|
||||
middleDiff = '';
|
||||
currentDiff = '';
|
||||
@ -28,15 +30,16 @@
|
||||
let diffLines = middleDiff.split('<br>');
|
||||
diffLines.forEach((line, index) => {
|
||||
lineClass = 'lineContext bg-zinc-800';
|
||||
let firstChar = line.replace(htmlTagRegex, '').slice(0, 1);
|
||||
if (index < 4) {
|
||||
lineClass = 'lineDiff bg-zinc-900 text-zinc-500';
|
||||
} else if (line.slice(0, 2) == '@@') {
|
||||
lineClass = 'lineSplit bg-blue-900';
|
||||
} else if (line.slice(0, 1) == '+') {
|
||||
} else if (firstChar == '+') {
|
||||
if (!line.includes('+++')) {
|
||||
lineClass = 'lineSplit bg-green-900';
|
||||
}
|
||||
} else if (line.slice(0, 1) == '-') {
|
||||
} else if (firstChar == '-') {
|
||||
if (!line.includes('---')) {
|
||||
lineClass = 'lineSplit bg-red-900';
|
||||
}
|
||||
|
@ -76,21 +76,24 @@
|
||||
|
||||
let currentPath = '';
|
||||
let currentDiff = '';
|
||||
let addedContents = '';
|
||||
let fileContents = '';
|
||||
let fileContentsStatus = '';
|
||||
|
||||
// Replace HTML tags with an empty string
|
||||
function selectPath(path) {
|
||||
currentDiff = '';
|
||||
addedContents = '';
|
||||
fileContents = '';
|
||||
|
||||
if (gitDiff[path]) {
|
||||
currentPath = path;
|
||||
currentDiff = gitDiff[path];
|
||||
} else {
|
||||
let file = $filesStatus.filter((file) => file.path === path)[0];
|
||||
if (file && file.status === 'added') {
|
||||
if (file) {
|
||||
fileContentsStatus = file.status;
|
||||
getFile({ projectId: $project?.id, path: path }).then((contents) => {
|
||||
currentPath = path;
|
||||
addedContents = contents;
|
||||
fileContents = contents;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -278,8 +281,9 @@
|
||||
<div class="h-100 h-full max-h-screen flex-grow overflow-auto p-2">
|
||||
{#if currentDiff}
|
||||
<DiffViewer diff={currentDiff} path={currentPath} />
|
||||
{:else if addedContents}
|
||||
<pre class="bg-green-900">{addedContents}</pre>
|
||||
{:else if fileContents}
|
||||
<pre
|
||||
class={fileContentsStatus == 'added' ? 'bg-green-900' : 'bg-red-900'}>{fileContents}</pre>
|
||||
{:else}
|
||||
<div class="p-20 text-center text-lg text-zinc-400">Select a file to view changes.</div>
|
||||
{/if}
|
||||
|
Loading…
Reference in New Issue
Block a user