Skip to content

Commit b761473

Browse files
fast diff template
1 parent 4846599 commit b761473

File tree

12 files changed

+284
-362
lines changed

12 files changed

+284
-362
lines changed

packages/core/index.d.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ export declare const getDiffRange: (additions: DiffLine[], deletions: DiffLine[]
437437
getAdditionSyntax: (lineNumber: number) => SyntaxLineWithTemplate;
438438
getDeletionSyntax: (lineNumber: number) => SyntaxLineWithTemplate;
439439
}) => void;
440+
export declare const getEnableFastDiffTemplate: () => boolean;
440441
export declare const getLang: (fileName: string) => string;
441442
export declare const getPlainDiffTemplate: ({ diffLine, rawLine, operator, }: {
442443
diffLine: DiffLine;
@@ -456,6 +457,11 @@ export declare const getSyntaxDiffTemplate: ({ diffLine, syntaxLine, operator, }
456457
syntaxLine: SyntaxLineWithTemplate;
457458
operator: "add" | "del";
458459
}) => void;
460+
export declare const getSyntaxDiffTemplateByFastDiff: ({ diffLine, syntaxLine, operator, }: {
461+
diffLine: DiffLine;
462+
syntaxLine: SyntaxLineWithTemplate;
463+
operator: "add" | "del";
464+
}) => void;
459465
export declare const getSyntaxLineTemplate: (line: SyntaxLine) => string;
460466
export declare const getUnifiedContentLine: (diffFile: DiffFile) => DiffUnifiedContentLineItem[];
461467
export declare const getUnifiedLines: (diffFile: DiffFile) => DiffUnifiedLineItem[];
@@ -504,6 +510,7 @@ export declare const processTransformForFile: (content: string) => string;
504510
*/
505511
export declare const processTransformTemplateContent: (content: string) => string;
506512
export declare const resetDefaultComposeLength: () => void;
513+
export declare const resetEnableFastDiffTemplate: () => void;
507514
/**
508515
* Resets all transformation functions to their default state and disables transformation.
509516
*
@@ -513,6 +520,7 @@ export declare const resetDefaultComposeLength: () => void;
513520
* ```
514521
*/
515522
export declare const resetTransform: () => void;
523+
export declare const setEnableFastDiffTemplate: (enable: boolean) => void;
516524
/**
517525
* ⚠️ **WARNING: DANGEROUS OPERATION** ⚠️
518526
*
@@ -610,6 +618,7 @@ export declare function relativeChanges(addition: DiffLine, deletion: DiffLine):
610618
delRange: IRange;
611619
};
612620
export declare let composeLen: number;
621+
export declare let enableFastDiffTemplate: boolean;
613622
export interface DiffHunkItem extends DiffLineItem {
614623
isFirst: boolean;
615624
isLast: boolean;
@@ -625,7 +634,8 @@ export interface DiffRange {
625634
readonly range: {
626635
type: 1 | -1 | 0;
627636
str: string;
628-
location: number;
637+
startIndex: number;
638+
endIndex: number;
629639
length: number;
630640
}[];
631641
readonly hasLineChange?: boolean;

packages/core/src/parse/change-range.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export interface IRange {
1818
}
1919

2020
export interface DiffRange {
21-
readonly range: { type: 1 | -1 | 0; str: string; location: number; length: number }[];
21+
readonly range: { type: 1 | -1 | 0; str: string; startIndex: number; endIndex: number; length: number }[];
2222

2323
readonly hasLineChange?: boolean;
2424

@@ -216,11 +216,23 @@ export function diffChanges(addition: DiffLine, deletion: DiffLine): { addRange:
216216

217217
const aRange = diffRange
218218
.filter((i) => i[0] !== -1)
219-
.map((i) => ({ type: i[0], str: i[1], location: aStart, length: ((aStart += i[1].length), i[1].length) }));
219+
.map((i) => ({
220+
type: i[0],
221+
str: i[1],
222+
startIndex: aStart,
223+
endIndex: aStart + i[1].length - 1,
224+
length: ((aStart += i[1].length), i[1].length),
225+
}));
220226

221227
const bRange = diffRange
222228
.filter((i) => i[0] !== 1)
223-
.map((i) => ({ type: i[0], str: i[1], location: bStart, length: ((bStart += i[1].length), i[1].length) }));
229+
.map((i) => ({
230+
type: i[0],
231+
str: i[1],
232+
startIndex: bStart,
233+
endIndex: bStart + i[1].length - 1,
234+
length: ((bStart += i[1].length), i[1].length),
235+
}));
224236

225237
return {
226238
addRange: {

packages/core/src/parse/diff-tool.ts

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
import { relativeChanges } from "./change-range";
1+
import { diffChanges, relativeChanges } from "./change-range";
22
import { DiffLineType } from "./diff-line";
33
import { DiffHunkExpansionType } from "./raw-diff";
4-
import { getPlainDiffTemplate, getSyntaxDiffTemplate } from "./template";
4+
import {
5+
getEnableFastDiffTemplate,
6+
getPlainDiffTemplate,
7+
getPlainDiffTemplateByFastDiff,
8+
getSyntaxDiffTemplate,
9+
getSyntaxDiffTemplateByFastDiff,
10+
} from "./template";
511

612
import type { SyntaxLineWithTemplate } from "../file";
713
import type { DiffLine } from "./diff-line";
@@ -122,25 +128,53 @@ export const getDiffRange = (
122128
addition.changes = addRange;
123129
deletion.changes = delRange;
124130
}
125-
if (!addition.plainTemplate || !deletion.plainTemplate) {
126-
getPlainDiffTemplate({
131+
if (!getEnableFastDiffTemplate()) {
132+
if (!addition.plainTemplate || !deletion.plainTemplate) {
133+
getPlainDiffTemplate({
134+
diffLine: addition,
135+
rawLine: getAdditionRaw(addition.newLineNumber),
136+
operator: "add",
137+
});
138+
getPlainDiffTemplate({
139+
diffLine: deletion,
140+
rawLine: getDeletionRaw(deletion.oldLineNumber),
141+
operator: "del",
142+
});
143+
}
144+
if (!addition.syntaxTemplate || !deletion.syntaxTemplate) {
145+
getSyntaxDiffTemplate({
146+
diffLine: addition,
147+
syntaxLine: getAdditionSyntax(addition.newLineNumber),
148+
operator: "add",
149+
});
150+
getSyntaxDiffTemplate({
151+
diffLine: deletion,
152+
syntaxLine: getDeletionSyntax(deletion.oldLineNumber),
153+
operator: "del",
154+
});
155+
}
156+
} else {
157+
const _addition = addition.clone(getAdditionRaw(addition.newLineNumber) || addition.text || "");
158+
const _deletion = deletion.clone(getDeletionRaw(deletion.oldLineNumber) || deletion.text || "");
159+
const { addRange, delRange } = diffChanges(_addition, _deletion);
160+
addition.diffChanges = addRange;
161+
deletion.diffChanges = delRange;
162+
getPlainDiffTemplateByFastDiff({
127163
diffLine: addition,
128164
rawLine: getAdditionRaw(addition.newLineNumber),
129165
operator: "add",
130166
});
131-
getPlainDiffTemplate({
167+
getPlainDiffTemplateByFastDiff({
132168
diffLine: deletion,
133169
rawLine: getDeletionRaw(deletion.oldLineNumber),
134170
operator: "del",
135171
});
136-
}
137-
if (!addition.syntaxTemplate || !deletion.syntaxTemplate) {
138-
getSyntaxDiffTemplate({
172+
getSyntaxDiffTemplateByFastDiff({
139173
diffLine: addition,
140174
syntaxLine: getAdditionSyntax(addition.newLineNumber),
141175
operator: "add",
142176
});
143-
getSyntaxDiffTemplate({
177+
getSyntaxDiffTemplateByFastDiff({
144178
diffLine: deletion,
145179
syntaxLine: getDeletionSyntax(deletion.oldLineNumber),
146180
operator: "del",

packages/core/src/parse/template.ts

Lines changed: 134 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,19 @@ import type { SyntaxLineWithTemplate } from "../file";
88
import type { DiffLine } from "./diff-line";
99
import type { SyntaxLine } from "@git-diff-view/lowlight";
1010

11-
const defaultTransform = (content: string) => escapeHtml(content).replace(/\n/g, "").replace(/\r/g, "");
11+
let enableFastDiffTemplate = false;
12+
13+
export const getEnableFastDiffTemplate = () => enableFastDiffTemplate;
14+
15+
export const setEnableFastDiffTemplate = (enable: boolean) => {
16+
enableFastDiffTemplate = enable;
17+
};
18+
19+
export const resetEnableFastDiffTemplate = () => {
20+
enableFastDiffTemplate = false;
21+
};
22+
23+
export const defaultTransform = (content: string) => escapeHtml(content).replace(/\n/g, "").replace(/\r/g, "");
1224

1325
export const getPlainDiffTemplate = ({
1426
diffLine,
@@ -77,7 +89,7 @@ export const getPlainDiffTemplateByFastDiff = ({
7789

7890
let template = ``;
7991

80-
changes.range.forEach(({ type, str, location, length }, index, array) => {
92+
changes.range.forEach(({ type, str, startIndex, endIndex }, index, array) => {
8193
const isLatest = index === array.length - 1;
8294
if (type === 0) {
8395
template += `<span>${transform(str)}`;
@@ -87,7 +99,7 @@ export const getPlainDiffTemplateByFastDiff = ({
8799
: "";
88100
template += `</span>`;
89101
} else {
90-
template += `<span data-range-start="${location}" data-range-end="${location + length}">`;
102+
template += `<span data-range-start="${startIndex}" data-range-end="${endIndex}">`;
91103
template += `<span data-diff-highlight style="background-color: var(${operator === "add" ? addContentHighlightBGName : delContentHighlightBGName});border-radius: 0.2em;">${transform(str)}`;
92104
template +=
93105
isLatest && changes.newLineSymbol
@@ -166,6 +178,125 @@ export const getSyntaxDiffTemplate = ({
166178
diffLine.syntaxTemplateMode = "relative";
167179
};
168180

181+
export const getSyntaxDiffTemplateByFastDiff = ({
182+
diffLine,
183+
syntaxLine,
184+
operator,
185+
}: {
186+
diffLine: DiffLine;
187+
syntaxLine: SyntaxLineWithTemplate;
188+
operator: "add" | "del";
189+
}) => {
190+
if (!syntaxLine) return;
191+
192+
if (diffLine.syntaxTemplate && diffLine.syntaxTemplateMode === "fast-diff") return;
193+
194+
const changes = diffLine.diffChanges;
195+
196+
if (!changes || !changes.hasLineChange) return;
197+
198+
const transform = isTransformEnabled() ? processTransformTemplateContent : defaultTransform;
199+
200+
let template = "";
201+
202+
const allRange = changes.range.filter((item) => item.type !== 0);
203+
204+
let rangeIndex = 0;
205+
206+
syntaxLine?.nodeList?.forEach(({ node, wrapper }, index, array) => {
207+
template += `<span data-start="${node.startIndex}" data-end="${node.endIndex}" class="${(
208+
wrapper?.properties?.className || []
209+
)?.join(" ")}" style="${wrapper?.properties?.style || ""}">`;
210+
211+
let range = allRange[rangeIndex];
212+
213+
const isLastNode = index === array.length - 1;
214+
215+
for (let i = 0; i < node.value.length; i++) {
216+
const index = node.startIndex + i;
217+
const value = node.value[i];
218+
const isLastStr = i === node.value.length - 1;
219+
const isEndStr = isLastNode && i === node.value.length - 1;
220+
if (range) {
221+
// before start
222+
if (index < range.startIndex) {
223+
template += transform(value);
224+
if (isEndStr && changes.newLineSymbol) {
225+
template += `<span data-newline-symbol data-diff-highlight style="background-color: var(${operator === "add" ? addContentHighlightBGName : delContentHighlightBGName});border-radius: 0.2em;">${getSymbol(changes.newLineSymbol)}</span>`;
226+
}
227+
// start of range
228+
} else if (index === range.startIndex) {
229+
// current range all in the same node
230+
const isInSameNode = range.endIndex <= node.endIndex;
231+
if (isInSameNode) {
232+
template += `<span data-diff-highlight style="background-color: var(${operator === "add" ? addContentHighlightBGName : delContentHighlightBGName});border-radius: 0.2em;">`;
233+
} else {
234+
template += `<span data-diff-highlight style="background-color: var(${operator === "add" ? addContentHighlightBGName : delContentHighlightBGName});border-top-left-radius: 0.2em;border-bottom-left-radius: 0.2em;">`;
235+
}
236+
template += transform(value);
237+
if (isEndStr && changes.newLineSymbol) {
238+
template += `<span data-newline-symbol>${getSymbol(changes.newLineSymbol)}</span>`;
239+
}
240+
if (isLastStr) {
241+
template += `</span>`;
242+
} else if (range.startIndex === range.endIndex) {
243+
template += `</span>`;
244+
rangeIndex++;
245+
range = allRange[rangeIndex];
246+
}
247+
// inside range
248+
} else if (index < range.endIndex) {
249+
if (i === 0) {
250+
// current range all in the same node
251+
const isInSameNode = range.startIndex >= node.startIndex && range.endIndex <= node.endIndex;
252+
// current range end is in the same node
253+
const isEndInSameNode = range.endIndex <= node.endIndex;
254+
template += isInSameNode
255+
? `<span data-diff-highlight style="background-color: var(${operator === "add" ? addContentHighlightBGName : delContentHighlightBGName});border-radius: 0.2em;">`
256+
: isEndInSameNode
257+
? `<span data-diff-highlight style="background-color: var(${operator === "add" ? addContentHighlightBGName : delContentHighlightBGName});border-top-right-radius: 0.2em;border-bottom-right-radius: 0.2em;">`
258+
// current range crosses the node boundary
259+
: `<span data-diff-highlight style="background-color: var(${operator === "add" ? addContentHighlightBGName : delContentHighlightBGName});">`;
260+
}
261+
template += transform(value);
262+
if (isEndStr && changes.newLineSymbol) {
263+
template += `<span data-newline-symbol>${getSymbol(changes.newLineSymbol)}</span>`;
264+
}
265+
if (isLastStr) {
266+
template += `</span>`;
267+
}
268+
// end of range
269+
} else if (index === range.endIndex) {
270+
// current range all in the same node
271+
const isInSameNode = range.startIndex >= node.startIndex;
272+
if (isInSameNode) {
273+
template += transform(value);
274+
} else {
275+
if (i === 0) {
276+
template += `<span data-diff-highlight style="background-color: var(${operator === "add" ? addContentHighlightBGName : delContentHighlightBGName});border-top-right-radius: 0.2em;border-bottom-right-radius: 0.2em;">`;
277+
}
278+
template += transform(value);
279+
}
280+
if (isEndStr && changes.newLineSymbol) {
281+
template += `<span data-newline-symbol>${getSymbol(changes.newLineSymbol)}</span>`;
282+
}
283+
template += `</span>`;
284+
rangeIndex++;
285+
range = allRange[rangeIndex];
286+
// after range
287+
}
288+
} else {
289+
template += transform(value);
290+
}
291+
}
292+
template += `</span>`;
293+
});
294+
295+
diffLine.syntaxTemplate = template;
296+
297+
diffLine.syntaxTemplateMode = "fast-diff";
298+
};
299+
169300
export const getSyntaxLineTemplate = (line: SyntaxLine) => {
170301
let template = "";
171302

packages/file/index.d.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ export declare const getDiffRange: (additions: DiffLine[], deletions: DiffLine[]
436436
getAdditionSyntax: (lineNumber: number) => SyntaxLineWithTemplate;
437437
getDeletionSyntax: (lineNumber: number) => SyntaxLineWithTemplate;
438438
}) => void;
439+
export declare const getEnableFastDiffTemplate: () => boolean;
439440
export declare const getLang: (fileName: string) => string;
440441
export declare const getPlainDiffTemplate: ({ diffLine, rawLine, operator, }: {
441442
diffLine: DiffLine;
@@ -455,6 +456,11 @@ export declare const getSyntaxDiffTemplate: ({ diffLine, syntaxLine, operator, }
455456
syntaxLine: SyntaxLineWithTemplate;
456457
operator: "add" | "del";
457458
}) => void;
459+
export declare const getSyntaxDiffTemplateByFastDiff: ({ diffLine, syntaxLine, operator, }: {
460+
diffLine: DiffLine;
461+
syntaxLine: SyntaxLineWithTemplate;
462+
operator: "add" | "del";
463+
}) => void;
458464
export declare const getSyntaxLineTemplate: (line: SyntaxLine) => string;
459465
export declare const getUnifiedContentLine: (diffFile: DiffFile) => DiffUnifiedContentLineItem[];
460466
export declare const getUnifiedLines: (diffFile: DiffFile) => DiffUnifiedLineItem[];
@@ -503,6 +509,7 @@ export declare const processTransformForFile: (content: string) => string;
503509
*/
504510
export declare const processTransformTemplateContent: (content: string) => string;
505511
export declare const resetDefaultComposeLength: () => void;
512+
export declare const resetEnableFastDiffTemplate: () => void;
506513
/**
507514
* Resets all transformation functions to their default state and disables transformation.
508515
*
@@ -512,6 +519,7 @@ export declare const resetDefaultComposeLength: () => void;
512519
* ```
513520
*/
514521
export declare const resetTransform: () => void;
522+
export declare const setEnableFastDiffTemplate: (enable: boolean) => void;
515523
/**
516524
* ⚠️ **WARNING: DANGEROUS OPERATION** ⚠️
517525
*
@@ -609,6 +617,7 @@ export declare function relativeChanges(addition: DiffLine, deletion: DiffLine):
609617
delRange: IRange;
610618
};
611619
export declare let composeLen: number;
620+
export declare let enableFastDiffTemplate: boolean;
612621
export interface DiffHunkItem extends DiffLineItem {
613622
isFirst: boolean;
614623
isLast: boolean;
@@ -624,7 +633,8 @@ export interface DiffRange {
624633
readonly range: {
625634
type: 1 | -1 | 0;
626635
str: string;
627-
location: number;
636+
startIndex: number;
637+
endIndex: number;
628638
length: number;
629639
}[];
630640
readonly hasLineChange?: boolean;

0 commit comments

Comments
 (0)