Skip to content

Commit

Permalink
[chore] wip pretty line diff
Browse files Browse the repository at this point in the history
  • Loading branch information
MrWangJustToDo committed Jun 21, 2024
1 parent df0426b commit d8d1bfe
Show file tree
Hide file tree
Showing 19 changed files with 194 additions and 671 deletions.
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,9 @@ a React/Vue component to show the `git diff`/`file diff` result, just like Githu
```shell
# In React Project
pnpm add @git-diff-view/react
# full type need install
pnpm add -D @git-diff-view/core

# In Vue Project
pnpm add @git-diff-view/vue
# full type need install
pnpm add -D @git-diff-view/core

```

Expand Down Expand Up @@ -99,7 +95,7 @@ import "@git-diff-view/react/styles/diff-view.css";

```

#### 2. Use the `DiffView` component with `@git-diff-view/core`/`@git-diff-view/file`
#### 2. Use the `DiffView` component with `@git-diff-view/core` or `@git-diff-view/file`

```tsx
// with @git-diff-view/file
Expand Down
12 changes: 7 additions & 5 deletions packages/core/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Generated by dts-bundle-generator v9.5.1

import fastDiff from 'fast-diff';

export declare enum NewLineSymbol {
CRLF = 1,
CR = 2,
Expand Down Expand Up @@ -37,11 +39,10 @@ export declare class DiffLine {
readonly noTrailingNewLine: boolean;
needRematch: boolean;
range?: IRange;
constructor(text: string, type: DiffLineType, originalLineNumber: number | null, oldLineNumber: number | null, newLineNumber: number | null, noTrailingNewLine?: boolean, needRematch?: boolean, range?: IRange);
diffRange?: ReturnType<typeof fastDiff>;
constructor(text: string, type: DiffLineType, originalLineNumber: number | null, oldLineNumber: number | null, newLineNumber: number | null, noTrailingNewLine?: boolean, needRematch?: boolean, range?: IRange, diffRange?: ReturnType<typeof fastDiff>);
withNoTrailingNewLine(noTrailingNewLine: boolean): DiffLine;
isIncludeableLine(): boolean;
/** The content of the line, i.e., without the line type marker. */
get content(): string;
equals(other: DiffLine): boolean;
clone(text: string): DiffLine;
}
Expand Down Expand Up @@ -371,7 +372,7 @@ declare class File$1 {
}): void;
doRaw(): void;
}
export declare const getFile: (raw: string, lang: string, fileName?: string) => File$1;
export declare const getFile: (raw: string, lang: string, fileName?: string, uuid?: string) => File$1;
export declare const _cacheMap: Cache$1<string, File$1>;
export declare const composeLen = 40;
export interface SplitLineItem {
Expand Down Expand Up @@ -423,6 +424,7 @@ export declare class DiffFile {
readonly _oldFileName: string;
readonly _newFileName: string;
readonly _diffList: string[];
readonly uuid?: string;
_version_: string;
_oldFileContent: string;
_oldFileLang: string;
Expand All @@ -448,7 +450,7 @@ export declare class DiffFile {
};
hunks?: string[];
}, bundle?: ReturnType<DiffFile["getBundle"] | DiffFile["_getFullBundle"]>): DiffFile;
constructor(_oldFileName: string, _oldFileContent: string, _newFileName: string, _newFileContent: string, _diffList: string[], _oldFileLang?: string, _newFileLang?: string);
constructor(_oldFileName: string, _oldFileContent: string, _newFileName: string, _newFileContent: string, _diffList: string[], _oldFileLang?: string, _newFileLang?: string, uuid?: string);
initId(): void;
getId(): string;
clearId(): void;
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
],
"dependencies": {
"@git-diff-view/lowlight": "^0.0.14",
"fast-diff": "^1.3.0",
"highlight.js": "^11.9.0",
"lowlight": "^3.1.0"
},
Expand Down
45 changes: 38 additions & 7 deletions packages/core/src/diff-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ export class DiffFile {
_newFileContent: string,
readonly _diffList: string[],
_oldFileLang?: string,
_newFileLang?: string
_newFileLang?: string,
readonly uuid?: string
) {
Object.defineProperty(this, "__v_skip", { value: true });
let oldContent = _oldFileContent;
Expand Down Expand Up @@ -213,11 +214,21 @@ export class DiffFile {
if (!this._oldFileContent && !this._newFileContent) return;

if (this._oldFileContent) {
this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang, this._oldFileName);
this.#oldFileResult = getFile(
this._oldFileContent,
this._oldFileLang,
this._oldFileName,
this.uuid ? this.uuid + "-old" : undefined
);
}

if (this._newFileContent) {
this.#newFileResult = getFile(this._newFileContent, this._newFileLang, this._newFileName);
this.#newFileResult = getFile(
this._newFileContent,
this._newFileLang,
this._newFileName,
this.uuid ? this.uuid + "-new" : undefined
);
}
}

Expand Down Expand Up @@ -277,8 +288,18 @@ export class DiffFile {
if (!hasSymbolChanged && oldFileContent === newFileContent) return;
this._oldFileContent = oldFileContent;
this._newFileContent = newFileContent;
this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang, this._oldFileName);
this.#newFileResult = getFile(this._newFileContent, this._newFileLang, this._newFileName);
this.#oldFileResult = getFile(
this._oldFileContent,
this._oldFileLang,
this._oldFileName,
this.uuid ? this.uuid + "-old" : undefined
);
this.#newFileResult = getFile(
this._newFileContent,
this._newFileLang,
this._newFileName,
this.uuid ? this.uuid + "-new" : undefined
);
this.#oldFilePlaceholderLines = oldFilePlaceholderLines;
this.#newFilePlaceholderLines = newFilePlaceholderLines;
// all of the file just compose by diff, so we can not do the expand action
Expand Down Expand Up @@ -306,7 +327,12 @@ export class DiffFile {
}
if (!hasSymbolChanged && newFileContent === this._oldFileContent) return;
this._newFileContent = newFileContent;
this.#newFileResult = getFile(this._newFileContent, this._newFileLang, this._newFileName);
this.#newFileResult = getFile(
this._newFileContent,
this._newFileLang,
this._newFileName,
this.uuid ? this.uuid + "-new" : undefined
);
} else if (this.#newFileResult) {
let oldLineNumber = 1;
let newLineNumber = 1;
Expand All @@ -330,7 +356,12 @@ export class DiffFile {
}
if (!hasSymbolChanged && oldFileContent === this._newFileContent) return;
this._oldFileContent = oldFileContent;
this.#oldFileResult = getFile(this._oldFileContent, this._oldFileLang, this._oldFileName);
this.#oldFileResult = getFile(
this._oldFileContent,
this._oldFileLang,
this._oldFileName,
this.uuid ? this.uuid + "-old" : undefined
);
}

this.#composeRaw();
Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,12 @@ export class File {
}
}

export const getFile = (raw: string, lang: string, fileName?: string) => {
const key = raw + "--" + __VERSION__ + "--" + lang;
export const getFile = (raw: string, lang: string, fileName?: string, uuid?: string) => {
let key = raw + "--" + __VERSION__ + "--" + lang;

if (uuid) {
key = uuid + "--" + __VERSION__ + "--" + lang;
}

if (map.has(key)) return map.get(key);

Expand Down
99 changes: 90 additions & 9 deletions packages/core/src/parse/change-range.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import fastDiff from "fast-diff";

import type { DiffLine } from "./diff-line";

export enum NewLineSymbol {
CRLF = 1,
CR = 2,
LF = 3,
NEWLINE = 4,
NORMAL = 5,
}

export interface IRange {
Expand All @@ -17,6 +20,12 @@ export interface IRange {
readonly newLineSymbol?: NewLineSymbol;
}

export interface DiffRange {
readonly range: ReturnType<typeof fastDiff>;

readonly newLineSymbol?: NewLineSymbol;
}

const maxLength = 1000;

/** Get the maximum position in the range. */
Expand Down Expand Up @@ -47,6 +56,35 @@ function isInValidString(s: string) {
return s.trim().length === 0 || s.length >= maxLength;
}

function checkNewLineSymbolChange(
addition: DiffLine,
deletion: DiffLine
): { addSymbol: NewLineSymbol; delSymbol: NewLineSymbol } {
const stringA = addition.text;

const stringB = deletion.text;

const aEndStr = stringA.slice(-2);

const bEndStr = stringB.slice(-2);

const aSymbol =
aEndStr === "\r\n" ? NewLineSymbol.CRLF : aEndStr.endsWith("\r") ? NewLineSymbol.CR : NewLineSymbol.LF;

const bSymbol =
bEndStr === "\r\n" ? NewLineSymbol.CRLF : bEndStr.endsWith("\r") ? NewLineSymbol.CR : NewLineSymbol.LF;

const hasNewLineChanged = addition.noTrailingNewLine !== deletion.noTrailingNewLine;

if (hasNewLineChanged) {
return {
addSymbol: addition.noTrailingNewLine ? NewLineSymbol.NEWLINE : NewLineSymbol.NORMAL,
delSymbol: deletion.noTrailingNewLine ? NewLineSymbol.NEWLINE : NewLineSymbol.NORMAL,
};
}
return { addSymbol: aSymbol, delSymbol: bSymbol };
}

// TODO maybe could use the original content line
/** Get the changed ranges in the strings, relative to each other. */
export function relativeChanges(
Expand Down Expand Up @@ -117,20 +155,63 @@ export function relativeChanges(

/** Check two string have a diff range */
export function hasRelativeChange(addition: DiffLine, deletion: DiffLine): boolean {
const stringA = addition.text;

const stringB = deletion.text;

const _stringA = addition.text.trim();

const _stringB = deletion.text.trim();

const _addition = addition.clone(_stringA);
const aEndStr = stringA.slice(-2);

const bEndStr = stringB.slice(-2);

const aSymbol =
aEndStr === "\r\n" ? NewLineSymbol.CRLF : aEndStr.endsWith("\r") ? NewLineSymbol.CR : NewLineSymbol.LF;

const bSymbol =
bEndStr === "\r\n" ? NewLineSymbol.CRLF : bEndStr.endsWith("\r") ? NewLineSymbol.CR : NewLineSymbol.LF;

if (_stringA === _stringB) {
return true;
}

const _deletion = deletion.clone(_stringB);
if (
_stringA[0] === _stringB[0] ||
(_stringA[_stringA.length - 1] === _stringB[_stringB.length - 1] && aSymbol === bSymbol)
) {
return true;
}

const { stringARange, stringBRange } = relativeChanges(_addition, _deletion);
return false;
}

return (
stringARange.location > 0 ||
stringBRange.location > 0 ||
stringARange.length < _stringA.length ||
stringBRange.length < _stringB.length
);
export function diffChanges(
addition: DiffLine,
deletion: DiffLine
): { stringARange: DiffRange; stringBRange: DiffRange } {
const stringA = addition.text;

const stringB = deletion.text;

const _stringA = stringA.trimEnd();

const _stringB = stringB.trimEnd();

const res = checkNewLineSymbolChange(addition, deletion);

if (isInValidString(stringA) || isInValidString(stringB)) {
return {
stringARange: { range: [], newLineSymbol: res.addSymbol },
stringBRange: { range: [], newLineSymbol: res.delSymbol },
};
}

const diffRange = fastDiff(_stringA, _stringB, 0, true);

return {
stringARange: { range: diffRange, newLineSymbol: res.addSymbol },
stringBRange: { range: diffRange, newLineSymbol: res.delSymbol },
};
}
11 changes: 4 additions & 7 deletions packages/core/src/parse/diff-line.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { IRange } from "./change-range";
import type { DiffRange, IRange } from "./change-range";


/** indicate what a line in the diff represents */
export enum DiffLineType {
Expand All @@ -20,7 +21,8 @@ export class DiffLine {
public readonly newLineNumber: number | null,
public readonly noTrailingNewLine: boolean = false,
public needRematch: boolean = false,
public range?: IRange
public range?: IRange,
public diffRange?: DiffRange
) {}

public withNoTrailingNewLine(noTrailingNewLine: boolean): DiffLine {
Expand All @@ -38,11 +40,6 @@ export class DiffLine {
return this.type === DiffLineType.Add || this.type === DiffLineType.Delete;
}

/** The content of the line, i.e., without the line type marker. */
public get content(): string {
return this.text.substring(1);
}

public equals(other: DiffLine) {
return (
this.text === other.text &&
Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/parse/diff-tool.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { hasRelativeChange, relativeChanges } from "./change-range";
import { diffChanges, hasRelativeChange, relativeChanges } from "./change-range";
import { DiffLineType } from "./diff-line";
import { DiffHunkExpansionType } from "./raw-diff";

Expand Down Expand Up @@ -100,10 +100,14 @@ export const getDiffRange = (additions: DiffLine[], deletions: DiffLine[]) => {
const hasDiffRange = hasRelativeChange(addition, deletion);
if (hasDiffRange) {
const { stringARange, stringBRange } = relativeChanges(addition, deletion);
const { stringARange: _stringARange, stringBRange: _stringBRange } = diffChanges(addition, deletion);
addition.needRematch = true;
addition.range = stringARange;
deletion.needRematch = true;
deletion.range = stringBRange;
// TODO implement line diff
addition.diffRange = _stringARange;
deletion.diffRange = _stringBRange;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/file/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"diff parse"
],
"dependencies": {
"@git-diff-view/core": "v0.0.14",
"@git-diff-view/core": "^0.0.14",
"diff": "^5.2.0",
"highlight.js": "^11.9.0",
"lowlight": "^3.1.0"
Expand Down
Loading

0 comments on commit d8d1bfe

Please sign in to comment.