Skip to content

Commit

Permalink
completely rewrote Traverse, deleted hash.js and web.js
Browse files Browse the repository at this point in the history
  • Loading branch information
James Halliday committed Feb 18, 2011
1 parent 95712d9 commit 414c726
Show file tree
Hide file tree
Showing 15 changed files with 164 additions and 421 deletions.
4 changes: 2 additions & 2 deletions examples/negative.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#!/usr/bin/env node
var sys = require('sys');
var Traverse = require('traverse');

var fixed = Traverse([
5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 }
]).modify(function (x) {
if (x < 0) this.update(x + 128);
}).get()
sys.puts(sys.inspect(fixed));

console.dir(fixed);

/* Output:
[ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]
Expand Down
1 change: 0 additions & 1 deletion examples/stringify.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/usr/bin/env node
var Traverse = require('traverse');
var sys = require('sys');

var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];

Expand Down
153 changes: 153 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
module.exports = Traverse;
function Traverse (obj) {
if (!(this instanceof Traverse)) return new Traverse(obj);
this.value = obj;
}

Traverse.prototype.map = function (cb) {
var obj = Traverse.clone(this.value);
walk(obj, cb);
return obj;
};

Traverse.prototype.forEach = function (cb) {
walk(this.value, cb);
return this.value;
};

Traverse.prototype.paths = function () {
var acc = [];
this.forEach(function (x) {
acc.push(this.path);
});
return acc;
};

Traverse.prototype.nodes = function () {
var acc = [];
this.forEach(function (x) {
acc.push(this.node);
});
return acc;
};

Traverse.prototype.clone = function () {
// clone refObj for a properly immutable interface:
var refs = [];
var nodes = [];

return (function clone (ref) {
if (typeof ref == 'object' && ref !== null) {
var node = Array.isArray(ref) ? [] : {};
refs.push(ref);
nodes.push(node);

Object.keys(ref).forEach(function (key) {
var i = refs.indexOf(ref[key]);
if (i >= 0) {
node[key] = nodes[i];
}
else {
node[key] = clone(ref[key]);
}

});

refs.pop();
nodes.pop();

// To make instanceof work:
if (!Array.isArray(ref)) node.__proto__ = ref.__proto__;

// Probably there are other attributes worth copying
return node;
}
else {
return ref;
}
})(this.value);
};

function walk (root, cb) {
var path = [];
var parents = [];

return (function walker (node) {
var modifiers = {};

var state = {
node : node,
path : [].concat(path),
parent : parents.slice(-1)[0],
key : path.slice(-1)[0],
isRoot : node === root,
level : path.length,
circular : null,
update : function (x) {
if (state.isRoot) {
root = x;
}
else {
state.parent.node[state.key] = x;
}
state.node = x;
},
before : function (f) { modifiers.before = f },
after : function (f) { modifiers.after = f },
pre : function (f) { modifiers.pre = f },
post : function (f) { modifiers.post = f }
};

if (typeof node == 'object' && node !== null) {
state.isLeaf = Object.keys(node).length == 0
var circs = parents.filter(function (p) {
return node == p.node
});
if (circs.length) state.circular = circs[0];
}
else {
state.isLeaf = true;
}

state.notLeaf = !state.isLeaf;
state.notRoot = !state.isRoot;

// use return values to update if defined
var ret = cb.call(state, node);
if (ret !== undefined && state.update) state.update(ret);
if (modifiers.before) modifiers.before.call(state, state.node);

if (typeof state.node == 'object'
&& state.node !== null && !state.circular) {
parents.push(state);

var keys = Object.keys(state.node);
keys.forEach(function (key, i) {
path.push(key);

if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);

var child = walker(state.node[key]);
child.isLast = i == keys.length - 1;
child.isFirst = i == 0;

if (modifiers.post) modifiers.post.call(state, child);

path.pop();
});
parents.pop();
}

if (modifiers.after) modifiers.after.call(state, state.node);

return state;
})(root);
}

Object.keys(Traverse.prototype).forEach(function (key) {
Traverse[key] = function (obj) {
var args = [].slice.call(arguments, 1);
var t = Traverse(obj);
return t[key].apply(t, args);
};
});
218 changes: 0 additions & 218 deletions lib/hash.js

This file was deleted.

0 comments on commit 414c726

Please sign in to comment.