mirror of
https://github.com/flynx/diff.js.git
synced 2025-10-28 18:40:09 +00:00
refactoring...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
86d8e9882c
commit
0ce4e3ac9c
252
diff2.js
252
diff2.js
@ -89,54 +89,6 @@ module.CONTENT =
|
|||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
var WALK_HANDLERS =
|
|
||||||
module.WALK_HANDLERS = {
|
|
||||||
// prevent dissecting null...
|
|
||||||
null: {
|
|
||||||
walk: function(obj){
|
|
||||||
if(obj === null){
|
|
||||||
throw module.STOP } } },
|
|
||||||
|
|
||||||
set: {
|
|
||||||
walk: function(obj){
|
|
||||||
return obj instanceof Set
|
|
||||||
&& [...obj.values()].entries() } },
|
|
||||||
map: {
|
|
||||||
walk: function(obj){
|
|
||||||
return obj instanceof Map
|
|
||||||
&& obj.entries() } },
|
|
||||||
|
|
||||||
/* XXX should we handle array elements differently???
|
|
||||||
// ...these to simply mark attr type for the handler(..), not
|
|
||||||
// sure if the added complexity is worth it... (???)
|
|
||||||
array: {
|
|
||||||
walk: function(obj){
|
|
||||||
return obj instanceof Array
|
|
||||||
&& [...Object.entries(obj)]
|
|
||||||
.filter(function(e){
|
|
||||||
return !isNaN(parseInt(e)) }) }},
|
|
||||||
attr: {
|
|
||||||
walk: function(obj){
|
|
||||||
return obj instanceof Array ?
|
|
||||||
[...Object.entries(obj)]
|
|
||||||
.filter(function(e){
|
|
||||||
return isNaN(parseInt(e)) })
|
|
||||||
: typeof(obj) == 'object'
|
|
||||||
&& [...Object.entries(obj)] } },
|
|
||||||
/*/
|
|
||||||
attr: {
|
|
||||||
walk: function(obj){
|
|
||||||
return typeof(obj) == 'object'
|
|
||||||
&& Object.entries(obj) } },
|
|
||||||
//*/
|
|
||||||
proto: {
|
|
||||||
walk: function(obj){
|
|
||||||
return typeof(obj) == 'object'
|
|
||||||
&& obj.constructor.prototype !== obj.__proto__
|
|
||||||
&& [['__proto__', obj.__proto__]] }, },
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// walk(<handler>[, <options>])
|
// walk(<handler>[, <options>])
|
||||||
// walk(<handler>, <path>[, <options>])
|
// walk(<handler>, <path>[, <options>])
|
||||||
@ -167,32 +119,37 @@ module.WALK_HANDLERS = {
|
|||||||
// move the formatters and other stuff out...
|
// move the formatters and other stuff out...
|
||||||
// ...not sure if this is simpler yet...
|
// ...not sure if this is simpler yet...
|
||||||
// XXX can we decouple this from what we are walking???
|
// XXX can we decouple this from what we are walking???
|
||||||
|
// XXX should this be a constructor???
|
||||||
|
// ...for better introspection and instanceof testing...
|
||||||
var walk =
|
var walk =
|
||||||
module.walk =
|
module.walk =
|
||||||
function(handler, path=[], options={}){
|
function(handler, listers, path=[], options={}){
|
||||||
// normalize the handler...
|
// normalize the handler...
|
||||||
var _handler =
|
var _handler =
|
||||||
handler instanceof types.Generator ?
|
handler instanceof types.Generator ?
|
||||||
handler
|
handler
|
||||||
: function*(){ yield handler(...arguments) }
|
: function*(){ yield handler(...arguments) }
|
||||||
|
listers =
|
||||||
|
options.listers || listers
|
||||||
// parse args...
|
// parse args...
|
||||||
options =
|
options =
|
||||||
typeof(path) == 'object' && !(path instanceof Array) ?
|
typeof(path) == 'object' && !(path instanceof Array) ?
|
||||||
path
|
path
|
||||||
: options
|
: options
|
||||||
options =
|
options =
|
||||||
// inherit options from HANDLE_DEFAULTS of we don't already...
|
// XXX inherit options from HANDLE_DEFAULTS of we don't already...
|
||||||
|
// XXX do we need to do this???
|
||||||
!object.parentOf(module.HANDLE_DEFAULTS, options) ?
|
!object.parentOf(module.HANDLE_DEFAULTS, options) ?
|
||||||
Object.assign(
|
Object.assign(
|
||||||
{ __proto__: module.HANDLE_DEFAULTS },
|
{ __proto__: module.HANDLE_DEFAULTS },
|
||||||
options)
|
options)
|
||||||
: options
|
: options
|
||||||
var handlers = options.handlers || module.WALK_HANDLERS
|
|
||||||
// XXX do we need this in options???
|
|
||||||
var seen = options.seen = options.seen || new Map()
|
|
||||||
var p = path
|
|
||||||
|
|
||||||
var _walk = function*(obj, path=p, type=undefined){
|
var p = path
|
||||||
|
// NOTE: we are intentionally shadowing module.walk(..) here and thus
|
||||||
|
// use the shadowing function recursively. This is done to
|
||||||
|
// preserve the name for better introspection...
|
||||||
|
var walk = function*(obj, path=p, type=undefined, seen){
|
||||||
path = path instanceof Array ?
|
path = path instanceof Array ?
|
||||||
path
|
path
|
||||||
: typeof(path) == 'string' ?
|
: typeof(path) == 'string' ?
|
||||||
@ -201,6 +158,7 @@ function(handler, path=[], options={}){
|
|||||||
type = type || 'root'
|
type = type || 'root'
|
||||||
|
|
||||||
// handle reference loops...
|
// handle reference loops...
|
||||||
|
seen = seen || new Map()
|
||||||
if(seen.has(obj)){
|
if(seen.has(obj)){
|
||||||
yield* _handler(obj, path, seen.get(obj), 'LINK')
|
yield* _handler(obj, path, seen.get(obj), 'LINK')
|
||||||
return }
|
return }
|
||||||
@ -213,23 +171,20 @@ function(handler, path=[], options={}){
|
|||||||
// ..
|
// ..
|
||||||
// ]
|
// ]
|
||||||
var next =
|
var next =
|
||||||
[...Object.entries(handlers)
|
[...Object.entries(listers)
|
||||||
// NOTE: we need this to support throwing STOP...
|
// NOTE: we need this to support throwing STOP...
|
||||||
.iter()
|
.iter()
|
||||||
.filter(function([n, h]){
|
.filter(function([n, h]){
|
||||||
return h.walk
|
return h.list
|
||||||
&& !options['no' + n.capitalize()] })
|
&& !options['no' + n.capitalize()] })
|
||||||
.map(function([n, h]){
|
.map(function([n, h]){
|
||||||
// XXX should we call the handler(..) once per set of
|
var res = h.list(obj)
|
||||||
// next values (i.e. attrs, items, ...)???
|
|
||||||
var res = h.walk(obj)
|
|
||||||
return res
|
return res
|
||||||
&& [n, res] })
|
&& [n, res] })
|
||||||
.filter(function(e){
|
.filter(function(e){
|
||||||
return !!e }) ]
|
return !!e }) ]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// main object...
|
|
||||||
yield* _handler(obj, path, next, type)
|
yield* _handler(obj, path, next, type)
|
||||||
// next/children...
|
// next/children...
|
||||||
yield* next
|
yield* next
|
||||||
@ -238,7 +193,7 @@ function(handler, path=[], options={}){
|
|||||||
yield* items
|
yield* items
|
||||||
.iter()
|
.iter()
|
||||||
.map(function*([key, value]){
|
.map(function*([key, value]){
|
||||||
yield* _walk(value, path.concat(key), type) }) })
|
yield* walk(value, path.concat(key), type, seen) }) })
|
||||||
// handle STOP...
|
// handle STOP...
|
||||||
} catch(err){
|
} catch(err){
|
||||||
if(err === module.STOP){
|
if(err === module.STOP){
|
||||||
@ -248,27 +203,164 @@ function(handler, path=[], options={}){
|
|||||||
return }
|
return }
|
||||||
throw err } }
|
throw err } }
|
||||||
|
|
||||||
return _walk }
|
return walk }
|
||||||
|
|
||||||
|
|
||||||
// XXX rename...
|
var Walk =
|
||||||
|
module.Walk =
|
||||||
|
object.Constructor('Walk', {
|
||||||
|
options: {},
|
||||||
|
|
||||||
|
path: undefined,
|
||||||
|
|
||||||
|
handler: undefined,
|
||||||
|
listers: undefined,
|
||||||
|
|
||||||
|
// XXX handler is required...
|
||||||
|
__init__: function(handler, listers, options){
|
||||||
|
this.handler =
|
||||||
|
handler instanceof types.Generator ?
|
||||||
|
handler
|
||||||
|
: function*(){ yield handler(...arguments) }
|
||||||
|
this.listers = listers || {}
|
||||||
|
options = options || {}
|
||||||
|
this.options =
|
||||||
|
!object.parentOf(this.options, options) ?
|
||||||
|
options
|
||||||
|
: Object.assign(
|
||||||
|
{__proto__: this.options},
|
||||||
|
options) },
|
||||||
|
// XXX should str2path(..) be a static method????
|
||||||
|
__call__: function*(_, obj, path=[], type='root', seen=new Map()){
|
||||||
|
var that = this
|
||||||
|
var options = this.options
|
||||||
|
path = path instanceof Array ?
|
||||||
|
path
|
||||||
|
: typeof(path) == 'string' ?
|
||||||
|
str2path(path)
|
||||||
|
: []
|
||||||
|
// handle reference loops...
|
||||||
|
if(seen.has(obj)){
|
||||||
|
yield* this.handler(obj, path, seen.get(obj), 'LINK')
|
||||||
|
return }
|
||||||
|
typeof(obj) == 'object'
|
||||||
|
&& seen.set(obj, path)
|
||||||
|
|
||||||
|
// list...
|
||||||
|
//
|
||||||
|
// format:
|
||||||
|
// [
|
||||||
|
// [<handler-name>, [ [<key>, <value>], .. ]],
|
||||||
|
// ..
|
||||||
|
// ]
|
||||||
|
var next =
|
||||||
|
[...Object.entries(this.listers || {})
|
||||||
|
// NOTE: we need this to support throwing STOP...
|
||||||
|
.iter()
|
||||||
|
.filter(function([n, h]){
|
||||||
|
return h.list
|
||||||
|
&& !options['no' + n.capitalize()] })
|
||||||
|
.map(function([n, h]){
|
||||||
|
var res = h.list(obj)
|
||||||
|
return res
|
||||||
|
&& [n, res] })
|
||||||
|
.filter(function(e){
|
||||||
|
return !!e }) ]
|
||||||
|
// walk...
|
||||||
|
try {
|
||||||
|
yield* this.handler(obj, path, next, type)
|
||||||
|
// next/children...
|
||||||
|
yield* next
|
||||||
|
.iter()
|
||||||
|
.map(function*([type, items]){
|
||||||
|
yield* items
|
||||||
|
.iter()
|
||||||
|
.map(function*([key, value]){
|
||||||
|
yield* that(value, path.concat(key), type, seen) }) })
|
||||||
|
// handle STOP...
|
||||||
|
} catch(err){
|
||||||
|
if(err === module.STOP){
|
||||||
|
return
|
||||||
|
} else if(err instanceof module.STOP){
|
||||||
|
yield err.value
|
||||||
|
return }
|
||||||
|
throw err } },
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
var OBJECT_LISTERS =
|
||||||
|
module.OBJECT_LISTERS = {
|
||||||
|
// prevent dissecting null...
|
||||||
|
null: {
|
||||||
|
list: function(obj){
|
||||||
|
if(obj === null){
|
||||||
|
throw module.STOP } } },
|
||||||
|
|
||||||
|
set: {
|
||||||
|
list: function(obj){
|
||||||
|
return obj instanceof Set
|
||||||
|
&& [...obj.values()].entries() } },
|
||||||
|
map: {
|
||||||
|
list: function(obj){
|
||||||
|
return obj instanceof Map
|
||||||
|
&& obj.entries() } },
|
||||||
|
|
||||||
|
/* XXX should we handle array elements differently???
|
||||||
|
// ...these to simply mark attr type for the handler(..), not
|
||||||
|
// sure if the added complexity is worth it... (???)
|
||||||
|
array: {
|
||||||
|
list: function(obj){
|
||||||
|
return obj instanceof Array
|
||||||
|
&& [...Object.entries(obj)]
|
||||||
|
.filter(function(e){
|
||||||
|
return !isNaN(parseInt(e)) }) }},
|
||||||
|
attr: {
|
||||||
|
list: function(obj){
|
||||||
|
return obj instanceof Array ?
|
||||||
|
[...Object.entries(obj)]
|
||||||
|
.filter(function(e){
|
||||||
|
return isNaN(parseInt(e)) })
|
||||||
|
: typeof(obj) == 'object'
|
||||||
|
&& [...Object.entries(obj)] } },
|
||||||
|
/*/
|
||||||
|
attr: {
|
||||||
|
list: function(obj){
|
||||||
|
return typeof(obj) == 'object'
|
||||||
|
&& Object.entries(obj) } },
|
||||||
|
//*/
|
||||||
|
proto: {
|
||||||
|
list: function(obj){
|
||||||
|
return typeof(obj) == 'object'
|
||||||
|
&& obj.constructor.prototype !== obj.__proto__
|
||||||
|
&& [['__proto__', obj.__proto__]] }, },
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX rename -- objectWalker(..) ???
|
||||||
var walker =
|
var walker =
|
||||||
walk(function(obj, path, next, type){
|
module.walker =
|
||||||
// text...
|
//walk(
|
||||||
if(typeof(obj) == 'string' && obj.includes('\n')){
|
Walk(
|
||||||
next.push(['text', obj.split(/\n/g).entries()])
|
function(obj, path, next, type){
|
||||||
return [path, {type: 'text'}] }
|
// text...
|
||||||
|
if(typeof(obj) == 'string' && obj.includes('\n')){
|
||||||
return type == 'LINK' ?
|
next.push(['text', obj.split(/\n/g).entries()])
|
||||||
[path, 'LINK', next]
|
return [path, {type: 'text'}] }
|
||||||
: [
|
// other types...
|
||||||
path,
|
return type == 'LINK' ?
|
||||||
obj == null ?
|
[path, 'LINK', next]
|
||||||
obj
|
: [
|
||||||
: typeof(obj) == 'object' ?
|
path,
|
||||||
{type: obj.constructor.name}
|
obj == null ?
|
||||||
: obj,
|
obj
|
||||||
] })
|
: typeof(obj) == 'object' ?
|
||||||
|
{type: obj.constructor.name}
|
||||||
|
: obj,
|
||||||
|
] },
|
||||||
|
module.OBJECT_LISTERS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user