diff --git a/types/diff-match-patch/diff-match-patch-tests.ts b/types/diff-match-patch/diff-match-patch-tests.ts index 9226d7be4a..0f2af4451a 100644 --- a/types/diff-match-patch/diff-match-patch-tests.ts +++ b/types/diff-match-patch/diff-match-patch-tests.ts @@ -1,31 +1,261 @@ +import * as DiffMatchPatch from 'diff-match-patch'; -import DiffMatchPatch = require("diff-match-patch"); +function testDiffMainEach() { + const oldValue = "hello world, how are you?"; + const newValue = "hello again world. how have you been?"; -var oldValue = "hello world, how are you?"; -var newValue = "hello again world. how have you been?"; + const diffEngine = new DiffMatchPatch.diff_match_patch(); + const diffs = diffEngine.diff_main(oldValue, newValue); + diffEngine.diff_cleanupSemantic(diffs); -var diffEngine = new DiffMatchPatch.diff_match_patch(); -var diffs = diffEngine.diff_main(oldValue, newValue); -diffEngine.diff_cleanupSemantic(diffs); + let changes = ""; + let pattern = ""; -var changes = ""; -var pattern = ""; + diffs.forEach((diff) => { + const operation = diff[0]; // Operation (insert, delete, equal) + const text = diff[1]; // Text of change -diffs.forEach(function(diff) { - var operation = diff[0]; // Operation (insert, delete, equal) - var text = diff[1]; // Text of change - - switch (operation) { - case DiffMatchPatch.DIFF_INSERT: - pattern += "I"; - break; - case DiffMatchPatch.DIFF_DELETE: - pattern += "D"; - break; - case DiffMatchPatch.DIFF_EQUAL: - pattern += "E"; - break; - } + switch (operation) { + case DiffMatchPatch.DIFF_INSERT: + pattern += "I"; + break; + case DiffMatchPatch.DIFF_DELETE: + pattern += "D"; + break; + case DiffMatchPatch.DIFF_EQUAL: + pattern += "E"; + break; + } - changes += text; -}); + changes += text; + }); +} + +const DIFF_DELETE: number = DiffMatchPatch.DIFF_DELETE; +const DIFF_INSERT: number = DiffMatchPatch.DIFF_INSERT; +const DIFF_EQUAL: number = DiffMatchPatch.DIFF_EQUAL; +const dmp = new DiffMatchPatch.diff_match_patch(); + +// DIFF TEST FUNCTIONS + +function testDiffCommonPrefix() { + assertEquals(0, dmp.diff_commonPrefix('abc', 'xyz')); +} + +function testDiffCommonSuffix() { + assertEquals(0, dmp.diff_commonSuffix('abc', 'xyz')); +} + +function testDiffCommonOverlap() { + assertEquals(0, dmp.diff_commonOverlap_('', 'abcd')); +} + +function testDiffHalfMatch() { + dmp.Diff_Timeout = 1; + + assertEquals(null, dmp.diff_halfMatch_('1234567890', 'abcdef')); + + assertEquivalent(['12', '90', 'a', 'z', '345678'], dmp.diff_halfMatch_('1234567890', 'a345678z')); + + assertEquivalent(['12123', '123121', 'a', 'z', '1234123451234'], dmp.diff_halfMatch_('121231234123451234123121', 'a1234123451234z')); +} + +function testDiffLinesToChars() { + assertLinesToCharsResultEquals({chars1: '\x01\x02\x01', chars2: '\x02\x01\x02', lineArray: ['', 'alpha\n', 'beta\n']}, dmp.diff_linesToChars_('alpha\nbeta\nalpha\n', 'beta\nalpha\nbeta\n')); +} + +function testDiffCharsToLines() { + const diffs: DiffMatchPatch.Diff[] = [[DIFF_EQUAL, '\x01\x02\x01'], [DIFF_INSERT, '\x02\x01\x02']]; + dmp.diff_charsToLines_(diffs, ['', 'alpha\n', 'beta\n']); + assertEquivalent([[DIFF_EQUAL, 'alpha\nbeta\nalpha\n'], [DIFF_INSERT, 'beta\nalpha\nbeta\n']], diffs); +} + +function testDiffCleanupMerge() { + const diffs: DiffMatchPatch.Diff[] = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c']]; + dmp.diff_cleanupMerge(diffs); + assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c']], diffs); +} + +function testDiffCleanupSemanticLossless() { + const diffs: DiffMatchPatch.Diff[] = [[DIFF_EQUAL, 'AAA\r\n\r\nBBB'], [DIFF_INSERT, '\r\nDDD\r\n\r\nBBB'], [DIFF_EQUAL, '\r\nEEE']]; + dmp.diff_cleanupSemanticLossless(diffs); + assertEquivalent([[DIFF_EQUAL, 'AAA\r\n\r\n'], [DIFF_INSERT, 'BBB\r\nDDD\r\n\r\n'], [DIFF_EQUAL, 'BBB\r\nEEE']], diffs); +} + +function testDiffCleanupSemantic() { + const diffs: DiffMatchPatch.Diff[] = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, 'cd'], [DIFF_EQUAL, '12'], [DIFF_DELETE, 'e']]; + dmp.diff_cleanupSemantic(diffs); + assertEquivalent([[DIFF_DELETE, 'ab'], [DIFF_INSERT, 'cd'], [DIFF_EQUAL, '12'], [DIFF_DELETE, 'e']], diffs); +} + +function testDiffCleanupEfficiency() { + dmp.Diff_EditCost = 4; + + const diffs: DiffMatchPatch.Diff[] = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']]; + dmp.diff_cleanupEfficiency(diffs); + assertEquivalent([[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']], diffs); +} + +function testDiffPrettyHtml() { + const diffs: DiffMatchPatch.Diff[] = [[DIFF_EQUAL, 'a\n'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c&d']]; + assertEquals('
<B>b</B>c&d', dmp.diff_prettyHtml(diffs)); +} + +function testDiffText() { + const diffs: DiffMatchPatch.Diff[] = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, ' lazy']]; + assertEquals('jumps over the lazy', dmp.diff_text1(diffs)); + + assertEquals('jumped over a lazy', dmp.diff_text2(diffs)); +} + +function testDiffDelta() { + const diffs: DiffMatchPatch.Diff[] = + [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, ' lazy'], [DIFF_INSERT, 'old dog']]; + const text1 = dmp.diff_text1(diffs); + assertEquals('jumps over the lazy', text1); + + const delta = dmp.diff_toDelta(diffs); + assertEquals('=4\t-1\t+ed\t=6\t-3\t+a\t=5\t+old dog', delta); + + assertEquivalent(diffs, dmp.diff_fromDelta(text1, delta)); +} + +function testDiffXIndex() { + assertEquals(5, dmp.diff_xIndex([[DIFF_DELETE, 'a'], [DIFF_INSERT, '1234'], [DIFF_EQUAL, 'xyz']], 2)); +} + +function testDiffLevenshtein() { + assertEquals(4, dmp.diff_levenshtein([[DIFF_DELETE, 'abc'], [DIFF_INSERT, '1234'], [DIFF_EQUAL, 'xyz']])); +} + +function testDiffBisect() { + const a = 'cat'; + const b = 'map'; + assertEquivalent([[DIFF_DELETE, 'c'], [DIFF_INSERT, 'm'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, 't'], [DIFF_INSERT, 'p']], dmp.diff_bisect_(a, b, Number.MAX_VALUE)); +} + +function testDiffMain() { + assertEquivalent([], dmp.diff_main('', '', false)); + + dmp.Diff_Timeout = 0; + // Simple cases. + assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_INSERT, 'b']], dmp.diff_main('a', 'b', false)); +} + +// MATCH TEST FUNCTIONS + +function testMatchAlphabet() { + const expected: {[char: string]: number} = {}; + expected['a'] = 4; + expected['b'] = 2; + expected['c'] = 1; + assertEquivalent(expected, dmp.match_alphabet_('abc')); +} + +function testMatchBitap() { + dmp.Match_Distance = 100; + dmp.Match_Threshold = 0.5; + + assertEquals(5, dmp.match_bitap_('abcdefghijk', 'fgh', 5)); +} + +function testMatchMain() { + assertEquals(0, dmp.match_main('abcdef', 'abcdef', 1000)); +} + +// PATCH TEST FUNCTIONS + +function testPatchObj() { + // Patch Object. + const p = new DiffMatchPatch.patch_obj(); + assertEquals(null, p.start1); + assertEquals(null, p.start2); + + p.start1 = 20; + p.start2 = 21; + p.length1 = 18; + p.length2 = 17; + p.diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, '\nlaz']]; + const strp = p.toString(); + assertEquals('@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n %0Alaz\n', strp); +} + +function testPatchFromText() { + const strp = '@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n %0Alaz\n'; + assertEquals(strp, dmp.patch_fromText(strp)[0].toString()); +} + +function testPatchToText() { + const strp = '@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n laz\n'; + const p = dmp.patch_fromText(strp); + assertEquals(strp, dmp.patch_toText(p)); +} + +function testPatchAddContext() { + dmp.Patch_Margin = 4; + const p = dmp.patch_fromText('@@ -21,4 +21,10 @@\n-jump\n+somersault\n')[0]; + dmp.patch_addContext_(p, 'The quick brown fox jumps over the lazy dog.'); + assertEquals('@@ -17,12 +17,18 @@\n fox \n-jump\n+somersault\n s ov\n', p.toString()); +} + +function testPatchMake() { + const text1 = 'The quick brown fox jumps over the lazy dog.'; + const text2 = 'That quick brown fox jumped over a lazy dog.'; + let expectedPatch = '@@ -1,8 +1,7 @@\n Th\n-at\n+e\n qui\n@@ -21,17 +21,18 @@\n jump\n-ed\n+s\n over \n-a\n+the\n laz\n'; + let patches = dmp.patch_make(text2, text1); + assertEquals(expectedPatch, dmp.patch_toText(patches)); + + // Method 1 + expectedPatch = '@@ -1,11 +1,12 @@\n Th\n-e\n+at\n quick b\n@@ -22,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n laz\n'; + patches = dmp.patch_make(text1, text2); + assertEquals(expectedPatch, dmp.patch_toText(patches)); + + // Method 2 + const diffs = dmp.diff_main(text1, text2, false); + patches = dmp.patch_make(diffs); + assertEquals(expectedPatch, dmp.patch_toText(patches)); + + // Method 3 + patches = dmp.patch_make(text1, diffs); + assertEquals(expectedPatch, dmp.patch_toText(patches)); + + // Method 4 + patches = dmp.patch_make(text1, text2, diffs); + assertEquals(expectedPatch, dmp.patch_toText(patches)); +} + +function testPatchSplitMax() { + const patches = dmp.patch_make('abcdefghijklmnopqrstuvwxyz01234567890', 'XabXcdXefXghXijXklXmnXopXqrXstXuvXwxXyzX01X23X45X67X89X0'); + dmp.patch_splitMax(patches); + assertEquals( + [ + '@@ -1,32 +1,46 @@\n', + '+X\n ab\n+X\n cd\n+X\n ef\n+X\n gh\n+X\n ij\n+X\n kl\n+X\n mn\n+X\n op\n+X\n qr\n+X\n st\n+X\nuv\n+X\n wx\n+X\n yz\n+X\n 012345\n', + '@@ -25,13 +39,18 @@', + '\n zX01\n+X\n 23\n+X\n 45\n+X\n 67\n+X\n 89\n+X\n 0\n' + ].join(''), + dmp.patch_toText(patches)); +} + +function testPatchAddPadding() { + const patches = dmp.patch_make('', 'test'); + assertEquals('@@ -0,0 +1,4 @@\n+test\n', dmp.patch_toText(patches)); + dmp.patch_addPadding(patches); + assertEquals('@@ -1,8 +1,12 @@\n %01%02%03%04\n+test\n %01%02%03%04\n', dmp.patch_toText(patches)); +} + +function testPatchApply() { + dmp.Match_Distance = 1000; + dmp.Match_Threshold = 0.5; + dmp.Patch_DeleteThreshold = 0.5; + const patches = dmp.patch_make('The quick brown fox jumps over the lazy dog.', 'That quick brown fox jumped over a lazy dog.'); + const results = dmp.patch_apply(patches, 'The quick brown fox jumps over the lazy dog.'); + assertEquivalent(['That quick brown fox jumped over a lazy dog.', [true, true]], results); +} + +declare function assertEquals(expected: T, actual: T): void; + +declare function assertEquivalent(expected: T[], actual: T[]): void; +declare function assertEquivalent(expected: T, actual: T): void; + +declare function assertLinesToCharsResultEquals(expected: {chars1: string, chars2: string, lineArray: string[]}, actual: {chars1: string, chars2: string, lineArray: string[]}): void; diff --git a/types/diff-match-patch/index.d.ts b/types/diff-match-patch/index.d.ts index cfaeace764..9d27016691 100644 --- a/types/diff-match-patch/index.d.ts +++ b/types/diff-match-patch/index.d.ts @@ -1,22 +1,19 @@ -// Type definitions for diff-match-patch v1.0.0 +// Type definitions for diff-match-patch 1.0 // Project: https://www.npmjs.com/package/diff-match-patch // Definitions by: Asana // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +export type Diff = [number, string]; -type Diff = [number, string]; - -export declare class Patch { +export class patch_obj { diffs: Diff[]; - start1: number; - start2: number; + start1: number | null; + start2: number | null; length1: number; length2: number; } -export declare class diff_match_patch { - static new(): diff_match_patch; - +export class diff_match_patch { Diff_Timeout: number; Diff_EditCost: number; Match_Threshold: number; @@ -26,8 +23,13 @@ export declare class diff_match_patch { Match_MaxBits: number; diff_main(text1: string, text2: string, opt_checklines?: boolean, opt_deadline?: number): Diff[]; + diff_bisect_(text1: string, text2: string, deadline: number): Diff[]; + diff_linesToChars_(text1: string, text2: string): { chars1: string; chars2: string; lineArray: string[]; }; + diff_charsToLines_(diffs: Diff[], lineArray: string[]): void; diff_commonPrefix(text1: string, text2: string): number; diff_commonSuffix(text1: string, text2: string): number; + diff_commonOverlap_(text1: string, text2: string): number; + diff_halfMatch_(text1: string, text2: string): string[]; diff_cleanupSemantic(diffs: Diff[]): void; diff_cleanupSemanticLossless(diffs: Diff[]): void; diff_cleanupEfficiency(diffs: Diff[]): void; @@ -40,13 +42,22 @@ export declare class diff_match_patch { diff_toDelta(diffs: Diff[]): string; diff_fromDelta(text1: string, delta: string): Diff[]; - patch_make(text1: any, text2?: string): Patch[]; - patch_deepCopy(patches: Patch[]): Patch[]; - patch_apply(patches: Patch[], text: string): [string, boolean[]]; - patch_fromText(text: string): Patch[]; - patch_toText(patches: Patch[]): string; + match_main(text: string, pattern: string, loc: number): number; + match_bitap_(text: string, pattern: string, loc: number): number; + match_alphabet_(pattern: string): {[char: string]: number}; + + patch_addContext_(patch: patch_obj, text: string): void; + patch_make(a: string, opt_b: string | Diff[]): patch_obj[]; + patch_make(a: Diff[]): patch_obj[]; + patch_make(a: string, opt_b: string, opt_c: Diff[]): patch_obj[]; + patch_deepCopy(patches: patch_obj[]): patch_obj[]; + patch_apply(patches: patch_obj[], text: string): [string, boolean[]]; + patch_addPadding(patches: patch_obj[]): string; + patch_splitMax(patches: patch_obj[]): void; + patch_fromText(text: string): patch_obj[]; + patch_toText(patches: patch_obj[]): string; } -export declare var DIFF_DELETE: number; -export declare var DIFF_INSERT: number; -export declare var DIFF_EQUAL: number; +export const DIFF_DELETE: number; +export const DIFF_INSERT: number; +export const DIFF_EQUAL: number; diff --git a/types/diff-match-patch/tslint.json b/types/diff-match-patch/tslint.json new file mode 100644 index 0000000000..65c83fb1e3 --- /dev/null +++ b/types/diff-match-patch/tslint.json @@ -0,0 +1,6 @@ +{ + "extends": "dtslint/dt.json", + "rules": { + "dt-header": false + } +}