Skip to content

Instantly share code, notes, and snippets.

@JosePedroDias
Last active January 5, 2023 14:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JosePedroDias/605a294d11c708db68d8847805010c3c to your computer and use it in GitHub Desktop.
Save JosePedroDias/605a294d11c708db68d8847805010c3c to your computer and use it in GitHub Desktop.
filter JS complex tree with cycles
const ignoreKeys = new Set([
'parent',
'transform',
]);
const numberKeyRgx = /^[0-9]+$/;
const simpleKeyRgx = /^[a-zA-Z_\$][a-zA-Z0-9_\$]*$/;
const getExpr = function (key: string) {
if (numberKeyRgx.test(key)) return `[${key}]`;
return (simpleKeyRgx.test(key)) ? `.${key}` : `['${key}']`;
}
const pathMap = new Map<any, string>();
const rawPathMap = new Map<any, string[]>();
const visited = new Set<any>();
const getFromRawPath = function getFromRawPath(root: any, arr: string[]) {
let o = root;
for (let key of arr) o = o[key];
return o;
}
const process = function (root, humanReadable = false) {
pathMap.clear();
rawPathMap.clear();
visited.clear();
const s = JSON.stringify(
root,
function (key: string, value: any) {
if (visited.has(value)) return humanReadable ? `<REVISIT ${pathMap.get(value)}>` : `<REVISIT ${JSON.stringify(rawPathMap.get(value))}>`;
if (ignoreKeys.has(key)) return undefined; // '<IGNORED>';
if (typeof value === 'object' || typeof value === 'function') {
visited.add(value);
const ctx = pathMap.get(this);
const path = key === '' ? 'root' : `${ctx}${getExpr(key)}`;
pathMap.set(value, path);
const rawCtx = rawPathMap.get(this); // @ts-ignore
rawPathMap.set(value, key === '' ? undefined : rawCtx === undefined ? [key] : [...rawCtx, key]);
}
return value;
},
2
);
return JSON.parse(s);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment