unist-diff
unist utility to diff two trees.
Based on the vtree
diffing algorithm in virtual-dom
, but for Unist.
‼️ Work in progress / unstable / broken / experimental
See preliminary docs
One caveat is that unist does not support keys. Keys are what allow performant reordering of children. To deal with that, unist-diff
uses “synthetic” keys based on the properties on nodes (excluding their value or their children). This is not ideal but it’s better than nothing. Let’s see how it goes!
Install
npm:
npm install unist-diff
Use
var h = require('hastscript')
var diff = require('unist-diff')
var left = h('div', [
h('p', ['Some ', h('b', 'importance'), ' and ', h('i', 'emphasis'), '.']),
h('pre', h('code', 'foo()'))
])
var right = h('div', [
h('p', [
'Some ',
h('strong', 'importance'),
' and ',
h('em', 'emphasis'),
'.'
]),
h('pre', h('code', 'bar()'))
])
console.dir(diff(left, right), {depth: null})
Yields:
{
'1': [
{
type: 'insert',
left: null,
right: {
type: 'element',
tagName: 'strong',
properties: {},
children: [{type: 'text', value: 'importance'}]
}
},
{
type: 'insert',
left: null,
right: {
type: 'element',
tagName: 'em',
properties: {},
children: [{type: 'text', value: 'emphasis'}]
}
}
],
'3': {
type: 'remove',
left: {
type: 'element',
tagName: 'b',
properties: {},
children: [{type: 'text', value: 'importance'}]
},
right: null
},
'6': {
type: 'remove',
left: {
type: 'element',
tagName: 'i',
properties: {},
children: [{type: 'text', value: 'emphasis'}]
},
right: null
},
'11': {
type: 'text',
left: {type: 'text', value: 'foo()'},
right: {type: 'text', value: 'bar()'}
},
left: Node // Reference to the tree at `left`.
}
API
diff(left, right)
Diff two trees.
Parameters
Returns
Object.<Patch|Patches>
— Object mapping indices of nodes to one or more patches.
Patch
Patches represent changes. They come with three properties:
type
(string
) — Type of change (either'remove'
,'insert'
,'replace'
,'props'
,'text'
, or'order'
)left
(Node
, optional) — Left noderight
(Node
,PropsDiff
,MoveDiff
, optional) — New thing
remove
type
('remove'
)left
(Node
) — Left noderight
(null
)
insert
type
('insert'
)left
(null
)right
(Node
) — Right node
replace
props
text
order
PropsDiff
PropsDiff
is an object mapping keys to new values.
In the diff:
- If a key is removed, the key’s value is set to
undefined
- If the new value and the old value are both plain objects, the key’s value is set to a
PropsDiff
of both values - In all other cases, the key’s value is set to the new value
MoveDiff
MoveDiff
is an object with two arrays: removes
and inserts
. They always have equal lengths, and are never both empty. Objects in inserts
and removes
have the following properties:
left
(Node
) — The moved noderight
(number
) — The index this node moved from (when inremoves
) or to (when ininserts
)
Contribute
See contributing.md
in syntax-tree/.github
for ways to get started. See support.md
for ways to get help.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.