diff --git a/src/features/editor/views/GraphView/CustomNode/TextRenderer.tsx b/src/features/editor/views/GraphView/CustomNode/TextRenderer.tsx index 8ecb58e031c..71dcd07148c 100644 --- a/src/features/editor/views/GraphView/CustomNode/TextRenderer.tsx +++ b/src/features/editor/views/GraphView/CustomNode/TextRenderer.tsx @@ -10,6 +10,20 @@ const StyledRow = styled.span` vertical-align: middle; `; +function displayValue(val: any) { + if (typeof val === "string") { + // Remove wrapping quotes if present + const unquoted = val.replace(/^"(.*)"$/, "$1"); + // If the unquoted value is a number, display as number (no quotes) + if (/^-?\d+(\.\d+)?$/.test(unquoted)) { + return unquoted; + } + // Otherwise, display as string with quotes + return `"${unquoted}"`; + } + return val; +} + const isURL = (word: string) => { const urlPattern = /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/gm; @@ -47,7 +61,7 @@ export const TextRenderer = ({ children }: TextRendererProps) => { ); } - return <>{children}; + return {displayValue(children)}; }; function isColorFormat(colorString: string) { diff --git a/src/features/editor/views/TreeView/Value.tsx b/src/features/editor/views/TreeView/Value.tsx index 0046a9b8470..459b80db869 100644 --- a/src/features/editor/views/TreeView/Value.tsx +++ b/src/features/editor/views/TreeView/Value.tsx @@ -3,6 +3,7 @@ import type { DefaultTheme } from "styled-components"; import { useTheme } from "styled-components"; import { TextRenderer } from "../GraphView/CustomNode/TextRenderer"; + type TextColorFn = { theme: DefaultTheme; $value?: string | unknown; @@ -36,7 +37,7 @@ export const Value = (props: ValueProps) => { }), }} > - {JSON.stringify(value)} + {JSON.stringify(value)} ); }; diff --git a/src/lib/utils/jsonAdapter.ts b/src/lib/utils/jsonAdapter.ts index f0df0b908b5..19cb75840c0 100644 --- a/src/lib/utils/jsonAdapter.ts +++ b/src/lib/utils/jsonAdapter.ts @@ -1,22 +1,35 @@ import type { ParseError } from "jsonc-parser"; import { FileFormat } from "../../enums/file.enum"; +// Removes unused capture groups from the regex replacement function +function quoteLargeNumbers(input: string): string { + // Matches numbers with 16+ digits after : or - (YAML key or array), not already in quotes + // Also matches numbers in arrays and negative numbers + return input.replace( + /((:\s*|- )(-?\d{16,}))(?!\s*["\d])/g, + (_match, p1, _p2, p3) => p1.replace(p3, `"${p3}"`) + ); +} + export const contentToJson = (value: string, format = FileFormat.JSON): Promise => { return new Promise(async (resolve, reject) => { try { if (!value) return resolve({}); + // Preprocess value for all formats + const safeValue = quoteLargeNumbers(value); + if (format === FileFormat.JSON) { const { parse } = await import("jsonc-parser"); const errors: ParseError[] = []; - const result = parse(value, errors); - if (errors.length > 0) JSON.parse(value); + const result = parse(safeValue, errors); + if (errors.length > 0) JSON.parse(safeValue); return resolve(result); } if (format === FileFormat.YAML) { const { load } = await import("js-yaml"); - return resolve(load(value) as object); + return resolve(load(safeValue) as object); } if (format === FileFormat.XML) { @@ -29,12 +42,12 @@ export const contentToJson = (value: string, format = FileFormat.JSON): Promise< trimValues: true, parseTagValue: true, }); - return resolve(parser.parse(value)); + return resolve(parser.parse(safeValue)); } if (format === FileFormat.CSV) { const { csv2json } = await import("json-2-csv"); - const result = csv2json(value, { + const result = csv2json(safeValue, { trimFieldValues: true, trimHeaderFields: true, wrapBooleans: true,