123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- import { Node, parseTree } from "jsonc-parser";
- const calculateSize = (
- text: string | [string, string][],
- isParent = false,
- isFolded: 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 (!isFolded) 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(),
- };
- };
- export const parser = (jsonStr: string, isFolded = false) => {
- try{
- let json = parseTree(jsonStr);
- console.log(json);
- let nodes: NodeData[] = [];
- let edges: EdgeData[] = [];
- const addNodes = (
- text: any,
- width: number,
- height: number,
- parent: boolean,
- isEmpty?: boolean
- ) => {
- let actualId = String(nodes.length + 1);
- nodes = [
- ...nodes,
- {
- id: actualId,
- text: text,
- width: width,
- height: height,
- data: {
- isParent: parent,
- childrenCount: parent ? 1 : 0,
- isEmpty: isEmpty,
- },
- },
- ];
- return actualId;
- };
- const addEdges = (from: string, to: string) => {
- edges = [
- ...edges,
- {
- id: `e${from}-${to}`,
- from: from,
- to: to,
- },
- ];
- };
- let parentName: string = "";
- let bracketOpen: string[] = [];
- let objectsFromArray: number[] = [];
- let notHaveParent: string[] = [];
- let brothersNode: [string, string][] = [];
- let brothersParentId: string | undefined = "";
- let brotherKey: string = "";
- let brothersNodeProps: {
- id: string;
- parentId: string | undefined;
- objectsFromArrayId: number | undefined;
- }[] = [];
- const traverse = (
- objectToTraverse: Node,
- parentType?: string,
- myParentId?: string,
- nextType?: string
- ) => {
- let { type, children, value } = objectToTraverse;
- if (!children) {
- if (value !== undefined) {
- if (
- parentType === "property" &&
- nextType !== "object" &&
- nextType !== "array"
- ) {
- brothersParentId = myParentId;
- if (nextType === undefined) {
- // add key and value to brothers node
- brothersNode = [...brothersNode, [brotherKey, value]];
- } else {
- brotherKey = value;
- }
- } else if (parentType === "array") {
- const { width, height } = calculateSize(String(value), false, isFolded);
- const nodeFromArrayId = addNodes(String(value), width, height, false);
- if (myParentId) {
- addEdges(myParentId, nodeFromArrayId);
- }
- }
- if (nextType && parentType !== "array") {
- if (nextType === "object" || nextType === "array") {
- parentName = value;
- }
- }
- }
- } else if (children) {
- let parentId: string | undefined;
- if (type !== "property" && parentName !== "") {
- // add last brothers node and add parent node
- if (brothersNode.length > 0) {
- // end brothers node
- const { width, height } = calculateSize(brothersNode, false, isFolded);
- const brothersNodeId = addNodes(brothersNode, width, height, false);
- brothersNode = [];
- if (brothersParentId) {
- addEdges(brothersParentId, brothersNodeId);
- } else {
- notHaveParent = [...notHaveParent, brothersNodeId];
- }
- brothersNodeProps = [
- ...brothersNodeProps,
- {
- id: brothersNodeId,
- parentId: brothersParentId,
- objectsFromArrayId: objectsFromArray[objectsFromArray.length - 1],
- },
- ];
- }
- // add parent node
- const { width, height } = calculateSize(parentName, true, isFolded);
- parentId = addNodes(parentName, width, height, true);
- bracketOpen = [...bracketOpen, parentId];
- parentName = "";
- // add edges from parent node
- let brothersProps = brothersNodeProps.filter(
- e =>
- e.parentId === myParentId &&
- e.objectsFromArrayId === objectsFromArray[objectsFromArray.length - 1]
- );
- if (brothersProps.length > 0) {
- addEdges(brothersProps[brothersProps.length - 1].id, parentId);
- } else if (myParentId) {
- addEdges(myParentId, parentId);
- } else {
- notHaveParent = [...notHaveParent, parentId];
- }
- } else if (parentType === "array") {
- objectsFromArray = [...objectsFromArray, objectsFromArray.length + 1];
- }
- children.forEach((branch, index, array) => {
- if (array[index + 1]) {
- traverse(
- branch,
- type,
- bracketOpen[bracketOpen.length - 1],
- array[index + 1].type
- );
- } else {
- traverse(branch, type, bracketOpen[bracketOpen.length - 1]);
- }
- });
- if (type !== "property") {
- // when children end
- if (parentType !== "array") {
- if (bracketOpen.length > 0) {
- let newBracketOpen = [...bracketOpen];
- newBracketOpen.splice(newBracketOpen.length - 1);
- bracketOpen = [...newBracketOpen];
- }
- } else if (parentType === "array") {
- if (objectsFromArray.length > 0) {
- let newobjectsFromArray = [...objectsFromArray];
- newobjectsFromArray.splice(newobjectsFromArray.length - 1);
- objectsFromArray = [...newobjectsFromArray];
- }
- }
- // add brothers node when is the last node
- if (brothersNode.length > 0) {
- const { width, height } = calculateSize(brothersNode, false, isFolded);
- const brothersNodeId = addNodes(brothersNode, width, height, false);
- brothersNode = [];
- if (brothersParentId) {
- addEdges(brothersParentId, brothersNodeId);
- } else {
- notHaveParent = [...notHaveParent, brothersNodeId];
- }
- brothersNodeProps = [
- ...brothersNodeProps,
- {
- id: brothersNodeId,
- parentId: brothersParentId,
- objectsFromArrayId: objectsFromArray[objectsFromArray.length - 1],
- },
- ];
- }
- if (parentId) {
- let myChildrens = edges.filter(e => e.from === parentId);
- let myIndex = nodes.findIndex(e => e.id === parentId);
- let ModifyNodes = [...nodes];
- if (ModifyNodes[myIndex]) {
- ModifyNodes[myIndex].data.childrenCount = myChildrens.length;
- nodes = [...ModifyNodes];
- }
- }
- }
- }
- };
- if (json) {
- traverse(json);
- }
- if (notHaveParent.length > 1) {
- console.log(notHaveParent);
- const text = "";
- const { width, height } = calculateSize(text, false, isFolded);
- const emptyId = addNodes(text, width, height, false, true);
- notHaveParent.forEach(children => {
- addEdges(emptyId, children);
- });
- }
- if (nodes.length === 0 && json) {
- if (json.type === "array") {
- const text = "[]";
- const { width, height } = calculateSize(text, false, isFolded);
- addNodes(text, width, height, false);
- } else {
- const text = "{}";
- const { width, height } = calculateSize(text, false, isFolded);
- addNodes(text, width, height, false);
- }
- }
- return { nodes, edges };
- } catch (error) {
- console.error(error);
- return {
- nodes: [],
- edges: [],
- };
- }
- };
|