| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 | import { parse } from "jsonc-parser";const calculateSize = (  text: string | [string, string][],  isParent = false,  isExpanded: boolean) => {  let value = "";  if (typeof text === "string") value = text;  else value = text.map(([k, v]) => `${k}: ${v}`).join("\n");  const lineCount = value.split("\n");  const lineLengths = lineCount.map(line => line.length);  const longestLine = lineLengths.sort((a, b) => b - a)[0];  const getWidth = () => {    if (Array.isArray(text) && !text.length) return 40;    if (isExpanded) return 35 + longestLine * 8 + (isParent ? 60 : 0);    if (isParent) return 170;    return 200;  };  const getHeight = () => {    if (lineCount.length * 17.8 < 30) return 40;    return (lineCount.length + 1) * 18;  };  return {    width: getWidth(),    height: getHeight(),  };};const filterChild = ([_, v]) => {  const isNull = v === null;  const isArray = Array.isArray(v) && v.length;  const isObject = v instanceof Object;  return !isNull && (isArray || isObject);};const filterValues = ([k, v]) => {  if (Array.isArray(v) || v instanceof Object) return false;  return true;};function generateChildren(object: Object, isExpanded = true, nextId: () => string) {  if (!(object instanceof Object)) object = [object];  return Object.entries(object)    .filter(filterChild)    .flatMap(([key, v]) => {      const { width, height } = calculateSize(key, true, isExpanded);      const children = extract(v, isExpanded, nextId);      return [        {          id: nextId(),          text: key,          children,          width,          height,          data: {            isParent: true,            childrenCount: children.length,          },        },      ];    });}function generateNodeData(object: Object) {  if (object instanceof Object) {    const entries = Object.entries(object).filter(filterValues);    return entries;  }  return String(object);}const extract = (  os: string[] | object[] | null,  isExpanded = true,  nextId = (    id => () =>      String(++id)  )(0)) => {  if (!os) return [];  return [os].flat().map(o => {    const text = generateNodeData(o);    const { width, height } = calculateSize(text, false, isExpanded);    return {      id: nextId(),      text,      width,      height,      children: generateChildren(o, isExpanded, nextId),      data: {        isParent: false,        childrenCount: 0,        isEmpty: !text.length,      },    };  });};const flatten = (xs: { id: string; children: never[] }[]) =>  xs.flatMap(({ children, ...rest }) => [rest, ...flatten(children)]);const relationships = (xs: { id: string; children: never[] }[]) => {  return xs.flatMap(({ id: from, children = [] }) => [    ...children.map(({ id: to }) => ({      id: `e${from}-${to}`,      from,      to,    })),    ...relationships(children),  ]);};export const parser = (jsonStr: string, isExpanded = true) => {  try {    let json = parse(jsonStr);    if (!Array.isArray(json)) json = [json];    const nodes: NodeData[] = [];    const edges: EdgeData[] = [];    const mappedElements = extract(json, isExpanded);    const res = [...flatten(mappedElements), ...relationships(mappedElements)];    res.forEach(data => {      if (isNode(data)) {        nodes.push(data);      } else {        edges.push(data);      }    });    return { nodes, edges };  } catch (error) {    console.error(error);    return {      nodes: [],      edges: [],    };  }};function isNode(element: NodeData | EdgeData) {  if ("text" in element) return true;  return false;}
 |