Skip to content
Browse files

update readme

  • Loading branch information...
1 parent 6004897 commit d972743112841a18d9448b9c35160ee1d447c5e5 @dominictarr committed Jan 22, 2011
View
95 README.md
@@ -0,0 +1,95 @@
+
+#Traverser#
+
+search through a complex object (nearly) as easily as forEach
+
+all the nitty-gritty stuff is taken care of.
+
+including:
+ # checking for repeats.
+ # checking for cycles.
+ # getting the path the the current object. etc!
+
+#simple example#
+collect all branches in a tree.
+
+ var traverser = require('traverser')
+ , branches = []
+
+ function branch(props){
+ if(!props.reference) //since we check for references with will work in cyclic graphs, without stackoverflows.
+ branches.push(props.value)
+
+ props.each()//continue working through the children of this object.
+ }
+
+ traverser([1,2,{},3,["x"]],{branch: branch})
+
+ console.log(branches)
+
+#simple example2#
+collect all leaves in a tree. (only functions and primitives)
+
+ var traverser = require('traverser')
+
+ exports.leaves = leaves
+
+ function leaves (obj){
+ var leaves = []
+
+ function leaf(props){
+ leaves.push(props.value)
+ }
+
+ traverser(obj,{leaf: leaf})
+ return leaves
+ }
+
+ console.log(leaves([1,2,{},3,["x"]]))
+ //[1,2,3,'x']
+
+#complex example#
+even quite complex things like a topological sort are now achivable in ~30 lines.
+see `traverser/examples/topo-sort`
+
+
+#API#
+
+ `traverser (obj, options)`
+
+ obj: graph/tree to traverse
+
+ options: (each of the following is optional)
+ {
+ branch: function to call on a branch of the tree (by default, where typeof == 'object'
+ , leaf: function to call on primitives and functions
+ , isBranch: return true if current value should be treated as a branch
+ }
+
+each function is passed one arg, a properties object which describes the state of the traverse.
+
+ {
+ value: this object
+ , parent: object which this item is a property of. (null if your on the root object)
+ , key: key of this item on parent. (null if your on the root object)
+ , path: [list of keys from root object to current item]
+ , reference: true if this object is a repeat
+ , circular: true if this object is in the ancestors list.
+ , seen: list of objects seen so far
+ , ancestors: list of objects between value and root object.
+
+ //when your in the branch function, you need to call one of the following to iterate over the children.
+ //none of these require an argument.
+
+ , each: iterate over each property
+ , find: iterate untill the first truthy return, returns the item.
+ , map: collects return values into an Array
+ , copy: copies objects, preserving whether it's a {} or a []
+ , max: iterate over all properties and return max return value
+ , min: iterate over all properties and return min return value
+ }
+
+###feel free to ask me questions if you need help!###
+
+###see https://github.com/dominictarr/trees for more examples.###
+
View
282 equals.js
@@ -1,282 +0,0 @@
-//equals
-
-var traverser = require('traverser/traverser2')
- , log = require('logger')
- , style = require('style')
-
-var styles =
- { red : style().red.styler
- , green: style().green.styler }
-
-exports.trees = trees
-exports.graphs = graphs
-exports.isTree = isTree
-exports.isDag = isDag
-exports.isCyclic = isCyclic
-exports.topologyType = topologyType
-
-function graphs (a,b){
- //check whether a == b, assuming a tree struture
- var diff =
- { left:{}
- , right: {}
- , eq: false
- }
-
- subgraph(a,b,diff.left)
- subgraph(b,a,diff.right)
- diff.eq = diff.left.eq && diff.right.eq
-
- diff.message = diff.left.message + (diff.eq ? ' == ' : ' != ') + diff.right.message
- return diff
-}
-
-function subgraph(self,other,diff){
- var matched = true
-
- var seen = []
- diff.message = traverser(self,{branch: branch, leaf: leaf, isBranch: traverser.isComplex, pre:true})
-
-
- function leaf(p){
- var x = styles.green
- if(p.value !== rGet(p.path,other)){
- matched = false
- x = styles.red
- }
- return x(key(p,p.value))
- }
- function branch(p){
- var ov = rGet(p.path,other)
- , index
- , x = styles.green
- if(ov === undefined) {
- matched = false
- x = styles.red
- }
- if((ov instanceof Array) !== (p.value instanceof Array)) {
- matched = false
- x = styles.red
- }
-
- index = seen.indexOf(ov)
- if(-1 == index)
- seen.push(ov)
-
- if(/*ref && */p.reference && index != p.index.seen) {
- x = styles.red
- matched = false
- return styles.red('var' + p.index.repeated)
- } else if (p.circular) {
- return styles.green('var' + p.index.repeated)
- } return group(p,x)
- }
-
- if(diff)
- diff.eq = matched
- return matched
-}
-
-function trees (a,b){
- var diff =
- { left:{}
- , right: {}
- , eq: false
- }
- subtree(a,b,diff.left)
- subtree(b,a,diff.right)
- diff.eq = diff.left.eq && diff.right.eq
- diff.message = diff.left.message + (diff.eq ? ' == ' : ' != ') + diff.right.message
- return diff
-}
-
-function subtree(self,other,diff,allow,soft){
- var matched = true
- , x = styles.green
- diff.message = traverser(self,{branch: branch, leaf: leaf, isBranch: traverser.isComplex})
-
- function branch(p){
- var ov = rGet(p.path,other)
- if(ov === undefined){
- matched = false
- }
- if((ov instanceof Array) !== (p.value instanceof Array)) {
- matched = false
- x = styles.red
- }
- if(p.circular)
- if(allow) {
- if(ov !== p.value)
- matched = false
- return '[circular]'
- } else
- throw new Error("infinite tree. cannot compare tree due to circular reference\n"
- + "self:" + inspect(self) + '\n'
- + "other:" + inspect(other) )
-
-/* if(ov === p.value)
- return group(p,x)*/
- return group(p,x)
- }
- function leaf(p){
- var x = styles.green
- , ov = rGet(p.path,other)
- if((!soft && p.value !== ov) || (soft && p.value != ov)){
- matched = false
- x = styles.red
- }
- return x(key(p,p.value))
- }
- diff.eq = matched
- return matched
-}
-
-
-function rGet(path,obj){
- for (i in path){
- var key = path[i]
- obj = obj[key]
- if(!obj)
- return obj
- }
- return obj
-}
-
-/**
-* topologyType (obj)
-*
-* returns 'cyclic', 'dag', 'tree' if obj has circular references,
-* or has repeated but non circular references, or just single references, respectively.
-*/
-
-function topologyType(obj){
- var struct = 'tree'
- traverser(obj,{branch: check, leaf: rFalse})
-
- function check(p){
- if(p.circular)
- return struct = 'cyclic'
- else {
- if(p.reference)
- struct = 'dag'
- return p.find()
- }
- }
- return struct
-}
-
-function rFalse(){ return false; }
-
-function isTree (obj){
- return topologyType(obj) === 'tree' }
-function isDag (obj){
- return topologyType(obj) === 'dag' }
-function isCyclic (obj){
- return topologyType(obj) === 'cyclic' }
-
-/*
-idea: immutable object datatypes... instead setting property a on x,
-create new object y = {a: whatever} and set y.__proto__ = x
-thus, x.a = first
-but also, y.a = whatever
-but otherwise y shares structure with x.
-
-this will be handy for generating the properties object.
-would need to specificially adapt this for Array style object, and probably forbid shift...
-and handle the order of keys...
-*/
-
-function key (p,rest){
- return (!p.parent || p.parent instanceof Array ? '' : p.key + ': ') + rest
-}
-function group (p,style){
- var b
- , pre = ''
- , post = ''
-
- if(p.referenced){
- pre = '(var' + p.index.repeated + '='
- post = ')' }
-
- if(p.value instanceof Array){
- b = ['[',']']
- } else if (p.value instanceof Function) {
- b = ['[function ()',']']
- } else { b = ['{','}'] }
- var items = p.map()
- , length = 0
- , join = ', '
- items.forEach(function (x){ length += ('' + x).length})
- return pre + key(p,style(b[0]) + items.join(join) + style(b[1])) + post
-}
-
-function format(s,ml){
- if(!/\n/.exec(s))
- return s
- if(ml === undefined && s.length > 80)
- ml = true
- s = s.replace(/\n/g,ml ? '\\n\n' : '\\n').split('\n')
- if(/\\u\d+\[\d+m/.exec(s[s.length - 1]))
- s.pop()
-
- return '\n( ' +
- s.map(function (x){
- return '\'' + x + '\''
- })
- .join('\n+ ') + ')\n'
-}
-
-exports.string = function (x,y){
- var diff =
- { left:{}
- , right:{}
- , eq: x == y
- }
- if(isNaN(x) && isNaN(y) && ('number' === typeof x || 'number' === typeof y)){
- diff.message = styles.red(x) + ' != ' + styles.red(y) + ' (this is correct js: WTF?)'
- diff.at = 0
- return diff
- }
-
- x = '' + x
- y = '' + y
-
- var l = '' + x, s = '' + y
- if(y.length > x.length){
- l = y; s = x
- }
- if(!diff.eq)
- for(i in l){
- if (y[i] !== x[i]){
- diff.left.message =
- '' + styles.green(x.slice(0,i) || '')
- + styles.red(x.slice(i,x.length) || '')
- diff.right.message =
- '' + styles.green(y.slice(0,i) || '')
- + styles.red(y.slice(i,y.length) || '')
-
- diff.message =
- format(diff.left.message)
- + (diff.eq ? ' == ' : ' != ')
- + format(diff.right.message)
- diff.at = i
- return diff
- }
- }
- diff.message = styles.green(x) + ' == ' + styles.green(y)
- return diff
-}
-
-exports.deep = function (left,right){
- var diff =
- { left:{}
- , right: {}
- , eq: false
- }
- subtree(left,right,diff.left,true,true)
- subtree(right,left,diff.right,true,true)
- diff.eq = diff.left.eq && diff.right.eq
- diff.message = diff.left.message + (diff.eq ? ' == ' : ' != ') + diff.right.message
- return diff
-}
-
View
20 examples/branches.js
@@ -0,0 +1,20 @@
+ var traverser = require('traverser')
+
+exports.branches = branches
+
+function branches (obj){
+ var branches = []
+
+ function branch(props){
+ if(!props.reference)
+ branches.push(props.value)
+
+ props.each()//continue working through the children of this object.
+ }
+
+ traverser(obj,{branch: branch})
+ return branches
+}
+
+ console.log(branches([1,2,{},3,["x"]]))
+ //[ [ 1, 2, {}, 3, [ 'x' ] ], {}, [ 'x' ] ]
View
18 examples/leaves.js
@@ -0,0 +1,18 @@
+ var traverser = require('traverser')
+
+exports.leaves = leaves
+
+function leaves (obj){
+ var leaves = []
+
+ function leaf(props){
+ leaves.push(props.value)
+ }
+
+ traverser(obj,{leaf: leaf})
+ return leaves
+}
+
+ console.log(leaves([1,2,{},3,["x"]]))
+
+ //[ [ 1, 2, 3, 'x' ]
View
182 examples/topo-sort.js
@@ -0,0 +1,182 @@
+//topographical sort
+
+var traverse = require('traverser')
+
+exports = module.exports = sort
+
+ function sort(depends) {
+ var levels = []
+ , requires = {}
+
+ if(Object.keys(depends).length == 0)
+ return []
+
+ traverse(depends,{branch: roots})
+
+ sorted = levels.reduce(function (x,y){
+ return x.concat(y)
+ })
+
+ return sorted.map(deps)
+
+ function roots(p){
+ var level = p.max() + 0
+ if(p.parent){
+ levels[level] = levels[level] || []
+ if(-1 == levels[level].indexOf(p.key))
+ levels[level].push(p.key)
+ requires[p.key] = Object.keys(p.value)
+ }
+ return level + 1
+ }
+ function deps(x){
+ return [x,requires[x]]
+ }
+ }
+
+exports.flat = flat
+ function flat(depends) {
+ var levels = []
+ , requires = {}
+
+ if(Object.keys(depends).length == 0)
+ return []
+
+ traverse(depends,{branch: roots})
+
+ sorted = levels.reduce(function (x,y){
+ return x.concat(y)
+ })
+
+ return sorted
+
+ function roots(p){
+ var level = p.max() + 0
+ if(p.parent){
+ levels[level] = levels[level] || []
+ if(-1 == levels[level].indexOf(p.key))
+ levels[level].push(p.key)
+ requires[p.key] = Object.keys(p.value)
+ }
+ return level + 1
+ }
+ }
+
+ var simple =
+ { x:
+ { y:
+ { z: {}
+ , a: {}}}}
+
+ console.log(flat(simple))
+ console.log(sort(simple))
+
+//a much more complex example, tree is acutal dependencies, generated by remap (> npm install remap)
+
+ var var0,var1,var2,var3,var4,var5,var6,var7,var8,var9,var10
+ ,var11,var12,var13,var14,var15,var16,var17,var18,var19,var20
+ ,var21,var22,var23,var24
+
+var complex =
+{
+ 'meta-test/asynct_adapter': {
+ 'async_testing/lib/testing': {
+ assert: var1={}
+ , path: var2={}
+ , fs: var0={}
+ , child_process: var3={}
+ , 'async_testing/lib/messages': {}
+ , inspect: var6={
+ 'inspect/inspect': {}
+ }
+ }
+ , 'meta-test/test_reports': {
+ easyfs: {
+ 'easyfs/easyfs': {
+ fs: var0
+ , util: var4={}
+ , assert: var1
+ , path: var2
+ , child_process: var3
+ }
+ }
+ , util: var4
+ , assert: var1
+ , query: {
+ 'query/query': {
+ inspect: var6
+ }
+ }
+ }
+ , inspect: var6
+ , 'style/error': var10={
+ style: var8={
+ 'style/style': {}
+ }
+ }
+ , style: var8
+ , '/home/dominic/dev/miniorm/test/miniorm-async.asynct.js': {
+ 'miniorm/miniorm-async': {
+ dirty: {
+ 'dirty/lib/dirty': {
+ 'dirty/lib/dirty/dirty': {
+ fs: var0
+ , sys: {}
+ , events: {}
+ }
+ }
+ }
+ , curry: var13={
+ 'curry/curry': {}
+ }
+ , 'traverser/iterators': var19={
+ logger: var14={
+ 'style/error': var10
+ , style: var8
+ , inspect: var6
+ }
+ , curry: var13
+ }
+ , logger: var14
+ }
+ , it: {
+ 'it/it': {
+ 'c-assert': {
+ 'c-assert/c-assert': {
+ assert: var1
+ , 'traverser/equals': {
+ 'traverser/traverser2': var24={
+ inspect: var6
+ , logger: var14
+ , curry: var13
+ , 'traverser/iterators': var19
+ }
+ , logger: var14
+ , style: var8
+ }
+ , style: var8
+ }
+ }
+ , 'it/assert': {
+ assert: var1
+ , 'traverser/traverser2': var24
+ , logger: var14
+ , inspect: var6
+ }
+ , logger: var14
+ , inspect: var6
+ , 'render/render2': {
+ traverser: {
+ 'traverser/traverser2': var24
+ }
+ , logger: var14
+ }
+ }
+ }
+ }
+ }
+ }
+
+ console.log(flat(complex))
+ console.log(sort(complex))
+
View
83 immutable.js
@@ -1,83 +0,0 @@
-//immutable
-var log = require('logger')
-
-module.exports = exports = immutable
-/*
- what about giving immutable a histroy function?
- toArray(key)
-
- I'm trying to be way to clever.
- just do it with max elegance & worry about optomisations when you have measurements.
-*/
-function immutable (obj){
- Object.defineProperty(obj,'mutate',
- { enumerable: false
- , value:
- function (_obj){
- _obj.__proto__ = obj
- return immutable(_obj)
- }
- })
- Object.freeze(obj)
- return obj
-}
-exports.Array = empty
-
-//I've added so many functions inside this
-//i'm not sure this is a good way.
-//using proto isn't an advantage here.
-//except that for (...) still works the same.
-/*
-I definately want a stackable list type,
- three ways:
- 1. immutable prototype stack
- 2. lispy list stack
- 3. duplicate arrays.
-
- if i can comeup with a clean API i can benchmark each method...
-
-*/
-function empty(){
- return new A
-}
-function A (parent,value){
- var self = this
-
- hide(self,'push',function(x){
- var n = new A(self,x)
- n.__proto__ = self
- log('push:', x,n)
- return this.mutate(n)
- })
- hide(self,'toArray',function (){
- var a = []
- for(i in self){
- a[i] = self[i]
- }
- return a
- })
- hide(self,'forEach',function (f){
- for(i in self){
- f(self[i],i,self)
- }
- })
- hide(self,'map',function (f){
- var a = []
- for(i in self){
- a[i] = f(self[i],i,self)
- }
- return a
- })
-
- if(parent){
- hide(self,'length',parent.length + 1)
- self[parent.length] = value
- } else {
- hide(self,'length',0)
- immutable(self)
- }
-}
-
-function hide(obj,key,value){
- Object.defineProperty(obj,key,{enumerable: false, value: value})
-}
View
12 imutable.js
@@ -1,12 +0,0 @@
-//immutable
-
-
-module.exports = immutable
-
-function immutable (obj){
- obj.mutate = function (_obj){
- _obj.__proto__ = obj
- return immutable(_obj)
- }
- Object.freeze(obj)
-}
View
2 index.js
@@ -1 +1 @@
-module.exports = require('./traverser2')
+module.exports = require('./traverser')
View
2 iterators.js
@@ -1,5 +1,5 @@
//iterators
-var log = require('logger')
+//var log = require('logger')
/*
~~~~~~~~~~~~~~~~~~~~~~~~
View
20 package.json
@@ -0,0 +1,20 @@
+{
+ "name": "traverser",
+ "description": "helper for traversing each item in the tree or graph",
+ "version": "0.0.0",
+ "homepage": "https://github.com/dominictarr/traverser",
+ "repository": "git://github.com/dominictarr/traverser.git",
+ "author": "Dominic Tarr <dominic.tarr@gmail.com>",
+ "main": "traverser",
+ "directories": {
+ "lib": "",
+ "example": "examples"
+ },
+ "modules": {
+ "traverser.sync": "traverser.sync",
+ "iterators": "iterators"
+ },
+ "engines": {
+ "node": "*"
+ }
+}
View
35 sort.js
@@ -1,35 +0,0 @@
-//topographical sort
-
-var traverse = require('traverser/traverser2')
- , log = require('logger')
-
-module.exports =
- function sort(depends) {
- var levels = []
- , requires = {}
-
- if(Object.keys(depends).length == 0)
- return []
-
- traverse(depends,{branch: roots})
-
- sorted = levels.reduce(function (x,y){
- return x.concat(y)
- })
-
- return sorted.map(deps)
-
- function roots(p){
- var level = p.max() + 0
- if(p.parent){
- levels[level] = levels[level] || []
- if(-1 == levels[level].indexOf(p.key))
- levels[level].push(p.key)
- requires[p.key] = Object.keys(p.value)
- }
- return level + 1
- }
- function deps(x){
- return [x,requires[x]]
- }
- }
View
163 test/equals.expresso.js
@@ -1,163 +0,0 @@
-//equals.expresso
-/*
- checks the equality of complex objects,
- generates a colour coded message to show the difference.
-
-*/
-var equals = require('traverser/equals')
- , inspect = require('inspect')
- , log = require('logger')
-// , curry = require('curry')
-exports ['can compare trees correctly'] = function (test){
-
- /*on a tree, only values are compared, and references are assumed not to exist.
- */
-
- var a,b,b2,c,d
- , x = function (){"source code"}
- , y = function (){"source code 2"}
- var eq =
- //[a ,b ,tree,dag,cyclic]
- [ [[],[],true,true]
- , [[1,2,3],[1,2,4],false,false]
- , [[],[[]],false,false]
- , [[],[{}],false,false]
- , [[],{},false,false]
- , [[[]],[{}],false,false]
- , [[[]],[],false,false]
- , [[1,2,3,4,[5,5],6,76,78,8,45,456],[1,2,3,4,[5,6],6,7326,78,8,45,456],false,false]
- , [{a: 'asdsd', b :'asdgsb',c: 525234},{a: 'asdsd', b :'asdgsb',c: 5252334},false,false]
- , [a = [1,2,3],a,true,true]
- , [[[1,2,3],[1,2,3]],[a,a], true,false]
- , [b = [],b, Error,true]
- , [[1,2,3,x],[1,2,3,x], true,true]
- , [[1,2,3,x],[1,2,3,y], false,false]
- , [b,b2 = [], Error,true]
- , [c = [1,2,3], [1,2,3,[1,2,3,[1,2,3]]], Error,false]
- ]
-
- b.push(b)
- b2.push(b2)
- c.push(c)
-
-/*
- how to deal with infinite trees?
- for example:
- a = [1,2,3]
- a.push(a)
-
- has the same values as:
- b = [1,2,3,[1,2,3]]
- b[3].push(b)
-
- although they are not graph equal...
-
- simplest solution: don't allow it. throw infinite tree exception.
-
-*/
- eq.forEach(function (e,k){
- var r
- if(e[2] == Error){
- try {
- r = equals.trees(e[0],e[1])
- test.ok(false,"did not throw error on infinite tree:" + r)
- } catch (err){
- if(-1 == err.message.indexOf('infinite tree'))
- throw err + "ooops"
- }
- } else {
- r = equals.trees(e[0],e[1])
- log('tree equals:', r.message)
- test.equal(r.eq,e[2],
- "expected [" + k + ']' + inspect(e[0]) + (e[2]?' to':' to not') + " tree equal " + inspect(e[1]))
- }
-// log('self:',e[0])
- var diff = equals.graphs(e[0],e[1])
- log('graph difference:',diff.message)
- test.equal(diff.eq,e[3],
- "expected [" + k + ']' + inspect(e[0]) + (e[3]?' to':' to not') + " graph equal " + inspect(e[1]))
- })
-
-}
-
-exports ['can check for structure type tree/dag/cyclic'] = function (test){
-
- var a,b,c // for dags
- var x,y,z // for dags
-
- var trees = [ []
- , {a:1,b:2,c:3}
- , {a:1,b: [1,2,3], b2: [1,2,3]} ]
- var dags = [[b = [1,2,3], b,b,b]
- , {a:1,b:b,c:{b: b}}
- , {a:1,c: c = [1,2,3], b2: [1,2,c]} ]
- var cyclic = [x = [b = [1,2,3], b,b]
- , y = {a:1,b:b,c:{b: b}}
- , z = {a:1,c: c = [1,2,3], b2: [1,2,c]} ]
-
- x.push(x)
- y.c.y = y
- z.c.push(z)
-
-/* trees.forEach(function (t){
- })*/
-
- trees.forEach(function (t){
- checkTopo(t,'tree',equals.isTree)
- })
- dags.forEach(function (t){
- checkTopo(t,'dag',equals.isDag)
- })
- cyclic.forEach(function (t){
- checkTopo(t,'cyclic',equals.isCyclic)
- })
-
- function checkTopo(t,type,func){
- var got = equals.topologyType(t)
- test.equal(got,type, 'expected ' + inspect(t) + " to be a '" + type + "', but got '" + got + "'")
- test.equal(func(t),true, 'expected ' + func.name + "(" + inspect(t) + ") to be true")
- }
-}
-
-exports ['string equals'] = function (test){
- var
- neq =
- [ [ 'a','b' ,0 ]
- , [ 'aa','ab',1 ]
- , [ 'aabababbbbabbaaw','aabababbbbabxbaa',12 ]
- , [ 'aab\naba\nbbb\nbab\nnba\n','aab\naba\nbbb\nbab\nnba\n\n',20 ]
- , [ 3.141592653,22/7,4 ]
- , [ ' _____ _\n'
- + '|_ _|__ ___| |_\n'
- + ' | |/ _ \\/ __| __|\n'
- + ' | | __/\\__ \\ |_\n'
- + ' |_|\\___||___/\\__|\n'
- , ' _____ _\n'
- + '|_ _|__ ___| |_\n'
- + ' | |/ _ \/ __| __|\n'
- + ' | | __/\__ \ |_\n'
- + ' |_|\___||___/\__|\n'
- , 45]
- , [true, false,0]
- , [null, undefined]
- , [0, false]
- , [12352,NaN,0]
- , [NaN,NaN,0]//stupid, but consistant with ==
- , ['NaN',NaN,0]//stupid, but consistant with ==
- ]
-
- neq.forEach(function (n){
- var r = equals.string(n[0],n[1])
- var eq = !(n.length == 3)
- test.equal(r.eq,eq)
- test.ok(r.message,"message property should exist")
- log('string equals:', r.message)
- if(!eq)
- test.equal(r.at,n[2])
- })
-}
-/*
-exports ['deep equals'] = function (test){
-
-
-}*/
View
73 test/immutable.expresso.js
@@ -1,73 +0,0 @@
-//immutable.expresso
-var immutable = require('traverser/immutable')
- , describe = require('should').describe
- , log = require('logger')
-exports ['can lock down objects with immutable'] = function (test){
- var x = immutable({x:'X'})
-
- log(x)
-
- var it =
- describe(x,'immutable object x')
- it.should.have.property('x','X')
- it.should.have.property('mutate').a('function')
-}
-
-exports ['should throw exception if you try an extend it.'] = function (test){
- var x = immutable({x:'X'})
- log(x)
-
- test.throws(function (){
- x.y = 'Ysdfasfsd'
- })
-}
-exports ['should not respond if you try and change something.'] = function (test){
- var x = immutable({x:'unchanged'})
-
- x.x = 'qw4tsdfhsdfh'
-
- describe(x,'immutable object x')
- .should.have.property('x','unchanged')
-}
-exports ['can call mutate function to add another layer..'] = function (test){
- var x = immutable({x:'unchanged'})
-
- y = x.mutate({y:'MUTATED'})
-
- var it =
- describe(y,'immutable object y')
- it.should.have.property('x','unchanged')
- it.should.have.property('y','MUTATED')
-
- describe(y.__proto__,'prototype of immutable object y')
- .should.eql(x)
-}
-
-function toA(s){
-
- var a = []
- for(i in s){
- a[i] = s[i]
- }
- return a
-}
-
-exports ['ImmutableArray can push'] = function (test){
- var x = immutable.Array()
- , y = x.push(1)
- , z = y.push(2)
-
-// describe(x,'empty immutable array').should.eql([])
-
-// var it =
- describe(y,'immutable array [0]')
- .should.have.property('0',1)
-
- var it =
- describe(z,'immutable array [1]')
- it.should.have.property('0',1)
- it.should.have.property('1',2)
-
- describe(z.toArray(),'immutable array [1,2]').should.eql([1,2])
- describe(z.length,'immutable array [1,2]').should.eql([1,2].length)
-}
View
59 test/sort.expresso.js
@@ -1,59 +0,0 @@
-//sort.expresso
-
-/*
- test topographical sort
-*/
-
-var sort = require('traverser/sort')
- , describe = require('should').describe
-
-function checkSort(graph){
-
- var deps = sort(graph)
- , seen = []
- deps.forEach(each)
-
- function each(e){
- var module = e[0]
- , requires = e[1]
-
- requires.forEach(checkSeen)
-
- function checkSeen(s){
- describe(seen,"modules already seen")
- .should.contain(s)
- }
- seen.push(module)
- }
-}
-
-exports ['can topographical sort'] = function (test){
-var a
- , graph =
-{ 'remap/test/.examples/e':
- { 'remap/test/.examples/a': a = {}
- , 'remap/test/.examples/d':
- {'remap/test/.examples/a': a}
- , 'remap/test/.examples/b':
- {'remap/test/.examples/c': {} } } }
-
- checkSort(graph)
-}
-
-exports ['can topographical sort2'] = function (test){
-var var0,var1,var2,var3,
- graph =
-{ 'remap/modules': { 'path': var0 = {}
- , 'remap/resolve': var1 = {'remap/common': var2 = {}, path: var0}
- , 'remap/loading': { 'remap/common': var2
- , 'remap/module': {'path': var0, 'remap/common': var2}
- , 'remap/resolve': var1
- , 'assert': var3 = {} }
- , 'assert': var3 } }
-
- checkSort(graph)
-}
-
-exports ['empty tree returns empty list'] = function (test){
- test.deepEqual(sort({}),[])
-}
View
2 test/traverser2.asynct.js → test/traverser.asynct.js
@@ -1,7 +1,7 @@
//traverser2.expresso.js
var describe = require('should').describe
- , traverser = require('traverser/traverser2')
+ , traverser = require('traverser')
, inspect = require('inspect')
, log = require('logger')
View
2 test/traverser2.expresso.js → test/traverser.expresso.js
@@ -1,7 +1,7 @@
//traverser2.expresso.js
var describe = require('should').describe
- , traverser = require('traverser/traverser2.sync')
+ , traverser = require('traverser/traverser.sync')
, inspect = require('inspect')
, log = require('logger')
View
33 test/trees.expresso.js
@@ -1,33 +0,0 @@
-//trees.expresso.js
-/*
-Tree helper methods,
-branches -> get all branches.
-leaves -> get all leaves.
-paths -> get all paths.
-*/
-
-var tr
-var trees = require('traverser/trees')
- , inspect = require('inspect')
- , describe = require('should').describe
-
-var a,b,c,d,e
-
-var tree =
- a = { a: 7
- , b: b =
- { c: c = [1,2,3]}
- , d: d =
- { e: e = {x: 'X'}}}
-var branches = [a,b,c,d,e]
-var leaves = [7,1,2,3,'X']
-
-exports ['branches lists all branches'] = function (test){
-
- describe(trees.branches(tree), 'branches of ' + inspect(tree))
- .should.eql(branches)
-}
-exports ['leaves gets all leaves'] = function (test){
- describe(trees.leaves(tree),'leaves of ' + inspect(tree))
- .should.eql(leaves)
-}
View
174 test/untangle.complex.expresso.js
@@ -1,174 +0,0 @@
-var var0,var1,var2,var3,var4,var5,var6,var7,var8,var9,var10
- ,var11,var12,var13,var14,var15,var16,var17,var18,var19,var20
- ,var21,var22,var23,var24
-var complex =
-{
- 'meta-test/asynct_adapter': {
- 'async_testing/lib/testing': {
- assert: var1={}
- , path: var2={}
- , fs: var0={}
- , child_process: var3={}
- , 'async_testing/lib/messages': {}
- , inspect: var6={
- 'inspect/inspect': {}
- }
- }
- , 'meta-test/test_reports': {
- easyfs: {
- 'easyfs/easyfs': {
- fs: var0
- , util: var4={}
- , assert: var1
- , path: var2
- , child_process: var3
- }
- }
- , util: var4
- , assert: var1
- , query: {
- 'query/query': {
- inspect: var6
- }
- }
- }
- , inspect: var6
- , 'style/error': var10={
- style: var8={
- 'style/style': {}
- }
- }
- , style: var8
- , '/home/dominic/dev/miniorm/test/miniorm-async.asynct.js': {
- 'miniorm/miniorm-async': {
- dirty: {
- 'dirty/lib/dirty': {
- 'dirty/lib/dirty/dirty': {
- fs: var0
- , sys: {}
- , events: {}
- }
- }
- }
- , curry: var13={
- 'curry/curry': {}
- }
- , 'traverser/iterators': var19={
- logger: var14={
- 'style/error': var10
- , style: var8
- , inspect: var6
- }
- , curry: var13
- }
- , logger: var14
- }
- , it: {
- 'it/it': {
- 'c-assert': {
- 'c-assert/c-assert': {
- assert: var1
- , 'traverser/equals': {
- 'traverser/traverser2': var24={
- inspect: var6
- , logger: var14
- , curry: var13
- , 'traverser/iterators': var19
- }
- , logger: var14
- , style: var8
- }
- , style: var8
- }
- }
- , 'it/assert': {
- assert: var1
- , 'traverser/traverser2': var24
- , logger: var14
- , inspect: var6
- }
- , logger: var14
- , inspect: var6
- , 'render/render2': {
- traverser: {
- 'traverser/traverser2': var24
- }
- , logger: var14
- }
- }
- }
- }
- }
- }
- var REF0,REF1,REF2,REF3,REF4,REF5,REF6,REF7,REF8
-var wrong =
-{ 'meta-test/asynct_adapter': { 'async_testing/lib/testing': { assert: REF0 = {}
- , path: REF1 = {}
- , fs: REF2 = {}
- , child_process: REF3 = {}
- , 'async_testing/lib/messages': {}
- , inspect: REF4 = {'inspect/inspect': {}} }
- , 'meta-test/test_reports': { easyfs: { 'easyfs/easyfs': {fs: REF2, util: {}, assert: REF0, path: REF1, child_process: REF3} }
- , util: REF2
- , assert: REF0
- , query: {'query/query': {inspect: REF4}} }
- , inspect: REF4
- , 'style/error': {style: {'style/style': REF5 = {}}}
- , style: REF3
- , '/home/dominic/dev/miniorm/test/miniorm-async.asynct.js': REF6 =
- { 'miniorm/miniorm-async': REF7 =
- { dirty: { 'dirty/lib/dirty': {'dirty/lib/dirty/dirty': {fs: REF2, sys: {}, events: REF8 = {}}} }
- , curry: {'curry/curry': {}}
- , 'traverser/iterators': {logger: {'style/error': REF1, style: REF3, inspect: REF4}, curry: REF5}
- , logger: REF7 }
- , it: { 'it/it': { 'c-assert': { 'c-assert/c-assert': { assert: REF0
- , 'traverser/equals': { 'traverser/traverser2': { inspect: REF4
- , logger: REF7
- , curry: REF5
- , 'traverser/iterators': REF6 }
- , logger: REF7
- , style: REF3 }
- , style: REF3 } }
- , 'it/assert': { assert: REF0
- , 'traverser/traverser2': REF8
- , logger: REF7
- , inspect: REF4 }
- , logger: REF7
- , inspect: REF4
- , 'render/render2': {traverser: {'traverser/traverser2': REF8}, logger: REF7} } } } } }
-
-var untangle = require('traverser/untangle2')
- , equals = require('traverser/equals')
- , inspect = require('inspect')
- , assert = require('c-assert')
- , log = require('logger')
-exports ['untangle complex graphs'] = function (test){
-
-var untangled = untangle.untangle(complex)
-var retangled = untangle.retangle(untangled)
-
- log(
- '\n##############################################\n'
- , "COMPLEX\n"
- , complex
- , '\n##############################################\n'
- , "UNTANGLED\n"
- , untangled
- , '\n##############################################\n'
- , "RETANGLED\n"
- , retangled
- , '\n##############################################\n\n')
-
- , jsoned = untangle.parse(untangle.stringify(complex))
-
- assert.ok(!equals.graphs(wrong,complex).eq,'equals.graphs returned equal for wrong and complex ')
- assert.equal(inspect(untangled),inspect(complex))
- assert.equal(inspect(jsoned),inspect(complex))
- assert.ok(equals.graphs(retangled,complex).eq,'equals.graphs returned equal for retangled and complex ')
- assert.ok(equals.graphs(jsoned,complex).eq,'equals.graphs returned equal for retangled and complex ')
-// log(equals.graphs(wrong,complex).message)// I don't have the rendering good enough... so this is not readible.
-// assert.ok(equals.graphs(json,complex))
-// assert.equal(inspect(json),inspect(complex))
-
-
-}
View
75 test/untangle.expresso.js
@@ -1,75 +0,0 @@
-
-var t = require('traverser/untangle2')
- , log = require('logger')
- , equals = require('traverser/equals')
- , inspect = require('inspect')
-exports ['can remove repeats from a object to be JSONed'] = function (test){
- var a
- , x = [a = [1,2,3],a]
- , y = [[1,2,3],[1,2,3]]
-
- test.equal(JSON.stringify(x),JSON.stringify(y))
-
-// test.deepEqual(x,retangle(untangle(x)))
- test.strictEqual(x[0],x[1])
- log('untangled:',t.untangle(x))
- var z = t.retangle(t.untangle(x))
- test.strictEqual(x[0],x[1])
-}
-exports ['can remove cycles from a object to be JSONed'] = function (test){
- var x = [1]
- x.push(x)
-
- test.strictEqual(x,x[1])
- var _z = t.untangle(x)
-
- log('untangled:', _z)
-
- var z = t.retangle(_z)
-
- log('retangled:', z)
-
- test.strictEqual(z,z[1])
-}
-exports ['handles null values'] = function (test){
- var x = [1,2,3,null,4]
- , $x = t.untangle(x)
- , _x = t.retangle($x)
-
- test.deepEqual(x,_x)
-}
-
-
-exports ['can untangle and serialize to JSON and parse back'] = function (test){
- var x = [10,20,30], a, b, c = {a : a = [1,2,3], x: x}, e, f, d = [1,2,3,34,x,6534]
- x.push(x)
- c.c = c
- var these =
- [ [a,a]
- , x
- , {a : a, a2: a, x: x}
- , c
- , 'hello'
- , { a : a
- , a2: e =
- { z: 'asdfasddgsdafgasg'
- , x: x
- , y: 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
- }
- , x: x
- , f: {a: a, b: b, c: c, d: d,e: e }
- }
- ]
-
- these.forEach(function(x){
- log(x)
- var y = t.retangle(JSON.parse(JSON.stringify(t.untangle(x))))
- , z = t.parse(t.stringify(x))
- test.ok(equals.graphs(x,y), "expected " + inspect(x) + " to equal " + inspect(y))
-
- test.ok(equals.graphs(x,z), "expected " + inspect(x) + " to equal " + inspect(z))
-
- })
-
-}
-//*/
View
2 traverser2.js → traverser.js
@@ -1,6 +1,6 @@
//traverser2
var inspect = require('inspect')
- , log = require('logger')
+// , log = require('logger')
, curry = require('curry')
, sync = require('./iterators').sync
, async = require('./iterators').async
View
7 traverser2.sync.js → traverser.sync.js
@@ -1,7 +1,5 @@
-//traverser2.sync
-var inspect = require('inspect')
- , log = require('logger')
- , curry = require('curry')
+//traverser.sync
+var curry = require('curry')
, sync = require('./iterators').sync
module.exports = traverse
@@ -51,7 +49,6 @@ function traverse (object,opts){
{ parent: null
, key: null
, value: object
- , before: true
, circular: false
, reference: false
, path: []
View
30 trees.js
@@ -1,30 +0,0 @@
-
-var traverser = require('./traverser2')
-
-exports.branches = branches
-
-function branches(tree){
- var b = []
- traverser(tree,{branch: branch})
- return b
-
- function branch(p){
- if(!p.reference){
- b.push(p.value)
- p.each()
- }
- }
-}
-
-exports.leaves = leaves
-
-function leaves(tree){
- var l = []
- traverser(tree,{leaf: leaf})
- return l
- function leaf(p){
- l.push(p.value)
- }
-}
-
-
View
100 untangle.js
@@ -1,100 +0,0 @@
-
-var traverser = require('traverser/traverser2')
- , log = require('logger')
- , assert = require('assert')
- , render = require('render/render2')
-
-exports.retangle = retangle
-exports.untangle = untangle
-exports.stringify = stringify
-exports.parse = parse
-
-/*
-this will fail if you use the forbidden keys,
- '*=','*@' and '*^'
-
-to be totally robust, it should escape them.
-
-instead it throws an exception, which is better than a mysterious error.
-*/
- function setPath(obj,path,value){
- for(var i = 0; i < path.length -1; i ++){
- var key = path[i]
- if(obj[key])
- obj = obj[key]
- else
- obj[key] = {}
- }
- obj[path[path.length - 1]] = value
- }
-
-function untangle(obj){
- var paths = []
- , reffed = []
- , reffed_paths = []
- , seen = []
- , links = {}
- , t = traverser(obj,{branch: branch, pre: true})
-// log('UNTANGLED:',{payload: obj, links: links})
- return t
-
- function branch(p){
-
- if(p.value['*$'] || p.value['*='] || p.value['*^'])
- throw new Error("object uses FORBIDDEN PROPERTY NAMES:"
- + " '*$','*=' & '*^' have a special meaning in untangle.")
-
- if(p.referenced){
-
- assert.equal(p.index.repeated, p.repeated.indexOf(p.value))
- if(-1 == reffed.indexOf(p.value)){
- assert.ok(!p.reference,'reference')
- reffed_paths[p.index.repeated] = [].concat(p.path)
- reffed[p.index.repeated] = p.value
- } else {
- setPath(links,p.path,reffed_paths[p.index.repeated])
- }
- }
- paths.push([].concat(p.path))
- seen.push(p.value)
-
- if (p.reference) {
-
-// assert.strictEqual(p.repeated[p.index.repeated],p.value)
-// assert.strictEqual(reffed[p.index.repeated],p.value, "expected:" + render(reffed[p.index.repeated]) + ' === ' + render(p.value) + '\n, within:' + render(p.repeated) + " \ncopied:" + render(reffed))
-
- return {'[Repeated]': reffed_paths[p.index.repeated]}
- }
- return p.copy()
- }
-}
-
-function get(obj,path){
- for(i in path){
- obj = obj[path[i]]
- }
- return obj
-}
-
-function retangle(obj){
- return traverser(obj,{branch: branch})
-
- function branch(p){
- if(p.value && p.value['[Repeated]']){
- return get(obj,p.value['[Repeated]'])
- }
- return p.copy()
- }
-}
-
-function stringify(obj,func){
- try {
- return JSON.stringify(untangle(obj),func)
- } catch (err){
- log('PROBLEM WHEN TRYING TO STRINGIFY:',obj)
- throw err
- }
-}
-function parse(string,func){
- return retangle(JSON.parse(string,func))
-}
View
75 untangle2.js
@@ -1,75 +0,0 @@
-//untangle2.js
-
-//just thought of a much more space-efficent way.
-
-var traverse = require('traverser')
- , log = require('logger')
- , assert = require('assert')
- , render = require('render/render2')
-
-
-
-exports.retangle = retangle
-exports.untangle = untangle
-exports.stringify = stringify
-exports.parse = parse
-
-function untangle(obj){
- var repeats = []
- var t = traverse(obj,{ branch: branch, pre: true })
-
-// log("unTANGLED",t)
- return t
-
- function branch (p){
- if(p.referenced && -1 == repeats.indexOf(p.value)){
- repeats.push(p.value)
- return { '*@': p.index.repeated
- , '*=': p.copy() }
- }
- else if (p.reference){
- return { '*^': p.index.repeated }
- }
- if(p.value == null)
- return null//this is a bug in traverser.
- return p.copy()
- }
-}
-function retangle(obj){
-
- var repeats = []
- var t = traverse(obj,{ branch: branch})
-
- //log("reTANGLED",[obj, repeats])
- return obj
-
- function branch (p){
- if(!p.value){
- log("NULL?", p.value)
- return p.value
- }
- if(p.value['*@'] !== undefined && p.value['*='] !== undefined){
- repeats[p.value['*@']] = p.value['*=']
- if(p.parent)
- p.parent[p.key] = p.value['*=']
- else
- obj = p.value['*=']
- }
- else if (p.value['*^'] !== undefined){
- p.parent[p.key] = repeats[p.value['*^']] //p.value.REPEATED
-// return repeats[REPEATED_INDEX]
- }
- return p.each()
- }
-}
-
-
-
-function stringify(obj,b,c){
- return JSON.stringify(untangle(obj),b,c)
-}
-function parse(obj,b,c){
- return retangle(JSON.parse(obj,b,c))
-}
-
-

0 comments on commit d972743

Please sign in to comment.
Something went wrong with that request. Please try again.