Generates structurual diffs for two JS objects. Objects can have circular references.
The first of all purpose of library -- to create nice diffs for assertion libraries.
npm install structured-diff
let api = require('structured-diff');
let objectDiff = api.generateDiff(
{ some: 'foo', object: true },
{ object: 'is', cool: ['yes', true] }
);
// or
let stringDiff = new api.Diff('some string', 'another string');
// Get unified diff with inline diffs in each line with 4 lines of context
// before and after changed lines
let unified = objectDiff.unified(4);
// Get inline diff with 4 lines of context before and after changed lines
let inline = stringDiff.inline(4);
diff
has format describing by JSON Schemas.
Also see Diff format section.
Also see examples.
Module exports object with one function and one class for generating diffs:
Creates diffs by comparing expected
and actual
. Both parameters must be strings.
Parameters
expected
: Base string which will be show as removed part of diffactual
: New string which will be showed as added part of diffoptions
: Options for diff algorithm. Optional parameter, defaults to{}
. Supported options:ignoreWhitespace
(type:boolean
, default:false
): ignores whitespace changes in lines;newlineIsToken
(type:boolean
, default:false
): iftrue
, each symbol\n
or sequence\r\n
considered as separate token, otherwise it includes as part in preceding token;ignoreCase
(type:boolean
, default:false
): iftrue
, tokens are compared case-insensitive;comparator
(type:function(String, String) -> boolean
, default:undefined
): function for comparing tokens, must return-1
,0
, or1
if first token less then, equals or greater then second accordingly;hint
(type:Object|string
, default:undefined
): the hint to diff algorithm with what type of objects it works. Can be or string with type name or object{ type: string, ... }
with type and additional options dependent on type. For now only one type is known with one additional option:{ type: 'json', indent: Number }
. Parameterindent
specify indentation size, used for JSON stringification. This hint will be used by diff algorithm for produce nice output in differences in indents
Converts Diff
object to array with hunks or lines, depending on presence of the context
parameter. If the context
is undefined
then method returns an array, each element of which
represents one line of the text. The text is divided into lines by \n
symbol or \r\n
sequence. Otherwise array contains hunks with only changed lines and specified number of context
lines before and after changed lines. In particular, if context===0
, each hunk contains only
the changed lines.
If context===null
then method returns one hunk with all lines if there exist some changes and
empty array otherwise. It differs from behavior if context
is undefined
-- in this case
the array of all lines always returns even if there are no changes.
Each line for unified
method represented by the following object:
{ kind: ' /+/-', value: 'line value' }
// or
{ kind: '+/-', changes: [{ kind: ' /+/-', value: 'part of string' }] }
where
kind
: one of' '
,'+'
or'-'
. Represents kind of change -- line not changed (context line), line added inactual
or line is removed inactual
;value
: contains line text; for the changed lines existence of this property means that in them there are no inline differences, otherwise object contains propertychanges
. Context lines always contains only that property;changes
: array of objects represents inline changes in the line. This property is used instead ofvalue
property for lines with inline differences. Each array element is object with following structure:kind
: one of' '
,'+'
or'-'
. Represents kind of change -- piece not changed, piece added or removed;value
: string contains part of text that the same inexpected
andactual
, added or removed within line.
Each line for inline
method represented by the following object:
{ kind: ' /+/-/?', value: 'line value' }
// or
{ kind: '+/-', changes: [ { kind: ' /+/-', value: 'part of string' }] }
where
kind
: one of' '
,'+'
,'-'
or'?'
. Represents kind of change -- line not changed (context line), line added inactual
, line is removed inactual
, line contains inline differences;value
: for all kinds except'?'
, contains line text; for thekind = '?'
object contains propertychanges
instead of this property;changes
: array of objects represents inline changes in the line. This property is used only forkind = '?'
instead ofvalue
property. Each array element is object with following structure:kind
: one of' '
,'+'
or'-'
. Represents kind of change -- piece not changed, piece added or removed;value
: string contains part of text that the same inexpected
andactual
, added or removed within line.
Each hunk in both method results represented by the following object:
{
oldStart: <Number>, oldLines: <Number>,
newStart: <Number>, newLines: <Number>,
lines: <array of Line objects described above>
}
oldStart
represents line number (starts with 1) when the hunk is begin in expected
string and
oldLines
represents all lines in the hunk that come from expected
(context lines and removed lines).
newStart
and newLines
represents the same things in the actual
string, but newLines
count
context lines and added lines.
Parameters
context
: Number of unchanged lines to include in result around changed lines (specified count applied to lines below and above changed lines, so 2 means up to 4 context lines)
Returns: See description
Creates diffs by comparing expected
and actual
converted to strings.
If both expected
and actual
are already strings, then the behavior is the same as
new Diff(expected, actual, options)
. Otherwise both objects will be converted to strings
with use of the stable algorithm working with circular references. At the moment stringification
performed with safe-stable-stringify. This
is optional dependency so you can use this method only if it is installed, otherwise method
throw Error
.
Parameters
expected
:Object
, Base object which will be show as removed part of diffactual
:Object
, New object which will be showed as added part of diff
Returns: Object[]
, Array with one change
element for each line of text diff between
stringified representation of compared objects. Each change
object can also have information
about inline differences.
In both diff formats deletions appears before insertions in changed parts.
Function Diff.unified
returns array when each element describes one line in unified diff output.
Description of format also available as JSON Schema v7.
Each array element has kind
property:
' '
-- line not changed (the same in both sides). Line content in thevalue
property'-'
-- line is removed (line is exist inexpected
and missing inactual
). Line content or invalue
or inchanges
property'+'
-- line is inserted (line is missing inexpected
and exist inactual
). Line content or invalue
or inchanges
property
When line kind is +
or -
, line content can have inline changes.
Inline changes stored in the property changes
as array of inlineChange
object with properties kind
and value
.
Each value
always string with part of line content and kind
property has values:
' '
-- this part of line not changed (the same in both sides)'-'
-- this part of line is removed (is exist inexpected
and missing inactual
)'+'
-- this part of line is inserted (is missing inexpected
and exist inactual
)
When line do not have inline changes it can contains property value
instead of changes
with string with all line content.
For example from Usage section the following diff will be generated (variable unified
):
[
{ kind: ' ', value: '{' },
{
kind: '-',
changes: [
{ kind: ' ', value: ' "' },
{ kind: '-', value: 'some' },
{ kind: ' ', value: '": "' },
{ kind: '-', value: 'foo' },
{ kind: ' ', value: '"' }
]
},
{
kind: '-',
changes: [
{ kind: ' ', value: ' "' },
{ kind: '-', value: 'object' },
{ kind: ' ', value: '": ' },
{ kind: ' ', value: 'true' }
]
},
{
kind: '+',
changes: [
{ kind: ' ', value: ' "' },
{ kind: '+', value: 'object' },
{ kind: ' ', value: '": "' },
{ kind: '+', value: 'is' },
{ kind: ' ', value: '"' }
]
},
{
kind: '+',
changes: [
{ kind: ' ', value: ' "' },
{ kind: '+', value: 'cool' },
{ kind: ' ', value: '": ' },
{ kind: '+', value: '[' }
]
},
{ kind: '+', value: ' "yes"' },
{
kind: '+',
changes: [
{ kind: '+', value: ' ' },
{ kind: ' ', value: 'true' }
]
},
{ kind: '+', value: ' ]' },
{ kind: ' ', value: '}' }
]
Function Diff.inline
returns array when each element describes one line in inline diff output.
Description of format also available as JSON Schema v7.
Each array element has kind
property:
' '
-- line not changed (the same in both sides). Line content in thevalue
property'-'
-- line is removed (line is exist inexpected
and missing inactual
). Line content in thevalue
property'+'
-- line is inserted (line is missing inexpected
and exist inactual
). Line content in thevalue
property'?'
-- line exists in both sides but not identical. Line content in thechanges
property
When line kind is ?
, line content has inline changes.
Inline changes stored in the property changes
as array of inlineChange
object with properties kind
and value
.
Each value
always string with part of line content and kind
property has values:
' '
-- this part of line not changed (the same in both sides)'-'
-- this part of line is removed (is exist inexpected
and missing inactual
)'+'
-- this part of line is inserted (is missing inexpected
and exist inactual
)
For example from Usage section the following diff will be generated (variable inline
):
[
{
kind: '?',
changes: [
{ kind: '-', value: 'some' },
{ kind: '+', value: 'another' },
{ kind: ' ', value: ' string' }
]
}
]