Skip to content

Commit

Permalink
Refactor and reorganize for v0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
lionel-rowe committed Sep 18, 2024
1 parent 49baceb commit 87cefe1
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 40 deletions.
2 changes: 1 addition & 1 deletion deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"./utils": "./src/utils.ts"
},
"tasks": {
"test": "deno test --doc src tests"
"test": "deno test --doc src"
},
"imports": {
"@clearlylocal/diff-match-patch-unicode": "./src/mod.ts",
Expand Down
6 changes: 3 additions & 3 deletions tests/Differ.test.ts → src/Differ.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { assertEquals } from '@std/assert'
import { Differ, segmenters } from '../src/Differ.ts'
import { assertDiffsEqual, assertDiffsEqual2d } from './testUtils.ts'
import { DiffMatchPatchFull } from '../src/DiffMatchPatchFull.ts'
import { Differ, segmenters } from './Differ.ts'
import { assertDiffsEqual, assertDiffsEqual2d } from './_testUtils.ts'
import { DiffMatchPatchFull } from './_full/DiffMatchPatchFull.ts'

const differ = new Differ()

Expand Down
30 changes: 17 additions & 13 deletions src/Differ.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Diff, DiffOperation } from './Diff.ts'
import { DiffMatchPatch, MAX_SEGMENTS, MAX_SEGMENTS_2_3 } from './DiffMatchPatch.ts'
import { SegmentCodec, StringIter } from './SegmentCodec.ts'
import { DiffMatchPatch, MAX_SEGMENTS, MAX_SEGMENTS_2_3 } from './_DiffMatchPatch.ts'
import { SegmentCodec, StringIter } from './_SegmentCodec.ts'

/**
* Instance-level configuration options for the {@linkcode Differ} class to pass to the underlying
Expand All @@ -23,7 +23,9 @@ export type DiffOptions = {
*/
segmenter: Segmenter
/**
* Whether to join adjacent diffs.
* Whether to count consecutive diff operations containing multiple segments as a single diff.
* If `true`, a diff may contain multiple segments; if `false`, each segment will be a separate diff.
*
* @default {true}
*/
join: boolean
Expand Down Expand Up @@ -81,15 +83,18 @@ export class Differ {
}
}

#diffInternal(before: string, after: string, options: DiffOptions, maxBefore: number, maxAfter: number): {
#diffInternal(before: string, after: string, options: DiffOptions & { maxBefore: number; maxAfter: number }): {
encodedDiffs: Diff[]
codec?: SegmentCodec
decode: (encoded: string) => string[]
} {
const { segmenter, checkLines } = options
const { segmenter, checkLines, join, maxBefore, maxAfter } = options

// if no surrogate pairs present, we're entirely within the BMP, so no need to encode
if (segmenter === segmenters.char && !/[\uD800-\uDBFF]/.test([before, after].join(''))) {
return { encodedDiffs: this.#dmp.diff_main(before, after, checkLines, this.#deadline) }
return {
encodedDiffs: this.#dmp.diff_main(before, after, checkLines, this.#deadline),
decode: join ? (x) => [x] : (x) => x.split(''),
}
}

const segment = this.#toSegmentFn(segmenter)
Expand All @@ -101,7 +106,7 @@ export class Differ {

const encodedDiffs = this.#dmp.diff_main(chars1, chars2, checkLines, this.#deadline)

return { encodedDiffs, codec }
return { encodedDiffs, decode: codec.decode.bind(codec) }
}

/**
Expand Down Expand Up @@ -137,19 +142,18 @@ export class Differ {
return before ? [new Diff(DiffOperation.Equal, before)] : []
}

const opts = { ...defaultDiffOptions, ...options }
const opts = { ...defaultDiffOptions, ...options, maxBefore: MAX_SEGMENTS_2_3, maxAfter: MAX_SEGMENTS }
const { join } = opts

const { encodedDiffs, codec } = this.#diffInternal(before, after, opts, MAX_SEGMENTS_2_3, MAX_SEGMENTS)
if (codec == null) return encodedDiffs
const { encodedDiffs, decode } = this.#diffInternal(before, after, opts)

if (!join) {
return encodedDiffs.flatMap(
({ op, text }) => codec.decode(text).filter(Boolean).map((segment) => new Diff(op, segment)),
({ op, text }) => decode(text).filter(Boolean).map((segment) => new Diff(op, segment)),
)
}

return encodedDiffs.map(({ op, text }) => new Diff(op, codec.decode(text).join(''))).filter((x) => x.text)
return encodedDiffs.map(({ op, text }) => new Diff(op, decode(text).join(''))).filter((x) => x.text)
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/DiffMatchPatch.ts → src/_DiffMatchPatch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Diff, DiffOperation } from './Diff.ts'

// reduced version - removed props/methods that are currently unused by `Differ`
// reduced version - removed props/methods that are currently unused by `Differ` class

/**
* Diff Match and Patch
Expand All @@ -26,9 +26,9 @@ import { Diff, DiffOperation } from './Diff.ts'
* @author [email protected] (Neil Fraser)
*/

// max BMP code point. hard limit w/o significant refactoring
/** `0xFFFF`: Max BMP code point. Hard limit w/o significant refactoring */
export const MAX_SEGMENTS = 0xFFFF
// round(MAX_SEGMENTS * 2 / 3)
/** `= round(MAX_SEGMENTS * 2 / 3)` */
export const MAX_SEGMENTS_2_3 = 0xAAAA

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/SegmentCodec.test.ts → src/_SegmentCodec.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AssertionError } from '@std/assert/assertion-error'
import { assertEquals, assertThrows } from '@std/assert'
import { SegmentCodec } from '../src/SegmentCodec.ts'
import { SegmentCodec } from './_SegmentCodec.ts'

Deno.test(SegmentCodec.name, async (t) => {
await t.step('happy path', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/SegmentCodec.ts → src/_SegmentCodec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class SegmentCodec {
return out
}

decode(text: string): string[] {
return [...text].map((char) => this.#decoded.get(char) ?? '')
decode(encoded: string): string[] {
return [...encoded].map((char) => this.#decoded.get(char) ?? '')
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { assert, assertEquals } from '@std/assert'
import { DiffMatchPatchFull as DiffMatchPatch } from '../src/DiffMatchPatchFull.ts'
import { Diff, DiffOperation } from '../src/Diff.ts'
import { Patch } from '../src/Patch.ts'
import { assertDiffsEqual } from './testUtils.ts'
import { makeDiffs } from '../src/utils.ts'
import { DiffMatchPatchFull as DiffMatchPatch } from './DiffMatchPatchFull.ts'
import { Diff, DiffOperation } from '../Diff.ts'
import { Patch } from './Patch.ts'
import { assertDiffsEqual } from '../_testUtils.ts'
import { makeDiffs } from '../utils.ts'

// Tests here are modified from `google/diff-match-patch` tests
// to ensure parity after the various refactoring (ESM, classes, TS, etc.)
Expand Down
4 changes: 2 additions & 2 deletions src/DiffMatchPatchFull.ts → src/_full/DiffMatchPatchFull.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Diff, DiffOperation } from './Diff.ts'
import { DiffMatchPatch } from './DiffMatchPatch.ts'
import { Diff, DiffOperation } from '../Diff.ts'
import { DiffMatchPatch } from '../_DiffMatchPatch.ts'
import { Patch } from './Patch.ts'

// full version (extending reduced version) - re-add props/methods that are currently unused by `Differ`
Expand Down
4 changes: 2 additions & 2 deletions src/Patch.ts → src/_full/Patch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DiffOperation } from './Diff.ts'
import type { Diff } from './Diff.ts'
import { DiffOperation } from '../Diff.ts'
import type { Diff } from '../Diff.ts'

/**
* Class representing one patch operation.
Expand Down
2 changes: 1 addition & 1 deletion tests/testUtils.ts → src/_testUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assertEquals } from '@std/assert/equals'
import { DiffLike, makeDiffs } from '../src/utils.ts'
import { DiffLike, makeDiffs } from './utils.ts'

export function assertDiffsEqual(d1: readonly DiffLike[], d2: readonly DiffLike[]) {
assertEquals(makeDiffs(d1), makeDiffs(d2))
Expand Down
10 changes: 3 additions & 7 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Diff, DiffOperation } from './Diff.ts'
import { assert } from '@std/assert/assert'
import { Diff, type DiffOperation } from './Diff.ts'

/**
* A `Diff` or a tuple of `[operation, text]` (loosely typed for convenience as an input to `makeDiff`).
Expand All @@ -20,10 +20,6 @@ export function makeDiff(d: DiffLike): Diff {
if (d instanceof Diff) return d
const [op, text] = d
assert(typeof text === 'string')
return new Diff(getOpWithAssertion(op), text)
}

function getOpWithAssertion(op: unknown): DiffOperation {
assert(op === -1 || op === 0 || op === 1)
return op
assert(op === DiffOperation.Delete || op === DiffOperation.Insert || op === DiffOperation.Equal)
return new Diff(op, text)
}

0 comments on commit 87cefe1

Please sign in to comment.