mirror of
https://github.com/flynx/diff.js.git
synced 2025-10-28 18:40:09 +00:00
experimenting...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
78136895a0
commit
04b703309e
180
diff2.js
180
diff2.js
@ -7,6 +7,7 @@
|
|||||||
(function(require){ var module={} // make module AMD/node compatible...
|
(function(require){ var module={} // make module AMD/node compatible...
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
|
var object = require('ig-object')
|
||||||
var types = require('ig-types')
|
var types = require('ig-types')
|
||||||
|
|
||||||
|
|
||||||
@ -275,6 +276,19 @@ module.HANDLERS = {
|
|||||||
//false: { match: false },
|
//false: { match: false },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var HANDLE_DEFAULTS =
|
||||||
|
module.HANDLE_DEFAULTS = {
|
||||||
|
flat: true,
|
||||||
|
|
||||||
|
flatPaths: true,
|
||||||
|
|
||||||
|
// handlers: <object>,
|
||||||
|
// seen: <map>
|
||||||
|
|
||||||
|
// no<handler-name>: true | false,
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// handle(obj[,options])
|
// handle(obj[,options])
|
||||||
// handle(obj, path[,options])
|
// handle(obj, path[,options])
|
||||||
@ -302,9 +316,17 @@ var handle =
|
|||||||
module.handle =
|
module.handle =
|
||||||
function*(obj, path=[], options={}){
|
function*(obj, path=[], options={}){
|
||||||
// parse args...
|
// parse args...
|
||||||
options = typeof(path) == 'object' && !(path instanceof Array) ?
|
options =
|
||||||
|
typeof(path) == 'object' && !(path instanceof Array) ?
|
||||||
path
|
path
|
||||||
: options
|
: options
|
||||||
|
options =
|
||||||
|
// inherit options from HANDLE_DEFAULTS of we don't already...
|
||||||
|
!object.parentOf(module.HANDLE_DEFAULTS, options) ?
|
||||||
|
Object.assign(
|
||||||
|
{ __proto__: module.HANDLE_DEFAULTS },
|
||||||
|
options)
|
||||||
|
: options
|
||||||
path = path instanceof Array ?
|
path = path instanceof Array ?
|
||||||
path
|
path
|
||||||
: typeof(path) == 'string' ?
|
: typeof(path) == 'string' ?
|
||||||
@ -330,22 +352,29 @@ function*(obj, path=[], options={}){
|
|||||||
: [p, v]) }
|
: [p, v]) }
|
||||||
|
|
||||||
// handle the object...
|
// handle the object...
|
||||||
|
var res = [path, ]
|
||||||
var handlers = options.handlers || module.HANDLERS
|
var handlers = options.handlers || module.HANDLERS
|
||||||
var res = [path]
|
|
||||||
yield* Object.entries(handlers)
|
yield* Object.entries(handlers)
|
||||||
.iter()
|
.iter()
|
||||||
.filter(function([_, handler]){
|
.filter(function([name, handler]){
|
||||||
return !!handler.handle })
|
return handler.handle
|
||||||
|
// skip options.no<handler-name>...
|
||||||
|
&& !options['no'+ name.capitalize()] })
|
||||||
.map(function*([name, handler]){
|
.map(function*([name, handler]){
|
||||||
// skip...
|
|
||||||
if(!!options['no'+ name.capitalize()]){
|
|
||||||
return }
|
|
||||||
// expand aliases...
|
// expand aliases...
|
||||||
var h = handler
|
var h = handler
|
||||||
while(h && typeof(h.handle) == 'string'){
|
while(h && typeof(h.handle) == 'string'){
|
||||||
h = handlers[h.handle] }
|
h = handlers[h.handle] }
|
||||||
// XXX should .handle(..) be called in the context of h or handler???
|
// XXX should .handle(..) be called in the context of h or handler???
|
||||||
res = h.handle.call(handler, obj, res, next, stop, options)
|
res = h.handle.call(handler, obj, res, next, stop, options)
|
||||||
|
|
||||||
|
// non-flat mode...
|
||||||
|
!options.flat
|
||||||
|
&& _next.length > 0
|
||||||
|
// XXX need to get the parent result to add .children to...
|
||||||
|
&& console.log('!!!!!!!!!!!!!!')
|
||||||
|
//&& parent.children.concat([...doNext()])
|
||||||
|
|
||||||
yield res
|
yield res
|
||||||
&& [path, res] })
|
&& [path, res] })
|
||||||
// clean out remains of handlers that rejected the obj...
|
// clean out remains of handlers that rejected the obj...
|
||||||
@ -359,6 +388,113 @@ function*(obj, path=[], options={}){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var WALK_HANDLERS = {
|
||||||
|
map: {
|
||||||
|
walk: function(obj){
|
||||||
|
return obj instanceof Map
|
||||||
|
&& obj.entries() } },
|
||||||
|
set: {
|
||||||
|
walk: function(obj){
|
||||||
|
return obj instanceof Set
|
||||||
|
&& obj.values() } },
|
||||||
|
attrs: {
|
||||||
|
walk: function(obj){
|
||||||
|
return typeof(obj) == 'object'
|
||||||
|
&& Object.entries(obj) } },
|
||||||
|
text: {
|
||||||
|
walk: function(obj){
|
||||||
|
return typeof(obj) == 'string'
|
||||||
|
&& obj.includes('\n')
|
||||||
|
&& obj.split(/\n/g) } },
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// walk(<handler>[, <options>])
|
||||||
|
// walk(<handler>, <path>[, <options>])
|
||||||
|
// -> <walker>
|
||||||
|
//
|
||||||
|
// <handler>(<obj>, <path>, <next>, <type>)
|
||||||
|
// -> <value>
|
||||||
|
// !> STOP(<value>)
|
||||||
|
//
|
||||||
|
// <walker>(<obj>)
|
||||||
|
// <walker>(<obj>, <path>)
|
||||||
|
// -> <generator>
|
||||||
|
// -> <value>
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// XXX the idea here is to try to decouple the walk from the format and
|
||||||
|
// move the formatters and other stuff out...
|
||||||
|
// ...not sure if this is simpler yet...
|
||||||
|
var walk =
|
||||||
|
module.walk =
|
||||||
|
function(handler, path=[], options={}){
|
||||||
|
// parse args...
|
||||||
|
options =
|
||||||
|
typeof(path) == 'object' && !(path instanceof Array) ?
|
||||||
|
path
|
||||||
|
: options
|
||||||
|
options =
|
||||||
|
// inherit options from HANDLE_DEFAULTS of we don't already...
|
||||||
|
!object.parentOf(module.HANDLE_DEFAULTS, options) ?
|
||||||
|
Object.assign(
|
||||||
|
{ __proto__: module.HANDLE_DEFAULTS },
|
||||||
|
options)
|
||||||
|
: options
|
||||||
|
|
||||||
|
var _walk = function*(obj, path=path, type=undefined){
|
||||||
|
path = path instanceof Array ?
|
||||||
|
path
|
||||||
|
: typeof(path) == 'string' ?
|
||||||
|
str2path(path)
|
||||||
|
: []
|
||||||
|
type = type || 'root'
|
||||||
|
|
||||||
|
var handlers = options.handlers || module.HANDLERS
|
||||||
|
// format:
|
||||||
|
// [
|
||||||
|
// [<handler-name>, [ [<key>, <value>], .. ]],
|
||||||
|
// ..
|
||||||
|
// ]
|
||||||
|
var next = Object.entries(handlers)
|
||||||
|
.filter(function([n, h]){
|
||||||
|
return h.walk
|
||||||
|
&& !options['no' + n.capitalize()] })
|
||||||
|
.map(function([n, h]){
|
||||||
|
// XXX should we call the handler(..) once per set of
|
||||||
|
// next values (i.e. attrs, items, ...)???
|
||||||
|
var res = h.walk.call(obj)
|
||||||
|
return res
|
||||||
|
&& [n, res] })
|
||||||
|
.filter(function(e){
|
||||||
|
return !!e })
|
||||||
|
|
||||||
|
try {
|
||||||
|
// main object...
|
||||||
|
if(handler instanceof types.Generator){
|
||||||
|
yield* handler(obj, path, next, type)
|
||||||
|
} else {
|
||||||
|
yield handler(obj, path, next, type) }
|
||||||
|
// next/children...
|
||||||
|
yield* next
|
||||||
|
.iter()
|
||||||
|
.map(function*([type, items]){
|
||||||
|
yield* items
|
||||||
|
.iter()
|
||||||
|
.map(function([key, value]){
|
||||||
|
yield* _walk(value, path.concat(key), type) }) })
|
||||||
|
// handle STOP...
|
||||||
|
} catch(err){
|
||||||
|
if(err === module.STOP){
|
||||||
|
return
|
||||||
|
} else if(err instanceof module.STOP){
|
||||||
|
yield err.value
|
||||||
|
return }
|
||||||
|
throw err } }
|
||||||
|
|
||||||
|
return _walk }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
@ -389,6 +525,8 @@ var path2str =
|
|||||||
module.path2str =
|
module.path2str =
|
||||||
function(p){
|
function(p){
|
||||||
return '/'+ p
|
return '/'+ p
|
||||||
|
// flatten lispPaths...
|
||||||
|
.flat(Infinity)
|
||||||
.map(serializePathElem)
|
.map(serializePathElem)
|
||||||
.reduce(function(res, e){
|
.reduce(function(res, e){
|
||||||
e = e === module.CONTENT ?
|
e = e === module.CONTENT ?
|
||||||
@ -420,6 +558,7 @@ var deserializePathElem = function(p){
|
|||||||
// XXX PROBLEM: need to be able to reference '' in {'': 123}, i.e, how do
|
// XXX PROBLEM: need to be able to reference '' in {'': 123}, i.e, how do
|
||||||
// we stringify ['']???
|
// we stringify ['']???
|
||||||
// [''] => ???
|
// [''] => ???
|
||||||
|
// XXX add support for options.lispPaths
|
||||||
var str2path =
|
var str2path =
|
||||||
module.str2path =
|
module.str2path =
|
||||||
function(str){
|
function(str){
|
||||||
@ -754,7 +893,7 @@ function(A, B, cmp){
|
|||||||
// 2) selectively match keys...
|
// 2) selectively match keys...
|
||||||
// ...need to test how complex this will be...
|
// ...need to test how complex this will be...
|
||||||
//
|
//
|
||||||
var diff =
|
var keyValueDiff =
|
||||||
function(A, B){
|
function(A, B){
|
||||||
return diffSections(
|
return diffSections(
|
||||||
[...handle(A)
|
[...handle(A)
|
||||||
@ -770,6 +909,26 @@ function(A, B){
|
|||||||
&& av.type
|
&& av.type
|
||||||
&& av.type == bv.type )) }) }
|
&& av.type == bv.type )) }) }
|
||||||
|
|
||||||
|
// XXX this completely ignores the path/key...
|
||||||
|
// XXX this works great for arrays but is questionable on other stuff...
|
||||||
|
var valueDiff =
|
||||||
|
function(A, B){
|
||||||
|
return diffSections(
|
||||||
|
[...handle(A)
|
||||||
|
.chain(serializePaths)],
|
||||||
|
[...handle(B)
|
||||||
|
.chain(serializePaths)],
|
||||||
|
// XXX add link support...
|
||||||
|
function([ap, av], [bp, bv]){
|
||||||
|
return av == bv
|
||||||
|
|| (typeof(av) == 'object'
|
||||||
|
&& typeof(bv) == 'object'
|
||||||
|
&& av.type
|
||||||
|
&& av.type == bv.type ) }) }
|
||||||
|
|
||||||
|
|
||||||
|
var diff = valueDiff
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
@ -857,7 +1016,7 @@ console.log([
|
|||||||
)])
|
)])
|
||||||
|
|
||||||
|
|
||||||
// use spec to create a new object...
|
/*/ use spec to create a new object...
|
||||||
console.log('\n\n---\n',
|
console.log('\n\n---\n',
|
||||||
[...handle(write(null, handle(o)))
|
[...handle(write(null, handle(o)))
|
||||||
.chain(
|
.chain(
|
||||||
@ -865,6 +1024,7 @@ console.log('\n\n---\n',
|
|||||||
// make the output a bit more compact...
|
// make the output a bit more compact...
|
||||||
stripAttr('source'),
|
stripAttr('source'),
|
||||||
)])
|
)])
|
||||||
|
//*/
|
||||||
|
|
||||||
|
|
||||||
/* XXX
|
/* XXX
|
||||||
@ -886,10 +1046,12 @@ console.log([...handle(B).chain(serializePaths)])
|
|||||||
console.log(diff(B, A))
|
console.log(diff(B, A))
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
|
/*
|
||||||
console.log(JSON.stringify(diff(
|
console.log(JSON.stringify(diff(
|
||||||
[1,4,2,3],
|
[1,4,2,3],
|
||||||
[1,2,3],
|
[1,2,3],
|
||||||
), null, ' '))
|
), null, ' '))
|
||||||
|
//*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
"homepage": "https://github.com/flynx/object-diff.js#readme",
|
"homepage": "https://github.com/flynx/object-diff.js#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"generic-walk": "^1.4.0",
|
"generic-walk": "^1.4.0",
|
||||||
"ig-object": "^2.2.0",
|
"ig-object": "*",
|
||||||
"ig-types": "*"
|
"ig-types": "*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user