Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Always set added and removed to true or false, rather than le…
…aving them unset or explicitly using `undefined`

Resolves #233
  • Loading branch information
ExplodingCabbage committed Jan 2, 2024
commit 64cf050c03c9489fdfa162f4b6205b68102e8e56
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,8 @@ All methods above which accept the optional `callback` method will run in sync m
Many of the methods above return change objects. These objects consist of the following fields:

* `value`: Text content
* `added`: True if the value was inserted into the new string
* `removed`: True if the value was removed from the old string

Note that some cases may omit a particular flag field. Comparison on the flag fields should always be done in a truthy or falsy manner.
* `added`: true if the value was inserted into the new string, otherwise false
* `removed`: true if the value was removed from the old string, otherwise false

## Examples

Expand Down
8 changes: 4 additions & 4 deletions src/diff/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Diff.prototype = {
let newPos = this.extractCommon(bestPath[0], newString, oldString, 0);
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
// Identity per the equality and tokenizer
return done([{value: this.join(newString), count: newString.length}]);
return done([{value: this.join(newString), count: newString.length, added: false, removed: false}]);
}

// Once we hit the right edge of the edit graph on some diagonal k, we can
Expand Down Expand Up @@ -95,9 +95,9 @@ Diff.prototype = {
// path whose position in the old string is the farthest from the origin
// and does not pass the bounds of the diff graph
if (!canRemove || (canAdd && removePath.oldPos < addPath.oldPos)) {
basePath = self.addToPath(addPath, true, undefined, 0);
basePath = self.addToPath(addPath, true, false, 0);
} else {
basePath = self.addToPath(removePath, undefined, true, 1);
basePath = self.addToPath(removePath, false, true, 1);
}

newPos = self.extractCommon(basePath, newString, oldString, diagonalPath);
Expand Down Expand Up @@ -173,7 +173,7 @@ Diff.prototype = {
}

if (commonCount) {
basePath.lastComponent = {count: commonCount, previousComponent: basePath.lastComponent};
basePath.lastComponent = {count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false};
}

basePath.oldPos = oldPos;
Expand Down
30 changes: 15 additions & 15 deletions test/diff/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ describe('diff/array', function() {
const diffResult = diffArrays([a, b, c], [a, c, b]);
console.log(diffResult);
expect(diffResult).to.deep.equals([
{count: 1, value: [a]},
{count: 1, value: [b], removed: true, added: undefined},
{count: 1, value: [c]},
{count: 1, value: [b], removed: undefined, added: true}
{count: 1, value: [a], removed: false, added: false},
{count: 1, value: [b], removed: true, added: false},
{count: 1, value: [c], removed: false, added: false},
{count: 1, value: [b], removed: false, added: true}
]);
});
it('should diff falsey values', function() {
Expand All @@ -24,20 +24,20 @@ describe('diff/array', function() {
const arrayB = [c, b, a, b, a, c];
const diffResult = diffArrays(arrayA, arrayB);
expect(diffResult).to.deep.equals([
{count: 2, value: [a, b], removed: true, added: undefined},
{count: 1, value: [c]},
{count: 1, value: [b], removed: undefined, added: true},
{count: 2, value: [a, b]},
{count: 1, value: [b], removed: true, added: undefined},
{count: 1, value: [a]},
{count: 1, value: [c], removed: undefined, added: true}
{count: 2, value: [a, b], removed: true, added: false},
{count: 1, value: [c], removed: false, added: false},
{count: 1, value: [b], removed: false, added: true},
{count: 2, value: [a, b], removed: false, added: false},
{count: 1, value: [b], removed: true, added: false},
{count: 1, value: [a], removed: false, added: false},
{count: 1, value: [c], removed: false, added: true}
]);
});
describe('anti-aliasing', function() {
// Test apparent contract that no chunk value is ever an input argument.
const value = [0, 1, 2];
const expected = [
{count: value.length, value: value}
{count: value.length, value: value, removed: false, added: false}
];

const input = value.slice();
Expand Down Expand Up @@ -70,9 +70,9 @@ describe('diff/array', function() {
const diffResult = diffArrays([a, b, c], [a, b, d], { comparator: comparator });
console.log(diffResult);
expect(diffResult).to.deep.equals([
{count: 2, value: [a, b]},
{count: 1, value: [c], removed: true, added: undefined},
{count: 1, value: [d], removed: undefined, added: true}
{count: 2, value: [a, b], removed: false, added: false},
{count: 1, value: [c], removed: true, added: false},
{count: 1, value: [d], removed: false, added: true}
]);
});
});
Expand Down
82 changes: 41 additions & 41 deletions test/diff/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ describe('diff/json', function() {
{a: 123, b: 456, c: 789},
{a: 123, b: 456}
)).to.eql([
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n' },
{ count: 1, value: ' "c": 789\n', added: undefined, removed: true },
{ count: 1, value: '}' }
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n', removed: false, added: false },
{ count: 1, value: ' "c": 789\n', added: false, removed: true },
{ count: 1, value: '}', removed: false, added: false }
]);
});

Expand All @@ -21,9 +21,9 @@ describe('diff/json', function() {
{a: 123, b: 456, c: 789},
{b: 456, a: 123}
)).to.eql([
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n' },
{ count: 1, value: ' "c": 789\n', added: undefined, removed: true },
{ count: 1, value: '}' }
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n', removed: false, added: false },
{ count: 1, value: ' "c": 789\n', added: false, removed: true },
{ count: 1, value: '}', removed: false, added: false }
]);
});

Expand All @@ -32,9 +32,9 @@ describe('diff/json', function() {
{a: 123, b: 456, c: [1, 2, {foo: 'bar'}, 4]},
{a: 123, b: 456, c: [1, {foo: 'bar'}, 4]}
)).to.eql([
{ count: 5, value: '{\n "a": 123,\n "b": 456,\n "c": [\n 1,\n' },
{ count: 1, value: ' 2,\n', added: undefined, removed: true },
{ count: 6, value: ' {\n "foo": "bar"\n },\n 4\n ]\n}' }
{ count: 5, value: '{\n "a": 123,\n "b": 456,\n "c": [\n 1,\n', removed: false, added: false },
{ count: 1, value: ' 2,\n', added: false, removed: true },
{ count: 6, value: ' {\n "foo": "bar"\n },\n 4\n ]\n}', removed: false, added: false }
]);
});

Expand All @@ -43,12 +43,12 @@ describe('diff/json', function() {
{a: new Date(123), b: new Date(456), c: new Date(789)},
{a: new Date(124), b: new Date(456)}
)).to.eql([
{ count: 1, value: '{\n' },
{ count: 1, value: ' "a": "1970-01-01T00:00:00.123Z",\n', added: undefined, removed: true },
{ count: 1, value: ' "a": "1970-01-01T00:00:00.124Z",\n', added: true, removed: undefined },
{ count: 1, value: ' "b": "1970-01-01T00:00:00.456Z",\n' },
{ count: 1, value: ' "c": "1970-01-01T00:00:00.789Z"\n', added: undefined, removed: true },
{ count: 1, value: '}' }
{ count: 1, value: '{\n', removed: false, added: false },
{ count: 1, value: ' "a": "1970-01-01T00:00:00.123Z",\n', added: false, removed: true },
{ count: 1, value: ' "a": "1970-01-01T00:00:00.124Z",\n', added: true, removed: false },
{ count: 1, value: ' "b": "1970-01-01T00:00:00.456Z",\n', removed: false, added: false },
{ count: 1, value: ' "c": "1970-01-01T00:00:00.789Z"\n', added: false, removed: true },
{ count: 1, value: '}', removed: false, added: false }
]);
});

Expand All @@ -57,24 +57,24 @@ describe('diff/json', function() {
{a: 123, b: 456, c: null},
{a: 123, b: 456}
)).to.eql([
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n' },
{ count: 1, value: ' "c": null\n', added: undefined, removed: true },
{ count: 1, value: '}' }
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n', removed: false, added: false },
{ count: 1, value: ' "c": null\n', added: false, removed: true },
{ count: 1, value: '}', removed: false, added: false }
]);
expect(diffJson(
{a: 123, b: 456, c: undefined},
{a: 123, b: 456}
)).to.eql([
{ count: 4, value: '{\n "a": 123,\n "b": 456\n}' }
{ count: 4, value: '{\n "a": 123,\n "b": 456\n}', removed: false, added: false }
]);
expect(diffJson(
{a: 123, b: 456, c: undefined},
{a: 123, b: 456},
{undefinedReplacement: null}
)).to.eql([
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n' },
{ count: 1, value: ' "c": null\n', added: undefined, removed: true },
{ count: 1, value: '}' }
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n', removed: false, added: false },
{ count: 1, value: ' "c": null\n', added: false, removed: true },
{ count: 1, value: '}', removed: false, added: false }
]);
});

Expand All @@ -83,9 +83,9 @@ describe('diff/json', function() {
JSON.stringify({a: 123, b: 456, c: 789}, undefined, ' '),
JSON.stringify({a: 123, b: 456}, undefined, ' ')
)).to.eql([
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n' },
{ count: 1, value: ' "c": 789\n', added: undefined, removed: true },
{ count: 1, value: '}' }
{ count: 3, value: '{\n "a": 123,\n "b": 456,\n', removed: false, added: false },
{ count: 1, value: ' "c": 789\n', added: false, removed: true },
{ count: 1, value: '}', removed: false, added: false }
]);
});

Expand Down Expand Up @@ -143,43 +143,43 @@ describe('diff/json', function() {
{a: 123},
{a: /foo/}
)).to.eql([
{ count: 1, value: '{\n' },
{ count: 1, value: ' \"a\": 123\n', added: undefined, removed: true },
{ count: 1, value: ' \"a\": {}\n', added: true, removed: undefined },
{ count: 1, value: '}' }
{ count: 1, value: '{\n', removed: false, added: false },
{ count: 1, value: ' \"a\": 123\n', added: false, removed: true },
{ count: 1, value: ' \"a\": {}\n', added: true, removed: false },
{ count: 1, value: '}', removed: false, added: false }
]);

expect(diffJson(
{a: 123},
{a: /foo/gi},
{stringifyReplacer: (k, v) => v instanceof RegExp ? v.toString() : v}
)).to.eql([
{ count: 1, value: '{\n' },
{ count: 1, value: ' \"a\": 123\n', added: undefined, removed: true },
{ count: 1, value: ' \"a\": "/foo/gi"\n', added: true, removed: undefined },
{ count: 1, value: '}' }
{ count: 1, value: '{\n', removed: false, added: false },
{ count: 1, value: ' \"a\": 123\n', added: false, removed: true },
{ count: 1, value: ' \"a\": "/foo/gi"\n', added: true, removed: false },
{ count: 1, value: '}', removed: false, added: false }
]);

expect(diffJson(
{a: 123},
{a: new Error('ohaider')},
{stringifyReplacer: (k, v) => v instanceof Error ? `${v.name}: ${v.message}` : v}
)).to.eql([
{ count: 1, value: '{\n' },
{ count: 1, value: ' \"a\": 123\n', added: undefined, removed: true },
{ count: 1, value: ' \"a\": "Error: ohaider"\n', added: true, removed: undefined },
{ count: 1, value: '}' }
{ count: 1, value: '{\n', removed: false, added: false },
{ count: 1, value: ' \"a\": 123\n', added: false, removed: true },
{ count: 1, value: ' \"a\": "Error: ohaider"\n', added: true, removed: false },
{ count: 1, value: '}', removed: false, added: false }
]);

expect(diffJson(
{a: 123},
{a: [new Error('ohaider')]},
{stringifyReplacer: (k, v) => v instanceof Error ? `${v.name}: ${v.message}` : v}
)).to.eql([
{ count: 1, value: '{\n' },
{ count: 1, value: ' \"a\": 123\n', added: undefined, removed: true },
{ count: 3, value: ' \"a\": [\n "Error: ohaider"\n ]\n', added: true, removed: undefined },
{ count: 1, value: '}' }
{ count: 1, value: '{\n', removed: false, added: false },
{ count: 1, value: ' \"a\": 123\n', added: false, removed: true },
{ count: 3, value: ' \"a\": [\n "Error: ohaider"\n ]\n', added: true, removed: false },
{ count: 1, value: '}', removed: false, added: false }
]);
});
});
Expand Down
10 changes: 5 additions & 5 deletions test/diff/line.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,18 @@ describe('diff/line', function() {

describe('#diffLinesNL', function() {
expect(diffLines('restaurant', 'restaurant\n', {newlineIsToken: true})).to.eql([
{value: 'restaurant', count: 1},
{value: '\n', count: 1, added: true, removed: undefined}
{value: 'restaurant', count: 1, added: false, removed: false},
{value: '\n', count: 1, added: true, removed: false}
]);
expect(diffLines('restaurant', 'restaurant\nhello', {newlineIsToken: true})).to.eql([
{value: 'restaurant', count: 1},
{value: '\nhello', count: 2, added: true, removed: undefined}
{value: 'restaurant', count: 1, added: false, removed: false},
{value: '\nhello', count: 2, added: true, removed: false}
]);
});

describe('Strip trailing CR', function() {
expect(diffLines('line\nline', 'line\r\nline', {stripTrailingCr: true})).to.eql([
{value: 'line\nline', count: 2}
{value: 'line\nline', count: 2, added: false, removed: false}
]);
});
});
22 changes: 11 additions & 11 deletions test/diff/word.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,23 @@ describe('WordDiff', function() {
});

it('should include count with identity cases', function() {
expect(diffWords('foo', 'foo')).to.eql([{value: 'foo', count: 1}]);
expect(diffWords('foo bar', 'foo bar')).to.eql([{value: 'foo bar', count: 3}]);
expect(diffWords('foo', 'foo')).to.eql([{value: 'foo', count: 1, removed: false, added: false}]);
expect(diffWords('foo bar', 'foo bar')).to.eql([{value: 'foo bar', count: 3, removed: false, added: false}]);
});
it('should include count with empty cases', function() {
expect(diffWords('foo', '')).to.eql([{value: 'foo', count: 1, added: undefined, removed: true}]);
expect(diffWords('foo bar', '')).to.eql([{value: 'foo bar', count: 3, added: undefined, removed: true}]);
expect(diffWords('foo', '')).to.eql([{value: 'foo', count: 1, added: false, removed: true}]);
expect(diffWords('foo bar', '')).to.eql([{value: 'foo bar', count: 3, added: false, removed: true}]);

expect(diffWords('', 'foo')).to.eql([{value: 'foo', count: 1, added: true, removed: undefined}]);
expect(diffWords('', 'foo bar')).to.eql([{value: 'foo bar', count: 3, added: true, removed: undefined}]);
expect(diffWords('', 'foo')).to.eql([{value: 'foo', count: 1, added: true, removed: false}]);
expect(diffWords('', 'foo bar')).to.eql([{value: 'foo bar', count: 3, added: true, removed: false}]);
});

it('should ignore whitespace', function() {
expect(diffWords('hase igel fuchs', 'hase igel fuchs')).to.eql([{ count: 5, value: 'hase igel fuchs' }]);
expect(diffWords('hase igel fuchs', 'hase igel fuchs\n')).to.eql([{ count: 5, value: 'hase igel fuchs\n' }]);
expect(diffWords('hase igel fuchs\n', 'hase igel fuchs')).to.eql([{ count: 5, value: 'hase igel fuchs\n' }]);
expect(diffWords('hase igel fuchs', 'hase igel\nfuchs')).to.eql([{ count: 5, value: 'hase igel\nfuchs' }]);
expect(diffWords('hase igel\nfuchs', 'hase igel fuchs')).to.eql([{ count: 5, value: 'hase igel fuchs' }]);
expect(diffWords('hase igel fuchs', 'hase igel fuchs')).to.eql([{ count: 5, value: 'hase igel fuchs', removed: false, added: false }]);
expect(diffWords('hase igel fuchs', 'hase igel fuchs\n')).to.eql([{ count: 5, value: 'hase igel fuchs\n', removed: false, added: false }]);
expect(diffWords('hase igel fuchs\n', 'hase igel fuchs')).to.eql([{ count: 5, value: 'hase igel fuchs\n', removed: false, added: false }]);
expect(diffWords('hase igel fuchs', 'hase igel\nfuchs')).to.eql([{ count: 5, value: 'hase igel\nfuchs', removed: false, added: false }]);
expect(diffWords('hase igel\nfuchs', 'hase igel fuchs')).to.eql([{ count: 5, value: 'hase igel fuchs', removed: false, added: false }]);
});

it('should diff whitespace with flag', function() {
Expand Down