mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-16 15:45:13 +00:00
69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
// Forked from: https://github.com/YChebotaev/json-decycle/blob/master/src/index.ts
|
|
// Replaced `$ref` with `$reference` to avoid conflicts with OpenAPI
|
|
|
|
const isObject = (value: any): value is object =>
|
|
typeof value === 'object' &&
|
|
value != null &&
|
|
!(value instanceof Boolean) &&
|
|
!(value instanceof Date) &&
|
|
!(value instanceof Number) &&
|
|
!(value instanceof RegExp) &&
|
|
!(value instanceof String);
|
|
|
|
const toPointer = (parts: string[]) =>
|
|
`#${parts.map((part) => String(part).replace(/~/g, '~0').replace(/\//g, '~1')).join('/')}`;
|
|
|
|
export const decycle = () => {
|
|
const paths = new WeakMap();
|
|
|
|
return function replacer(this: any, key: string | symbol, value: any) {
|
|
if (key !== '$reference' && isObject(value)) {
|
|
const seen = paths.has(value);
|
|
|
|
if (seen) {
|
|
return { $reference: toPointer(paths.get(value)) };
|
|
}
|
|
|
|
paths.set(value, [...(paths.get(this) ?? []), key]);
|
|
}
|
|
|
|
return value;
|
|
};
|
|
};
|
|
|
|
export function retrocycle() {
|
|
const parents = new WeakMap();
|
|
const keys = new WeakMap();
|
|
const refs = new Set();
|
|
|
|
function dereference(this: { [k: string]: any }, ref: { $reference: string }) {
|
|
const parts = ref.$reference.slice(1).split('/');
|
|
let key: any;
|
|
let value = this;
|
|
|
|
for (let i = 0; i < parts.length; i++) {
|
|
key = parts[i]?.replace(/~1/g, '/').replace(/~0/g, '~');
|
|
value = value[key];
|
|
}
|
|
|
|
const parent = parents.get(ref);
|
|
parent[keys.get(ref)] = value;
|
|
}
|
|
|
|
return function reviver(this: object, key: string | symbol, value: any) {
|
|
if (key === '$reference') {
|
|
refs.add(this);
|
|
} else if (isObject(value)) {
|
|
const isRoot = key === '' && Object.keys(this).length === 1;
|
|
if (isRoot) {
|
|
refs.forEach(dereference as any, this);
|
|
} else {
|
|
parents.set(value, this);
|
|
keys.set(value, key);
|
|
}
|
|
}
|
|
|
|
return value;
|
|
};
|
|
}
|