zent
Version:
一套前端设计语言和基于React的实现
224 lines (223 loc) • 6.7 kB
JavaScript
import { __assign } from "tslib";
import { isPathEqual } from './path-fns';
import { getNodeDepth } from './node-fns';
export function clone(from, cloneNode) {
var stack = from.map(function (n) { return ({
node: cloneNode(n, null),
children: n.children,
}); });
var trees = stack.map(function (n) { return n.node; });
var _loop_1 = function () {
var state = stack.pop();
if (!state) {
return "continue";
}
var node = state.node, children = state.children;
children === null || children === void 0 ? void 0 : children.forEach(function (n) {
var m = cloneNode(n, node);
stack.push({ node: m, children: n.children });
node.children.push(m);
});
};
while (stack.length > 0) {
_loop_1();
}
return trees;
}
export function insertPath(trees, path, createNode) {
path = path.slice();
var stack = [
{
parent: null,
children: trees,
node: path.shift(),
},
];
var _loop_2 = function () {
var frame = stack.pop();
if (!frame) {
return "continue";
}
var children = frame.children, node = frame.node;
if (!node) {
return "break";
}
var nval = node.value;
var matchedNode = children.find(function (n) { return n.value === nval; });
if (!matchedNode) {
matchedNode = createNode(node, frame.parent);
children.push(matchedNode);
}
stack.push({
parent: matchedNode,
children: matchedNode.children,
node: path.shift(),
});
};
while (stack.length > 0) {
var state_1 = _loop_2();
if (state_1 === "break")
break;
}
return trees;
}
var Forest = (function () {
function Forest(from) {
this.trees = this.build(from);
}
Forest.prototype.build = function (from) {
return clone(from, createNode);
};
Forest.prototype.reducePath = function (callback, initialValue) {
var stack = reverse(this.trees);
var path = [];
var acc = initialValue;
var earlyExit = false;
var terminate = function () {
earlyExit = true;
};
while (stack.length > 0) {
var node = stack.pop();
if (!node) {
continue;
}
var depth = getNodeDepth(node);
while (depth <= path.length) {
path.pop();
}
path.push(node);
if (node.children.length > 0) {
reversePush(stack, node.children);
}
else {
acc = callback(acc, path.slice(), terminate);
if (earlyExit) {
break;
}
}
}
return acc;
};
Forest.prototype.reduceNode = function (callback, initialValue) {
var stack = reverse(this.trees);
var acc = initialValue;
var earlyExit = false;
var terminate = function () {
earlyExit = true;
};
while (stack.length > 0) {
var node = stack.pop();
if (!node) {
continue;
}
acc = callback(acc, node, terminate);
if (earlyExit) {
break;
}
if (node.children.length > 0) {
reversePush(stack, node.children);
}
}
return acc;
};
Forest.prototype.reduceNodeDfs = function (callback, initialValue) {
var stack = this.trees.map(function (n) { return ({
node: n,
phase: 'recurse',
}); });
var acc = initialValue;
var earlyExit = false;
var terminate = function () {
earlyExit = true;
};
while (stack.length > 0) {
var frame = stack.pop();
if (!frame) {
continue;
}
var node = frame.node, phase = frame.phase;
if (phase === 'recurse') {
stack.push({
node: node,
phase: 'visit',
});
node.children.forEach(function (node) {
stack.push({
node: node,
phase: 'recurse',
});
});
}
else if (phase === 'visit') {
acc = callback(acc, node, terminate);
if (earlyExit) {
break;
}
}
}
return acc;
};
Forest.prototype.sort = function (paths) {
return this.reducePath(function (acc, path) {
if (paths.some(function (x) { return isPathEqual(x, path); })) {
acc.push(path);
}
return acc;
}, []);
};
Forest.prototype.clone = function () {
return new Forest(this.trees);
};
Forest.prototype.insertPath = function (path) {
insertPath(this.trees, path, createNode);
return this;
};
Forest.prototype.getTrees = function () {
return this.trees;
};
Forest.prototype.getPathByValue = function (values) {
return this.reducePath(function (found, path, terminate) {
if (values.length > path.length || values.length === 0) {
return found;
}
var size = values.length;
var i;
for (i = 0; i < size; i++) {
if (path[i].value !== values[i]) {
return found;
}
}
terminate();
return i === path.length ? path : path.slice(0, size);
}, []);
};
Forest.prototype.getPaths = function (startNode, predicate) {
var depth = getNodeDepth(startNode);
var idx = depth - 1;
var value = startNode.value;
return this.reducePath(function (acc, path) {
if (path.length > idx &&
path[idx].value === value &&
(!predicate || predicate(path))) {
acc.push(path);
}
return acc;
}, []);
};
return Forest;
}());
export { Forest };
function reverse(arr) {
var ret = arr.slice();
ret.reverse();
return ret;
}
function reversePush(arr, from) {
for (var i = from.length - 1; i >= 0; i--) {
arr.push(from[i]);
}
return arr;
}
function createNode(node, parent) {
return __assign(__assign({}, node), { parent: parent, children: [] });
}