mirror of
https://github.com/flynx/diff.js.git
synced 2025-10-29 19:10:11 +00:00
reworked the .flatten(..) framework...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
d3ac8e3a46
commit
86797be419
179
diff.js
179
diff.js
@ -491,6 +491,27 @@ var Types = {
|
|||||||
return obj
|
return obj
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// XXX experimental...
|
||||||
|
// XXX need to sort out return values...
|
||||||
|
walk: function(diff, func, path){
|
||||||
|
// no changes...
|
||||||
|
if(diff == null){
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// flat diff...
|
||||||
|
if(diff instanceof Array){
|
||||||
|
return diff.map(func)
|
||||||
|
|
||||||
|
// tree diff...
|
||||||
|
} else {
|
||||||
|
var handler = this.getHandler(diff.type)
|
||||||
|
if(handler == null || !handler.walk){
|
||||||
|
throw new TypeError('Can\'t walk type: '+ diff.type)
|
||||||
|
}
|
||||||
|
return handler.walk.call(this, diff, func, path || [])
|
||||||
|
}
|
||||||
|
},
|
||||||
// Flatten the tree diff format...
|
// Flatten the tree diff format...
|
||||||
//
|
//
|
||||||
// XXX might be good to include some type info so as to enable patching
|
// XXX might be good to include some type info so as to enable patching
|
||||||
@ -505,6 +526,13 @@ var Types = {
|
|||||||
// ...it might also be possible to provide vertical/topological
|
// ...it might also be possible to provide vertical/topological
|
||||||
// "fuzz", need to think about this...
|
// "fuzz", need to think about this...
|
||||||
// XXX TEST: the format should survive JSON.parse(JSON.stringify(..))...
|
// XXX TEST: the format should survive JSON.parse(JSON.stringify(..))...
|
||||||
|
flatten: function(diff, options){
|
||||||
|
options = options || {}
|
||||||
|
var res = []
|
||||||
|
this.walk(diff, function(change){ res.push(change) })
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
/* XXX LEGACY...
|
||||||
flatten: function(diff, res, path, options){
|
flatten: function(diff, res, path, options){
|
||||||
res = res || []
|
res = res || []
|
||||||
path = path || []
|
path = path || []
|
||||||
@ -522,6 +550,7 @@ var Types = {
|
|||||||
|
|
||||||
return handler.flatten.call(this, diff, res, path, options)
|
return handler.flatten.call(this, diff, res, path, options)
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// User API...
|
// User API...
|
||||||
@ -598,13 +627,18 @@ var Types = {
|
|||||||
|
|
||||||
// Patch (update) obj via diff...
|
// Patch (update) obj via diff...
|
||||||
//
|
//
|
||||||
patch: function(diff, obj){
|
patch: function(diff, obj, options){
|
||||||
// XXX
|
// XXX approach:
|
||||||
|
// - check
|
||||||
|
// - flatten
|
||||||
|
// - run patch
|
||||||
|
// - might be a good idea to enable handlers to handle
|
||||||
|
// their own updates...
|
||||||
},
|
},
|
||||||
|
|
||||||
// Check if diff is applicable to obj...
|
// Check if diff is applicable to obj...
|
||||||
//
|
//
|
||||||
check: function(diff, obj){
|
check: function(diff, obj, options){
|
||||||
// XXX
|
// XXX
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -700,9 +734,22 @@ Types.set('Basic', {
|
|||||||
check: function(obj, options){
|
check: function(obj, options){
|
||||||
return typeof(obj) != 'object' },
|
return typeof(obj) != 'object' },
|
||||||
handle: function(obj, diff, A, B, options){
|
handle: function(obj, diff, A, B, options){
|
||||||
obj.A = A
|
;(!options.keep_none && A === NONE)
|
||||||
obj.B = B
|
|| (obj.A = A)
|
||||||
|
;(!options.keep_none && B === NONE)
|
||||||
|
|| (obj.B = B)
|
||||||
},
|
},
|
||||||
|
walk: function(diff, func, path){
|
||||||
|
var change = {
|
||||||
|
path: path,
|
||||||
|
}
|
||||||
|
'A' in diff
|
||||||
|
&& (change.A = diff.A)
|
||||||
|
'B' in diff
|
||||||
|
&& (change.B = diff.B)
|
||||||
|
return func(change)
|
||||||
|
},
|
||||||
|
/* XXX LEGACY...
|
||||||
flatten: function(diff, res, path, options){
|
flatten: function(diff, res, path, options){
|
||||||
res.push({
|
res.push({
|
||||||
path: path,
|
path: path,
|
||||||
@ -711,6 +758,7 @@ Types.set('Basic', {
|
|||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
|
//*/
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -729,6 +777,18 @@ Types.set(Object, {
|
|||||||
// - attr ordering...
|
// - attr ordering...
|
||||||
// - prototypes
|
// - prototypes
|
||||||
},
|
},
|
||||||
|
walk: function(diff, func, path){
|
||||||
|
var that = this
|
||||||
|
return (diff.items || [])
|
||||||
|
.map(function(e){
|
||||||
|
var i = e[0]
|
||||||
|
var p = path.concat([i])
|
||||||
|
var v = e[1]
|
||||||
|
|
||||||
|
return that.walk(v, func, p)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/* XXX LEGACY...
|
||||||
flatten: function(diff, res, path, options){
|
flatten: function(diff, res, path, options){
|
||||||
var that = this
|
var that = this
|
||||||
;(diff.items || [])
|
;(diff.items || [])
|
||||||
@ -741,6 +801,7 @@ Types.set(Object, {
|
|||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
|
//*/
|
||||||
|
|
||||||
// part handlers...
|
// part handlers...
|
||||||
attributes: function(diff, A, B, options, filter){
|
attributes: function(diff, A, B, options, filter){
|
||||||
@ -802,6 +863,32 @@ Types.set(Array, {
|
|||||||
obj.length = A.length != B.length ? [A.length, B.length] : []
|
obj.length = A.length != B.length ? [A.length, B.length] : []
|
||||||
obj.items = this.get(Array).items.call(this, diff, A, B, options)
|
obj.items = this.get(Array).items.call(this, diff, A, B, options)
|
||||||
},
|
},
|
||||||
|
walk: function(diff, func, path){
|
||||||
|
var that = this
|
||||||
|
var NONE = this.NONE
|
||||||
|
var res = []
|
||||||
|
// length...
|
||||||
|
diff.length != null
|
||||||
|
&& res.push(func({
|
||||||
|
path: path.concat('length'),
|
||||||
|
A: diff.length[0],
|
||||||
|
B: diff.length[1],
|
||||||
|
}))
|
||||||
|
// items...
|
||||||
|
return res.concat((diff.items || [])
|
||||||
|
.map(function(e){
|
||||||
|
var v = e[2]
|
||||||
|
|
||||||
|
// index...
|
||||||
|
var i = e[0] == e[1] ?
|
||||||
|
e[0]
|
||||||
|
: [e[0], e[1]]
|
||||||
|
var p = path.concat([i])
|
||||||
|
|
||||||
|
return that.walk(v, func, p)
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
/* XXX LEGACY...
|
||||||
flatten: function(diff, res, path, options){
|
flatten: function(diff, res, path, options){
|
||||||
var that = this
|
var that = this
|
||||||
var NONE = this.NONE
|
var NONE = this.NONE
|
||||||
@ -839,6 +926,7 @@ Types.set(Array, {
|
|||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
|
//*/
|
||||||
|
|
||||||
// part handlers...
|
// part handlers...
|
||||||
items: function(diff, A, B, options){
|
items: function(diff, A, B, options){
|
||||||
@ -925,6 +1013,20 @@ Types.set('Text', {
|
|||||||
options.min_text_length = -1
|
options.min_text_length = -1
|
||||||
return this.handle(Array, obj, diff, A.split(/\n/), B.split(/\n/), options)
|
return this.handle(Array, obj, diff, A.split(/\n/), B.split(/\n/), options)
|
||||||
},
|
},
|
||||||
|
walk: function(diff, func, path){
|
||||||
|
// use the array walk but add 'Text' type to each change...
|
||||||
|
// NOTE: we need to abide by the protocol and call Array's
|
||||||
|
// .flatten(..) the context of the main object...
|
||||||
|
return this.get(Array).walk.call(this, diff, function(c){
|
||||||
|
// skip length changes...
|
||||||
|
if(c.path[c.path.length-1] == 'length'){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.type = 'Text'
|
||||||
|
return func(c)
|
||||||
|
}, path)
|
||||||
|
},
|
||||||
|
/* XXX LEGACY...
|
||||||
flatten: function(diff, res, path, options){
|
flatten: function(diff, res, path, options){
|
||||||
options = Object.create(options || {})
|
options = Object.create(options || {})
|
||||||
;('no_length' in options)
|
;('no_length' in options)
|
||||||
@ -939,6 +1041,7 @@ Types.set('Text', {
|
|||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
|
//*/
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -1041,7 +1144,8 @@ function(A, B, options, types){
|
|||||||
|
|
||||||
diff: options.tree_diff ?
|
diff: options.tree_diff ?
|
||||||
types.diff(A, B, options)
|
types.diff(A, B, options)
|
||||||
: types.flatten(Types.diff(A, B, options), null, null, options)
|
//: types.flatten(Types.diff(A, B, options), null, null, options)
|
||||||
|
: types.flatten(Types.diff(A, B, options), options)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
||||||
@ -1061,6 +1165,69 @@ function(diff, obj, options, types){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var _patch = function(diff, obj){
|
||||||
|
var NONE = diff.options.placeholders.NONE
|
||||||
|
var EMPTY = diff.options.placeholders.EMPTY
|
||||||
|
|
||||||
|
diff.diff
|
||||||
|
.forEach(function(change){
|
||||||
|
// replace the object itself...
|
||||||
|
if(path.length == 0){
|
||||||
|
return change.B
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = change.type || 'item'
|
||||||
|
|
||||||
|
var target = change.path
|
||||||
|
.slice(0, -1)
|
||||||
|
.reduce(function(res, e){
|
||||||
|
return res[e]}, obj)
|
||||||
|
var key = change.path[change.path.length-1]
|
||||||
|
|
||||||
|
if(type == 'item'){
|
||||||
|
// object attr...
|
||||||
|
if(typeof(key) == typeof('str')){
|
||||||
|
if(change.B.type == EMPTY.type){
|
||||||
|
delete target[key]
|
||||||
|
|
||||||
|
} else {
|
||||||
|
target[key] = change.B
|
||||||
|
}
|
||||||
|
|
||||||
|
// array item...
|
||||||
|
} else {
|
||||||
|
var i = key instanceof Array ? key[0] : key
|
||||||
|
var j = key instanceof Array ? key[1] : key
|
||||||
|
|
||||||
|
if(i == null){
|
||||||
|
target.splice(j, 0, change.B)
|
||||||
|
|
||||||
|
} else if(j == null){
|
||||||
|
// XXX better EMPTY check -- use diff
|
||||||
|
if(!('B' in change) || change.B.type == EMPTY.type){
|
||||||
|
delete target[i]
|
||||||
|
|
||||||
|
} else if(!('B' in change) || change.B.type == NONE.type){
|
||||||
|
target.splice(i, 1)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(i == j){
|
||||||
|
target[j] = change.B
|
||||||
|
|
||||||
|
} else {
|
||||||
|
target[j] = change.B
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* vim:set ts=4 sw=4 : */ return module })
|
* vim:set ts=4 sw=4 : */ return module })
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user