@croct/content-model
Version:
A library for modeling, validating and interpolating structured content.
75 lines (74 loc) • 2.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.clean = clean;
exports.toposort = toposort;
/**
* Remove undefined values from an object.
*
* @param object The object to remove undefined values.
*
* @returns The object without undefined values.
*
* @internal
*/
function clean(object) {
const result = {};
for (const [key, value] of Object.entries(object)) {
if (value !== undefined) {
result[key] = value;
}
}
return result;
}
/**
* Sorts a list of nodes in topological order.
*
* @param graph The map of nodes to their dependencies.
*
* @returns {TopologicalOrdering} The list of nodes in topological order.
*/
function toposort(graph) {
const resolved = new Set();
const unresolved = new Set();
const cycles = {};
// Recursive function to visit nodes in the graph
function visit(node, chain = new Set()) {
// If the node has already been resolved, return
if (resolved.has(node)) {
return;
}
// If the node is not in the graph, add it to the resolved list and return
if (!graph.has(node)) {
resolved.add(node);
return;
}
// If the node is already in the chain, it means there is a dependency cycle
// Add it to the unresolved list and return
if (chain.has(node)) {
chain.forEach(unresolved.add, unresolved);
const chainList = Array.from(chain);
cycles[node] = [...chainList.slice(chainList.indexOf(node)), node];
return;
}
// Visit each of the node's dependencies
for (const dependency of graph.get(node)) {
visit(dependency, new Set([...chain, node]));
if (dependency in cycles) {
unresolved.add(node);
break;
}
}
if (!unresolved.has(node)) {
// Add the node to the resolved list
resolved.add(node);
}
}
// Visit each node in the graph
for (const node of graph.keys()) {
visit(node);
}
return {
order: Array.from(resolved),
cycles: cycles,
};
}