{"id":14984984,"url":"https://github.com/jeremiah-shaulov/diff_kit","last_synced_at":"2025-07-04T02:36:07.328Z","repository":{"id":62422737,"uuid":"500520150","full_name":"jeremiah-shaulov/diff_kit","owner":"jeremiah-shaulov","description":"Deno lib that compares 2 strings and generates result like assertEquals(), also in HTML","archived":false,"fork":false,"pushed_at":"2024-09-10T19:42:56.000Z","size":96,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-10T23:15:21.532Z","etag":null,"topics":["deno","diff"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jeremiah-shaulov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-06T16:58:47.000Z","updated_at":"2025-01-08T18:05:52.000Z","dependencies_parsed_at":"2024-09-10T22:07:11.728Z","dependency_job_id":null,"html_url":"https://github.com/jeremiah-shaulov/diff_kit","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeremiah-shaulov%2Fdiff_kit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeremiah-shaulov%2Fdiff_kit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeremiah-shaulov%2Fdiff_kit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeremiah-shaulov%2Fdiff_kit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeremiah-shaulov","download_url":"https://codeload.github.com/jeremiah-shaulov/diff_kit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248312134,"owners_count":21082638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","diff"],"created_at":"2024-09-24T14:10:02.386Z","updated_at":"2025-04-10T23:15:29.596Z","avatar_url":"https://github.com/jeremiah-shaulov.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# diff_kit\nDeno lib that compares 2 strings and generates result like assertEquals(), also in HTML.\n\n## Example\n\n```ts\n// To download and run this example:\n// curl 'https://raw.githubusercontent.com/jeremiah-shaulov/diff_kit/v2.0.5/README.md' | perl -ne '$y=$1 if /^```(ts\\b)?/;  print $_ if $y\u0026\u0026$m;  $m=$y\u0026\u0026($m||m~^// deno .*?/example1.ts~)' \u003e /tmp/example1.ts\n// deno run /tmp/example1.ts\n\nimport {diff, DiffText, DiffTerm, DiffHtml} from 'https://deno.land/x/diff_kit@v2.0.5/mod.ts';\n\nconst left =\n`abc\ndef\n`;\nconst right =\n`abc\nde*f\n`;\n\nconsole.log('--- Default (terminal colors) ---');\nlet result = diff(left, right);\nconsole.log(result);\n\nconsole.log('--- Plain text ---');\nresult = diff(left, right, new DiffText({indentWidth: 2}));\nconsole.log(result);\n\nconsole.log('--- Terminal colors ---');\nresult = diff(left, right, new DiffTerm({indentWidth: 2}));\nconsole.log(result);\n\nconsole.log('--- HTML ---');\nresult = diff(left, right, new DiffHtml({indentWidth: 2}));\nconsole.log(result);\n```\n\n![Screenshot](img/screenshot.png)\n\n## diff()\n\nThe main function that this module exports is called `diff()`.\n\n```ts\ninterface DiffSubj\n{\treadonly length: number;\n\tcharCodeAt(i: number): number;\n\tslice(from: number, to: number): string;\n}\n\nfunction diff(left: DiffSubj, right: DiffSubj, diffHandler: DiffHandler=new DiffTerm({indentWidth: 4})): string\n```\n\n`DiffSubj` interface is string-compatible, and the most usual use case is to pass strings to the `diff()` function.\n\n## How the result is generated\n\nThe 3rd parameter of `diff()` is of `DiffHandler` type. `DiffHandler` has exactly this implementation:\n\n```ts\nclass DiffHandler\n{\tleft: DiffSubj = '';\n\tright: DiffSubj = '';\n\n\tposLeft = 0;\n\tposRight = 0;\n\n\tprotected result = '';\n\n\taddEqual(endPosLeft: number)\n\t{\tthis.result += this.left.slice(this.posLeft, endPosLeft);\n\t}\n\n\taddDiff(endPosLeft: number, endPosRight: number)\n\t{\tif (endPosRight \u003e this.posRight)\n\t\t{\tthis.result += '[-]';\n\t\t\tthis.result += this.right.slice(this.posRight, endPosRight);\n\t\t}\n\t\tif (endPosLeft \u003e this.posLeft)\n\t\t{\tthis.result += '[+]';\n\t\t\tthis.result += this.left.slice(this.posLeft, endPosLeft);\n\t\t}\n\t\tthis.result += '[=]';\n\t}\n\n\ttoString()\n\t{\treturn this.result;\n\t}\n}\n```\n\nWhen 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 `[-]...[+]...[=]`.\n\n```ts\n// To download and run this example:\n// curl 'https://raw.githubusercontent.com/jeremiah-shaulov/diff_kit/v2.0.5/README.md' | perl -ne '$y=$1 if /^```(ts\\b)?/;  print $_ if $y\u0026\u0026$m;  $m=$y\u0026\u0026($m||m~^// deno .*?/example2.ts~)' \u003e /tmp/example2.ts\n// deno run /tmp/example2.ts\n\nimport {diff, DiffHandler} from 'https://deno.land/x/diff_kit@v2.0.5/mod.ts';\n\nconst left =\n`abc\ndef\n`;\nconst right =\n`abc\nde*f\n`;\n\nconsole.log(diff(left, right, new DiffHandler));\n```\n\nResult:\n\n```\nabc\nde[-]*[=]f\n```\n\n`diff()` calls the following methods and properties of `DiffHandler` to produce the result:\n- `left` and `right` properties are set to the first and the second `diff()` parameter.\n- `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)`.\n- `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).\n- Before calling `addEqual()` and `addDiff()`, `posLeft` and `posRight` properties are set to current positions in the `left` and `right`.\n- `toString()` - at last, the object is converted to string to produce the result.\n\nThe same method is not called twice in sequence. That is, for example, after `addEqual()` either `addDiff()` or `toString()` will be called.\n\nTo produce results in different formats, use subclasses of `DiffHandler` that have different implementations of `addEqual()` and `addDiff()`.\n\nThis library contains 3 classes that provide visualization of the diff result:\n- `DiffText` - generates line-by-line comparison in plain text.\n- `DiffTerm` - generates line-by-line comparison with highlighting different parts using terminal colors. This is very similar to standard `assertEquals()` function.\n- `DiffHtml` - like the previous, but generates HTML.\n\nAll these classes provide option to adjust colors and markup:\n\n```ts\nclass DiffText extends DiffHandler\n{\tconstructor(options?: DiffTextOptions, styles?: DiffTextStyles);\n}\nclass DiffTerm extends DiffText\n{\tconstructor(options?: DiffTextOptions, styles?: DiffTextStyles);\n}\nclass DiffHtml extends DiffText\n{\tconstructor(options?: DiffTextOptions, styles?: DiffTextStyles);\n}\n\ninterface DiffTextOptions\n{\t/**\tNumber of spaces to be used as indent: from 0 to 10 (inclusive), or -1 for TAB.\n\t **/\n\tindentWidth?: number;\n}\n\ninterface DiffTextStyles\n{\t/**\tWhat to insert before \"-\" char that denotes line deletion. Like `\u003cb style=\"color:red\"\u003e`\n\t **/\n\tminusBegin?: string;\n\n\t/**\tWhat to insert after \"-\" char that denotes line deletion. Like `\u003c/b\u003e`\n\t **/\n\tminusEnd?: string;\n\n\t/**\tWhat to insert before \"+\" char that denotes line insertion. Like `\u003cb style=\"color:green\"\u003e`\n\t **/\n\tplusBegin?: string;\n\n\t/**\tWhat to insert after \"+\" char that denotes line insertion. Like `\u003c/b\u003e`\n\t **/\n\tplusEnd?: string;\n\n\t/**\tWhat to insert in the beginning of deleted line. Like `\u003cspan style=\"color:red\"\u003e`\n\t **/\n\tdeletedLightBegin?: string;\n\n\t/**\tWhat to insert in the end of deleted line. Like `\u003c/span\u003e`\n\t **/\n\tdeletedLightEnd?: string;\n\n\t/**\tWhat to insert in the beginning of inserted line. Like `\u003cspan style=\"color:green\"\u003e`\n\t **/\n\tinsertedLightBegin?: string;\n\n\t/**\tWhat to insert in the end of inserted line. Like `\u003c/span\u003e`\n\t **/\n\tinsertedLightEnd?: string;\n\n\t/**\tWhat to insert where actual deleted chars on the line are starting. Like `\u003cspan style=\"background-color:red; color:white\"\u003e`\n\t **/\n\tdeletedBegin?: string;\n\n\t/**\tWhat to insert where actual deleted chars on the line are ending. Like `\u003c/span\u003e`\n\t **/\n\tdeletedEnd?: string;\n\n\t/**\tWhat to insert where actual inserted chars on the line are starting. Like `\u003cspan style=\"background-color:green; color:white\"\u003e`\n\t **/\n\tinsertedBegin?: string;\n\n\t/**\tWhat to insert where actual inserted chars on the line are ending. Like `\u003c/span\u003e`\n\t **/\n\tinsertedEnd?: string;\n}\n```\n\n## Extending this library\n\nYou 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_`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeremiah-shaulov%2Fdiff_kit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeremiah-shaulov%2Fdiff_kit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeremiah-shaulov%2Fdiff_kit/lists"}