@atomist/rug
Version:
TypeScript model for Atomist Rugs, see http://docs.atomist.com/
127 lines (126 loc) • 4.4 kB
JavaScript
;
/**
* Helper functions for working with TreeNodes in simple
* cases where we don't need a path expression.
*/
Object.defineProperty(exports, "__esModule", { value: true });
function hasTag(n, t) {
return n.nodeTags().indexOf(t) > -1;
}
exports.hasTag = hasTag;
function findPathFromAncestor(n, nodeTest) {
var parent = n.parent(); // Makes checking for parent function later easy
if (parent == null) {
// We couldn't resolve the path
return null;
}
else if (nodeTest(parent)) {
// console.log(`Gotcha: Parent is ${parent}`)
// TODO what if it's not unique - need position, but then parent.children may reinitialize.
// Not if a mutable container, admittedly
return "/" + n.nodeName();
}
else if (parent.parent()) {
return findPathFromAncestor(parent, nodeTest) + ("/" + n.nodeName());
}
else {
return null;
}
}
exports.findPathFromAncestor = findPathFromAncestor;
function findPathFromAncestorWithTag(n, tag) {
var r = findPathFromAncestor(n, function (node) { return node.nodeTags().contains(tag); });
return r;
}
exports.findPathFromAncestorWithTag = findPathFromAncestorWithTag;
/**
* Return an ancestor meeting the given criteria
* or null if it cannot be found
*/
function findAncestor(n, nodeTest) {
var parent = n.parent(); // Makes checking for parent function later easy
if (parent == null) {
return null;
}
else if (nodeTest(parent)) {
// console.log(`Gotcha: Parent is ${parent}`)
return parent;
}
else if (parent.parent()) {
return findAncestor(parent, nodeTest);
}
else {
return null;
}
}
exports.findAncestor = findAncestor;
/**
* Find an ancestor with a given tag
*/
function findAncestorWithTag(n, tag) {
var r = findAncestor(n, function (node) { return node.nodeTags().indexOf(tag) !== -1; });
return r;
}
exports.findAncestorWithTag = findAncestorWithTag;
function nodeAndTagsStringifier(tn) {
if (tn.children().length === 0) {
return tn.nodeName() + ":[" + tn.value() + "]";
}
return tn.nodeName() + ":[" + tn.nodeTags().join(", ") + "]";
}
exports.nodeAndTagsStringifier = nodeAndTagsStringifier;
function nodeAndValueStringifier(tn, maxLen) {
if (maxLen === void 0) { maxLen = 30; }
if (tn.children().length === 0 || tn.value().length < maxLen) {
return tn.nodeName() + ":[" + tn.value() + "]";
}
return tn.nodeName() + ":len=" + tn.value().length;
}
exports.nodeAndValueStringifier = nodeAndValueStringifier;
function stringifyInternal(tn, nodeStringifier) {
var shorterString = nodeStringifier(tn);
var lines = [shorterString].concat(
// oh for flatMap...
exports.flatten(tn.children()
.filter(function (k) { return k.value().length > 0; })
.map(function (k) { return stringifyInternal(k, nodeStringifier); })));
return lines.filter(function (l) { return l.length > 0; }).map(function (l) { return " " + l; });
}
// TODO move to a utility module
exports.flatten = function (arr) { return arr.reduce(function (acc, val) { return acc.concat(Array.isArray(val) ? exports.flatten(val) : val); }, []); };
/**
* Pretty string dump
*/
function stringify(tn, nodeStringifier) {
if (nodeStringifier === void 0) { nodeStringifier = nodeAndValueStringifier; }
return stringifyInternal(tn, nodeStringifier).join("\n");
}
exports.stringify = stringify;
/**
* Use as replacer argument in JSON.stringify.
* Essentially a curried functionality, allowing us to pass in a stringifier
*/
function nodeReplacer(nodeStringifier) {
if (nodeStringifier === void 0) { nodeStringifier = nodeAndValueStringifier; }
return function (key, value) {
if (value.nodeTags && value.value && value.children) {
// TextTreeNode
return {
__kind__: "TextTreeNode",
name: value.nodeName(),
tags: value.nodeTags().join(","),
structure: nodeStringifier(value),
};
}
else if (value.nodeTags) {
return {
__kind__: "GraphNode",
name: value.nodeName(),
tags: value.nodeTags().join(","),
toString: value + "",
};
}
return value;
};
}
exports.nodeReplacer = nodeReplacer;