diff --git a/projects/ngx-diff/src/inline-diff/diff-calculation.interface.ts b/projects/ngx-diff/src/lib/common/diff-calculation.interface.ts
similarity index 77%
rename from projects/ngx-diff/src/inline-diff/diff-calculation.interface.ts
rename to projects/ngx-diff/src/lib/common/diff-calculation.interface.ts
index 87680dc..c5b4d4b 100644
--- a/projects/ngx-diff/src/inline-diff/diff-calculation.interface.ts
+++ b/projects/ngx-diff/src/lib/common/diff-calculation.interface.ts
@@ -1,10 +1,12 @@
+import { LineDiffType } from './line-diff-type';
+
/* Holds the state of the calculation of the diff result we intend to display.
* > lines contains the data that will be displayed on screen.
* > lineInOldText keeps track of the document line number in the [oldText] input.
* > lineInNewText keeps track of the document line number in the [newText] input.
*/
export interface IDiffCalculation {
- lines: Array<[string, string, string, string]>;
+ lines: Array<[LineDiffType, number | null, number | null, string]>;
lineInOldText: number;
lineInNewText: number;
}
diff --git a/projects/ngx-diff/src/lib/common/line-diff-type.ts b/projects/ngx-diff/src/lib/common/line-diff-type.ts
new file mode 100644
index 0000000..f347d3c
--- /dev/null
+++ b/projects/ngx-diff/src/lib/common/line-diff-type.ts
@@ -0,0 +1,5 @@
+export const enum LineDiffType {
+ Equal = 1,
+ Insert = 2,
+ Delete = 3,
+}
diff --git a/projects/ngx-diff/src/lib/common/line-select-event.ts b/projects/ngx-diff/src/lib/common/line-select-event.ts
new file mode 100644
index 0000000..4fc0cda
--- /dev/null
+++ b/projects/ngx-diff/src/lib/common/line-select-event.ts
@@ -0,0 +1,9 @@
+import { LineDiffType } from './line-diff-type';
+
+export type LineSelectEvent = {
+ index: number;
+ type: LineDiffType;
+ lineNumberInOldText: number | null;
+ lineNumberInNewText: number | null;
+ line: string;
+};
diff --git a/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.html b/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.html
index be23b94..82a1972 100644
--- a/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.html
+++ b/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.html
@@ -1,23 +1,32 @@
-
-
-
{{ lineDiff[1] }}
-
-
{{ lineDiff[2] }}
-
-
+
{{ lineDiff[2] | lineNumber }}
-
-
diff --git a/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.scss b/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.scss
index 9eb3eda..18b6397 100644
--- a/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.scss
+++ b/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.scss
@@ -26,7 +26,6 @@ div.inline-diff-content-wrapper {
div.inline-diff-old {
width: 50px;
text-align: center;
- color: #484848;
}
div.inline-diff-equal>div.inline-diff-old,
@@ -47,7 +46,6 @@ div.inline-diff-delete>div.inline-diff-new {
div.inline-diff-new {
width: 50px;
text-align: center;
- color: #484848;
border-right: 1px solid #888888;
}
@@ -81,3 +79,24 @@ div.inline-diff-text {
background-color: #dedede;
border-right: 1px solid #888888;
}
+
+.line-selector {
+ color: #484848;
+
+ &:hover {
+ cursor: pointer;
+ color: mix(white, #484848, 30%);
+ }
+
+ &.selected {
+ border-top: 1px solid red;
+ border-left: 1px solid red;
+ border-bottom: 1px solid red;
+ }
+}
+
+.line-content.selected {
+ border-top: 1px solid red;
+ border-right: 1px solid red;
+ border-bottom: 1px solid red;
+}
diff --git a/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.spec.ts b/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.spec.ts
index af1fb05..395a73d 100644
--- a/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.spec.ts
+++ b/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.spec.ts
@@ -2,6 +2,8 @@ import { Diff, DiffOp } from 'diff-match-patch-ts';
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { LineDiffType } from '../../common/line-diff-type';
+import { LineNumberPipe } from '../../pipes/line-number/line-number.pipe';
import { DiffMatchPatchService } from '../../services/diff-match-patch/diff-match-patch.service';
import { InlineDiffComponent } from './inline-diff.component';
@@ -23,7 +25,7 @@ describe('InlineDiffComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [InlineDiffComponent],
+ declarations: [InlineDiffComponent, LineNumberPipe],
providers: [{ provide: DiffMatchPatchService, useClass: DiffMatchPatchServiceMock }],
}).compileComponents();
@@ -42,23 +44,23 @@ describe('InlineDiffComponent', () => {
it('should have correct line numbers', () => {
const leftLineNumbers = component.calculatedDiff.map((x) => x[1]);
- expect(leftLineNumbers).toEqual(['1', '2', '-', '-', '3', '4', '5', '6']);
+ expect(leftLineNumbers).toEqual([1, 2, null, null, 3, 4, 5, 6]);
const rightLineNumbers = component.calculatedDiff.map((x) => x[2]);
- expect(rightLineNumbers).toEqual(['1', '2', '3', '4', '-', '-', '5', '6']);
+ expect(rightLineNumbers).toEqual([1, 2, 3, 4, null, null, 5, 6]);
});
it('should have correct class annotations', () => {
const classes = component.calculatedDiff.map((x) => x[0]);
expect(classes).toEqual([
- 'inline-diff-equal',
- 'inline-diff-equal',
- 'inline-diff-insert',
- 'inline-diff-insert',
- 'inline-diff-delete',
- 'inline-diff-delete',
- 'inline-diff-equal',
- 'inline-diff-equal',
+ LineDiffType.Equal,
+ LineDiffType.Equal,
+ LineDiffType.Insert,
+ LineDiffType.Insert,
+ LineDiffType.Delete,
+ LineDiffType.Delete,
+ LineDiffType.Equal,
+ LineDiffType.Equal,
]);
});
diff --git a/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.ts b/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.ts
index 80a5703..f5344fd 100644
--- a/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.ts
+++ b/projects/ngx-diff/src/lib/components/inline-diff/inline-diff.component.ts
@@ -1,10 +1,14 @@
import { Diff, DiffOp } from 'diff-match-patch-ts';
-import { Component, Input, OnChanges, OnInit } from '@angular/core';
+import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
-import { IDiffCalculation } from '../../../inline-diff/diff-calculation.interface';
+import { IDiffCalculation } from '../../common/diff-calculation.interface';
+import { LineDiffType } from '../../common/line-diff-type';
+import { LineSelectEvent } from '../../common/line-select-event';
import { DiffMatchPatchService } from '../../services/diff-match-patch/diff-match-patch.service';
+type LineDiff = [LineDiffType, number | null, number | null, string, string];
+
@Component({
selector: 'inline-diff',
templateUrl: './inline-diff.component.html',
@@ -20,7 +24,11 @@ export class InlineDiffComponent implements OnInit, OnChanges {
@Input()
public lineContextSize: number | undefined;
- public calculatedDiff: Array<[string, string, string, string]>;
+ @Output()
+ public selectedLineChange = new EventEmitter
();
+
+ public calculatedDiff: LineDiff[];
+ public selectedLine?: LineDiff;
public isContentEqual: boolean;
public constructor(private readonly dmp: DiffMatchPatchService) {
@@ -36,6 +44,18 @@ export class InlineDiffComponent implements OnInit, OnChanges {
this.updateHtml();
}
+ public selectLine(index: number, lineDiff: LineDiff): void {
+ this.selectedLine = lineDiff;
+ const [type, lineNumberInOldText, lineNumberInNewText, line] = lineDiff;
+ this.selectedLineChange.emit({
+ index,
+ type,
+ lineNumberInOldText,
+ lineNumberInNewText,
+ line,
+ });
+ }
+
private updateHtml(): void {
if (typeof this.oldText === 'number' || typeof this.oldText === 'boolean') {
this.oldText = this.oldText.toString();
@@ -87,7 +107,11 @@ export class InlineDiffComponent implements OnInit, OnChanges {
}
}
- this.calculatedDiff = diffCalculation.lines;
+ this.calculatedDiff = diffCalculation.lines.map(
+ ([type, lineNumberInOldText, lineNumberInNewText, line]) => {
+ return [type, lineNumberInOldText, lineNumberInNewText, line, this.getCssClass(type)];
+ },
+ );
}
/* If the number of diffLines is greater than lineContextSize then we may need to adjust the diff
@@ -125,7 +149,7 @@ export class InlineDiffComponent implements OnInit, OnChanges {
this.outputEqualDiffLines(diffLines.slice(0, this.lineContextSize), diffCalculation);
// Output a special line indicating that some content is equal and has been skipped
- diffCalculation.lines.push(['inline-diff-equal', '...', '...', '...']);
+ diffCalculation.lines.push([LineDiffType.Equal, null, null, '...']);
const numberOfSkippedLines = diffLines.length - 2 * this.lineContextSize;
diffCalculation.lineInOldText += numberOfSkippedLines;
diffCalculation.lineInNewText += numberOfSkippedLines;
@@ -146,9 +170,9 @@ export class InlineDiffComponent implements OnInit, OnChanges {
private outputEqualDiffLines(diffLines: string[], diffCalculation: IDiffCalculation): void {
for (const line of diffLines) {
diffCalculation.lines.push([
- 'inline-diff-equal',
- `${diffCalculation.lineInOldText}`,
- `${diffCalculation.lineInNewText}`,
+ LineDiffType.Equal,
+ diffCalculation.lineInOldText,
+ diffCalculation.lineInNewText,
line,
]);
diffCalculation.lineInOldText++;
@@ -158,25 +182,28 @@ export class InlineDiffComponent implements OnInit, OnChanges {
private outputDeleteDiff(diffLines: string[], diffCalculation: IDiffCalculation): void {
for (const line of diffLines) {
- diffCalculation.lines.push([
- 'inline-diff-delete',
- `${diffCalculation.lineInOldText}`,
- '-',
- line,
- ]);
+ diffCalculation.lines.push([LineDiffType.Delete, diffCalculation.lineInOldText, null, line]);
diffCalculation.lineInOldText++;
}
}
private outputInsertDiff(diffLines: string[], diffCalculation: IDiffCalculation): void {
for (const line of diffLines) {
- diffCalculation.lines.push([
- 'inline-diff-insert',
- '-',
- `${diffCalculation.lineInNewText}`,
- line,
- ]);
+ diffCalculation.lines.push([LineDiffType.Insert, null, diffCalculation.lineInNewText, line]);
diffCalculation.lineInNewText++;
}
}
+
+ private getCssClass(type: LineDiffType): string {
+ switch (type) {
+ case LineDiffType.Equal:
+ return 'inline-diff-equal';
+ case LineDiffType.Insert:
+ return 'inline-diff-insert';
+ case LineDiffType.Delete:
+ return 'inline-diff-delete';
+ default:
+ return 'unknown';
+ }
+ }
}
diff --git a/projects/ngx-diff/src/lib/pipes/line-number/line-number.pipe.spec.ts b/projects/ngx-diff/src/lib/pipes/line-number/line-number.pipe.spec.ts
new file mode 100644
index 0000000..d5f1664
--- /dev/null
+++ b/projects/ngx-diff/src/lib/pipes/line-number/line-number.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { LineNumberPipe } from './line-number.pipe';
+
+describe('LineNumberPipe', () => {
+ it('create an instance', () => {
+ const pipe = new LineNumberPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/projects/ngx-diff/src/lib/pipes/line-number/line-number.pipe.ts b/projects/ngx-diff/src/lib/pipes/line-number/line-number.pipe.ts
new file mode 100644
index 0000000..cbc1dfa
--- /dev/null
+++ b/projects/ngx-diff/src/lib/pipes/line-number/line-number.pipe.ts
@@ -0,0 +1,10 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'lineNumber',
+})
+export class LineNumberPipe implements PipeTransform {
+ public transform(value: number | null): string {
+ return value === null ? '-' : `${value}`;
+ }
+}
diff --git a/projects/ngx-diff/src/ngx-diff.module.ts b/projects/ngx-diff/src/ngx-diff.module.ts
index 1ab839e..4d20c62 100644
--- a/projects/ngx-diff/src/ngx-diff.module.ts
+++ b/projects/ngx-diff/src/ngx-diff.module.ts
@@ -2,9 +2,10 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { InlineDiffComponent } from './lib/components/inline-diff/inline-diff.component';
+import { LineNumberPipe } from './lib/pipes/line-number/line-number.pipe';
@NgModule({
- declarations: [InlineDiffComponent],
+ declarations: [InlineDiffComponent, LineNumberPipe],
exports: [InlineDiffComponent],
imports: [CommonModule],
})
diff --git a/projects/ngx-diff/src/public-api.ts b/projects/ngx-diff/src/public-api.ts
index c42204f..364c07b 100644
--- a/projects/ngx-diff/src/public-api.ts
+++ b/projects/ngx-diff/src/public-api.ts
@@ -2,6 +2,8 @@
* Public API Surface of ngx-diff
*/
-export { DiffMatchPatchService } from './lib/services/diff-match-patch/diff-match-patch.service';
-export { InlineDiffComponent } from './lib/components/inline-diff/inline-diff.component';
-export { NgxDiffModule } from './ngx-diff.module';
+export * from './lib/services/diff-match-patch/diff-match-patch.service';
+export * from './lib/components/inline-diff/inline-diff.component';
+export * from './lib/common/line-select-event';
+export * from './lib/common/line-diff-type';
+export * from './ngx-diff.module';
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 72fd8e2..bfca223 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,531 +1,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-