Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jeremiah-shaulov/diff_kit
Deno lib that compares 2 strings and generates result like assertEquals(), also in HTML
https://github.com/jeremiah-shaulov/diff_kit
deno diff
Last synced: 3 months ago
JSON representation
Deno lib that compares 2 strings and generates result like assertEquals(), also in HTML
- Host: GitHub
- URL: https://github.com/jeremiah-shaulov/diff_kit
- Owner: jeremiah-shaulov
- License: mit
- Created: 2022-06-06T16:58:47.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-09-10T19:42:56.000Z (4 months ago)
- Last Synced: 2024-09-30T18:41:25.771Z (3 months ago)
- Topics: deno, diff
- Language: TypeScript
- Homepage:
- Size: 93.8 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# diff_kit
Deno lib that compares 2 strings and generates result like assertEquals(), also in HTML.## Example
```ts
// To download and run this example:
// curl 'https://raw.githubusercontent.com/jeremiah-shaulov/diff_kit/v2.0.5/README.md' | perl -ne '$y=$1 if /^```(ts\b)?/; print $_ if $y&&$m; $m=$y&&($m||m~^// deno .*?/example1.ts~)' > /tmp/example1.ts
// deno run /tmp/example1.tsimport {diff, DiffText, DiffTerm, DiffHtml} from 'https://deno.land/x/[email protected]/mod.ts';
const left =
`abc
def
`;
const right =
`abc
de*f
`;console.log('--- Default (terminal colors) ---');
let result = diff(left, right);
console.log(result);console.log('--- Plain text ---');
result = diff(left, right, new DiffText({indentWidth: 2}));
console.log(result);console.log('--- Terminal colors ---');
result = diff(left, right, new DiffTerm({indentWidth: 2}));
console.log(result);console.log('--- HTML ---');
result = diff(left, right, new DiffHtml({indentWidth: 2}));
console.log(result);
```![Screenshot](img/screenshot.png)
## diff()
The main function that this module exports is called `diff()`.
```ts
interface DiffSubj
{ readonly length: number;
charCodeAt(i: number): number;
slice(from: number, to: number): string;
}function diff(left: DiffSubj, right: DiffSubj, diffHandler: DiffHandler=new DiffTerm({indentWidth: 4})): string
````DiffSubj` interface is string-compatible, and the most usual use case is to pass strings to the `diff()` function.
## How the result is generated
The 3rd parameter of `diff()` is of `DiffHandler` type. `DiffHandler` has exactly this implementation:
```ts
class DiffHandler
{ left: DiffSubj = '';
right: DiffSubj = '';posLeft = 0;
posRight = 0;protected result = '';
addEqual(endPosLeft: number)
{ this.result += this.left.slice(this.posLeft, endPosLeft);
}addDiff(endPosLeft: number, endPosRight: number)
{ if (endPosRight > this.posRight)
{ this.result += '[-]';
this.result += this.right.slice(this.posRight, endPosRight);
}
if (endPosLeft > this.posLeft)
{ this.result += '[+]';
this.result += this.left.slice(this.posLeft, endPosLeft);
}
this.result += '[=]';
}toString()
{ return this.result;
}
}
```When an instance of `DiffHandler` is used as a parameter to `diff()`, the very basic plain text diff is generated: deleted parts will be marked with `[-]...[=]`, inserted parts with `[+]...[=]`, and changed parts with `[-]...[+]...[=]`.
```ts
// To download and run this example:
// curl 'https://raw.githubusercontent.com/jeremiah-shaulov/diff_kit/v2.0.5/README.md' | perl -ne '$y=$1 if /^```(ts\b)?/; print $_ if $y&&$m; $m=$y&&($m||m~^// deno .*?/example2.ts~)' > /tmp/example2.ts
// deno run /tmp/example2.tsimport {diff, DiffHandler} from 'https://deno.land/x/[email protected]/mod.ts';
const left =
`abc
def
`;
const right =
`abc
de*f
`;console.log(diff(left, right, new DiffHandler));
```Result:
```
abc
de[-]*[=]f
````diff()` calls the following methods and properties of `DiffHandler` to produce the result:
- `left` and `right` properties are set to the first and the second `diff()` parameter.
- `addEqual(endPosLeft: number)` is called to add a text part that is the same for both the left-hand and the right-hand sides of the diff. `this.posLeft` contains the starting index of the part, and `endPosLeft` is the end index, so to extract the part do: `this.left.slice(this.posLeft, endPosLeft)`.
- `addDiff(endPosLeft: number, endPosRight: number)` is called to add a part that is different. The left part is `this.left.slice(this.posLeft, endPosLeft)`, and the right is `this.right.slice(this.posRight, endPosRight)`. One of the parts can be empty (but not both).
- Before calling `addEqual()` and `addDiff()`, `posLeft` and `posRight` properties are set to current positions in the `left` and `right`.
- `toString()` - at last, the object is converted to string to produce the result.The same method is not called twice in sequence. That is, for example, after `addEqual()` either `addDiff()` or `toString()` will be called.
To produce results in different formats, use subclasses of `DiffHandler` that have different implementations of `addEqual()` and `addDiff()`.
This library contains 3 classes that provide visualization of the diff result:
- `DiffText` - generates line-by-line comparison in plain text.
- `DiffTerm` - generates line-by-line comparison with highlighting different parts using terminal colors. This is very similar to standard `assertEquals()` function.
- `DiffHtml` - like the previous, but generates HTML.All these classes provide option to adjust colors and markup:
```ts
class DiffText extends DiffHandler
{ constructor(options?: DiffTextOptions, styles?: DiffTextStyles);
}
class DiffTerm extends DiffText
{ constructor(options?: DiffTextOptions, styles?: DiffTextStyles);
}
class DiffHtml extends DiffText
{ constructor(options?: DiffTextOptions, styles?: DiffTextStyles);
}interface DiffTextOptions
{ /** Number of spaces to be used as indent: from 0 to 10 (inclusive), or -1 for TAB.
**/
indentWidth?: number;
}interface DiffTextStyles
{ /** What to insert before "-" char that denotes line deletion. Like ``
**/
minusBegin?: string;/** What to insert after "-" char that denotes line deletion. Like ``
**/
minusEnd?: string;/** What to insert before "+" char that denotes line insertion. Like ``
**/
plusBegin?: string;/** What to insert after "+" char that denotes line insertion. Like ``
**/
plusEnd?: string;/** What to insert in the beginning of deleted line. Like ``
**/
deletedLightBegin?: string;/** What to insert in the end of deleted line. Like ``
**/
deletedLightEnd?: string;/** What to insert in the beginning of inserted line. Like ``
**/
insertedLightBegin?: string;/** What to insert in the end of inserted line. Like ``
**/
insertedLightEnd?: string;/** What to insert where actual deleted chars on the line are starting. Like ``
**/
deletedBegin?: string;/** What to insert where actual deleted chars on the line are ending. Like ``
**/
deletedEnd?: string;/** What to insert where actual inserted chars on the line are starting. Like ``
**/
insertedBegin?: string;/** What to insert where actual inserted chars on the line are ending. Like ``
**/
insertedEnd?: string;
}
```## Extending this library
You can create your own subclass of `DiffHandler` to generate the result in different form, and use it in your project, or to publish it to `deno.land/x`. It's recommended to prefix the library name with `diff_kit_ex_`.