json-term 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,7 +65,16 @@ curl -s https://api.com/v2/config | jsonx diff config.v1.json
65
65
  jsonx diff a.json b.json --no-unchanged
66
66
  ```
67
67
 
68
- ### 3. Non-Interactive Pretty-Print (for scripts & CI)
68
+ ### 3. Simple Colorized JSON View (jq-style with Bold Keys)
69
+ ```bash
70
+ # Print syntax-highlighted standard JSON format
71
+ jsonx --raw data.json
72
+
73
+ # Piped stream
74
+ curl -s https://api.github.com/users/octocat | jsonx --raw
75
+ ```
76
+
77
+ ### 4. Non-Interactive Pretty Tree Print (for scripts & CI)
69
78
  ```bash
70
79
  # Print formatted tree to stdout
71
80
  jsonx --print data.json
@@ -74,6 +83,7 @@ jsonx --print data.json
74
83
  jsonx data.json --depth 2 --print
75
84
  ```
76
85
 
86
+
77
87
  ---
78
88
 
79
89
  ## ⌨️ Interactive TUI Keybindings
@@ -112,11 +122,15 @@ const data = {
112
122
  active: true,
113
123
  };
114
124
 
115
- // 1. Pretty Print Formatted Tree String
125
+ // 1. Syntax-Highlighted Standard JSON String
126
+ const colored = colorizeJSON(data);
127
+ console.log(colored);
128
+
129
+ // 2. Pretty Print Formatted Tree String
116
130
  const tree = buildTree(data, "myService", "$", 0, 2);
117
131
  console.log(prettyPrintTree(tree));
118
132
 
119
- // 2. Compute Structural Diff
133
+ // 3. Compute Structural Diff
120
134
  const oldConfig = { port: 8080, debug: true };
121
135
  const newConfig = { port: 8443, debug: true, ssl: true };
122
136
 
@@ -125,7 +139,7 @@ const stats = calculateDiffStats(diffTree);
125
139
  console.log(`Changes: +${stats.added} -${stats.removed} ~${stats.modified}`);
126
140
  console.log(prettyPrintDiff(diffTree));
127
141
 
128
- // 3. Launch Interactive TUI Programmatically
142
+ // 4. Launch Interactive TUI Programmatically
129
143
  const viewer = new InteractiveViewer(tree);
130
144
  await viewer.start();
131
145
  ```
@@ -136,6 +150,8 @@ await viewer.start();
136
150
 
137
151
  | Option | Shorthand | Default | Description |
138
152
  | :--- | :--- | :--- | :--- |
153
+ | `--raw` | `-r` | `false` | Print standard syntax-highlighted JSON (bold keys & typed colors) |
154
+ | `--format <type>` | `-F` | `"tree"` | Output format (`tree` or `json`) |
139
155
  | `--print` | `-p` | `false` | Non-interactive formatted print to stdout |
140
156
  | `--depth <number>` | `-d` | `2` | Initial tree expansion depth |
141
157
  | `--search <query>` | `-s` | `""` | Initial filter query for keys/values |
@@ -143,6 +159,7 @@ await viewer.start();
143
159
  | `--version` | `-v` | | Output version |
144
160
  | `--help` | `-h` | | Display help menu |
145
161
 
162
+
146
163
  ---
147
164
 
148
165
  ## 🧪 Development & Testing
package/dist/cli.js CHANGED
@@ -137,6 +137,29 @@ function prettyPrintTree(node, indent = "", isLast = true) {
137
137
  }
138
138
  return lines.join("\n");
139
139
  }
140
+ function colorizeJSON(data, space = 2) {
141
+ const jsonStr = typeof data === "string" ? data : JSON.stringify(data, null, space);
142
+ if (!jsonStr) return "";
143
+ return jsonStr.replace(
144
+ /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
145
+ (match) => {
146
+ if (/^"/.test(match)) {
147
+ if (/:$/.test(match)) {
148
+ const keyName = match.slice(0, -1);
149
+ return import_picocolors.default.bold(import_picocolors.default.cyan(keyName)) + import_picocolors.default.dim(":");
150
+ }
151
+ return import_picocolors.default.green(match);
152
+ }
153
+ if (/true|false/.test(match)) {
154
+ return import_picocolors.default.magenta(match);
155
+ }
156
+ if (/null/.test(match)) {
157
+ return import_picocolors.default.dim(match);
158
+ }
159
+ return import_picocolors.default.yellow(match);
160
+ }
161
+ );
162
+ }
140
163
 
141
164
  // src/differ.ts
142
165
  var import_picocolors2 = __toESM(require("picocolors"));
@@ -637,7 +660,7 @@ function parseJSON(raw, label = "Input") {
637
660
  }
638
661
  async function main() {
639
662
  const program = new import_commander.Command();
640
- program.name("json-term").description("High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.").version("1.0.0", "-v, --version", "Output the current version").argument("[file]", "JSON file to view or compare").option("-p, --print", "Print formatted non-interactive tree to stdout", false).option("-d, --depth <number>", "Initial tree expansion depth", (val) => parseInt(val, 10), 2).option("-s, --search <query>", "Filter tree by key or value query").action(async (fileArg, options) => {
663
+ program.name("json-term").description("High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.").version("1.1.0", "-v, --version", "Output the current version").argument("[file]", "JSON file to view or compare").option("-p, --print", "Print formatted non-interactive output to stdout", false).option("-F, --format <format>", "Output format: 'tree' or 'json'", "tree").option("-r, --raw", "Print standard syntax-highlighted JSON (shorthand for --format json --print)", false).option("-d, --depth <number>", "Initial tree expansion depth", (val) => parseInt(val, 10), 2).option("-s, --search <query>", "Filter tree by key or value query").action(async (fileArg, options) => {
641
664
  try {
642
665
  let raw = "";
643
666
  if (fileArg) {
@@ -654,6 +677,10 @@ async function main() {
654
677
  process.exit(1);
655
678
  }
656
679
  const data = parseJSON(raw, fileArg || "stdin");
680
+ if (options.raw || options.format === "json") {
681
+ console.log(colorizeJSON(data));
682
+ return;
683
+ }
657
684
  const tree = buildTree(data, fileArg || "root", "$", 0, options.depth);
658
685
  if (options.print || !process.stdin.isTTY) {
659
686
  console.log(prettyPrintTree(tree));
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/formatter.ts","../src/differ.ts","../src/interactive.ts","../src/utils/clipboard.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"fs\";\nimport pc from \"picocolors\";\nimport { buildTree, prettyPrintTree } from \"./formatter.js\";\nimport { diffJSON, prettyPrintDiff, calculateDiffStats } from \"./differ.js\";\nimport { InteractiveViewer } from \"./interactive.js\";\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n if (process.stdin.isTTY) {\n resolve(\"\");\n return;\n }\n\n process.stdin.setEncoding(\"utf-8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(data.trim());\n });\n setTimeout(() => {\n if (!data) resolve(\"\");\n }, 100);\n });\n}\n\nfunction parseJSON(raw: string, label = \"Input\"): any {\n try {\n return JSON.parse(raw);\n } catch (err: any) {\n throw new Error(`Invalid JSON in ${label}: ${err.message}`);\n }\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name(\"json-term\")\n .description(\"High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.\")\n .version(\"1.0.0\", \"-v, --version\", \"Output the current version\")\n .argument(\"[file]\", \"JSON file to view or compare\")\n .option(\"-p, --print\", \"Print formatted non-interactive tree to stdout\", false)\n .option(\"-d, --depth <number>\", \"Initial tree expansion depth\", (val) => parseInt(val, 10), 2)\n .option(\"-s, --search <query>\", \"Filter tree by key or value query\")\n .action(async (fileArg, options) => {\n try {\n let raw = \"\";\n if (fileArg) {\n if (!fs.existsSync(fileArg)) {\n console.error(pc.red(`Error: File not found: ${fileArg}`));\n process.exit(1);\n }\n raw = await fs.promises.readFile(fileArg, \"utf-8\");\n } else {\n raw = await readStdin();\n }\n\n if (!raw) {\n program.help();\n process.exit(1);\n }\n\n const data = parseJSON(raw, fileArg || \"stdin\");\n const tree = buildTree(data, fileArg || \"root\", \"$\", 0, options.depth);\n\n if (options.print || !process.stdin.isTTY) {\n console.log(prettyPrintTree(tree));\n } else {\n const viewer = new InteractiveViewer(tree, false);\n await viewer.start();\n }\n } catch (err: any) {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n }\n });\n\n // Diff subcommand\n program\n .command(\"diff <fileA> [fileB]\")\n .description(\"Structural JSON diff between two files or stdin\")\n .option(\"-p, --print\", \"Print formatted non-interactive diff to stdout\", false)\n .option(\"-d, --depth <number>\", \"Initial expansion depth\", (val) => parseInt(val, 10), 3)\n .option(\"--no-unchanged\", \"Hide unchanged nodes from the diff view\", false)\n .action(async (fileA, fileB, diffOptions) => {\n try {\n if (!fs.existsSync(fileA)) {\n console.error(pc.red(`Error: File not found: ${fileA}`));\n process.exit(1);\n }\n const rawA = await fs.promises.readFile(fileA, \"utf-8\");\n const dataA = parseJSON(rawA, fileA);\n\n let dataB: any;\n if (fileB) {\n if (!fs.existsSync(fileB)) {\n console.error(pc.red(`Error: File not found: ${fileB}`));\n process.exit(1);\n }\n const rawB = await fs.promises.readFile(fileB, \"utf-8\");\n dataB = parseJSON(rawB, fileB);\n } else {\n const stdinData = await readStdin();\n if (!stdinData) {\n console.error(pc.red(\"Error: Please specify second file or pipe JSON via stdin.\"));\n process.exit(1);\n }\n dataB = parseJSON(stdinData, \"stdin\");\n }\n\n const diffTree = diffJSON(dataA, dataB, `${fileA} ↔ ${fileB || \"stdin\"}`, \"$\", 0, diffOptions.depth);\n const stats = calculateDiffStats(diffTree);\n\n if (diffOptions.print || !process.stdin.isTTY) {\n console.log(\n pc.bold(\n `Diff Stats: ${pc.green(`+${stats.added}`)} ${pc.red(`-${stats.removed}`)} ${pc.yellow(`~${stats.modified}`)} ${pc.dim(`=${stats.unchanged}`)}\\n`\n )\n );\n console.log(prettyPrintDiff(diffTree, { showUnchanged: diffOptions.unchanged }));\n } else {\n const viewer = new InteractiveViewer(diffTree, true);\n await viewer.start();\n }\n } catch (err: any) {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n }\n });\n\n await program.parseAsync(process.argv);\n}\n\nmain().catch((err) => {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n});\n","import pc from \"picocolors\";\nimport { JSONValueType, TreeNode } from \"./types.js\";\n\n/**\n * Determine the JSON value type.\n */\nexport function getValueType(value: any): JSONValueType {\n if (value === null || value === undefined) return \"null\";\n if (Array.isArray(value)) return \"array\";\n const t = typeof value;\n if (t === \"object\") return \"object\";\n if (t === \"string\") return \"string\";\n if (t === \"number\") return \"number\";\n if (t === \"boolean\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Colorize and format a single JSON value according to its type.\n */\nexport function formatValue(value: any, truncateLen = 80): string {\n const type = getValueType(value);\n\n switch (type) {\n case \"string\": {\n const str = JSON.stringify(value);\n const truncated = str.length > truncateLen ? str.slice(0, truncateLen - 3) + '...\"' : str;\n return pc.green(truncated);\n }\n case \"number\":\n return pc.yellow(String(value));\n case \"boolean\":\n return pc.magenta(String(value));\n case \"null\":\n return pc.dim(\"null\");\n case \"array\":\n return pc.dim(`[${value.length} items]`);\n case \"object\":\n return pc.dim(`{${Object.keys(value).length} keys}`);\n default:\n return String(value);\n }\n}\n\n/**\n * Format an object key with bold coloring.\n */\nexport function formatKey(key: string): string {\n return pc.bold(pc.cyan(key));\n}\n\n/**\n * Build a flat or nested TreeNode hierarchy from any JavaScript/JSON data.\n */\nexport function buildTree(\n data: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 2,\n parentId?: string\n): TreeNode {\n const type = getValueType(data);\n const id = `${path}-${key || \"root\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n const node: TreeNode = {\n id,\n key,\n value: data,\n type,\n depth,\n path,\n collapsed,\n parentId,\n };\n\n if (type === \"object\" && data !== null) {\n const keys = Object.keys(data);\n node.itemCount = keys.length;\n node.children = keys.map((k) =>\n buildTree(\n data[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n } else if (type === \"array\") {\n node.itemCount = data.length;\n node.children = data.map((item: any, idx: number) =>\n buildTree(\n item,\n `[${idx}]`,\n `${path}[${idx}]`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n }\n\n return node;\n}\n\n/**\n * Pretty-print JSON tree structure to terminal string.\n */\nexport function prettyPrintTree(node: TreeNode, indent = \"\", isLast = true): string {\n const isRoot = node.depth === 0;\n const marker = node.type === \"object\" || node.type === \"array\" ? (node.collapsed ? pc.cyan(\"▶ \") : pc.cyan(\"▼ \")) : pc.dim(\"• \");\n\n let line = \"\";\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch) + marker;\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += marker + (node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(pc.white(\"root: \")));\n }\n\n if (node.type === \"object\") {\n line += pc.dim(`{ ${node.itemCount} keys }`);\n } else if (node.type === \"array\") {\n line += pc.dim(`[ ${node.itemCount} items ]`);\n } else {\n line += formatValue(node.value);\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n lines.push(prettyPrintTree(child, nextIndent, childIsLast));\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import pc from \"picocolors\";\nimport { DiffNode, DiffStatus, JSONValueType } from \"./types.js\";\nimport { getValueType, formatValue, formatKey } from \"./formatter.js\";\n\nexport interface DiffStats {\n added: number;\n removed: number;\n modified: number;\n unchanged: number;\n}\n\n/**\n * Compare two JSON values structurally and return a recursive DiffNode tree.\n */\nexport function diffJSON(\n a: any,\n b: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 3\n): DiffNode {\n const typeA = getValueType(a);\n const typeB = getValueType(b);\n const id = `${path}-${key || \"diff\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n // Case 1: Value added (a is undefined, b exists)\n if (a === undefined && b !== undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"added\",\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n if (typeB === \"object\" && b !== null) {\n node.itemCount = Object.keys(b).length;\n node.children = Object.keys(b).map((k) =>\n diffJSON(undefined, b[k], k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeB === \"array\") {\n node.itemCount = b.length;\n node.children = b.map((item: any, idx: number) =>\n diffJSON(undefined, item, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 2: Value removed (a exists, b is undefined)\n if (a !== undefined && b === undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"removed\",\n oldValue: a,\n type: typeA,\n collapsed: false,\n };\n if (typeA === \"object\" && a !== null) {\n node.itemCount = Object.keys(a).length;\n node.children = Object.keys(a).map((k) =>\n diffJSON(a[k], undefined, k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeA === \"array\") {\n node.itemCount = a.length;\n node.children = a.map((item: any, idx: number) =>\n diffJSON(item, undefined, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 3: Type changed (e.g. from string to number or object to array)\n if (typeA !== typeB) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Case 4: Both are Objects\n if (typeA === \"object\" && a !== null && b !== null) {\n const allKeys = Array.from(new Set([...Object.keys(a), ...Object.keys(b)]));\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (const k of allKeys) {\n const child = diffJSON(\n a[k],\n b[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"object\",\n itemCount: allKeys.length,\n collapsed,\n children,\n };\n }\n\n // Case 5: Both are Arrays\n if (typeA === \"array\") {\n const maxLen = Math.max(a.length, b.length);\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (let i = 0; i < maxLen; i++) {\n const child = diffJSON(\n a[i],\n b[i],\n `[${i}]`,\n `${path}[${i}]`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"array\",\n itemCount: maxLen,\n collapsed,\n children,\n };\n }\n\n // Case 6: Primitive values comparison\n if (a !== b) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Unchanged primitive\n return {\n id,\n key,\n path,\n depth,\n status: \"unchanged\",\n oldValue: a,\n newValue: b,\n type: typeA,\n collapsed,\n };\n}\n\n/**\n * Calculate summary metrics for the diff.\n */\nexport function calculateDiffStats(node: DiffNode): DiffStats {\n const stats: DiffStats = { added: 0, removed: 0, modified: 0, unchanged: 0 };\n\n function traverse(n: DiffNode) {\n if (n.children && n.children.length > 0) {\n n.children.forEach(traverse);\n } else {\n stats[n.status]++;\n }\n }\n\n traverse(node);\n return stats;\n}\n\n/**\n * Pretty-print structural diff to terminal string.\n */\nexport function prettyPrintDiff(\n node: DiffNode,\n options: { showUnchanged?: boolean } = {},\n indent = \"\",\n isLast = true\n): string {\n const showUnchanged = options.showUnchanged ?? true;\n\n if (!showUnchanged && node.status === \"unchanged\" && (!node.children || node.children.length === 0)) {\n return \"\";\n }\n\n const isRoot = node.depth === 0;\n let prefix = \" \";\n let statusColor = pc.dim;\n\n if (node.status === \"added\") {\n prefix = pc.green(\"+ \");\n statusColor = pc.green;\n } else if (node.status === \"removed\") {\n prefix = pc.red(\"- \");\n statusColor = pc.red;\n } else if (node.status === \"modified\") {\n prefix = pc.yellow(\"~ \");\n statusColor = pc.yellow;\n }\n\n let line = prefix;\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch);\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(\"diff: \");\n }\n\n if (node.status === \"added\") {\n line += statusColor(formatValue(node.newValue));\n } else if (node.status === \"removed\") {\n line += statusColor(formatValue(node.oldValue));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n line += statusColor(`{ ${node.itemCount} items modified }`);\n } else {\n line += `${pc.red(formatValue(node.oldValue))} ${pc.dim(\"->\")} ${pc.green(formatValue(node.newValue))}`;\n }\n } else {\n // Unchanged\n line += pc.dim(formatValue(node.newValue));\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n const childStr = prettyPrintDiff(child, options, nextIndent, childIsLast);\n if (childStr) lines.push(childStr);\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import readline from \"readline\";\nimport pc from \"picocolors\";\nimport { TreeNode, DiffNode } from \"./types.js\";\nimport { formatKey, formatValue } from \"./formatter.js\";\nimport { copyToClipboard } from \"./utils/clipboard.js\";\n\ntype AnyNode = TreeNode | DiffNode;\n\ninterface FlatItem {\n node: AnyNode;\n depth: number;\n isDiff: boolean;\n}\n\n/**\n * Interactive Terminal Tree Explorer for JSON data and Diffs.\n */\nexport class InteractiveViewer {\n private root: AnyNode;\n private flatList: FlatItem[] = [];\n private selectedIndex = 0;\n private searchQuery = \"\";\n private isSearching = false;\n private searchInput = \"\";\n private notification = \"\";\n private notificationTimer: NodeJS.Timeout | null = null;\n private isDiff: boolean;\n\n constructor(root: AnyNode, isDiff = false) {\n this.root = root;\n this.isDiff = isDiff;\n this.rebuildFlatList();\n }\n\n private isDiffNode(node: AnyNode): node is DiffNode {\n return this.isDiff && \"status\" in node;\n }\n\n private rebuildFlatList(): void {\n const list: FlatItem[] = [];\n\n const traverse = (node: AnyNode, currentDepth: number) => {\n // If search query is active, filter matching nodes or their parents\n if (this.searchQuery) {\n const query = this.searchQuery.toLowerCase();\n const keyMatch = node.key && node.key.toLowerCase().includes(query);\n const pathMatch = node.path && node.path.toLowerCase().includes(query);\n const valMatch =\n \"value\" in node\n ? JSON.stringify(node.value).toLowerCase().includes(query)\n : \"newValue\" in node\n ? JSON.stringify(node.newValue).toLowerCase().includes(query)\n : false;\n\n if (!keyMatch && !pathMatch && !valMatch && (!node.children || node.children.length === 0)) {\n return;\n }\n }\n\n list.push({ node, depth: currentDepth, isDiff: this.isDiff });\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n for (const child of node.children) {\n traverse(child, currentDepth + 1);\n }\n }\n };\n\n traverse(this.root, 0);\n this.flatList = list;\n\n if (this.selectedIndex >= this.flatList.length) {\n this.selectedIndex = Math.max(0, this.flatList.length - 1);\n }\n }\n\n private setNotification(msg: string): void {\n this.notification = msg;\n if (this.notificationTimer) clearTimeout(this.notificationTimer);\n this.notificationTimer = setTimeout(() => {\n this.notification = \"\";\n this.render();\n }, 2500);\n }\n\n private render(): void {\n const rows = process.stdout.rows || 24;\n const maxVisibleRows = Math.max(5, rows - 5);\n\n // Calculate window scroll offset\n let startIdx = 0;\n if (this.selectedIndex >= maxVisibleRows) {\n startIdx = this.selectedIndex - maxVisibleRows + 1;\n }\n const endIdx = Math.min(this.flatList.length, startIdx + maxVisibleRows);\n\n // Clear terminal screen\n process.stdout.write(\"\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25l\"); // hide cursor\n\n // 1. Header Bar\n const title = this.isDiff ? \" JSON Structural Diff Explorer \" : \" Interactive JSON Tree Explorer \";\n console.log(pc.bgCyan(pc.black(pc.bold(` ${title} `)) + pc.dim(` [Total items: ${this.flatList.length}]`)));\n\n // 2. Render visible items\n for (let i = startIdx; i < endIdx; i++) {\n const { node, depth } = this.flatList[i];\n const isSelected = i === this.selectedIndex;\n const indent = \" \".repeat(depth);\n\n let marker = \"• \";\n if (node.children && node.children.length > 0) {\n marker = node.collapsed ? \"▶ \" : \"▼ \";\n }\n\n let lineContent = \"\";\n\n if (this.isDiffNode(node)) {\n let diffPrefix = \" \";\n if (node.status === \"added\") diffPrefix = pc.green(\"+ \");\n else if (node.status === \"removed\") diffPrefix = pc.red(\"- \");\n else if (node.status === \"modified\") diffPrefix = pc.yellow(\"~ \");\n\n lineContent = diffPrefix + indent + marker;\n if (node.key) lineContent += formatKey(node.key) + pc.dim(\": \");\n\n if (node.status === \"added\") {\n lineContent += pc.green(formatValue(node.newValue, 50));\n } else if (node.status === \"removed\") {\n lineContent += pc.red(formatValue(node.oldValue, 50));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n lineContent += pc.yellow(`{ ${node.itemCount} modified }`);\n } else {\n lineContent += `${pc.red(formatValue(node.oldValue, 25))} -> ${pc.green(formatValue(node.newValue, 25))}`;\n }\n } else {\n lineContent += pc.dim(formatValue(node.newValue, 50));\n }\n } else {\n const treeNode = node as TreeNode;\n lineContent = indent + marker;\n if (treeNode.key) lineContent += formatKey(treeNode.key) + pc.dim(\": \");\n\n if (treeNode.type === \"object\") {\n lineContent += pc.dim(`{ ${treeNode.itemCount} keys }`);\n } else if (treeNode.type === \"array\") {\n lineContent += pc.dim(`[ ${treeNode.itemCount} items ]`);\n } else {\n lineContent += formatValue(treeNode.value, 60);\n }\n }\n\n if (isSelected) {\n console.log(pc.bgBlue(pc.white(pc.bold(`> ${lineContent}`))));\n } else {\n console.log(` ${lineContent}`);\n }\n }\n\n // 3. Status Bar & Footer\n const selectedItem = this.flatList[this.selectedIndex];\n const currentPath = selectedItem ? selectedItem.node.path : \"$\";\n\n console.log(\"\\n\" + pc.dim(\"─\".repeat(Math.min(process.stdout.columns || 80, 80))));\n if (this.notification) {\n console.log(pc.green(pc.bold(` ${this.notification}`)));\n } else if (this.isSearching) {\n console.log(pc.yellow(pc.bold(` Search: /${this.searchInput}█`)));\n } else {\n console.log(pc.bold(pc.cyan(` Path: ${currentPath}`)));\n console.log(\n pc.dim(\" [↑/↓] Move [Enter/Space] Toggle [e] Expand All [c] Collapse All [p] Copy Path [y] Copy Val [/] Search [q] Exit\")\n );\n }\n }\n\n private expandAll(node: AnyNode): void {\n node.collapsed = false;\n if (node.children) node.children.forEach((c) => this.expandAll(c));\n }\n\n private collapseAll(node: AnyNode): void {\n if (node.depth > 0) node.collapsed = true;\n if (node.children) node.children.forEach((c) => this.collapseAll(c));\n }\n\n public async start(): Promise<void> {\n if (!process.stdin.isTTY) {\n return;\n }\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n this.render();\n\n return new Promise((resolve) => {\n const onKeypress = async (str: string, key: readline.Key) => {\n if (this.isSearching) {\n if (key.name === \"return\") {\n this.searchQuery = this.searchInput;\n this.isSearching = false;\n this.rebuildFlatList();\n this.render();\n return;\n }\n if (key.name === \"escape\") {\n this.isSearching = false;\n this.searchInput = \"\";\n this.render();\n return;\n }\n if (key.name === \"backspace\") {\n this.searchInput = this.searchInput.slice(0, -1);\n this.render();\n return;\n }\n if (str && str.length === 1) {\n this.searchInput += str;\n this.render();\n return;\n }\n }\n\n // Navigation\n if (key.name === \"up\" || key.name === \"k\") {\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.render();\n }\n } else if (key.name === \"down\" || key.name === \"j\") {\n if (this.selectedIndex < this.flatList.length - 1) {\n this.selectedIndex++;\n this.render();\n }\n } else if (key.name === \"return\" || key.name === \"space\" || key.name === \"right\" || key.name === \"left\") {\n const item = this.flatList[this.selectedIndex];\n if (item && item.node.children && item.node.children.length > 0) {\n item.node.collapsed = !item.node.collapsed;\n this.rebuildFlatList();\n this.render();\n }\n } else if (str === \"e\" || str === \"E\") {\n this.expandAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"c\" || str === \"C\") {\n this.collapseAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"p\" || str === \"P\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n await copyToClipboard(item.node.path);\n this.setNotification(`✔ Copied JSONPath: ${item.node.path}`);\n }\n } else if (str === \"y\" || str === \"Y\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n const val = \"value\" in item.node ? item.node.value : (item.node as DiffNode).newValue;\n const textToCopy = typeof val === \"object\" ? JSON.stringify(val, null, 2) : String(val);\n await copyToClipboard(textToCopy);\n this.setNotification(`✔ Copied value to clipboard!`);\n }\n } else if (str === \"/\") {\n this.isSearching = true;\n this.searchInput = \"\";\n this.render();\n } else if (key.ctrl && key.name === \"c\" || key.name === \"escape\" || str === \"q\" || str === \"Q\") {\n // Cleanup & Exit\n process.stdin.removeListener(\"keypress\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n process.stdout.write(\"\\x1b[?25h\\n\"); // show cursor\n resolve();\n }\n };\n\n process.stdin.on(\"keypress\", onKeypress);\n });\n }\n}\n","import { exec } from \"child_process\";\nimport os from \"os\";\n\n/**\n * Copy text to system clipboard across macOS, Linux, and Windows.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const platform = os.platform();\n\n return new Promise((resolve) => {\n let proc;\n if (platform === \"darwin\") {\n proc = exec(\"pbcopy\", (err) => resolve(!err));\n } else if (platform === \"win32\") {\n proc = exec(\"clip\", (err) => resolve(!err));\n } else {\n // Linux: Try wl-copy then xclip\n proc = exec(\"wl-copy 2>/dev/null || xclip -selection clipboard 2>/dev/null || xsel --clipboard --input\", (err) => {\n resolve(!err);\n });\n }\n\n if (proc.stdin) {\n proc.stdin.write(text);\n proc.stdin.end();\n } else {\n resolve(false);\n }\n });\n}\n"],"mappings":"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","names":["import_picocolors","pc","import_picocolors","pc","import_picocolors","os","pc","readline","fs","pc"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/formatter.ts","../src/differ.ts","../src/interactive.ts","../src/utils/clipboard.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"fs\";\nimport pc from \"picocolors\";\nimport { buildTree, prettyPrintTree, colorizeJSON } from \"./formatter.js\";\nimport { diffJSON, prettyPrintDiff, calculateDiffStats } from \"./differ.js\";\nimport { InteractiveViewer } from \"./interactive.js\";\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n if (process.stdin.isTTY) {\n resolve(\"\");\n return;\n }\n\n process.stdin.setEncoding(\"utf-8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(data.trim());\n });\n setTimeout(() => {\n if (!data) resolve(\"\");\n }, 100);\n });\n}\n\nfunction parseJSON(raw: string, label = \"Input\"): any {\n try {\n return JSON.parse(raw);\n } catch (err: any) {\n throw new Error(`Invalid JSON in ${label}: ${err.message}`);\n }\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name(\"json-term\")\n .description(\"High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.\")\n .version(\"1.1.0\", \"-v, --version\", \"Output the current version\")\n .argument(\"[file]\", \"JSON file to view or compare\")\n .option(\"-p, --print\", \"Print formatted non-interactive output to stdout\", false)\n .option(\"-F, --format <format>\", \"Output format: 'tree' or 'json'\", \"tree\")\n .option(\"-r, --raw\", \"Print standard syntax-highlighted JSON (shorthand for --format json --print)\", false)\n .option(\"-d, --depth <number>\", \"Initial tree expansion depth\", (val) => parseInt(val, 10), 2)\n .option(\"-s, --search <query>\", \"Filter tree by key or value query\")\n .action(async (fileArg, options) => {\n try {\n let raw = \"\";\n if (fileArg) {\n if (!fs.existsSync(fileArg)) {\n console.error(pc.red(`Error: File not found: ${fileArg}`));\n process.exit(1);\n }\n raw = await fs.promises.readFile(fileArg, \"utf-8\");\n } else {\n raw = await readStdin();\n }\n\n if (!raw) {\n program.help();\n process.exit(1);\n }\n\n const data = parseJSON(raw, fileArg || \"stdin\");\n\n // If raw/json format requested, print colorized JSON directly\n if (options.raw || options.format === \"json\") {\n console.log(colorizeJSON(data));\n return;\n }\n\n const tree = buildTree(data, fileArg || \"root\", \"$\", 0, options.depth);\n\n if (options.print || !process.stdin.isTTY) {\n console.log(prettyPrintTree(tree));\n } else {\n const viewer = new InteractiveViewer(tree, false);\n await viewer.start();\n }\n } catch (err: any) {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n }\n });\n\n // Diff subcommand\n program\n .command(\"diff <fileA> [fileB]\")\n .description(\"Structural JSON diff between two files or stdin\")\n .option(\"-p, --print\", \"Print formatted non-interactive diff to stdout\", false)\n .option(\"-d, --depth <number>\", \"Initial expansion depth\", (val) => parseInt(val, 10), 3)\n .option(\"--no-unchanged\", \"Hide unchanged nodes from the diff view\", false)\n .action(async (fileA, fileB, diffOptions) => {\n try {\n if (!fs.existsSync(fileA)) {\n console.error(pc.red(`Error: File not found: ${fileA}`));\n process.exit(1);\n }\n const rawA = await fs.promises.readFile(fileA, \"utf-8\");\n const dataA = parseJSON(rawA, fileA);\n\n let dataB: any;\n if (fileB) {\n if (!fs.existsSync(fileB)) {\n console.error(pc.red(`Error: File not found: ${fileB}`));\n process.exit(1);\n }\n const rawB = await fs.promises.readFile(fileB, \"utf-8\");\n dataB = parseJSON(rawB, fileB);\n } else {\n const stdinData = await readStdin();\n if (!stdinData) {\n console.error(pc.red(\"Error: Please specify second file or pipe JSON via stdin.\"));\n process.exit(1);\n }\n dataB = parseJSON(stdinData, \"stdin\");\n }\n\n const diffTree = diffJSON(dataA, dataB, `${fileA} ↔ ${fileB || \"stdin\"}`, \"$\", 0, diffOptions.depth);\n const stats = calculateDiffStats(diffTree);\n\n if (diffOptions.print || !process.stdin.isTTY) {\n console.log(\n pc.bold(\n `Diff Stats: ${pc.green(`+${stats.added}`)} ${pc.red(`-${stats.removed}`)} ${pc.yellow(`~${stats.modified}`)} ${pc.dim(`=${stats.unchanged}`)}\\n`\n )\n );\n console.log(prettyPrintDiff(diffTree, { showUnchanged: diffOptions.unchanged }));\n } else {\n const viewer = new InteractiveViewer(diffTree, true);\n await viewer.start();\n }\n } catch (err: any) {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n }\n });\n\n await program.parseAsync(process.argv);\n}\n\nmain().catch((err) => {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n});\n","import pc from \"picocolors\";\nimport { JSONValueType, TreeNode } from \"./types.js\";\n\n/**\n * Determine the JSON value type.\n */\nexport function getValueType(value: any): JSONValueType {\n if (value === null || value === undefined) return \"null\";\n if (Array.isArray(value)) return \"array\";\n const t = typeof value;\n if (t === \"object\") return \"object\";\n if (t === \"string\") return \"string\";\n if (t === \"number\") return \"number\";\n if (t === \"boolean\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Colorize and format a single JSON value according to its type.\n */\nexport function formatValue(value: any, truncateLen = 80): string {\n const type = getValueType(value);\n\n switch (type) {\n case \"string\": {\n const str = JSON.stringify(value);\n const truncated = str.length > truncateLen ? str.slice(0, truncateLen - 3) + '...\"' : str;\n return pc.green(truncated);\n }\n case \"number\":\n return pc.yellow(String(value));\n case \"boolean\":\n return pc.magenta(String(value));\n case \"null\":\n return pc.dim(\"null\");\n case \"array\":\n return pc.dim(`[${value.length} items]`);\n case \"object\":\n return pc.dim(`{${Object.keys(value).length} keys}`);\n default:\n return String(value);\n }\n}\n\n/**\n * Format an object key with bold coloring.\n */\nexport function formatKey(key: string): string {\n return pc.bold(pc.cyan(key));\n}\n\n/**\n * Build a flat or nested TreeNode hierarchy from any JavaScript/JSON data.\n */\nexport function buildTree(\n data: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 2,\n parentId?: string\n): TreeNode {\n const type = getValueType(data);\n const id = `${path}-${key || \"root\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n const node: TreeNode = {\n id,\n key,\n value: data,\n type,\n depth,\n path,\n collapsed,\n parentId,\n };\n\n if (type === \"object\" && data !== null) {\n const keys = Object.keys(data);\n node.itemCount = keys.length;\n node.children = keys.map((k) =>\n buildTree(\n data[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n } else if (type === \"array\") {\n node.itemCount = data.length;\n node.children = data.map((item: any, idx: number) =>\n buildTree(\n item,\n `[${idx}]`,\n `${path}[${idx}]`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n }\n\n return node;\n}\n\n/**\n * Pretty-print JSON tree structure to terminal string.\n */\nexport function prettyPrintTree(node: TreeNode, indent = \"\", isLast = true): string {\n const isRoot = node.depth === 0;\n const marker = node.type === \"object\" || node.type === \"array\" ? (node.collapsed ? pc.cyan(\"▶ \") : pc.cyan(\"▼ \")) : pc.dim(\"• \");\n\n let line = \"\";\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch) + marker;\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += marker + (node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(pc.white(\"root: \")));\n }\n\n if (node.type === \"object\") {\n line += pc.dim(`{ ${node.itemCount} keys }`);\n } else if (node.type === \"array\") {\n line += pc.dim(`[ ${node.itemCount} items ]`);\n } else {\n line += formatValue(node.value);\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n lines.push(prettyPrintTree(child, nextIndent, childIsLast));\n });\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Colorize and format standard JSON structure with bold keys and typed syntax highlighting.\n */\nexport function colorizeJSON(data: any, space = 2): string {\n const jsonStr = typeof data === \"string\" ? data : JSON.stringify(data, null, space);\n if (!jsonStr) return \"\";\n\n return jsonStr.replace(\n /(\"(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)/g,\n (match) => {\n // Object key with trailing colon\n if (/^\"/.test(match)) {\n if (/:$/.test(match)) {\n const keyName = match.slice(0, -1);\n return pc.bold(pc.cyan(keyName)) + pc.dim(\":\");\n }\n // String value\n return pc.green(match);\n }\n // Boolean value\n if (/true|false/.test(match)) {\n return pc.magenta(match);\n }\n // Null value\n if (/null/.test(match)) {\n return pc.dim(match);\n }\n // Number value\n return pc.yellow(match);\n }\n );\n}\n\n","import pc from \"picocolors\";\nimport { DiffNode, DiffStatus, JSONValueType } from \"./types.js\";\nimport { getValueType, formatValue, formatKey } from \"./formatter.js\";\n\nexport interface DiffStats {\n added: number;\n removed: number;\n modified: number;\n unchanged: number;\n}\n\n/**\n * Compare two JSON values structurally and return a recursive DiffNode tree.\n */\nexport function diffJSON(\n a: any,\n b: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 3\n): DiffNode {\n const typeA = getValueType(a);\n const typeB = getValueType(b);\n const id = `${path}-${key || \"diff\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n // Case 1: Value added (a is undefined, b exists)\n if (a === undefined && b !== undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"added\",\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n if (typeB === \"object\" && b !== null) {\n node.itemCount = Object.keys(b).length;\n node.children = Object.keys(b).map((k) =>\n diffJSON(undefined, b[k], k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeB === \"array\") {\n node.itemCount = b.length;\n node.children = b.map((item: any, idx: number) =>\n diffJSON(undefined, item, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 2: Value removed (a exists, b is undefined)\n if (a !== undefined && b === undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"removed\",\n oldValue: a,\n type: typeA,\n collapsed: false,\n };\n if (typeA === \"object\" && a !== null) {\n node.itemCount = Object.keys(a).length;\n node.children = Object.keys(a).map((k) =>\n diffJSON(a[k], undefined, k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeA === \"array\") {\n node.itemCount = a.length;\n node.children = a.map((item: any, idx: number) =>\n diffJSON(item, undefined, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 3: Type changed (e.g. from string to number or object to array)\n if (typeA !== typeB) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Case 4: Both are Objects\n if (typeA === \"object\" && a !== null && b !== null) {\n const allKeys = Array.from(new Set([...Object.keys(a), ...Object.keys(b)]));\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (const k of allKeys) {\n const child = diffJSON(\n a[k],\n b[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"object\",\n itemCount: allKeys.length,\n collapsed,\n children,\n };\n }\n\n // Case 5: Both are Arrays\n if (typeA === \"array\") {\n const maxLen = Math.max(a.length, b.length);\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (let i = 0; i < maxLen; i++) {\n const child = diffJSON(\n a[i],\n b[i],\n `[${i}]`,\n `${path}[${i}]`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"array\",\n itemCount: maxLen,\n collapsed,\n children,\n };\n }\n\n // Case 6: Primitive values comparison\n if (a !== b) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Unchanged primitive\n return {\n id,\n key,\n path,\n depth,\n status: \"unchanged\",\n oldValue: a,\n newValue: b,\n type: typeA,\n collapsed,\n };\n}\n\n/**\n * Calculate summary metrics for the diff.\n */\nexport function calculateDiffStats(node: DiffNode): DiffStats {\n const stats: DiffStats = { added: 0, removed: 0, modified: 0, unchanged: 0 };\n\n function traverse(n: DiffNode) {\n if (n.children && n.children.length > 0) {\n n.children.forEach(traverse);\n } else {\n stats[n.status]++;\n }\n }\n\n traverse(node);\n return stats;\n}\n\n/**\n * Pretty-print structural diff to terminal string.\n */\nexport function prettyPrintDiff(\n node: DiffNode,\n options: { showUnchanged?: boolean } = {},\n indent = \"\",\n isLast = true\n): string {\n const showUnchanged = options.showUnchanged ?? true;\n\n if (!showUnchanged && node.status === \"unchanged\" && (!node.children || node.children.length === 0)) {\n return \"\";\n }\n\n const isRoot = node.depth === 0;\n let prefix = \" \";\n let statusColor = pc.dim;\n\n if (node.status === \"added\") {\n prefix = pc.green(\"+ \");\n statusColor = pc.green;\n } else if (node.status === \"removed\") {\n prefix = pc.red(\"- \");\n statusColor = pc.red;\n } else if (node.status === \"modified\") {\n prefix = pc.yellow(\"~ \");\n statusColor = pc.yellow;\n }\n\n let line = prefix;\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch);\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(\"diff: \");\n }\n\n if (node.status === \"added\") {\n line += statusColor(formatValue(node.newValue));\n } else if (node.status === \"removed\") {\n line += statusColor(formatValue(node.oldValue));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n line += statusColor(`{ ${node.itemCount} items modified }`);\n } else {\n line += `${pc.red(formatValue(node.oldValue))} ${pc.dim(\"->\")} ${pc.green(formatValue(node.newValue))}`;\n }\n } else {\n // Unchanged\n line += pc.dim(formatValue(node.newValue));\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n const childStr = prettyPrintDiff(child, options, nextIndent, childIsLast);\n if (childStr) lines.push(childStr);\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import readline from \"readline\";\nimport pc from \"picocolors\";\nimport { TreeNode, DiffNode } from \"./types.js\";\nimport { formatKey, formatValue } from \"./formatter.js\";\nimport { copyToClipboard } from \"./utils/clipboard.js\";\n\ntype AnyNode = TreeNode | DiffNode;\n\ninterface FlatItem {\n node: AnyNode;\n depth: number;\n isDiff: boolean;\n}\n\n/**\n * Interactive Terminal Tree Explorer for JSON data and Diffs.\n */\nexport class InteractiveViewer {\n private root: AnyNode;\n private flatList: FlatItem[] = [];\n private selectedIndex = 0;\n private searchQuery = \"\";\n private isSearching = false;\n private searchInput = \"\";\n private notification = \"\";\n private notificationTimer: NodeJS.Timeout | null = null;\n private isDiff: boolean;\n\n constructor(root: AnyNode, isDiff = false) {\n this.root = root;\n this.isDiff = isDiff;\n this.rebuildFlatList();\n }\n\n private isDiffNode(node: AnyNode): node is DiffNode {\n return this.isDiff && \"status\" in node;\n }\n\n private rebuildFlatList(): void {\n const list: FlatItem[] = [];\n\n const traverse = (node: AnyNode, currentDepth: number) => {\n // If search query is active, filter matching nodes or their parents\n if (this.searchQuery) {\n const query = this.searchQuery.toLowerCase();\n const keyMatch = node.key && node.key.toLowerCase().includes(query);\n const pathMatch = node.path && node.path.toLowerCase().includes(query);\n const valMatch =\n \"value\" in node\n ? JSON.stringify(node.value).toLowerCase().includes(query)\n : \"newValue\" in node\n ? JSON.stringify(node.newValue).toLowerCase().includes(query)\n : false;\n\n if (!keyMatch && !pathMatch && !valMatch && (!node.children || node.children.length === 0)) {\n return;\n }\n }\n\n list.push({ node, depth: currentDepth, isDiff: this.isDiff });\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n for (const child of node.children) {\n traverse(child, currentDepth + 1);\n }\n }\n };\n\n traverse(this.root, 0);\n this.flatList = list;\n\n if (this.selectedIndex >= this.flatList.length) {\n this.selectedIndex = Math.max(0, this.flatList.length - 1);\n }\n }\n\n private setNotification(msg: string): void {\n this.notification = msg;\n if (this.notificationTimer) clearTimeout(this.notificationTimer);\n this.notificationTimer = setTimeout(() => {\n this.notification = \"\";\n this.render();\n }, 2500);\n }\n\n private render(): void {\n const rows = process.stdout.rows || 24;\n const maxVisibleRows = Math.max(5, rows - 5);\n\n // Calculate window scroll offset\n let startIdx = 0;\n if (this.selectedIndex >= maxVisibleRows) {\n startIdx = this.selectedIndex - maxVisibleRows + 1;\n }\n const endIdx = Math.min(this.flatList.length, startIdx + maxVisibleRows);\n\n // Clear terminal screen\n process.stdout.write(\"\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25l\"); // hide cursor\n\n // 1. Header Bar\n const title = this.isDiff ? \" JSON Structural Diff Explorer \" : \" Interactive JSON Tree Explorer \";\n console.log(pc.bgCyan(pc.black(pc.bold(` ${title} `)) + pc.dim(` [Total items: ${this.flatList.length}]`)));\n\n // 2. Render visible items\n for (let i = startIdx; i < endIdx; i++) {\n const { node, depth } = this.flatList[i];\n const isSelected = i === this.selectedIndex;\n const indent = \" \".repeat(depth);\n\n let marker = \"• \";\n if (node.children && node.children.length > 0) {\n marker = node.collapsed ? \"▶ \" : \"▼ \";\n }\n\n let lineContent = \"\";\n\n if (this.isDiffNode(node)) {\n let diffPrefix = \" \";\n if (node.status === \"added\") diffPrefix = pc.green(\"+ \");\n else if (node.status === \"removed\") diffPrefix = pc.red(\"- \");\n else if (node.status === \"modified\") diffPrefix = pc.yellow(\"~ \");\n\n lineContent = diffPrefix + indent + marker;\n if (node.key) lineContent += formatKey(node.key) + pc.dim(\": \");\n\n if (node.status === \"added\") {\n lineContent += pc.green(formatValue(node.newValue, 50));\n } else if (node.status === \"removed\") {\n lineContent += pc.red(formatValue(node.oldValue, 50));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n lineContent += pc.yellow(`{ ${node.itemCount} modified }`);\n } else {\n lineContent += `${pc.red(formatValue(node.oldValue, 25))} -> ${pc.green(formatValue(node.newValue, 25))}`;\n }\n } else {\n lineContent += pc.dim(formatValue(node.newValue, 50));\n }\n } else {\n const treeNode = node as TreeNode;\n lineContent = indent + marker;\n if (treeNode.key) lineContent += formatKey(treeNode.key) + pc.dim(\": \");\n\n if (treeNode.type === \"object\") {\n lineContent += pc.dim(`{ ${treeNode.itemCount} keys }`);\n } else if (treeNode.type === \"array\") {\n lineContent += pc.dim(`[ ${treeNode.itemCount} items ]`);\n } else {\n lineContent += formatValue(treeNode.value, 60);\n }\n }\n\n if (isSelected) {\n console.log(pc.bgBlue(pc.white(pc.bold(`> ${lineContent}`))));\n } else {\n console.log(` ${lineContent}`);\n }\n }\n\n // 3. Status Bar & Footer\n const selectedItem = this.flatList[this.selectedIndex];\n const currentPath = selectedItem ? selectedItem.node.path : \"$\";\n\n console.log(\"\\n\" + pc.dim(\"─\".repeat(Math.min(process.stdout.columns || 80, 80))));\n if (this.notification) {\n console.log(pc.green(pc.bold(` ${this.notification}`)));\n } else if (this.isSearching) {\n console.log(pc.yellow(pc.bold(` Search: /${this.searchInput}█`)));\n } else {\n console.log(pc.bold(pc.cyan(` Path: ${currentPath}`)));\n console.log(\n pc.dim(\" [↑/↓] Move [Enter/Space] Toggle [e] Expand All [c] Collapse All [p] Copy Path [y] Copy Val [/] Search [q] Exit\")\n );\n }\n }\n\n private expandAll(node: AnyNode): void {\n node.collapsed = false;\n if (node.children) node.children.forEach((c) => this.expandAll(c));\n }\n\n private collapseAll(node: AnyNode): void {\n if (node.depth > 0) node.collapsed = true;\n if (node.children) node.children.forEach((c) => this.collapseAll(c));\n }\n\n public async start(): Promise<void> {\n if (!process.stdin.isTTY) {\n return;\n }\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n this.render();\n\n return new Promise((resolve) => {\n const onKeypress = async (str: string, key: readline.Key) => {\n if (this.isSearching) {\n if (key.name === \"return\") {\n this.searchQuery = this.searchInput;\n this.isSearching = false;\n this.rebuildFlatList();\n this.render();\n return;\n }\n if (key.name === \"escape\") {\n this.isSearching = false;\n this.searchInput = \"\";\n this.render();\n return;\n }\n if (key.name === \"backspace\") {\n this.searchInput = this.searchInput.slice(0, -1);\n this.render();\n return;\n }\n if (str && str.length === 1) {\n this.searchInput += str;\n this.render();\n return;\n }\n }\n\n // Navigation\n if (key.name === \"up\" || key.name === \"k\") {\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.render();\n }\n } else if (key.name === \"down\" || key.name === \"j\") {\n if (this.selectedIndex < this.flatList.length - 1) {\n this.selectedIndex++;\n this.render();\n }\n } else if (key.name === \"return\" || key.name === \"space\" || key.name === \"right\" || key.name === \"left\") {\n const item = this.flatList[this.selectedIndex];\n if (item && item.node.children && item.node.children.length > 0) {\n item.node.collapsed = !item.node.collapsed;\n this.rebuildFlatList();\n this.render();\n }\n } else if (str === \"e\" || str === \"E\") {\n this.expandAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"c\" || str === \"C\") {\n this.collapseAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"p\" || str === \"P\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n await copyToClipboard(item.node.path);\n this.setNotification(`✔ Copied JSONPath: ${item.node.path}`);\n }\n } else if (str === \"y\" || str === \"Y\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n const val = \"value\" in item.node ? item.node.value : (item.node as DiffNode).newValue;\n const textToCopy = typeof val === \"object\" ? JSON.stringify(val, null, 2) : String(val);\n await copyToClipboard(textToCopy);\n this.setNotification(`✔ Copied value to clipboard!`);\n }\n } else if (str === \"/\") {\n this.isSearching = true;\n this.searchInput = \"\";\n this.render();\n } else if (key.ctrl && key.name === \"c\" || key.name === \"escape\" || str === \"q\" || str === \"Q\") {\n // Cleanup & Exit\n process.stdin.removeListener(\"keypress\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n process.stdout.write(\"\\x1b[?25h\\n\"); // show cursor\n resolve();\n }\n };\n\n process.stdin.on(\"keypress\", onKeypress);\n });\n }\n}\n","import { exec } from \"child_process\";\nimport os from \"os\";\n\n/**\n * Copy text to system clipboard across macOS, Linux, and Windows.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const platform = os.platform();\n\n return new Promise((resolve) => {\n let proc;\n if (platform === \"darwin\") {\n proc = exec(\"pbcopy\", (err) => resolve(!err));\n } else if (platform === \"win32\") {\n proc = exec(\"clip\", (err) => resolve(!err));\n } else {\n // Linux: Try wl-copy then xclip\n proc = exec(\"wl-copy 2>/dev/null || xclip -selection clipboard 2>/dev/null || xsel --clipboard --input\", (err) => {\n resolve(!err);\n });\n }\n\n if (proc.stdin) {\n proc.stdin.write(text);\n proc.stdin.end();\n } else {\n resolve(false);\n }\n });\n}\n"],"mappings":"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","names":["import_picocolors","pc","import_picocolors","pc","import_picocolors","os","pc","readline","fs","pc"]}
package/dist/cli.mjs CHANGED
@@ -114,6 +114,29 @@ function prettyPrintTree(node, indent = "", isLast = true) {
114
114
  }
115
115
  return lines.join("\n");
116
116
  }
117
+ function colorizeJSON(data, space = 2) {
118
+ const jsonStr = typeof data === "string" ? data : JSON.stringify(data, null, space);
119
+ if (!jsonStr) return "";
120
+ return jsonStr.replace(
121
+ /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
122
+ (match) => {
123
+ if (/^"/.test(match)) {
124
+ if (/:$/.test(match)) {
125
+ const keyName = match.slice(0, -1);
126
+ return pc.bold(pc.cyan(keyName)) + pc.dim(":");
127
+ }
128
+ return pc.green(match);
129
+ }
130
+ if (/true|false/.test(match)) {
131
+ return pc.magenta(match);
132
+ }
133
+ if (/null/.test(match)) {
134
+ return pc.dim(match);
135
+ }
136
+ return pc.yellow(match);
137
+ }
138
+ );
139
+ }
117
140
 
118
141
  // src/differ.ts
119
142
  import pc2 from "picocolors";
@@ -614,7 +637,7 @@ function parseJSON(raw, label = "Input") {
614
637
  }
615
638
  async function main() {
616
639
  const program = new Command();
617
- program.name("json-term").description("High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.").version("1.0.0", "-v, --version", "Output the current version").argument("[file]", "JSON file to view or compare").option("-p, --print", "Print formatted non-interactive tree to stdout", false).option("-d, --depth <number>", "Initial tree expansion depth", (val) => parseInt(val, 10), 2).option("-s, --search <query>", "Filter tree by key or value query").action(async (fileArg, options) => {
640
+ program.name("json-term").description("High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.").version("1.1.0", "-v, --version", "Output the current version").argument("[file]", "JSON file to view or compare").option("-p, --print", "Print formatted non-interactive output to stdout", false).option("-F, --format <format>", "Output format: 'tree' or 'json'", "tree").option("-r, --raw", "Print standard syntax-highlighted JSON (shorthand for --format json --print)", false).option("-d, --depth <number>", "Initial tree expansion depth", (val) => parseInt(val, 10), 2).option("-s, --search <query>", "Filter tree by key or value query").action(async (fileArg, options) => {
618
641
  try {
619
642
  let raw = "";
620
643
  if (fileArg) {
@@ -631,6 +654,10 @@ async function main() {
631
654
  process.exit(1);
632
655
  }
633
656
  const data = parseJSON(raw, fileArg || "stdin");
657
+ if (options.raw || options.format === "json") {
658
+ console.log(colorizeJSON(data));
659
+ return;
660
+ }
634
661
  const tree = buildTree(data, fileArg || "root", "$", 0, options.depth);
635
662
  if (options.print || !process.stdin.isTTY) {
636
663
  console.log(prettyPrintTree(tree));
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/formatter.ts","../src/differ.ts","../src/interactive.ts","../src/utils/clipboard.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"fs\";\nimport pc from \"picocolors\";\nimport { buildTree, prettyPrintTree } from \"./formatter.js\";\nimport { diffJSON, prettyPrintDiff, calculateDiffStats } from \"./differ.js\";\nimport { InteractiveViewer } from \"./interactive.js\";\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n if (process.stdin.isTTY) {\n resolve(\"\");\n return;\n }\n\n process.stdin.setEncoding(\"utf-8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(data.trim());\n });\n setTimeout(() => {\n if (!data) resolve(\"\");\n }, 100);\n });\n}\n\nfunction parseJSON(raw: string, label = \"Input\"): any {\n try {\n return JSON.parse(raw);\n } catch (err: any) {\n throw new Error(`Invalid JSON in ${label}: ${err.message}`);\n }\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name(\"json-term\")\n .description(\"High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.\")\n .version(\"1.0.0\", \"-v, --version\", \"Output the current version\")\n .argument(\"[file]\", \"JSON file to view or compare\")\n .option(\"-p, --print\", \"Print formatted non-interactive tree to stdout\", false)\n .option(\"-d, --depth <number>\", \"Initial tree expansion depth\", (val) => parseInt(val, 10), 2)\n .option(\"-s, --search <query>\", \"Filter tree by key or value query\")\n .action(async (fileArg, options) => {\n try {\n let raw = \"\";\n if (fileArg) {\n if (!fs.existsSync(fileArg)) {\n console.error(pc.red(`Error: File not found: ${fileArg}`));\n process.exit(1);\n }\n raw = await fs.promises.readFile(fileArg, \"utf-8\");\n } else {\n raw = await readStdin();\n }\n\n if (!raw) {\n program.help();\n process.exit(1);\n }\n\n const data = parseJSON(raw, fileArg || \"stdin\");\n const tree = buildTree(data, fileArg || \"root\", \"$\", 0, options.depth);\n\n if (options.print || !process.stdin.isTTY) {\n console.log(prettyPrintTree(tree));\n } else {\n const viewer = new InteractiveViewer(tree, false);\n await viewer.start();\n }\n } catch (err: any) {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n }\n });\n\n // Diff subcommand\n program\n .command(\"diff <fileA> [fileB]\")\n .description(\"Structural JSON diff between two files or stdin\")\n .option(\"-p, --print\", \"Print formatted non-interactive diff to stdout\", false)\n .option(\"-d, --depth <number>\", \"Initial expansion depth\", (val) => parseInt(val, 10), 3)\n .option(\"--no-unchanged\", \"Hide unchanged nodes from the diff view\", false)\n .action(async (fileA, fileB, diffOptions) => {\n try {\n if (!fs.existsSync(fileA)) {\n console.error(pc.red(`Error: File not found: ${fileA}`));\n process.exit(1);\n }\n const rawA = await fs.promises.readFile(fileA, \"utf-8\");\n const dataA = parseJSON(rawA, fileA);\n\n let dataB: any;\n if (fileB) {\n if (!fs.existsSync(fileB)) {\n console.error(pc.red(`Error: File not found: ${fileB}`));\n process.exit(1);\n }\n const rawB = await fs.promises.readFile(fileB, \"utf-8\");\n dataB = parseJSON(rawB, fileB);\n } else {\n const stdinData = await readStdin();\n if (!stdinData) {\n console.error(pc.red(\"Error: Please specify second file or pipe JSON via stdin.\"));\n process.exit(1);\n }\n dataB = parseJSON(stdinData, \"stdin\");\n }\n\n const diffTree = diffJSON(dataA, dataB, `${fileA} ↔ ${fileB || \"stdin\"}`, \"$\", 0, diffOptions.depth);\n const stats = calculateDiffStats(diffTree);\n\n if (diffOptions.print || !process.stdin.isTTY) {\n console.log(\n pc.bold(\n `Diff Stats: ${pc.green(`+${stats.added}`)} ${pc.red(`-${stats.removed}`)} ${pc.yellow(`~${stats.modified}`)} ${pc.dim(`=${stats.unchanged}`)}\\n`\n )\n );\n console.log(prettyPrintDiff(diffTree, { showUnchanged: diffOptions.unchanged }));\n } else {\n const viewer = new InteractiveViewer(diffTree, true);\n await viewer.start();\n }\n } catch (err: any) {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n }\n });\n\n await program.parseAsync(process.argv);\n}\n\nmain().catch((err) => {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n});\n","import pc from \"picocolors\";\nimport { JSONValueType, TreeNode } from \"./types.js\";\n\n/**\n * Determine the JSON value type.\n */\nexport function getValueType(value: any): JSONValueType {\n if (value === null || value === undefined) return \"null\";\n if (Array.isArray(value)) return \"array\";\n const t = typeof value;\n if (t === \"object\") return \"object\";\n if (t === \"string\") return \"string\";\n if (t === \"number\") return \"number\";\n if (t === \"boolean\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Colorize and format a single JSON value according to its type.\n */\nexport function formatValue(value: any, truncateLen = 80): string {\n const type = getValueType(value);\n\n switch (type) {\n case \"string\": {\n const str = JSON.stringify(value);\n const truncated = str.length > truncateLen ? str.slice(0, truncateLen - 3) + '...\"' : str;\n return pc.green(truncated);\n }\n case \"number\":\n return pc.yellow(String(value));\n case \"boolean\":\n return pc.magenta(String(value));\n case \"null\":\n return pc.dim(\"null\");\n case \"array\":\n return pc.dim(`[${value.length} items]`);\n case \"object\":\n return pc.dim(`{${Object.keys(value).length} keys}`);\n default:\n return String(value);\n }\n}\n\n/**\n * Format an object key with bold coloring.\n */\nexport function formatKey(key: string): string {\n return pc.bold(pc.cyan(key));\n}\n\n/**\n * Build a flat or nested TreeNode hierarchy from any JavaScript/JSON data.\n */\nexport function buildTree(\n data: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 2,\n parentId?: string\n): TreeNode {\n const type = getValueType(data);\n const id = `${path}-${key || \"root\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n const node: TreeNode = {\n id,\n key,\n value: data,\n type,\n depth,\n path,\n collapsed,\n parentId,\n };\n\n if (type === \"object\" && data !== null) {\n const keys = Object.keys(data);\n node.itemCount = keys.length;\n node.children = keys.map((k) =>\n buildTree(\n data[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n } else if (type === \"array\") {\n node.itemCount = data.length;\n node.children = data.map((item: any, idx: number) =>\n buildTree(\n item,\n `[${idx}]`,\n `${path}[${idx}]`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n }\n\n return node;\n}\n\n/**\n * Pretty-print JSON tree structure to terminal string.\n */\nexport function prettyPrintTree(node: TreeNode, indent = \"\", isLast = true): string {\n const isRoot = node.depth === 0;\n const marker = node.type === \"object\" || node.type === \"array\" ? (node.collapsed ? pc.cyan(\"▶ \") : pc.cyan(\"▼ \")) : pc.dim(\"• \");\n\n let line = \"\";\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch) + marker;\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += marker + (node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(pc.white(\"root: \")));\n }\n\n if (node.type === \"object\") {\n line += pc.dim(`{ ${node.itemCount} keys }`);\n } else if (node.type === \"array\") {\n line += pc.dim(`[ ${node.itemCount} items ]`);\n } else {\n line += formatValue(node.value);\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n lines.push(prettyPrintTree(child, nextIndent, childIsLast));\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import pc from \"picocolors\";\nimport { DiffNode, DiffStatus, JSONValueType } from \"./types.js\";\nimport { getValueType, formatValue, formatKey } from \"./formatter.js\";\n\nexport interface DiffStats {\n added: number;\n removed: number;\n modified: number;\n unchanged: number;\n}\n\n/**\n * Compare two JSON values structurally and return a recursive DiffNode tree.\n */\nexport function diffJSON(\n a: any,\n b: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 3\n): DiffNode {\n const typeA = getValueType(a);\n const typeB = getValueType(b);\n const id = `${path}-${key || \"diff\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n // Case 1: Value added (a is undefined, b exists)\n if (a === undefined && b !== undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"added\",\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n if (typeB === \"object\" && b !== null) {\n node.itemCount = Object.keys(b).length;\n node.children = Object.keys(b).map((k) =>\n diffJSON(undefined, b[k], k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeB === \"array\") {\n node.itemCount = b.length;\n node.children = b.map((item: any, idx: number) =>\n diffJSON(undefined, item, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 2: Value removed (a exists, b is undefined)\n if (a !== undefined && b === undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"removed\",\n oldValue: a,\n type: typeA,\n collapsed: false,\n };\n if (typeA === \"object\" && a !== null) {\n node.itemCount = Object.keys(a).length;\n node.children = Object.keys(a).map((k) =>\n diffJSON(a[k], undefined, k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeA === \"array\") {\n node.itemCount = a.length;\n node.children = a.map((item: any, idx: number) =>\n diffJSON(item, undefined, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 3: Type changed (e.g. from string to number or object to array)\n if (typeA !== typeB) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Case 4: Both are Objects\n if (typeA === \"object\" && a !== null && b !== null) {\n const allKeys = Array.from(new Set([...Object.keys(a), ...Object.keys(b)]));\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (const k of allKeys) {\n const child = diffJSON(\n a[k],\n b[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"object\",\n itemCount: allKeys.length,\n collapsed,\n children,\n };\n }\n\n // Case 5: Both are Arrays\n if (typeA === \"array\") {\n const maxLen = Math.max(a.length, b.length);\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (let i = 0; i < maxLen; i++) {\n const child = diffJSON(\n a[i],\n b[i],\n `[${i}]`,\n `${path}[${i}]`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"array\",\n itemCount: maxLen,\n collapsed,\n children,\n };\n }\n\n // Case 6: Primitive values comparison\n if (a !== b) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Unchanged primitive\n return {\n id,\n key,\n path,\n depth,\n status: \"unchanged\",\n oldValue: a,\n newValue: b,\n type: typeA,\n collapsed,\n };\n}\n\n/**\n * Calculate summary metrics for the diff.\n */\nexport function calculateDiffStats(node: DiffNode): DiffStats {\n const stats: DiffStats = { added: 0, removed: 0, modified: 0, unchanged: 0 };\n\n function traverse(n: DiffNode) {\n if (n.children && n.children.length > 0) {\n n.children.forEach(traverse);\n } else {\n stats[n.status]++;\n }\n }\n\n traverse(node);\n return stats;\n}\n\n/**\n * Pretty-print structural diff to terminal string.\n */\nexport function prettyPrintDiff(\n node: DiffNode,\n options: { showUnchanged?: boolean } = {},\n indent = \"\",\n isLast = true\n): string {\n const showUnchanged = options.showUnchanged ?? true;\n\n if (!showUnchanged && node.status === \"unchanged\" && (!node.children || node.children.length === 0)) {\n return \"\";\n }\n\n const isRoot = node.depth === 0;\n let prefix = \" \";\n let statusColor = pc.dim;\n\n if (node.status === \"added\") {\n prefix = pc.green(\"+ \");\n statusColor = pc.green;\n } else if (node.status === \"removed\") {\n prefix = pc.red(\"- \");\n statusColor = pc.red;\n } else if (node.status === \"modified\") {\n prefix = pc.yellow(\"~ \");\n statusColor = pc.yellow;\n }\n\n let line = prefix;\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch);\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(\"diff: \");\n }\n\n if (node.status === \"added\") {\n line += statusColor(formatValue(node.newValue));\n } else if (node.status === \"removed\") {\n line += statusColor(formatValue(node.oldValue));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n line += statusColor(`{ ${node.itemCount} items modified }`);\n } else {\n line += `${pc.red(formatValue(node.oldValue))} ${pc.dim(\"->\")} ${pc.green(formatValue(node.newValue))}`;\n }\n } else {\n // Unchanged\n line += pc.dim(formatValue(node.newValue));\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n const childStr = prettyPrintDiff(child, options, nextIndent, childIsLast);\n if (childStr) lines.push(childStr);\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import readline from \"readline\";\nimport pc from \"picocolors\";\nimport { TreeNode, DiffNode } from \"./types.js\";\nimport { formatKey, formatValue } from \"./formatter.js\";\nimport { copyToClipboard } from \"./utils/clipboard.js\";\n\ntype AnyNode = TreeNode | DiffNode;\n\ninterface FlatItem {\n node: AnyNode;\n depth: number;\n isDiff: boolean;\n}\n\n/**\n * Interactive Terminal Tree Explorer for JSON data and Diffs.\n */\nexport class InteractiveViewer {\n private root: AnyNode;\n private flatList: FlatItem[] = [];\n private selectedIndex = 0;\n private searchQuery = \"\";\n private isSearching = false;\n private searchInput = \"\";\n private notification = \"\";\n private notificationTimer: NodeJS.Timeout | null = null;\n private isDiff: boolean;\n\n constructor(root: AnyNode, isDiff = false) {\n this.root = root;\n this.isDiff = isDiff;\n this.rebuildFlatList();\n }\n\n private isDiffNode(node: AnyNode): node is DiffNode {\n return this.isDiff && \"status\" in node;\n }\n\n private rebuildFlatList(): void {\n const list: FlatItem[] = [];\n\n const traverse = (node: AnyNode, currentDepth: number) => {\n // If search query is active, filter matching nodes or their parents\n if (this.searchQuery) {\n const query = this.searchQuery.toLowerCase();\n const keyMatch = node.key && node.key.toLowerCase().includes(query);\n const pathMatch = node.path && node.path.toLowerCase().includes(query);\n const valMatch =\n \"value\" in node\n ? JSON.stringify(node.value).toLowerCase().includes(query)\n : \"newValue\" in node\n ? JSON.stringify(node.newValue).toLowerCase().includes(query)\n : false;\n\n if (!keyMatch && !pathMatch && !valMatch && (!node.children || node.children.length === 0)) {\n return;\n }\n }\n\n list.push({ node, depth: currentDepth, isDiff: this.isDiff });\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n for (const child of node.children) {\n traverse(child, currentDepth + 1);\n }\n }\n };\n\n traverse(this.root, 0);\n this.flatList = list;\n\n if (this.selectedIndex >= this.flatList.length) {\n this.selectedIndex = Math.max(0, this.flatList.length - 1);\n }\n }\n\n private setNotification(msg: string): void {\n this.notification = msg;\n if (this.notificationTimer) clearTimeout(this.notificationTimer);\n this.notificationTimer = setTimeout(() => {\n this.notification = \"\";\n this.render();\n }, 2500);\n }\n\n private render(): void {\n const rows = process.stdout.rows || 24;\n const maxVisibleRows = Math.max(5, rows - 5);\n\n // Calculate window scroll offset\n let startIdx = 0;\n if (this.selectedIndex >= maxVisibleRows) {\n startIdx = this.selectedIndex - maxVisibleRows + 1;\n }\n const endIdx = Math.min(this.flatList.length, startIdx + maxVisibleRows);\n\n // Clear terminal screen\n process.stdout.write(\"\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25l\"); // hide cursor\n\n // 1. Header Bar\n const title = this.isDiff ? \" JSON Structural Diff Explorer \" : \" Interactive JSON Tree Explorer \";\n console.log(pc.bgCyan(pc.black(pc.bold(` ${title} `)) + pc.dim(` [Total items: ${this.flatList.length}]`)));\n\n // 2. Render visible items\n for (let i = startIdx; i < endIdx; i++) {\n const { node, depth } = this.flatList[i];\n const isSelected = i === this.selectedIndex;\n const indent = \" \".repeat(depth);\n\n let marker = \"• \";\n if (node.children && node.children.length > 0) {\n marker = node.collapsed ? \"▶ \" : \"▼ \";\n }\n\n let lineContent = \"\";\n\n if (this.isDiffNode(node)) {\n let diffPrefix = \" \";\n if (node.status === \"added\") diffPrefix = pc.green(\"+ \");\n else if (node.status === \"removed\") diffPrefix = pc.red(\"- \");\n else if (node.status === \"modified\") diffPrefix = pc.yellow(\"~ \");\n\n lineContent = diffPrefix + indent + marker;\n if (node.key) lineContent += formatKey(node.key) + pc.dim(\": \");\n\n if (node.status === \"added\") {\n lineContent += pc.green(formatValue(node.newValue, 50));\n } else if (node.status === \"removed\") {\n lineContent += pc.red(formatValue(node.oldValue, 50));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n lineContent += pc.yellow(`{ ${node.itemCount} modified }`);\n } else {\n lineContent += `${pc.red(formatValue(node.oldValue, 25))} -> ${pc.green(formatValue(node.newValue, 25))}`;\n }\n } else {\n lineContent += pc.dim(formatValue(node.newValue, 50));\n }\n } else {\n const treeNode = node as TreeNode;\n lineContent = indent + marker;\n if (treeNode.key) lineContent += formatKey(treeNode.key) + pc.dim(\": \");\n\n if (treeNode.type === \"object\") {\n lineContent += pc.dim(`{ ${treeNode.itemCount} keys }`);\n } else if (treeNode.type === \"array\") {\n lineContent += pc.dim(`[ ${treeNode.itemCount} items ]`);\n } else {\n lineContent += formatValue(treeNode.value, 60);\n }\n }\n\n if (isSelected) {\n console.log(pc.bgBlue(pc.white(pc.bold(`> ${lineContent}`))));\n } else {\n console.log(` ${lineContent}`);\n }\n }\n\n // 3. Status Bar & Footer\n const selectedItem = this.flatList[this.selectedIndex];\n const currentPath = selectedItem ? selectedItem.node.path : \"$\";\n\n console.log(\"\\n\" + pc.dim(\"─\".repeat(Math.min(process.stdout.columns || 80, 80))));\n if (this.notification) {\n console.log(pc.green(pc.bold(` ${this.notification}`)));\n } else if (this.isSearching) {\n console.log(pc.yellow(pc.bold(` Search: /${this.searchInput}█`)));\n } else {\n console.log(pc.bold(pc.cyan(` Path: ${currentPath}`)));\n console.log(\n pc.dim(\" [↑/↓] Move [Enter/Space] Toggle [e] Expand All [c] Collapse All [p] Copy Path [y] Copy Val [/] Search [q] Exit\")\n );\n }\n }\n\n private expandAll(node: AnyNode): void {\n node.collapsed = false;\n if (node.children) node.children.forEach((c) => this.expandAll(c));\n }\n\n private collapseAll(node: AnyNode): void {\n if (node.depth > 0) node.collapsed = true;\n if (node.children) node.children.forEach((c) => this.collapseAll(c));\n }\n\n public async start(): Promise<void> {\n if (!process.stdin.isTTY) {\n return;\n }\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n this.render();\n\n return new Promise((resolve) => {\n const onKeypress = async (str: string, key: readline.Key) => {\n if (this.isSearching) {\n if (key.name === \"return\") {\n this.searchQuery = this.searchInput;\n this.isSearching = false;\n this.rebuildFlatList();\n this.render();\n return;\n }\n if (key.name === \"escape\") {\n this.isSearching = false;\n this.searchInput = \"\";\n this.render();\n return;\n }\n if (key.name === \"backspace\") {\n this.searchInput = this.searchInput.slice(0, -1);\n this.render();\n return;\n }\n if (str && str.length === 1) {\n this.searchInput += str;\n this.render();\n return;\n }\n }\n\n // Navigation\n if (key.name === \"up\" || key.name === \"k\") {\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.render();\n }\n } else if (key.name === \"down\" || key.name === \"j\") {\n if (this.selectedIndex < this.flatList.length - 1) {\n this.selectedIndex++;\n this.render();\n }\n } else if (key.name === \"return\" || key.name === \"space\" || key.name === \"right\" || key.name === \"left\") {\n const item = this.flatList[this.selectedIndex];\n if (item && item.node.children && item.node.children.length > 0) {\n item.node.collapsed = !item.node.collapsed;\n this.rebuildFlatList();\n this.render();\n }\n } else if (str === \"e\" || str === \"E\") {\n this.expandAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"c\" || str === \"C\") {\n this.collapseAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"p\" || str === \"P\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n await copyToClipboard(item.node.path);\n this.setNotification(`✔ Copied JSONPath: ${item.node.path}`);\n }\n } else if (str === \"y\" || str === \"Y\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n const val = \"value\" in item.node ? item.node.value : (item.node as DiffNode).newValue;\n const textToCopy = typeof val === \"object\" ? JSON.stringify(val, null, 2) : String(val);\n await copyToClipboard(textToCopy);\n this.setNotification(`✔ Copied value to clipboard!`);\n }\n } else if (str === \"/\") {\n this.isSearching = true;\n this.searchInput = \"\";\n this.render();\n } else if (key.ctrl && key.name === \"c\" || key.name === \"escape\" || str === \"q\" || str === \"Q\") {\n // Cleanup & Exit\n process.stdin.removeListener(\"keypress\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n process.stdout.write(\"\\x1b[?25h\\n\"); // show cursor\n resolve();\n }\n };\n\n process.stdin.on(\"keypress\", onKeypress);\n });\n }\n}\n","import { exec } from \"child_process\";\nimport os from \"os\";\n\n/**\n * Copy text to system clipboard across macOS, Linux, and Windows.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const platform = os.platform();\n\n return new Promise((resolve) => {\n let proc;\n if (platform === \"darwin\") {\n proc = exec(\"pbcopy\", (err) => resolve(!err));\n } else if (platform === \"win32\") {\n proc = exec(\"clip\", (err) => resolve(!err));\n } else {\n // Linux: Try wl-copy then xclip\n proc = exec(\"wl-copy 2>/dev/null || xclip -selection clipboard 2>/dev/null || xsel --clipboard --input\", (err) => {\n resolve(!err);\n });\n }\n\n if (proc.stdin) {\n proc.stdin.write(text);\n proc.stdin.end();\n } else {\n resolve(false);\n }\n });\n}\n"],"mappings":"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","names":["pc","pc","pc","pc","pc","pc"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/formatter.ts","../src/differ.ts","../src/interactive.ts","../src/utils/clipboard.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"fs\";\nimport pc from \"picocolors\";\nimport { buildTree, prettyPrintTree, colorizeJSON } from \"./formatter.js\";\nimport { diffJSON, prettyPrintDiff, calculateDiffStats } from \"./differ.js\";\nimport { InteractiveViewer } from \"./interactive.js\";\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n if (process.stdin.isTTY) {\n resolve(\"\");\n return;\n }\n\n process.stdin.setEncoding(\"utf-8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(data.trim());\n });\n setTimeout(() => {\n if (!data) resolve(\"\");\n }, 100);\n });\n}\n\nfunction parseJSON(raw: string, label = \"Input\"): any {\n try {\n return JSON.parse(raw);\n } catch (err: any) {\n throw new Error(`Invalid JSON in ${label}: ${err.message}`);\n }\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name(\"json-term\")\n .description(\"High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.\")\n .version(\"1.1.0\", \"-v, --version\", \"Output the current version\")\n .argument(\"[file]\", \"JSON file to view or compare\")\n .option(\"-p, --print\", \"Print formatted non-interactive output to stdout\", false)\n .option(\"-F, --format <format>\", \"Output format: 'tree' or 'json'\", \"tree\")\n .option(\"-r, --raw\", \"Print standard syntax-highlighted JSON (shorthand for --format json --print)\", false)\n .option(\"-d, --depth <number>\", \"Initial tree expansion depth\", (val) => parseInt(val, 10), 2)\n .option(\"-s, --search <query>\", \"Filter tree by key or value query\")\n .action(async (fileArg, options) => {\n try {\n let raw = \"\";\n if (fileArg) {\n if (!fs.existsSync(fileArg)) {\n console.error(pc.red(`Error: File not found: ${fileArg}`));\n process.exit(1);\n }\n raw = await fs.promises.readFile(fileArg, \"utf-8\");\n } else {\n raw = await readStdin();\n }\n\n if (!raw) {\n program.help();\n process.exit(1);\n }\n\n const data = parseJSON(raw, fileArg || \"stdin\");\n\n // If raw/json format requested, print colorized JSON directly\n if (options.raw || options.format === \"json\") {\n console.log(colorizeJSON(data));\n return;\n }\n\n const tree = buildTree(data, fileArg || \"root\", \"$\", 0, options.depth);\n\n if (options.print || !process.stdin.isTTY) {\n console.log(prettyPrintTree(tree));\n } else {\n const viewer = new InteractiveViewer(tree, false);\n await viewer.start();\n }\n } catch (err: any) {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n }\n });\n\n // Diff subcommand\n program\n .command(\"diff <fileA> [fileB]\")\n .description(\"Structural JSON diff between two files or stdin\")\n .option(\"-p, --print\", \"Print formatted non-interactive diff to stdout\", false)\n .option(\"-d, --depth <number>\", \"Initial expansion depth\", (val) => parseInt(val, 10), 3)\n .option(\"--no-unchanged\", \"Hide unchanged nodes from the diff view\", false)\n .action(async (fileA, fileB, diffOptions) => {\n try {\n if (!fs.existsSync(fileA)) {\n console.error(pc.red(`Error: File not found: ${fileA}`));\n process.exit(1);\n }\n const rawA = await fs.promises.readFile(fileA, \"utf-8\");\n const dataA = parseJSON(rawA, fileA);\n\n let dataB: any;\n if (fileB) {\n if (!fs.existsSync(fileB)) {\n console.error(pc.red(`Error: File not found: ${fileB}`));\n process.exit(1);\n }\n const rawB = await fs.promises.readFile(fileB, \"utf-8\");\n dataB = parseJSON(rawB, fileB);\n } else {\n const stdinData = await readStdin();\n if (!stdinData) {\n console.error(pc.red(\"Error: Please specify second file or pipe JSON via stdin.\"));\n process.exit(1);\n }\n dataB = parseJSON(stdinData, \"stdin\");\n }\n\n const diffTree = diffJSON(dataA, dataB, `${fileA} ↔ ${fileB || \"stdin\"}`, \"$\", 0, diffOptions.depth);\n const stats = calculateDiffStats(diffTree);\n\n if (diffOptions.print || !process.stdin.isTTY) {\n console.log(\n pc.bold(\n `Diff Stats: ${pc.green(`+${stats.added}`)} ${pc.red(`-${stats.removed}`)} ${pc.yellow(`~${stats.modified}`)} ${pc.dim(`=${stats.unchanged}`)}\\n`\n )\n );\n console.log(prettyPrintDiff(diffTree, { showUnchanged: diffOptions.unchanged }));\n } else {\n const viewer = new InteractiveViewer(diffTree, true);\n await viewer.start();\n }\n } catch (err: any) {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n }\n });\n\n await program.parseAsync(process.argv);\n}\n\nmain().catch((err) => {\n console.error(pc.red(`Error: ${err.message || err}`));\n process.exit(1);\n});\n","import pc from \"picocolors\";\nimport { JSONValueType, TreeNode } from \"./types.js\";\n\n/**\n * Determine the JSON value type.\n */\nexport function getValueType(value: any): JSONValueType {\n if (value === null || value === undefined) return \"null\";\n if (Array.isArray(value)) return \"array\";\n const t = typeof value;\n if (t === \"object\") return \"object\";\n if (t === \"string\") return \"string\";\n if (t === \"number\") return \"number\";\n if (t === \"boolean\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Colorize and format a single JSON value according to its type.\n */\nexport function formatValue(value: any, truncateLen = 80): string {\n const type = getValueType(value);\n\n switch (type) {\n case \"string\": {\n const str = JSON.stringify(value);\n const truncated = str.length > truncateLen ? str.slice(0, truncateLen - 3) + '...\"' : str;\n return pc.green(truncated);\n }\n case \"number\":\n return pc.yellow(String(value));\n case \"boolean\":\n return pc.magenta(String(value));\n case \"null\":\n return pc.dim(\"null\");\n case \"array\":\n return pc.dim(`[${value.length} items]`);\n case \"object\":\n return pc.dim(`{${Object.keys(value).length} keys}`);\n default:\n return String(value);\n }\n}\n\n/**\n * Format an object key with bold coloring.\n */\nexport function formatKey(key: string): string {\n return pc.bold(pc.cyan(key));\n}\n\n/**\n * Build a flat or nested TreeNode hierarchy from any JavaScript/JSON data.\n */\nexport function buildTree(\n data: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 2,\n parentId?: string\n): TreeNode {\n const type = getValueType(data);\n const id = `${path}-${key || \"root\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n const node: TreeNode = {\n id,\n key,\n value: data,\n type,\n depth,\n path,\n collapsed,\n parentId,\n };\n\n if (type === \"object\" && data !== null) {\n const keys = Object.keys(data);\n node.itemCount = keys.length;\n node.children = keys.map((k) =>\n buildTree(\n data[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n } else if (type === \"array\") {\n node.itemCount = data.length;\n node.children = data.map((item: any, idx: number) =>\n buildTree(\n item,\n `[${idx}]`,\n `${path}[${idx}]`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n }\n\n return node;\n}\n\n/**\n * Pretty-print JSON tree structure to terminal string.\n */\nexport function prettyPrintTree(node: TreeNode, indent = \"\", isLast = true): string {\n const isRoot = node.depth === 0;\n const marker = node.type === \"object\" || node.type === \"array\" ? (node.collapsed ? pc.cyan(\"▶ \") : pc.cyan(\"▼ \")) : pc.dim(\"• \");\n\n let line = \"\";\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch) + marker;\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += marker + (node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(pc.white(\"root: \")));\n }\n\n if (node.type === \"object\") {\n line += pc.dim(`{ ${node.itemCount} keys }`);\n } else if (node.type === \"array\") {\n line += pc.dim(`[ ${node.itemCount} items ]`);\n } else {\n line += formatValue(node.value);\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n lines.push(prettyPrintTree(child, nextIndent, childIsLast));\n });\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Colorize and format standard JSON structure with bold keys and typed syntax highlighting.\n */\nexport function colorizeJSON(data: any, space = 2): string {\n const jsonStr = typeof data === \"string\" ? data : JSON.stringify(data, null, space);\n if (!jsonStr) return \"\";\n\n return jsonStr.replace(\n /(\"(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)/g,\n (match) => {\n // Object key with trailing colon\n if (/^\"/.test(match)) {\n if (/:$/.test(match)) {\n const keyName = match.slice(0, -1);\n return pc.bold(pc.cyan(keyName)) + pc.dim(\":\");\n }\n // String value\n return pc.green(match);\n }\n // Boolean value\n if (/true|false/.test(match)) {\n return pc.magenta(match);\n }\n // Null value\n if (/null/.test(match)) {\n return pc.dim(match);\n }\n // Number value\n return pc.yellow(match);\n }\n );\n}\n\n","import pc from \"picocolors\";\nimport { DiffNode, DiffStatus, JSONValueType } from \"./types.js\";\nimport { getValueType, formatValue, formatKey } from \"./formatter.js\";\n\nexport interface DiffStats {\n added: number;\n removed: number;\n modified: number;\n unchanged: number;\n}\n\n/**\n * Compare two JSON values structurally and return a recursive DiffNode tree.\n */\nexport function diffJSON(\n a: any,\n b: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 3\n): DiffNode {\n const typeA = getValueType(a);\n const typeB = getValueType(b);\n const id = `${path}-${key || \"diff\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n // Case 1: Value added (a is undefined, b exists)\n if (a === undefined && b !== undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"added\",\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n if (typeB === \"object\" && b !== null) {\n node.itemCount = Object.keys(b).length;\n node.children = Object.keys(b).map((k) =>\n diffJSON(undefined, b[k], k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeB === \"array\") {\n node.itemCount = b.length;\n node.children = b.map((item: any, idx: number) =>\n diffJSON(undefined, item, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 2: Value removed (a exists, b is undefined)\n if (a !== undefined && b === undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"removed\",\n oldValue: a,\n type: typeA,\n collapsed: false,\n };\n if (typeA === \"object\" && a !== null) {\n node.itemCount = Object.keys(a).length;\n node.children = Object.keys(a).map((k) =>\n diffJSON(a[k], undefined, k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeA === \"array\") {\n node.itemCount = a.length;\n node.children = a.map((item: any, idx: number) =>\n diffJSON(item, undefined, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 3: Type changed (e.g. from string to number or object to array)\n if (typeA !== typeB) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Case 4: Both are Objects\n if (typeA === \"object\" && a !== null && b !== null) {\n const allKeys = Array.from(new Set([...Object.keys(a), ...Object.keys(b)]));\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (const k of allKeys) {\n const child = diffJSON(\n a[k],\n b[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"object\",\n itemCount: allKeys.length,\n collapsed,\n children,\n };\n }\n\n // Case 5: Both are Arrays\n if (typeA === \"array\") {\n const maxLen = Math.max(a.length, b.length);\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (let i = 0; i < maxLen; i++) {\n const child = diffJSON(\n a[i],\n b[i],\n `[${i}]`,\n `${path}[${i}]`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"array\",\n itemCount: maxLen,\n collapsed,\n children,\n };\n }\n\n // Case 6: Primitive values comparison\n if (a !== b) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Unchanged primitive\n return {\n id,\n key,\n path,\n depth,\n status: \"unchanged\",\n oldValue: a,\n newValue: b,\n type: typeA,\n collapsed,\n };\n}\n\n/**\n * Calculate summary metrics for the diff.\n */\nexport function calculateDiffStats(node: DiffNode): DiffStats {\n const stats: DiffStats = { added: 0, removed: 0, modified: 0, unchanged: 0 };\n\n function traverse(n: DiffNode) {\n if (n.children && n.children.length > 0) {\n n.children.forEach(traverse);\n } else {\n stats[n.status]++;\n }\n }\n\n traverse(node);\n return stats;\n}\n\n/**\n * Pretty-print structural diff to terminal string.\n */\nexport function prettyPrintDiff(\n node: DiffNode,\n options: { showUnchanged?: boolean } = {},\n indent = \"\",\n isLast = true\n): string {\n const showUnchanged = options.showUnchanged ?? true;\n\n if (!showUnchanged && node.status === \"unchanged\" && (!node.children || node.children.length === 0)) {\n return \"\";\n }\n\n const isRoot = node.depth === 0;\n let prefix = \" \";\n let statusColor = pc.dim;\n\n if (node.status === \"added\") {\n prefix = pc.green(\"+ \");\n statusColor = pc.green;\n } else if (node.status === \"removed\") {\n prefix = pc.red(\"- \");\n statusColor = pc.red;\n } else if (node.status === \"modified\") {\n prefix = pc.yellow(\"~ \");\n statusColor = pc.yellow;\n }\n\n let line = prefix;\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch);\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(\"diff: \");\n }\n\n if (node.status === \"added\") {\n line += statusColor(formatValue(node.newValue));\n } else if (node.status === \"removed\") {\n line += statusColor(formatValue(node.oldValue));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n line += statusColor(`{ ${node.itemCount} items modified }`);\n } else {\n line += `${pc.red(formatValue(node.oldValue))} ${pc.dim(\"->\")} ${pc.green(formatValue(node.newValue))}`;\n }\n } else {\n // Unchanged\n line += pc.dim(formatValue(node.newValue));\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n const childStr = prettyPrintDiff(child, options, nextIndent, childIsLast);\n if (childStr) lines.push(childStr);\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import readline from \"readline\";\nimport pc from \"picocolors\";\nimport { TreeNode, DiffNode } from \"./types.js\";\nimport { formatKey, formatValue } from \"./formatter.js\";\nimport { copyToClipboard } from \"./utils/clipboard.js\";\n\ntype AnyNode = TreeNode | DiffNode;\n\ninterface FlatItem {\n node: AnyNode;\n depth: number;\n isDiff: boolean;\n}\n\n/**\n * Interactive Terminal Tree Explorer for JSON data and Diffs.\n */\nexport class InteractiveViewer {\n private root: AnyNode;\n private flatList: FlatItem[] = [];\n private selectedIndex = 0;\n private searchQuery = \"\";\n private isSearching = false;\n private searchInput = \"\";\n private notification = \"\";\n private notificationTimer: NodeJS.Timeout | null = null;\n private isDiff: boolean;\n\n constructor(root: AnyNode, isDiff = false) {\n this.root = root;\n this.isDiff = isDiff;\n this.rebuildFlatList();\n }\n\n private isDiffNode(node: AnyNode): node is DiffNode {\n return this.isDiff && \"status\" in node;\n }\n\n private rebuildFlatList(): void {\n const list: FlatItem[] = [];\n\n const traverse = (node: AnyNode, currentDepth: number) => {\n // If search query is active, filter matching nodes or their parents\n if (this.searchQuery) {\n const query = this.searchQuery.toLowerCase();\n const keyMatch = node.key && node.key.toLowerCase().includes(query);\n const pathMatch = node.path && node.path.toLowerCase().includes(query);\n const valMatch =\n \"value\" in node\n ? JSON.stringify(node.value).toLowerCase().includes(query)\n : \"newValue\" in node\n ? JSON.stringify(node.newValue).toLowerCase().includes(query)\n : false;\n\n if (!keyMatch && !pathMatch && !valMatch && (!node.children || node.children.length === 0)) {\n return;\n }\n }\n\n list.push({ node, depth: currentDepth, isDiff: this.isDiff });\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n for (const child of node.children) {\n traverse(child, currentDepth + 1);\n }\n }\n };\n\n traverse(this.root, 0);\n this.flatList = list;\n\n if (this.selectedIndex >= this.flatList.length) {\n this.selectedIndex = Math.max(0, this.flatList.length - 1);\n }\n }\n\n private setNotification(msg: string): void {\n this.notification = msg;\n if (this.notificationTimer) clearTimeout(this.notificationTimer);\n this.notificationTimer = setTimeout(() => {\n this.notification = \"\";\n this.render();\n }, 2500);\n }\n\n private render(): void {\n const rows = process.stdout.rows || 24;\n const maxVisibleRows = Math.max(5, rows - 5);\n\n // Calculate window scroll offset\n let startIdx = 0;\n if (this.selectedIndex >= maxVisibleRows) {\n startIdx = this.selectedIndex - maxVisibleRows + 1;\n }\n const endIdx = Math.min(this.flatList.length, startIdx + maxVisibleRows);\n\n // Clear terminal screen\n process.stdout.write(\"\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25l\"); // hide cursor\n\n // 1. Header Bar\n const title = this.isDiff ? \" JSON Structural Diff Explorer \" : \" Interactive JSON Tree Explorer \";\n console.log(pc.bgCyan(pc.black(pc.bold(` ${title} `)) + pc.dim(` [Total items: ${this.flatList.length}]`)));\n\n // 2. Render visible items\n for (let i = startIdx; i < endIdx; i++) {\n const { node, depth } = this.flatList[i];\n const isSelected = i === this.selectedIndex;\n const indent = \" \".repeat(depth);\n\n let marker = \"• \";\n if (node.children && node.children.length > 0) {\n marker = node.collapsed ? \"▶ \" : \"▼ \";\n }\n\n let lineContent = \"\";\n\n if (this.isDiffNode(node)) {\n let diffPrefix = \" \";\n if (node.status === \"added\") diffPrefix = pc.green(\"+ \");\n else if (node.status === \"removed\") diffPrefix = pc.red(\"- \");\n else if (node.status === \"modified\") diffPrefix = pc.yellow(\"~ \");\n\n lineContent = diffPrefix + indent + marker;\n if (node.key) lineContent += formatKey(node.key) + pc.dim(\": \");\n\n if (node.status === \"added\") {\n lineContent += pc.green(formatValue(node.newValue, 50));\n } else if (node.status === \"removed\") {\n lineContent += pc.red(formatValue(node.oldValue, 50));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n lineContent += pc.yellow(`{ ${node.itemCount} modified }`);\n } else {\n lineContent += `${pc.red(formatValue(node.oldValue, 25))} -> ${pc.green(formatValue(node.newValue, 25))}`;\n }\n } else {\n lineContent += pc.dim(formatValue(node.newValue, 50));\n }\n } else {\n const treeNode = node as TreeNode;\n lineContent = indent + marker;\n if (treeNode.key) lineContent += formatKey(treeNode.key) + pc.dim(\": \");\n\n if (treeNode.type === \"object\") {\n lineContent += pc.dim(`{ ${treeNode.itemCount} keys }`);\n } else if (treeNode.type === \"array\") {\n lineContent += pc.dim(`[ ${treeNode.itemCount} items ]`);\n } else {\n lineContent += formatValue(treeNode.value, 60);\n }\n }\n\n if (isSelected) {\n console.log(pc.bgBlue(pc.white(pc.bold(`> ${lineContent}`))));\n } else {\n console.log(` ${lineContent}`);\n }\n }\n\n // 3. Status Bar & Footer\n const selectedItem = this.flatList[this.selectedIndex];\n const currentPath = selectedItem ? selectedItem.node.path : \"$\";\n\n console.log(\"\\n\" + pc.dim(\"─\".repeat(Math.min(process.stdout.columns || 80, 80))));\n if (this.notification) {\n console.log(pc.green(pc.bold(` ${this.notification}`)));\n } else if (this.isSearching) {\n console.log(pc.yellow(pc.bold(` Search: /${this.searchInput}█`)));\n } else {\n console.log(pc.bold(pc.cyan(` Path: ${currentPath}`)));\n console.log(\n pc.dim(\" [↑/↓] Move [Enter/Space] Toggle [e] Expand All [c] Collapse All [p] Copy Path [y] Copy Val [/] Search [q] Exit\")\n );\n }\n }\n\n private expandAll(node: AnyNode): void {\n node.collapsed = false;\n if (node.children) node.children.forEach((c) => this.expandAll(c));\n }\n\n private collapseAll(node: AnyNode): void {\n if (node.depth > 0) node.collapsed = true;\n if (node.children) node.children.forEach((c) => this.collapseAll(c));\n }\n\n public async start(): Promise<void> {\n if (!process.stdin.isTTY) {\n return;\n }\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n this.render();\n\n return new Promise((resolve) => {\n const onKeypress = async (str: string, key: readline.Key) => {\n if (this.isSearching) {\n if (key.name === \"return\") {\n this.searchQuery = this.searchInput;\n this.isSearching = false;\n this.rebuildFlatList();\n this.render();\n return;\n }\n if (key.name === \"escape\") {\n this.isSearching = false;\n this.searchInput = \"\";\n this.render();\n return;\n }\n if (key.name === \"backspace\") {\n this.searchInput = this.searchInput.slice(0, -1);\n this.render();\n return;\n }\n if (str && str.length === 1) {\n this.searchInput += str;\n this.render();\n return;\n }\n }\n\n // Navigation\n if (key.name === \"up\" || key.name === \"k\") {\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.render();\n }\n } else if (key.name === \"down\" || key.name === \"j\") {\n if (this.selectedIndex < this.flatList.length - 1) {\n this.selectedIndex++;\n this.render();\n }\n } else if (key.name === \"return\" || key.name === \"space\" || key.name === \"right\" || key.name === \"left\") {\n const item = this.flatList[this.selectedIndex];\n if (item && item.node.children && item.node.children.length > 0) {\n item.node.collapsed = !item.node.collapsed;\n this.rebuildFlatList();\n this.render();\n }\n } else if (str === \"e\" || str === \"E\") {\n this.expandAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"c\" || str === \"C\") {\n this.collapseAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"p\" || str === \"P\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n await copyToClipboard(item.node.path);\n this.setNotification(`✔ Copied JSONPath: ${item.node.path}`);\n }\n } else if (str === \"y\" || str === \"Y\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n const val = \"value\" in item.node ? item.node.value : (item.node as DiffNode).newValue;\n const textToCopy = typeof val === \"object\" ? JSON.stringify(val, null, 2) : String(val);\n await copyToClipboard(textToCopy);\n this.setNotification(`✔ Copied value to clipboard!`);\n }\n } else if (str === \"/\") {\n this.isSearching = true;\n this.searchInput = \"\";\n this.render();\n } else if (key.ctrl && key.name === \"c\" || key.name === \"escape\" || str === \"q\" || str === \"Q\") {\n // Cleanup & Exit\n process.stdin.removeListener(\"keypress\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n process.stdout.write(\"\\x1b[?25h\\n\"); // show cursor\n resolve();\n }\n };\n\n process.stdin.on(\"keypress\", onKeypress);\n });\n }\n}\n","import { exec } from \"child_process\";\nimport os from \"os\";\n\n/**\n * Copy text to system clipboard across macOS, Linux, and Windows.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const platform = os.platform();\n\n return new Promise((resolve) => {\n let proc;\n if (platform === \"darwin\") {\n proc = exec(\"pbcopy\", (err) => resolve(!err));\n } else if (platform === \"win32\") {\n proc = exec(\"clip\", (err) => resolve(!err));\n } else {\n // Linux: Try wl-copy then xclip\n proc = exec(\"wl-copy 2>/dev/null || xclip -selection clipboard 2>/dev/null || xsel --clipboard --input\", (err) => {\n resolve(!err);\n });\n }\n\n if (proc.stdin) {\n proc.stdin.write(text);\n proc.stdin.end();\n } else {\n resolve(false);\n }\n });\n}\n"],"mappings":"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","names":["pc","pc","pc","pc","pc","pc"]}
package/dist/index.d.mts CHANGED
@@ -57,6 +57,10 @@ declare function buildTree(data: any, key?: string, path?: string, depth?: numbe
57
57
  * Pretty-print JSON tree structure to terminal string.
58
58
  */
59
59
  declare function prettyPrintTree(node: TreeNode, indent?: string, isLast?: boolean): string;
60
+ /**
61
+ * Colorize and format standard JSON structure with bold keys and typed syntax highlighting.
62
+ */
63
+ declare function colorizeJSON(data: any, space?: number): string;
60
64
 
61
65
  interface DiffStats {
62
66
  added: number;
@@ -108,4 +112,4 @@ declare class InteractiveViewer {
108
112
  */
109
113
  declare function copyToClipboard(text: string): Promise<boolean>;
110
114
 
111
- export { type DiffNode, type DiffOptions, type DiffStats, type DiffStatus, InteractiveViewer, type JSONValueType, type TreeNode, type ViewerOptions, buildTree, calculateDiffStats, copyToClipboard, diffJSON, formatKey, formatValue, getValueType, prettyPrintDiff, prettyPrintTree };
115
+ export { type DiffNode, type DiffOptions, type DiffStats, type DiffStatus, InteractiveViewer, type JSONValueType, type TreeNode, type ViewerOptions, buildTree, calculateDiffStats, colorizeJSON, copyToClipboard, diffJSON, formatKey, formatValue, getValueType, prettyPrintDiff, prettyPrintTree };
package/dist/index.d.ts CHANGED
@@ -57,6 +57,10 @@ declare function buildTree(data: any, key?: string, path?: string, depth?: numbe
57
57
  * Pretty-print JSON tree structure to terminal string.
58
58
  */
59
59
  declare function prettyPrintTree(node: TreeNode, indent?: string, isLast?: boolean): string;
60
+ /**
61
+ * Colorize and format standard JSON structure with bold keys and typed syntax highlighting.
62
+ */
63
+ declare function colorizeJSON(data: any, space?: number): string;
60
64
 
61
65
  interface DiffStats {
62
66
  added: number;
@@ -108,4 +112,4 @@ declare class InteractiveViewer {
108
112
  */
109
113
  declare function copyToClipboard(text: string): Promise<boolean>;
110
114
 
111
- export { type DiffNode, type DiffOptions, type DiffStats, type DiffStatus, InteractiveViewer, type JSONValueType, type TreeNode, type ViewerOptions, buildTree, calculateDiffStats, copyToClipboard, diffJSON, formatKey, formatValue, getValueType, prettyPrintDiff, prettyPrintTree };
115
+ export { type DiffNode, type DiffOptions, type DiffStats, type DiffStatus, InteractiveViewer, type JSONValueType, type TreeNode, type ViewerOptions, buildTree, calculateDiffStats, colorizeJSON, copyToClipboard, diffJSON, formatKey, formatValue, getValueType, prettyPrintDiff, prettyPrintTree };
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ __export(src_exports, {
33
33
  InteractiveViewer: () => InteractiveViewer,
34
34
  buildTree: () => buildTree,
35
35
  calculateDiffStats: () => calculateDiffStats,
36
+ colorizeJSON: () => colorizeJSON,
36
37
  copyToClipboard: () => copyToClipboard,
37
38
  diffJSON: () => diffJSON,
38
39
  formatKey: () => formatKey,
@@ -152,6 +153,29 @@ function prettyPrintTree(node, indent = "", isLast = true) {
152
153
  }
153
154
  return lines.join("\n");
154
155
  }
156
+ function colorizeJSON(data, space = 2) {
157
+ const jsonStr = typeof data === "string" ? data : JSON.stringify(data, null, space);
158
+ if (!jsonStr) return "";
159
+ return jsonStr.replace(
160
+ /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
161
+ (match) => {
162
+ if (/^"/.test(match)) {
163
+ if (/:$/.test(match)) {
164
+ const keyName = match.slice(0, -1);
165
+ return import_picocolors.default.bold(import_picocolors.default.cyan(keyName)) + import_picocolors.default.dim(":");
166
+ }
167
+ return import_picocolors.default.green(match);
168
+ }
169
+ if (/true|false/.test(match)) {
170
+ return import_picocolors.default.magenta(match);
171
+ }
172
+ if (/null/.test(match)) {
173
+ return import_picocolors.default.dim(match);
174
+ }
175
+ return import_picocolors.default.yellow(match);
176
+ }
177
+ );
178
+ }
155
179
 
156
180
  // src/differ.ts
157
181
  var import_picocolors2 = __toESM(require("picocolors"));
@@ -627,6 +651,7 @@ var InteractiveViewer = class {
627
651
  InteractiveViewer,
628
652
  buildTree,
629
653
  calculateDiffStats,
654
+ colorizeJSON,
630
655
  copyToClipboard,
631
656
  diffJSON,
632
657
  formatKey,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/formatter.ts","../src/differ.ts","../src/interactive.ts","../src/utils/clipboard.ts"],"sourcesContent":["export * from \"./types.js\";\nexport * from \"./formatter.js\";\nexport * from \"./differ.js\";\nexport * from \"./interactive.js\";\nexport * from \"./utils/clipboard.js\";\n","import pc from \"picocolors\";\nimport { JSONValueType, TreeNode } from \"./types.js\";\n\n/**\n * Determine the JSON value type.\n */\nexport function getValueType(value: any): JSONValueType {\n if (value === null || value === undefined) return \"null\";\n if (Array.isArray(value)) return \"array\";\n const t = typeof value;\n if (t === \"object\") return \"object\";\n if (t === \"string\") return \"string\";\n if (t === \"number\") return \"number\";\n if (t === \"boolean\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Colorize and format a single JSON value according to its type.\n */\nexport function formatValue(value: any, truncateLen = 80): string {\n const type = getValueType(value);\n\n switch (type) {\n case \"string\": {\n const str = JSON.stringify(value);\n const truncated = str.length > truncateLen ? str.slice(0, truncateLen - 3) + '...\"' : str;\n return pc.green(truncated);\n }\n case \"number\":\n return pc.yellow(String(value));\n case \"boolean\":\n return pc.magenta(String(value));\n case \"null\":\n return pc.dim(\"null\");\n case \"array\":\n return pc.dim(`[${value.length} items]`);\n case \"object\":\n return pc.dim(`{${Object.keys(value).length} keys}`);\n default:\n return String(value);\n }\n}\n\n/**\n * Format an object key with bold coloring.\n */\nexport function formatKey(key: string): string {\n return pc.bold(pc.cyan(key));\n}\n\n/**\n * Build a flat or nested TreeNode hierarchy from any JavaScript/JSON data.\n */\nexport function buildTree(\n data: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 2,\n parentId?: string\n): TreeNode {\n const type = getValueType(data);\n const id = `${path}-${key || \"root\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n const node: TreeNode = {\n id,\n key,\n value: data,\n type,\n depth,\n path,\n collapsed,\n parentId,\n };\n\n if (type === \"object\" && data !== null) {\n const keys = Object.keys(data);\n node.itemCount = keys.length;\n node.children = keys.map((k) =>\n buildTree(\n data[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n } else if (type === \"array\") {\n node.itemCount = data.length;\n node.children = data.map((item: any, idx: number) =>\n buildTree(\n item,\n `[${idx}]`,\n `${path}[${idx}]`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n }\n\n return node;\n}\n\n/**\n * Pretty-print JSON tree structure to terminal string.\n */\nexport function prettyPrintTree(node: TreeNode, indent = \"\", isLast = true): string {\n const isRoot = node.depth === 0;\n const marker = node.type === \"object\" || node.type === \"array\" ? (node.collapsed ? pc.cyan(\"▶ \") : pc.cyan(\"▼ \")) : pc.dim(\"• \");\n\n let line = \"\";\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch) + marker;\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += marker + (node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(pc.white(\"root: \")));\n }\n\n if (node.type === \"object\") {\n line += pc.dim(`{ ${node.itemCount} keys }`);\n } else if (node.type === \"array\") {\n line += pc.dim(`[ ${node.itemCount} items ]`);\n } else {\n line += formatValue(node.value);\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n lines.push(prettyPrintTree(child, nextIndent, childIsLast));\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import pc from \"picocolors\";\nimport { DiffNode, DiffStatus, JSONValueType } from \"./types.js\";\nimport { getValueType, formatValue, formatKey } from \"./formatter.js\";\n\nexport interface DiffStats {\n added: number;\n removed: number;\n modified: number;\n unchanged: number;\n}\n\n/**\n * Compare two JSON values structurally and return a recursive DiffNode tree.\n */\nexport function diffJSON(\n a: any,\n b: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 3\n): DiffNode {\n const typeA = getValueType(a);\n const typeB = getValueType(b);\n const id = `${path}-${key || \"diff\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n // Case 1: Value added (a is undefined, b exists)\n if (a === undefined && b !== undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"added\",\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n if (typeB === \"object\" && b !== null) {\n node.itemCount = Object.keys(b).length;\n node.children = Object.keys(b).map((k) =>\n diffJSON(undefined, b[k], k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeB === \"array\") {\n node.itemCount = b.length;\n node.children = b.map((item: any, idx: number) =>\n diffJSON(undefined, item, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 2: Value removed (a exists, b is undefined)\n if (a !== undefined && b === undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"removed\",\n oldValue: a,\n type: typeA,\n collapsed: false,\n };\n if (typeA === \"object\" && a !== null) {\n node.itemCount = Object.keys(a).length;\n node.children = Object.keys(a).map((k) =>\n diffJSON(a[k], undefined, k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeA === \"array\") {\n node.itemCount = a.length;\n node.children = a.map((item: any, idx: number) =>\n diffJSON(item, undefined, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 3: Type changed (e.g. from string to number or object to array)\n if (typeA !== typeB) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Case 4: Both are Objects\n if (typeA === \"object\" && a !== null && b !== null) {\n const allKeys = Array.from(new Set([...Object.keys(a), ...Object.keys(b)]));\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (const k of allKeys) {\n const child = diffJSON(\n a[k],\n b[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"object\",\n itemCount: allKeys.length,\n collapsed,\n children,\n };\n }\n\n // Case 5: Both are Arrays\n if (typeA === \"array\") {\n const maxLen = Math.max(a.length, b.length);\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (let i = 0; i < maxLen; i++) {\n const child = diffJSON(\n a[i],\n b[i],\n `[${i}]`,\n `${path}[${i}]`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"array\",\n itemCount: maxLen,\n collapsed,\n children,\n };\n }\n\n // Case 6: Primitive values comparison\n if (a !== b) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Unchanged primitive\n return {\n id,\n key,\n path,\n depth,\n status: \"unchanged\",\n oldValue: a,\n newValue: b,\n type: typeA,\n collapsed,\n };\n}\n\n/**\n * Calculate summary metrics for the diff.\n */\nexport function calculateDiffStats(node: DiffNode): DiffStats {\n const stats: DiffStats = { added: 0, removed: 0, modified: 0, unchanged: 0 };\n\n function traverse(n: DiffNode) {\n if (n.children && n.children.length > 0) {\n n.children.forEach(traverse);\n } else {\n stats[n.status]++;\n }\n }\n\n traverse(node);\n return stats;\n}\n\n/**\n * Pretty-print structural diff to terminal string.\n */\nexport function prettyPrintDiff(\n node: DiffNode,\n options: { showUnchanged?: boolean } = {},\n indent = \"\",\n isLast = true\n): string {\n const showUnchanged = options.showUnchanged ?? true;\n\n if (!showUnchanged && node.status === \"unchanged\" && (!node.children || node.children.length === 0)) {\n return \"\";\n }\n\n const isRoot = node.depth === 0;\n let prefix = \" \";\n let statusColor = pc.dim;\n\n if (node.status === \"added\") {\n prefix = pc.green(\"+ \");\n statusColor = pc.green;\n } else if (node.status === \"removed\") {\n prefix = pc.red(\"- \");\n statusColor = pc.red;\n } else if (node.status === \"modified\") {\n prefix = pc.yellow(\"~ \");\n statusColor = pc.yellow;\n }\n\n let line = prefix;\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch);\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(\"diff: \");\n }\n\n if (node.status === \"added\") {\n line += statusColor(formatValue(node.newValue));\n } else if (node.status === \"removed\") {\n line += statusColor(formatValue(node.oldValue));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n line += statusColor(`{ ${node.itemCount} items modified }`);\n } else {\n line += `${pc.red(formatValue(node.oldValue))} ${pc.dim(\"->\")} ${pc.green(formatValue(node.newValue))}`;\n }\n } else {\n // Unchanged\n line += pc.dim(formatValue(node.newValue));\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n const childStr = prettyPrintDiff(child, options, nextIndent, childIsLast);\n if (childStr) lines.push(childStr);\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import readline from \"readline\";\nimport pc from \"picocolors\";\nimport { TreeNode, DiffNode } from \"./types.js\";\nimport { formatKey, formatValue } from \"./formatter.js\";\nimport { copyToClipboard } from \"./utils/clipboard.js\";\n\ntype AnyNode = TreeNode | DiffNode;\n\ninterface FlatItem {\n node: AnyNode;\n depth: number;\n isDiff: boolean;\n}\n\n/**\n * Interactive Terminal Tree Explorer for JSON data and Diffs.\n */\nexport class InteractiveViewer {\n private root: AnyNode;\n private flatList: FlatItem[] = [];\n private selectedIndex = 0;\n private searchQuery = \"\";\n private isSearching = false;\n private searchInput = \"\";\n private notification = \"\";\n private notificationTimer: NodeJS.Timeout | null = null;\n private isDiff: boolean;\n\n constructor(root: AnyNode, isDiff = false) {\n this.root = root;\n this.isDiff = isDiff;\n this.rebuildFlatList();\n }\n\n private isDiffNode(node: AnyNode): node is DiffNode {\n return this.isDiff && \"status\" in node;\n }\n\n private rebuildFlatList(): void {\n const list: FlatItem[] = [];\n\n const traverse = (node: AnyNode, currentDepth: number) => {\n // If search query is active, filter matching nodes or their parents\n if (this.searchQuery) {\n const query = this.searchQuery.toLowerCase();\n const keyMatch = node.key && node.key.toLowerCase().includes(query);\n const pathMatch = node.path && node.path.toLowerCase().includes(query);\n const valMatch =\n \"value\" in node\n ? JSON.stringify(node.value).toLowerCase().includes(query)\n : \"newValue\" in node\n ? JSON.stringify(node.newValue).toLowerCase().includes(query)\n : false;\n\n if (!keyMatch && !pathMatch && !valMatch && (!node.children || node.children.length === 0)) {\n return;\n }\n }\n\n list.push({ node, depth: currentDepth, isDiff: this.isDiff });\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n for (const child of node.children) {\n traverse(child, currentDepth + 1);\n }\n }\n };\n\n traverse(this.root, 0);\n this.flatList = list;\n\n if (this.selectedIndex >= this.flatList.length) {\n this.selectedIndex = Math.max(0, this.flatList.length - 1);\n }\n }\n\n private setNotification(msg: string): void {\n this.notification = msg;\n if (this.notificationTimer) clearTimeout(this.notificationTimer);\n this.notificationTimer = setTimeout(() => {\n this.notification = \"\";\n this.render();\n }, 2500);\n }\n\n private render(): void {\n const rows = process.stdout.rows || 24;\n const maxVisibleRows = Math.max(5, rows - 5);\n\n // Calculate window scroll offset\n let startIdx = 0;\n if (this.selectedIndex >= maxVisibleRows) {\n startIdx = this.selectedIndex - maxVisibleRows + 1;\n }\n const endIdx = Math.min(this.flatList.length, startIdx + maxVisibleRows);\n\n // Clear terminal screen\n process.stdout.write(\"\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25l\"); // hide cursor\n\n // 1. Header Bar\n const title = this.isDiff ? \" JSON Structural Diff Explorer \" : \" Interactive JSON Tree Explorer \";\n console.log(pc.bgCyan(pc.black(pc.bold(` ${title} `)) + pc.dim(` [Total items: ${this.flatList.length}]`)));\n\n // 2. Render visible items\n for (let i = startIdx; i < endIdx; i++) {\n const { node, depth } = this.flatList[i];\n const isSelected = i === this.selectedIndex;\n const indent = \" \".repeat(depth);\n\n let marker = \"• \";\n if (node.children && node.children.length > 0) {\n marker = node.collapsed ? \"▶ \" : \"▼ \";\n }\n\n let lineContent = \"\";\n\n if (this.isDiffNode(node)) {\n let diffPrefix = \" \";\n if (node.status === \"added\") diffPrefix = pc.green(\"+ \");\n else if (node.status === \"removed\") diffPrefix = pc.red(\"- \");\n else if (node.status === \"modified\") diffPrefix = pc.yellow(\"~ \");\n\n lineContent = diffPrefix + indent + marker;\n if (node.key) lineContent += formatKey(node.key) + pc.dim(\": \");\n\n if (node.status === \"added\") {\n lineContent += pc.green(formatValue(node.newValue, 50));\n } else if (node.status === \"removed\") {\n lineContent += pc.red(formatValue(node.oldValue, 50));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n lineContent += pc.yellow(`{ ${node.itemCount} modified }`);\n } else {\n lineContent += `${pc.red(formatValue(node.oldValue, 25))} -> ${pc.green(formatValue(node.newValue, 25))}`;\n }\n } else {\n lineContent += pc.dim(formatValue(node.newValue, 50));\n }\n } else {\n const treeNode = node as TreeNode;\n lineContent = indent + marker;\n if (treeNode.key) lineContent += formatKey(treeNode.key) + pc.dim(\": \");\n\n if (treeNode.type === \"object\") {\n lineContent += pc.dim(`{ ${treeNode.itemCount} keys }`);\n } else if (treeNode.type === \"array\") {\n lineContent += pc.dim(`[ ${treeNode.itemCount} items ]`);\n } else {\n lineContent += formatValue(treeNode.value, 60);\n }\n }\n\n if (isSelected) {\n console.log(pc.bgBlue(pc.white(pc.bold(`> ${lineContent}`))));\n } else {\n console.log(` ${lineContent}`);\n }\n }\n\n // 3. Status Bar & Footer\n const selectedItem = this.flatList[this.selectedIndex];\n const currentPath = selectedItem ? selectedItem.node.path : \"$\";\n\n console.log(\"\\n\" + pc.dim(\"─\".repeat(Math.min(process.stdout.columns || 80, 80))));\n if (this.notification) {\n console.log(pc.green(pc.bold(` ${this.notification}`)));\n } else if (this.isSearching) {\n console.log(pc.yellow(pc.bold(` Search: /${this.searchInput}█`)));\n } else {\n console.log(pc.bold(pc.cyan(` Path: ${currentPath}`)));\n console.log(\n pc.dim(\" [↑/↓] Move [Enter/Space] Toggle [e] Expand All [c] Collapse All [p] Copy Path [y] Copy Val [/] Search [q] Exit\")\n );\n }\n }\n\n private expandAll(node: AnyNode): void {\n node.collapsed = false;\n if (node.children) node.children.forEach((c) => this.expandAll(c));\n }\n\n private collapseAll(node: AnyNode): void {\n if (node.depth > 0) node.collapsed = true;\n if (node.children) node.children.forEach((c) => this.collapseAll(c));\n }\n\n public async start(): Promise<void> {\n if (!process.stdin.isTTY) {\n return;\n }\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n this.render();\n\n return new Promise((resolve) => {\n const onKeypress = async (str: string, key: readline.Key) => {\n if (this.isSearching) {\n if (key.name === \"return\") {\n this.searchQuery = this.searchInput;\n this.isSearching = false;\n this.rebuildFlatList();\n this.render();\n return;\n }\n if (key.name === \"escape\") {\n this.isSearching = false;\n this.searchInput = \"\";\n this.render();\n return;\n }\n if (key.name === \"backspace\") {\n this.searchInput = this.searchInput.slice(0, -1);\n this.render();\n return;\n }\n if (str && str.length === 1) {\n this.searchInput += str;\n this.render();\n return;\n }\n }\n\n // Navigation\n if (key.name === \"up\" || key.name === \"k\") {\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.render();\n }\n } else if (key.name === \"down\" || key.name === \"j\") {\n if (this.selectedIndex < this.flatList.length - 1) {\n this.selectedIndex++;\n this.render();\n }\n } else if (key.name === \"return\" || key.name === \"space\" || key.name === \"right\" || key.name === \"left\") {\n const item = this.flatList[this.selectedIndex];\n if (item && item.node.children && item.node.children.length > 0) {\n item.node.collapsed = !item.node.collapsed;\n this.rebuildFlatList();\n this.render();\n }\n } else if (str === \"e\" || str === \"E\") {\n this.expandAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"c\" || str === \"C\") {\n this.collapseAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"p\" || str === \"P\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n await copyToClipboard(item.node.path);\n this.setNotification(`✔ Copied JSONPath: ${item.node.path}`);\n }\n } else if (str === \"y\" || str === \"Y\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n const val = \"value\" in item.node ? item.node.value : (item.node as DiffNode).newValue;\n const textToCopy = typeof val === \"object\" ? JSON.stringify(val, null, 2) : String(val);\n await copyToClipboard(textToCopy);\n this.setNotification(`✔ Copied value to clipboard!`);\n }\n } else if (str === \"/\") {\n this.isSearching = true;\n this.searchInput = \"\";\n this.render();\n } else if (key.ctrl && key.name === \"c\" || key.name === \"escape\" || str === \"q\" || str === \"Q\") {\n // Cleanup & Exit\n process.stdin.removeListener(\"keypress\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n process.stdout.write(\"\\x1b[?25h\\n\"); // show cursor\n resolve();\n }\n };\n\n process.stdin.on(\"keypress\", onKeypress);\n });\n }\n}\n","import { exec } from \"child_process\";\nimport os from \"os\";\n\n/**\n * Copy text to system clipboard across macOS, Linux, and Windows.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const platform = os.platform();\n\n return new Promise((resolve) => {\n let proc;\n if (platform === \"darwin\") {\n proc = exec(\"pbcopy\", (err) => resolve(!err));\n } else if (platform === \"win32\") {\n proc = exec(\"clip\", (err) => resolve(!err));\n } else {\n // Linux: Try wl-copy then xclip\n proc = exec(\"wl-copy 2>/dev/null || xclip -selection clipboard 2>/dev/null || xsel --clipboard --input\", (err) => {\n resolve(!err);\n });\n }\n\n if (proc.stdin) {\n proc.stdin.write(text);\n proc.stdin.end();\n } else {\n resolve(false);\n }\n });\n}\n"],"mappings":"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","names":["pc","import_picocolors","pc","import_picocolors","os","pc","readline"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/formatter.ts","../src/differ.ts","../src/interactive.ts","../src/utils/clipboard.ts"],"sourcesContent":["export * from \"./types.js\";\nexport * from \"./formatter.js\";\nexport * from \"./differ.js\";\nexport * from \"./interactive.js\";\nexport * from \"./utils/clipboard.js\";\n","import pc from \"picocolors\";\nimport { JSONValueType, TreeNode } from \"./types.js\";\n\n/**\n * Determine the JSON value type.\n */\nexport function getValueType(value: any): JSONValueType {\n if (value === null || value === undefined) return \"null\";\n if (Array.isArray(value)) return \"array\";\n const t = typeof value;\n if (t === \"object\") return \"object\";\n if (t === \"string\") return \"string\";\n if (t === \"number\") return \"number\";\n if (t === \"boolean\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Colorize and format a single JSON value according to its type.\n */\nexport function formatValue(value: any, truncateLen = 80): string {\n const type = getValueType(value);\n\n switch (type) {\n case \"string\": {\n const str = JSON.stringify(value);\n const truncated = str.length > truncateLen ? str.slice(0, truncateLen - 3) + '...\"' : str;\n return pc.green(truncated);\n }\n case \"number\":\n return pc.yellow(String(value));\n case \"boolean\":\n return pc.magenta(String(value));\n case \"null\":\n return pc.dim(\"null\");\n case \"array\":\n return pc.dim(`[${value.length} items]`);\n case \"object\":\n return pc.dim(`{${Object.keys(value).length} keys}`);\n default:\n return String(value);\n }\n}\n\n/**\n * Format an object key with bold coloring.\n */\nexport function formatKey(key: string): string {\n return pc.bold(pc.cyan(key));\n}\n\n/**\n * Build a flat or nested TreeNode hierarchy from any JavaScript/JSON data.\n */\nexport function buildTree(\n data: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 2,\n parentId?: string\n): TreeNode {\n const type = getValueType(data);\n const id = `${path}-${key || \"root\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n const node: TreeNode = {\n id,\n key,\n value: data,\n type,\n depth,\n path,\n collapsed,\n parentId,\n };\n\n if (type === \"object\" && data !== null) {\n const keys = Object.keys(data);\n node.itemCount = keys.length;\n node.children = keys.map((k) =>\n buildTree(\n data[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n } else if (type === \"array\") {\n node.itemCount = data.length;\n node.children = data.map((item: any, idx: number) =>\n buildTree(\n item,\n `[${idx}]`,\n `${path}[${idx}]`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n }\n\n return node;\n}\n\n/**\n * Pretty-print JSON tree structure to terminal string.\n */\nexport function prettyPrintTree(node: TreeNode, indent = \"\", isLast = true): string {\n const isRoot = node.depth === 0;\n const marker = node.type === \"object\" || node.type === \"array\" ? (node.collapsed ? pc.cyan(\"▶ \") : pc.cyan(\"▼ \")) : pc.dim(\"• \");\n\n let line = \"\";\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch) + marker;\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += marker + (node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(pc.white(\"root: \")));\n }\n\n if (node.type === \"object\") {\n line += pc.dim(`{ ${node.itemCount} keys }`);\n } else if (node.type === \"array\") {\n line += pc.dim(`[ ${node.itemCount} items ]`);\n } else {\n line += formatValue(node.value);\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n lines.push(prettyPrintTree(child, nextIndent, childIsLast));\n });\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Colorize and format standard JSON structure with bold keys and typed syntax highlighting.\n */\nexport function colorizeJSON(data: any, space = 2): string {\n const jsonStr = typeof data === \"string\" ? data : JSON.stringify(data, null, space);\n if (!jsonStr) return \"\";\n\n return jsonStr.replace(\n /(\"(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)/g,\n (match) => {\n // Object key with trailing colon\n if (/^\"/.test(match)) {\n if (/:$/.test(match)) {\n const keyName = match.slice(0, -1);\n return pc.bold(pc.cyan(keyName)) + pc.dim(\":\");\n }\n // String value\n return pc.green(match);\n }\n // Boolean value\n if (/true|false/.test(match)) {\n return pc.magenta(match);\n }\n // Null value\n if (/null/.test(match)) {\n return pc.dim(match);\n }\n // Number value\n return pc.yellow(match);\n }\n );\n}\n\n","import pc from \"picocolors\";\nimport { DiffNode, DiffStatus, JSONValueType } from \"./types.js\";\nimport { getValueType, formatValue, formatKey } from \"./formatter.js\";\n\nexport interface DiffStats {\n added: number;\n removed: number;\n modified: number;\n unchanged: number;\n}\n\n/**\n * Compare two JSON values structurally and return a recursive DiffNode tree.\n */\nexport function diffJSON(\n a: any,\n b: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 3\n): DiffNode {\n const typeA = getValueType(a);\n const typeB = getValueType(b);\n const id = `${path}-${key || \"diff\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n // Case 1: Value added (a is undefined, b exists)\n if (a === undefined && b !== undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"added\",\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n if (typeB === \"object\" && b !== null) {\n node.itemCount = Object.keys(b).length;\n node.children = Object.keys(b).map((k) =>\n diffJSON(undefined, b[k], k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeB === \"array\") {\n node.itemCount = b.length;\n node.children = b.map((item: any, idx: number) =>\n diffJSON(undefined, item, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 2: Value removed (a exists, b is undefined)\n if (a !== undefined && b === undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"removed\",\n oldValue: a,\n type: typeA,\n collapsed: false,\n };\n if (typeA === \"object\" && a !== null) {\n node.itemCount = Object.keys(a).length;\n node.children = Object.keys(a).map((k) =>\n diffJSON(a[k], undefined, k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeA === \"array\") {\n node.itemCount = a.length;\n node.children = a.map((item: any, idx: number) =>\n diffJSON(item, undefined, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 3: Type changed (e.g. from string to number or object to array)\n if (typeA !== typeB) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Case 4: Both are Objects\n if (typeA === \"object\" && a !== null && b !== null) {\n const allKeys = Array.from(new Set([...Object.keys(a), ...Object.keys(b)]));\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (const k of allKeys) {\n const child = diffJSON(\n a[k],\n b[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"object\",\n itemCount: allKeys.length,\n collapsed,\n children,\n };\n }\n\n // Case 5: Both are Arrays\n if (typeA === \"array\") {\n const maxLen = Math.max(a.length, b.length);\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (let i = 0; i < maxLen; i++) {\n const child = diffJSON(\n a[i],\n b[i],\n `[${i}]`,\n `${path}[${i}]`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"array\",\n itemCount: maxLen,\n collapsed,\n children,\n };\n }\n\n // Case 6: Primitive values comparison\n if (a !== b) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Unchanged primitive\n return {\n id,\n key,\n path,\n depth,\n status: \"unchanged\",\n oldValue: a,\n newValue: b,\n type: typeA,\n collapsed,\n };\n}\n\n/**\n * Calculate summary metrics for the diff.\n */\nexport function calculateDiffStats(node: DiffNode): DiffStats {\n const stats: DiffStats = { added: 0, removed: 0, modified: 0, unchanged: 0 };\n\n function traverse(n: DiffNode) {\n if (n.children && n.children.length > 0) {\n n.children.forEach(traverse);\n } else {\n stats[n.status]++;\n }\n }\n\n traverse(node);\n return stats;\n}\n\n/**\n * Pretty-print structural diff to terminal string.\n */\nexport function prettyPrintDiff(\n node: DiffNode,\n options: { showUnchanged?: boolean } = {},\n indent = \"\",\n isLast = true\n): string {\n const showUnchanged = options.showUnchanged ?? true;\n\n if (!showUnchanged && node.status === \"unchanged\" && (!node.children || node.children.length === 0)) {\n return \"\";\n }\n\n const isRoot = node.depth === 0;\n let prefix = \" \";\n let statusColor = pc.dim;\n\n if (node.status === \"added\") {\n prefix = pc.green(\"+ \");\n statusColor = pc.green;\n } else if (node.status === \"removed\") {\n prefix = pc.red(\"- \");\n statusColor = pc.red;\n } else if (node.status === \"modified\") {\n prefix = pc.yellow(\"~ \");\n statusColor = pc.yellow;\n }\n\n let line = prefix;\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch);\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(\"diff: \");\n }\n\n if (node.status === \"added\") {\n line += statusColor(formatValue(node.newValue));\n } else if (node.status === \"removed\") {\n line += statusColor(formatValue(node.oldValue));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n line += statusColor(`{ ${node.itemCount} items modified }`);\n } else {\n line += `${pc.red(formatValue(node.oldValue))} ${pc.dim(\"->\")} ${pc.green(formatValue(node.newValue))}`;\n }\n } else {\n // Unchanged\n line += pc.dim(formatValue(node.newValue));\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n const childStr = prettyPrintDiff(child, options, nextIndent, childIsLast);\n if (childStr) lines.push(childStr);\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import readline from \"readline\";\nimport pc from \"picocolors\";\nimport { TreeNode, DiffNode } from \"./types.js\";\nimport { formatKey, formatValue } from \"./formatter.js\";\nimport { copyToClipboard } from \"./utils/clipboard.js\";\n\ntype AnyNode = TreeNode | DiffNode;\n\ninterface FlatItem {\n node: AnyNode;\n depth: number;\n isDiff: boolean;\n}\n\n/**\n * Interactive Terminal Tree Explorer for JSON data and Diffs.\n */\nexport class InteractiveViewer {\n private root: AnyNode;\n private flatList: FlatItem[] = [];\n private selectedIndex = 0;\n private searchQuery = \"\";\n private isSearching = false;\n private searchInput = \"\";\n private notification = \"\";\n private notificationTimer: NodeJS.Timeout | null = null;\n private isDiff: boolean;\n\n constructor(root: AnyNode, isDiff = false) {\n this.root = root;\n this.isDiff = isDiff;\n this.rebuildFlatList();\n }\n\n private isDiffNode(node: AnyNode): node is DiffNode {\n return this.isDiff && \"status\" in node;\n }\n\n private rebuildFlatList(): void {\n const list: FlatItem[] = [];\n\n const traverse = (node: AnyNode, currentDepth: number) => {\n // If search query is active, filter matching nodes or their parents\n if (this.searchQuery) {\n const query = this.searchQuery.toLowerCase();\n const keyMatch = node.key && node.key.toLowerCase().includes(query);\n const pathMatch = node.path && node.path.toLowerCase().includes(query);\n const valMatch =\n \"value\" in node\n ? JSON.stringify(node.value).toLowerCase().includes(query)\n : \"newValue\" in node\n ? JSON.stringify(node.newValue).toLowerCase().includes(query)\n : false;\n\n if (!keyMatch && !pathMatch && !valMatch && (!node.children || node.children.length === 0)) {\n return;\n }\n }\n\n list.push({ node, depth: currentDepth, isDiff: this.isDiff });\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n for (const child of node.children) {\n traverse(child, currentDepth + 1);\n }\n }\n };\n\n traverse(this.root, 0);\n this.flatList = list;\n\n if (this.selectedIndex >= this.flatList.length) {\n this.selectedIndex = Math.max(0, this.flatList.length - 1);\n }\n }\n\n private setNotification(msg: string): void {\n this.notification = msg;\n if (this.notificationTimer) clearTimeout(this.notificationTimer);\n this.notificationTimer = setTimeout(() => {\n this.notification = \"\";\n this.render();\n }, 2500);\n }\n\n private render(): void {\n const rows = process.stdout.rows || 24;\n const maxVisibleRows = Math.max(5, rows - 5);\n\n // Calculate window scroll offset\n let startIdx = 0;\n if (this.selectedIndex >= maxVisibleRows) {\n startIdx = this.selectedIndex - maxVisibleRows + 1;\n }\n const endIdx = Math.min(this.flatList.length, startIdx + maxVisibleRows);\n\n // Clear terminal screen\n process.stdout.write(\"\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25l\"); // hide cursor\n\n // 1. Header Bar\n const title = this.isDiff ? \" JSON Structural Diff Explorer \" : \" Interactive JSON Tree Explorer \";\n console.log(pc.bgCyan(pc.black(pc.bold(` ${title} `)) + pc.dim(` [Total items: ${this.flatList.length}]`)));\n\n // 2. Render visible items\n for (let i = startIdx; i < endIdx; i++) {\n const { node, depth } = this.flatList[i];\n const isSelected = i === this.selectedIndex;\n const indent = \" \".repeat(depth);\n\n let marker = \"• \";\n if (node.children && node.children.length > 0) {\n marker = node.collapsed ? \"▶ \" : \"▼ \";\n }\n\n let lineContent = \"\";\n\n if (this.isDiffNode(node)) {\n let diffPrefix = \" \";\n if (node.status === \"added\") diffPrefix = pc.green(\"+ \");\n else if (node.status === \"removed\") diffPrefix = pc.red(\"- \");\n else if (node.status === \"modified\") diffPrefix = pc.yellow(\"~ \");\n\n lineContent = diffPrefix + indent + marker;\n if (node.key) lineContent += formatKey(node.key) + pc.dim(\": \");\n\n if (node.status === \"added\") {\n lineContent += pc.green(formatValue(node.newValue, 50));\n } else if (node.status === \"removed\") {\n lineContent += pc.red(formatValue(node.oldValue, 50));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n lineContent += pc.yellow(`{ ${node.itemCount} modified }`);\n } else {\n lineContent += `${pc.red(formatValue(node.oldValue, 25))} -> ${pc.green(formatValue(node.newValue, 25))}`;\n }\n } else {\n lineContent += pc.dim(formatValue(node.newValue, 50));\n }\n } else {\n const treeNode = node as TreeNode;\n lineContent = indent + marker;\n if (treeNode.key) lineContent += formatKey(treeNode.key) + pc.dim(\": \");\n\n if (treeNode.type === \"object\") {\n lineContent += pc.dim(`{ ${treeNode.itemCount} keys }`);\n } else if (treeNode.type === \"array\") {\n lineContent += pc.dim(`[ ${treeNode.itemCount} items ]`);\n } else {\n lineContent += formatValue(treeNode.value, 60);\n }\n }\n\n if (isSelected) {\n console.log(pc.bgBlue(pc.white(pc.bold(`> ${lineContent}`))));\n } else {\n console.log(` ${lineContent}`);\n }\n }\n\n // 3. Status Bar & Footer\n const selectedItem = this.flatList[this.selectedIndex];\n const currentPath = selectedItem ? selectedItem.node.path : \"$\";\n\n console.log(\"\\n\" + pc.dim(\"─\".repeat(Math.min(process.stdout.columns || 80, 80))));\n if (this.notification) {\n console.log(pc.green(pc.bold(` ${this.notification}`)));\n } else if (this.isSearching) {\n console.log(pc.yellow(pc.bold(` Search: /${this.searchInput}█`)));\n } else {\n console.log(pc.bold(pc.cyan(` Path: ${currentPath}`)));\n console.log(\n pc.dim(\" [↑/↓] Move [Enter/Space] Toggle [e] Expand All [c] Collapse All [p] Copy Path [y] Copy Val [/] Search [q] Exit\")\n );\n }\n }\n\n private expandAll(node: AnyNode): void {\n node.collapsed = false;\n if (node.children) node.children.forEach((c) => this.expandAll(c));\n }\n\n private collapseAll(node: AnyNode): void {\n if (node.depth > 0) node.collapsed = true;\n if (node.children) node.children.forEach((c) => this.collapseAll(c));\n }\n\n public async start(): Promise<void> {\n if (!process.stdin.isTTY) {\n return;\n }\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n this.render();\n\n return new Promise((resolve) => {\n const onKeypress = async (str: string, key: readline.Key) => {\n if (this.isSearching) {\n if (key.name === \"return\") {\n this.searchQuery = this.searchInput;\n this.isSearching = false;\n this.rebuildFlatList();\n this.render();\n return;\n }\n if (key.name === \"escape\") {\n this.isSearching = false;\n this.searchInput = \"\";\n this.render();\n return;\n }\n if (key.name === \"backspace\") {\n this.searchInput = this.searchInput.slice(0, -1);\n this.render();\n return;\n }\n if (str && str.length === 1) {\n this.searchInput += str;\n this.render();\n return;\n }\n }\n\n // Navigation\n if (key.name === \"up\" || key.name === \"k\") {\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.render();\n }\n } else if (key.name === \"down\" || key.name === \"j\") {\n if (this.selectedIndex < this.flatList.length - 1) {\n this.selectedIndex++;\n this.render();\n }\n } else if (key.name === \"return\" || key.name === \"space\" || key.name === \"right\" || key.name === \"left\") {\n const item = this.flatList[this.selectedIndex];\n if (item && item.node.children && item.node.children.length > 0) {\n item.node.collapsed = !item.node.collapsed;\n this.rebuildFlatList();\n this.render();\n }\n } else if (str === \"e\" || str === \"E\") {\n this.expandAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"c\" || str === \"C\") {\n this.collapseAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"p\" || str === \"P\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n await copyToClipboard(item.node.path);\n this.setNotification(`✔ Copied JSONPath: ${item.node.path}`);\n }\n } else if (str === \"y\" || str === \"Y\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n const val = \"value\" in item.node ? item.node.value : (item.node as DiffNode).newValue;\n const textToCopy = typeof val === \"object\" ? JSON.stringify(val, null, 2) : String(val);\n await copyToClipboard(textToCopy);\n this.setNotification(`✔ Copied value to clipboard!`);\n }\n } else if (str === \"/\") {\n this.isSearching = true;\n this.searchInput = \"\";\n this.render();\n } else if (key.ctrl && key.name === \"c\" || key.name === \"escape\" || str === \"q\" || str === \"Q\") {\n // Cleanup & Exit\n process.stdin.removeListener(\"keypress\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n process.stdout.write(\"\\x1b[?25h\\n\"); // show cursor\n resolve();\n }\n };\n\n process.stdin.on(\"keypress\", onKeypress);\n });\n }\n}\n","import { exec } from \"child_process\";\nimport os from \"os\";\n\n/**\n * Copy text to system clipboard across macOS, Linux, and Windows.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const platform = os.platform();\n\n return new Promise((resolve) => {\n let proc;\n if (platform === \"darwin\") {\n proc = exec(\"pbcopy\", (err) => resolve(!err));\n } else if (platform === \"win32\") {\n proc = exec(\"clip\", (err) => resolve(!err));\n } else {\n // Linux: Try wl-copy then xclip\n proc = exec(\"wl-copy 2>/dev/null || xclip -selection clipboard 2>/dev/null || xsel --clipboard --input\", (err) => {\n resolve(!err);\n });\n }\n\n if (proc.stdin) {\n proc.stdin.write(text);\n proc.stdin.end();\n } else {\n resolve(false);\n }\n });\n}\n"],"mappings":"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","names":["pc","import_picocolors","pc","import_picocolors","os","pc","readline"]}
package/dist/index.mjs CHANGED
@@ -107,6 +107,29 @@ function prettyPrintTree(node, indent = "", isLast = true) {
107
107
  }
108
108
  return lines.join("\n");
109
109
  }
110
+ function colorizeJSON(data, space = 2) {
111
+ const jsonStr = typeof data === "string" ? data : JSON.stringify(data, null, space);
112
+ if (!jsonStr) return "";
113
+ return jsonStr.replace(
114
+ /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
115
+ (match) => {
116
+ if (/^"/.test(match)) {
117
+ if (/:$/.test(match)) {
118
+ const keyName = match.slice(0, -1);
119
+ return pc.bold(pc.cyan(keyName)) + pc.dim(":");
120
+ }
121
+ return pc.green(match);
122
+ }
123
+ if (/true|false/.test(match)) {
124
+ return pc.magenta(match);
125
+ }
126
+ if (/null/.test(match)) {
127
+ return pc.dim(match);
128
+ }
129
+ return pc.yellow(match);
130
+ }
131
+ );
132
+ }
110
133
 
111
134
  // src/differ.ts
112
135
  import pc2 from "picocolors";
@@ -581,6 +604,7 @@ export {
581
604
  InteractiveViewer,
582
605
  buildTree,
583
606
  calculateDiffStats,
607
+ colorizeJSON,
584
608
  copyToClipboard,
585
609
  diffJSON,
586
610
  formatKey,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/formatter.ts","../src/differ.ts","../src/interactive.ts","../src/utils/clipboard.ts"],"sourcesContent":["import pc from \"picocolors\";\nimport { JSONValueType, TreeNode } from \"./types.js\";\n\n/**\n * Determine the JSON value type.\n */\nexport function getValueType(value: any): JSONValueType {\n if (value === null || value === undefined) return \"null\";\n if (Array.isArray(value)) return \"array\";\n const t = typeof value;\n if (t === \"object\") return \"object\";\n if (t === \"string\") return \"string\";\n if (t === \"number\") return \"number\";\n if (t === \"boolean\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Colorize and format a single JSON value according to its type.\n */\nexport function formatValue(value: any, truncateLen = 80): string {\n const type = getValueType(value);\n\n switch (type) {\n case \"string\": {\n const str = JSON.stringify(value);\n const truncated = str.length > truncateLen ? str.slice(0, truncateLen - 3) + '...\"' : str;\n return pc.green(truncated);\n }\n case \"number\":\n return pc.yellow(String(value));\n case \"boolean\":\n return pc.magenta(String(value));\n case \"null\":\n return pc.dim(\"null\");\n case \"array\":\n return pc.dim(`[${value.length} items]`);\n case \"object\":\n return pc.dim(`{${Object.keys(value).length} keys}`);\n default:\n return String(value);\n }\n}\n\n/**\n * Format an object key with bold coloring.\n */\nexport function formatKey(key: string): string {\n return pc.bold(pc.cyan(key));\n}\n\n/**\n * Build a flat or nested TreeNode hierarchy from any JavaScript/JSON data.\n */\nexport function buildTree(\n data: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 2,\n parentId?: string\n): TreeNode {\n const type = getValueType(data);\n const id = `${path}-${key || \"root\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n const node: TreeNode = {\n id,\n key,\n value: data,\n type,\n depth,\n path,\n collapsed,\n parentId,\n };\n\n if (type === \"object\" && data !== null) {\n const keys = Object.keys(data);\n node.itemCount = keys.length;\n node.children = keys.map((k) =>\n buildTree(\n data[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n } else if (type === \"array\") {\n node.itemCount = data.length;\n node.children = data.map((item: any, idx: number) =>\n buildTree(\n item,\n `[${idx}]`,\n `${path}[${idx}]`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n }\n\n return node;\n}\n\n/**\n * Pretty-print JSON tree structure to terminal string.\n */\nexport function prettyPrintTree(node: TreeNode, indent = \"\", isLast = true): string {\n const isRoot = node.depth === 0;\n const marker = node.type === \"object\" || node.type === \"array\" ? (node.collapsed ? pc.cyan(\"▶ \") : pc.cyan(\"▼ \")) : pc.dim(\"• \");\n\n let line = \"\";\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch) + marker;\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += marker + (node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(pc.white(\"root: \")));\n }\n\n if (node.type === \"object\") {\n line += pc.dim(`{ ${node.itemCount} keys }`);\n } else if (node.type === \"array\") {\n line += pc.dim(`[ ${node.itemCount} items ]`);\n } else {\n line += formatValue(node.value);\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n lines.push(prettyPrintTree(child, nextIndent, childIsLast));\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import pc from \"picocolors\";\nimport { DiffNode, DiffStatus, JSONValueType } from \"./types.js\";\nimport { getValueType, formatValue, formatKey } from \"./formatter.js\";\n\nexport interface DiffStats {\n added: number;\n removed: number;\n modified: number;\n unchanged: number;\n}\n\n/**\n * Compare two JSON values structurally and return a recursive DiffNode tree.\n */\nexport function diffJSON(\n a: any,\n b: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 3\n): DiffNode {\n const typeA = getValueType(a);\n const typeB = getValueType(b);\n const id = `${path}-${key || \"diff\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n // Case 1: Value added (a is undefined, b exists)\n if (a === undefined && b !== undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"added\",\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n if (typeB === \"object\" && b !== null) {\n node.itemCount = Object.keys(b).length;\n node.children = Object.keys(b).map((k) =>\n diffJSON(undefined, b[k], k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeB === \"array\") {\n node.itemCount = b.length;\n node.children = b.map((item: any, idx: number) =>\n diffJSON(undefined, item, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 2: Value removed (a exists, b is undefined)\n if (a !== undefined && b === undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"removed\",\n oldValue: a,\n type: typeA,\n collapsed: false,\n };\n if (typeA === \"object\" && a !== null) {\n node.itemCount = Object.keys(a).length;\n node.children = Object.keys(a).map((k) =>\n diffJSON(a[k], undefined, k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeA === \"array\") {\n node.itemCount = a.length;\n node.children = a.map((item: any, idx: number) =>\n diffJSON(item, undefined, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 3: Type changed (e.g. from string to number or object to array)\n if (typeA !== typeB) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Case 4: Both are Objects\n if (typeA === \"object\" && a !== null && b !== null) {\n const allKeys = Array.from(new Set([...Object.keys(a), ...Object.keys(b)]));\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (const k of allKeys) {\n const child = diffJSON(\n a[k],\n b[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"object\",\n itemCount: allKeys.length,\n collapsed,\n children,\n };\n }\n\n // Case 5: Both are Arrays\n if (typeA === \"array\") {\n const maxLen = Math.max(a.length, b.length);\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (let i = 0; i < maxLen; i++) {\n const child = diffJSON(\n a[i],\n b[i],\n `[${i}]`,\n `${path}[${i}]`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"array\",\n itemCount: maxLen,\n collapsed,\n children,\n };\n }\n\n // Case 6: Primitive values comparison\n if (a !== b) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Unchanged primitive\n return {\n id,\n key,\n path,\n depth,\n status: \"unchanged\",\n oldValue: a,\n newValue: b,\n type: typeA,\n collapsed,\n };\n}\n\n/**\n * Calculate summary metrics for the diff.\n */\nexport function calculateDiffStats(node: DiffNode): DiffStats {\n const stats: DiffStats = { added: 0, removed: 0, modified: 0, unchanged: 0 };\n\n function traverse(n: DiffNode) {\n if (n.children && n.children.length > 0) {\n n.children.forEach(traverse);\n } else {\n stats[n.status]++;\n }\n }\n\n traverse(node);\n return stats;\n}\n\n/**\n * Pretty-print structural diff to terminal string.\n */\nexport function prettyPrintDiff(\n node: DiffNode,\n options: { showUnchanged?: boolean } = {},\n indent = \"\",\n isLast = true\n): string {\n const showUnchanged = options.showUnchanged ?? true;\n\n if (!showUnchanged && node.status === \"unchanged\" && (!node.children || node.children.length === 0)) {\n return \"\";\n }\n\n const isRoot = node.depth === 0;\n let prefix = \" \";\n let statusColor = pc.dim;\n\n if (node.status === \"added\") {\n prefix = pc.green(\"+ \");\n statusColor = pc.green;\n } else if (node.status === \"removed\") {\n prefix = pc.red(\"- \");\n statusColor = pc.red;\n } else if (node.status === \"modified\") {\n prefix = pc.yellow(\"~ \");\n statusColor = pc.yellow;\n }\n\n let line = prefix;\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch);\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(\"diff: \");\n }\n\n if (node.status === \"added\") {\n line += statusColor(formatValue(node.newValue));\n } else if (node.status === \"removed\") {\n line += statusColor(formatValue(node.oldValue));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n line += statusColor(`{ ${node.itemCount} items modified }`);\n } else {\n line += `${pc.red(formatValue(node.oldValue))} ${pc.dim(\"->\")} ${pc.green(formatValue(node.newValue))}`;\n }\n } else {\n // Unchanged\n line += pc.dim(formatValue(node.newValue));\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n const childStr = prettyPrintDiff(child, options, nextIndent, childIsLast);\n if (childStr) lines.push(childStr);\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import readline from \"readline\";\nimport pc from \"picocolors\";\nimport { TreeNode, DiffNode } from \"./types.js\";\nimport { formatKey, formatValue } from \"./formatter.js\";\nimport { copyToClipboard } from \"./utils/clipboard.js\";\n\ntype AnyNode = TreeNode | DiffNode;\n\ninterface FlatItem {\n node: AnyNode;\n depth: number;\n isDiff: boolean;\n}\n\n/**\n * Interactive Terminal Tree Explorer for JSON data and Diffs.\n */\nexport class InteractiveViewer {\n private root: AnyNode;\n private flatList: FlatItem[] = [];\n private selectedIndex = 0;\n private searchQuery = \"\";\n private isSearching = false;\n private searchInput = \"\";\n private notification = \"\";\n private notificationTimer: NodeJS.Timeout | null = null;\n private isDiff: boolean;\n\n constructor(root: AnyNode, isDiff = false) {\n this.root = root;\n this.isDiff = isDiff;\n this.rebuildFlatList();\n }\n\n private isDiffNode(node: AnyNode): node is DiffNode {\n return this.isDiff && \"status\" in node;\n }\n\n private rebuildFlatList(): void {\n const list: FlatItem[] = [];\n\n const traverse = (node: AnyNode, currentDepth: number) => {\n // If search query is active, filter matching nodes or their parents\n if (this.searchQuery) {\n const query = this.searchQuery.toLowerCase();\n const keyMatch = node.key && node.key.toLowerCase().includes(query);\n const pathMatch = node.path && node.path.toLowerCase().includes(query);\n const valMatch =\n \"value\" in node\n ? JSON.stringify(node.value).toLowerCase().includes(query)\n : \"newValue\" in node\n ? JSON.stringify(node.newValue).toLowerCase().includes(query)\n : false;\n\n if (!keyMatch && !pathMatch && !valMatch && (!node.children || node.children.length === 0)) {\n return;\n }\n }\n\n list.push({ node, depth: currentDepth, isDiff: this.isDiff });\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n for (const child of node.children) {\n traverse(child, currentDepth + 1);\n }\n }\n };\n\n traverse(this.root, 0);\n this.flatList = list;\n\n if (this.selectedIndex >= this.flatList.length) {\n this.selectedIndex = Math.max(0, this.flatList.length - 1);\n }\n }\n\n private setNotification(msg: string): void {\n this.notification = msg;\n if (this.notificationTimer) clearTimeout(this.notificationTimer);\n this.notificationTimer = setTimeout(() => {\n this.notification = \"\";\n this.render();\n }, 2500);\n }\n\n private render(): void {\n const rows = process.stdout.rows || 24;\n const maxVisibleRows = Math.max(5, rows - 5);\n\n // Calculate window scroll offset\n let startIdx = 0;\n if (this.selectedIndex >= maxVisibleRows) {\n startIdx = this.selectedIndex - maxVisibleRows + 1;\n }\n const endIdx = Math.min(this.flatList.length, startIdx + maxVisibleRows);\n\n // Clear terminal screen\n process.stdout.write(\"\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25l\"); // hide cursor\n\n // 1. Header Bar\n const title = this.isDiff ? \" JSON Structural Diff Explorer \" : \" Interactive JSON Tree Explorer \";\n console.log(pc.bgCyan(pc.black(pc.bold(` ${title} `)) + pc.dim(` [Total items: ${this.flatList.length}]`)));\n\n // 2. Render visible items\n for (let i = startIdx; i < endIdx; i++) {\n const { node, depth } = this.flatList[i];\n const isSelected = i === this.selectedIndex;\n const indent = \" \".repeat(depth);\n\n let marker = \"• \";\n if (node.children && node.children.length > 0) {\n marker = node.collapsed ? \"▶ \" : \"▼ \";\n }\n\n let lineContent = \"\";\n\n if (this.isDiffNode(node)) {\n let diffPrefix = \" \";\n if (node.status === \"added\") diffPrefix = pc.green(\"+ \");\n else if (node.status === \"removed\") diffPrefix = pc.red(\"- \");\n else if (node.status === \"modified\") diffPrefix = pc.yellow(\"~ \");\n\n lineContent = diffPrefix + indent + marker;\n if (node.key) lineContent += formatKey(node.key) + pc.dim(\": \");\n\n if (node.status === \"added\") {\n lineContent += pc.green(formatValue(node.newValue, 50));\n } else if (node.status === \"removed\") {\n lineContent += pc.red(formatValue(node.oldValue, 50));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n lineContent += pc.yellow(`{ ${node.itemCount} modified }`);\n } else {\n lineContent += `${pc.red(formatValue(node.oldValue, 25))} -> ${pc.green(formatValue(node.newValue, 25))}`;\n }\n } else {\n lineContent += pc.dim(formatValue(node.newValue, 50));\n }\n } else {\n const treeNode = node as TreeNode;\n lineContent = indent + marker;\n if (treeNode.key) lineContent += formatKey(treeNode.key) + pc.dim(\": \");\n\n if (treeNode.type === \"object\") {\n lineContent += pc.dim(`{ ${treeNode.itemCount} keys }`);\n } else if (treeNode.type === \"array\") {\n lineContent += pc.dim(`[ ${treeNode.itemCount} items ]`);\n } else {\n lineContent += formatValue(treeNode.value, 60);\n }\n }\n\n if (isSelected) {\n console.log(pc.bgBlue(pc.white(pc.bold(`> ${lineContent}`))));\n } else {\n console.log(` ${lineContent}`);\n }\n }\n\n // 3. Status Bar & Footer\n const selectedItem = this.flatList[this.selectedIndex];\n const currentPath = selectedItem ? selectedItem.node.path : \"$\";\n\n console.log(\"\\n\" + pc.dim(\"─\".repeat(Math.min(process.stdout.columns || 80, 80))));\n if (this.notification) {\n console.log(pc.green(pc.bold(` ${this.notification}`)));\n } else if (this.isSearching) {\n console.log(pc.yellow(pc.bold(` Search: /${this.searchInput}█`)));\n } else {\n console.log(pc.bold(pc.cyan(` Path: ${currentPath}`)));\n console.log(\n pc.dim(\" [↑/↓] Move [Enter/Space] Toggle [e] Expand All [c] Collapse All [p] Copy Path [y] Copy Val [/] Search [q] Exit\")\n );\n }\n }\n\n private expandAll(node: AnyNode): void {\n node.collapsed = false;\n if (node.children) node.children.forEach((c) => this.expandAll(c));\n }\n\n private collapseAll(node: AnyNode): void {\n if (node.depth > 0) node.collapsed = true;\n if (node.children) node.children.forEach((c) => this.collapseAll(c));\n }\n\n public async start(): Promise<void> {\n if (!process.stdin.isTTY) {\n return;\n }\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n this.render();\n\n return new Promise((resolve) => {\n const onKeypress = async (str: string, key: readline.Key) => {\n if (this.isSearching) {\n if (key.name === \"return\") {\n this.searchQuery = this.searchInput;\n this.isSearching = false;\n this.rebuildFlatList();\n this.render();\n return;\n }\n if (key.name === \"escape\") {\n this.isSearching = false;\n this.searchInput = \"\";\n this.render();\n return;\n }\n if (key.name === \"backspace\") {\n this.searchInput = this.searchInput.slice(0, -1);\n this.render();\n return;\n }\n if (str && str.length === 1) {\n this.searchInput += str;\n this.render();\n return;\n }\n }\n\n // Navigation\n if (key.name === \"up\" || key.name === \"k\") {\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.render();\n }\n } else if (key.name === \"down\" || key.name === \"j\") {\n if (this.selectedIndex < this.flatList.length - 1) {\n this.selectedIndex++;\n this.render();\n }\n } else if (key.name === \"return\" || key.name === \"space\" || key.name === \"right\" || key.name === \"left\") {\n const item = this.flatList[this.selectedIndex];\n if (item && item.node.children && item.node.children.length > 0) {\n item.node.collapsed = !item.node.collapsed;\n this.rebuildFlatList();\n this.render();\n }\n } else if (str === \"e\" || str === \"E\") {\n this.expandAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"c\" || str === \"C\") {\n this.collapseAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"p\" || str === \"P\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n await copyToClipboard(item.node.path);\n this.setNotification(`✔ Copied JSONPath: ${item.node.path}`);\n }\n } else if (str === \"y\" || str === \"Y\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n const val = \"value\" in item.node ? item.node.value : (item.node as DiffNode).newValue;\n const textToCopy = typeof val === \"object\" ? JSON.stringify(val, null, 2) : String(val);\n await copyToClipboard(textToCopy);\n this.setNotification(`✔ Copied value to clipboard!`);\n }\n } else if (str === \"/\") {\n this.isSearching = true;\n this.searchInput = \"\";\n this.render();\n } else if (key.ctrl && key.name === \"c\" || key.name === \"escape\" || str === \"q\" || str === \"Q\") {\n // Cleanup & Exit\n process.stdin.removeListener(\"keypress\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n process.stdout.write(\"\\x1b[?25h\\n\"); // show cursor\n resolve();\n }\n };\n\n process.stdin.on(\"keypress\", onKeypress);\n });\n }\n}\n","import { exec } from \"child_process\";\nimport os from \"os\";\n\n/**\n * Copy text to system clipboard across macOS, Linux, and Windows.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const platform = os.platform();\n\n return new Promise((resolve) => {\n let proc;\n if (platform === \"darwin\") {\n proc = exec(\"pbcopy\", (err) => resolve(!err));\n } else if (platform === \"win32\") {\n proc = exec(\"clip\", (err) => resolve(!err));\n } else {\n // Linux: Try wl-copy then xclip\n proc = exec(\"wl-copy 2>/dev/null || xclip -selection clipboard 2>/dev/null || xsel --clipboard --input\", (err) => {\n resolve(!err);\n });\n }\n\n if (proc.stdin) {\n proc.stdin.write(text);\n proc.stdin.end();\n } else {\n resolve(false);\n }\n });\n}\n"],"mappings":"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","names":["pc","pc","pc","pc"]}
1
+ {"version":3,"sources":["../src/formatter.ts","../src/differ.ts","../src/interactive.ts","../src/utils/clipboard.ts"],"sourcesContent":["import pc from \"picocolors\";\nimport { JSONValueType, TreeNode } from \"./types.js\";\n\n/**\n * Determine the JSON value type.\n */\nexport function getValueType(value: any): JSONValueType {\n if (value === null || value === undefined) return \"null\";\n if (Array.isArray(value)) return \"array\";\n const t = typeof value;\n if (t === \"object\") return \"object\";\n if (t === \"string\") return \"string\";\n if (t === \"number\") return \"number\";\n if (t === \"boolean\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Colorize and format a single JSON value according to its type.\n */\nexport function formatValue(value: any, truncateLen = 80): string {\n const type = getValueType(value);\n\n switch (type) {\n case \"string\": {\n const str = JSON.stringify(value);\n const truncated = str.length > truncateLen ? str.slice(0, truncateLen - 3) + '...\"' : str;\n return pc.green(truncated);\n }\n case \"number\":\n return pc.yellow(String(value));\n case \"boolean\":\n return pc.magenta(String(value));\n case \"null\":\n return pc.dim(\"null\");\n case \"array\":\n return pc.dim(`[${value.length} items]`);\n case \"object\":\n return pc.dim(`{${Object.keys(value).length} keys}`);\n default:\n return String(value);\n }\n}\n\n/**\n * Format an object key with bold coloring.\n */\nexport function formatKey(key: string): string {\n return pc.bold(pc.cyan(key));\n}\n\n/**\n * Build a flat or nested TreeNode hierarchy from any JavaScript/JSON data.\n */\nexport function buildTree(\n data: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 2,\n parentId?: string\n): TreeNode {\n const type = getValueType(data);\n const id = `${path}-${key || \"root\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n const node: TreeNode = {\n id,\n key,\n value: data,\n type,\n depth,\n path,\n collapsed,\n parentId,\n };\n\n if (type === \"object\" && data !== null) {\n const keys = Object.keys(data);\n node.itemCount = keys.length;\n node.children = keys.map((k) =>\n buildTree(\n data[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n } else if (type === \"array\") {\n node.itemCount = data.length;\n node.children = data.map((item: any, idx: number) =>\n buildTree(\n item,\n `[${idx}]`,\n `${path}[${idx}]`,\n depth + 1,\n maxInitialDepth,\n id\n )\n );\n }\n\n return node;\n}\n\n/**\n * Pretty-print JSON tree structure to terminal string.\n */\nexport function prettyPrintTree(node: TreeNode, indent = \"\", isLast = true): string {\n const isRoot = node.depth === 0;\n const marker = node.type === \"object\" || node.type === \"array\" ? (node.collapsed ? pc.cyan(\"▶ \") : pc.cyan(\"▼ \")) : pc.dim(\"• \");\n\n let line = \"\";\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch) + marker;\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += marker + (node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(pc.white(\"root: \")));\n }\n\n if (node.type === \"object\") {\n line += pc.dim(`{ ${node.itemCount} keys }`);\n } else if (node.type === \"array\") {\n line += pc.dim(`[ ${node.itemCount} items ]`);\n } else {\n line += formatValue(node.value);\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n lines.push(prettyPrintTree(child, nextIndent, childIsLast));\n });\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Colorize and format standard JSON structure with bold keys and typed syntax highlighting.\n */\nexport function colorizeJSON(data: any, space = 2): string {\n const jsonStr = typeof data === \"string\" ? data : JSON.stringify(data, null, space);\n if (!jsonStr) return \"\";\n\n return jsonStr.replace(\n /(\"(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)/g,\n (match) => {\n // Object key with trailing colon\n if (/^\"/.test(match)) {\n if (/:$/.test(match)) {\n const keyName = match.slice(0, -1);\n return pc.bold(pc.cyan(keyName)) + pc.dim(\":\");\n }\n // String value\n return pc.green(match);\n }\n // Boolean value\n if (/true|false/.test(match)) {\n return pc.magenta(match);\n }\n // Null value\n if (/null/.test(match)) {\n return pc.dim(match);\n }\n // Number value\n return pc.yellow(match);\n }\n );\n}\n\n","import pc from \"picocolors\";\nimport { DiffNode, DiffStatus, JSONValueType } from \"./types.js\";\nimport { getValueType, formatValue, formatKey } from \"./formatter.js\";\n\nexport interface DiffStats {\n added: number;\n removed: number;\n modified: number;\n unchanged: number;\n}\n\n/**\n * Compare two JSON values structurally and return a recursive DiffNode tree.\n */\nexport function diffJSON(\n a: any,\n b: any,\n key?: string,\n path = \"$\",\n depth = 0,\n maxInitialDepth = 3\n): DiffNode {\n const typeA = getValueType(a);\n const typeB = getValueType(b);\n const id = `${path}-${key || \"diff\"}-${depth}`;\n const collapsed = depth >= maxInitialDepth;\n\n // Case 1: Value added (a is undefined, b exists)\n if (a === undefined && b !== undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"added\",\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n if (typeB === \"object\" && b !== null) {\n node.itemCount = Object.keys(b).length;\n node.children = Object.keys(b).map((k) =>\n diffJSON(undefined, b[k], k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeB === \"array\") {\n node.itemCount = b.length;\n node.children = b.map((item: any, idx: number) =>\n diffJSON(undefined, item, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 2: Value removed (a exists, b is undefined)\n if (a !== undefined && b === undefined) {\n const node: DiffNode = {\n id,\n key,\n path,\n depth,\n status: \"removed\",\n oldValue: a,\n type: typeA,\n collapsed: false,\n };\n if (typeA === \"object\" && a !== null) {\n node.itemCount = Object.keys(a).length;\n node.children = Object.keys(a).map((k) =>\n diffJSON(a[k], undefined, k, path === \"$\" ? k : `${path}.${k}`, depth + 1, maxInitialDepth)\n );\n } else if (typeA === \"array\") {\n node.itemCount = a.length;\n node.children = a.map((item: any, idx: number) =>\n diffJSON(item, undefined, `[${idx}]`, `${path}[${idx}]`, depth + 1, maxInitialDepth)\n );\n }\n return node;\n }\n\n // Case 3: Type changed (e.g. from string to number or object to array)\n if (typeA !== typeB) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Case 4: Both are Objects\n if (typeA === \"object\" && a !== null && b !== null) {\n const allKeys = Array.from(new Set([...Object.keys(a), ...Object.keys(b)]));\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (const k of allKeys) {\n const child = diffJSON(\n a[k],\n b[k],\n k,\n path === \"$\" ? k : `${path}.${k}`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"object\",\n itemCount: allKeys.length,\n collapsed,\n children,\n };\n }\n\n // Case 5: Both are Arrays\n if (typeA === \"array\") {\n const maxLen = Math.max(a.length, b.length);\n const children: DiffNode[] = [];\n let hasModifications = false;\n\n for (let i = 0; i < maxLen; i++) {\n const child = diffJSON(\n a[i],\n b[i],\n `[${i}]`,\n `${path}[${i}]`,\n depth + 1,\n maxInitialDepth\n );\n if (child.status !== \"unchanged\") hasModifications = true;\n children.push(child);\n }\n\n return {\n id,\n key,\n path,\n depth,\n status: hasModifications ? \"modified\" : \"unchanged\",\n oldValue: a,\n newValue: b,\n type: \"array\",\n itemCount: maxLen,\n collapsed,\n children,\n };\n }\n\n // Case 6: Primitive values comparison\n if (a !== b) {\n return {\n id,\n key,\n path,\n depth,\n status: \"modified\",\n oldValue: a,\n newValue: b,\n type: typeB,\n collapsed: false,\n };\n }\n\n // Unchanged primitive\n return {\n id,\n key,\n path,\n depth,\n status: \"unchanged\",\n oldValue: a,\n newValue: b,\n type: typeA,\n collapsed,\n };\n}\n\n/**\n * Calculate summary metrics for the diff.\n */\nexport function calculateDiffStats(node: DiffNode): DiffStats {\n const stats: DiffStats = { added: 0, removed: 0, modified: 0, unchanged: 0 };\n\n function traverse(n: DiffNode) {\n if (n.children && n.children.length > 0) {\n n.children.forEach(traverse);\n } else {\n stats[n.status]++;\n }\n }\n\n traverse(node);\n return stats;\n}\n\n/**\n * Pretty-print structural diff to terminal string.\n */\nexport function prettyPrintDiff(\n node: DiffNode,\n options: { showUnchanged?: boolean } = {},\n indent = \"\",\n isLast = true\n): string {\n const showUnchanged = options.showUnchanged ?? true;\n\n if (!showUnchanged && node.status === \"unchanged\" && (!node.children || node.children.length === 0)) {\n return \"\";\n }\n\n const isRoot = node.depth === 0;\n let prefix = \" \";\n let statusColor = pc.dim;\n\n if (node.status === \"added\") {\n prefix = pc.green(\"+ \");\n statusColor = pc.green;\n } else if (node.status === \"removed\") {\n prefix = pc.red(\"- \");\n statusColor = pc.red;\n } else if (node.status === \"modified\") {\n prefix = pc.yellow(\"~ \");\n statusColor = pc.yellow;\n }\n\n let line = prefix;\n if (!isRoot) {\n const branch = isLast ? \"└── \" : \"├── \";\n line += pc.dim(indent + branch);\n if (node.key) {\n line += formatKey(node.key) + pc.dim(\": \");\n }\n } else {\n line += node.key ? formatKey(node.key) + pc.dim(\": \") : pc.bold(\"diff: \");\n }\n\n if (node.status === \"added\") {\n line += statusColor(formatValue(node.newValue));\n } else if (node.status === \"removed\") {\n line += statusColor(formatValue(node.oldValue));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n line += statusColor(`{ ${node.itemCount} items modified }`);\n } else {\n line += `${pc.red(formatValue(node.oldValue))} ${pc.dim(\"->\")} ${pc.green(formatValue(node.newValue))}`;\n }\n } else {\n // Unchanged\n line += pc.dim(formatValue(node.newValue));\n }\n\n const lines = [line];\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n const nextIndent = isRoot ? \"\" : indent + (isLast ? \" \" : \"│ \");\n node.children.forEach((child, index) => {\n const childIsLast = index === node.children!.length - 1;\n const childStr = prettyPrintDiff(child, options, nextIndent, childIsLast);\n if (childStr) lines.push(childStr);\n });\n }\n\n return lines.join(\"\\n\");\n}\n","import readline from \"readline\";\nimport pc from \"picocolors\";\nimport { TreeNode, DiffNode } from \"./types.js\";\nimport { formatKey, formatValue } from \"./formatter.js\";\nimport { copyToClipboard } from \"./utils/clipboard.js\";\n\ntype AnyNode = TreeNode | DiffNode;\n\ninterface FlatItem {\n node: AnyNode;\n depth: number;\n isDiff: boolean;\n}\n\n/**\n * Interactive Terminal Tree Explorer for JSON data and Diffs.\n */\nexport class InteractiveViewer {\n private root: AnyNode;\n private flatList: FlatItem[] = [];\n private selectedIndex = 0;\n private searchQuery = \"\";\n private isSearching = false;\n private searchInput = \"\";\n private notification = \"\";\n private notificationTimer: NodeJS.Timeout | null = null;\n private isDiff: boolean;\n\n constructor(root: AnyNode, isDiff = false) {\n this.root = root;\n this.isDiff = isDiff;\n this.rebuildFlatList();\n }\n\n private isDiffNode(node: AnyNode): node is DiffNode {\n return this.isDiff && \"status\" in node;\n }\n\n private rebuildFlatList(): void {\n const list: FlatItem[] = [];\n\n const traverse = (node: AnyNode, currentDepth: number) => {\n // If search query is active, filter matching nodes or their parents\n if (this.searchQuery) {\n const query = this.searchQuery.toLowerCase();\n const keyMatch = node.key && node.key.toLowerCase().includes(query);\n const pathMatch = node.path && node.path.toLowerCase().includes(query);\n const valMatch =\n \"value\" in node\n ? JSON.stringify(node.value).toLowerCase().includes(query)\n : \"newValue\" in node\n ? JSON.stringify(node.newValue).toLowerCase().includes(query)\n : false;\n\n if (!keyMatch && !pathMatch && !valMatch && (!node.children || node.children.length === 0)) {\n return;\n }\n }\n\n list.push({ node, depth: currentDepth, isDiff: this.isDiff });\n\n if (!node.collapsed && node.children && node.children.length > 0) {\n for (const child of node.children) {\n traverse(child, currentDepth + 1);\n }\n }\n };\n\n traverse(this.root, 0);\n this.flatList = list;\n\n if (this.selectedIndex >= this.flatList.length) {\n this.selectedIndex = Math.max(0, this.flatList.length - 1);\n }\n }\n\n private setNotification(msg: string): void {\n this.notification = msg;\n if (this.notificationTimer) clearTimeout(this.notificationTimer);\n this.notificationTimer = setTimeout(() => {\n this.notification = \"\";\n this.render();\n }, 2500);\n }\n\n private render(): void {\n const rows = process.stdout.rows || 24;\n const maxVisibleRows = Math.max(5, rows - 5);\n\n // Calculate window scroll offset\n let startIdx = 0;\n if (this.selectedIndex >= maxVisibleRows) {\n startIdx = this.selectedIndex - maxVisibleRows + 1;\n }\n const endIdx = Math.min(this.flatList.length, startIdx + maxVisibleRows);\n\n // Clear terminal screen\n process.stdout.write(\"\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25l\"); // hide cursor\n\n // 1. Header Bar\n const title = this.isDiff ? \" JSON Structural Diff Explorer \" : \" Interactive JSON Tree Explorer \";\n console.log(pc.bgCyan(pc.black(pc.bold(` ${title} `)) + pc.dim(` [Total items: ${this.flatList.length}]`)));\n\n // 2. Render visible items\n for (let i = startIdx; i < endIdx; i++) {\n const { node, depth } = this.flatList[i];\n const isSelected = i === this.selectedIndex;\n const indent = \" \".repeat(depth);\n\n let marker = \"• \";\n if (node.children && node.children.length > 0) {\n marker = node.collapsed ? \"▶ \" : \"▼ \";\n }\n\n let lineContent = \"\";\n\n if (this.isDiffNode(node)) {\n let diffPrefix = \" \";\n if (node.status === \"added\") diffPrefix = pc.green(\"+ \");\n else if (node.status === \"removed\") diffPrefix = pc.red(\"- \");\n else if (node.status === \"modified\") diffPrefix = pc.yellow(\"~ \");\n\n lineContent = diffPrefix + indent + marker;\n if (node.key) lineContent += formatKey(node.key) + pc.dim(\": \");\n\n if (node.status === \"added\") {\n lineContent += pc.green(formatValue(node.newValue, 50));\n } else if (node.status === \"removed\") {\n lineContent += pc.red(formatValue(node.oldValue, 50));\n } else if (node.status === \"modified\") {\n if (node.type === \"object\" || node.type === \"array\") {\n lineContent += pc.yellow(`{ ${node.itemCount} modified }`);\n } else {\n lineContent += `${pc.red(formatValue(node.oldValue, 25))} -> ${pc.green(formatValue(node.newValue, 25))}`;\n }\n } else {\n lineContent += pc.dim(formatValue(node.newValue, 50));\n }\n } else {\n const treeNode = node as TreeNode;\n lineContent = indent + marker;\n if (treeNode.key) lineContent += formatKey(treeNode.key) + pc.dim(\": \");\n\n if (treeNode.type === \"object\") {\n lineContent += pc.dim(`{ ${treeNode.itemCount} keys }`);\n } else if (treeNode.type === \"array\") {\n lineContent += pc.dim(`[ ${treeNode.itemCount} items ]`);\n } else {\n lineContent += formatValue(treeNode.value, 60);\n }\n }\n\n if (isSelected) {\n console.log(pc.bgBlue(pc.white(pc.bold(`> ${lineContent}`))));\n } else {\n console.log(` ${lineContent}`);\n }\n }\n\n // 3. Status Bar & Footer\n const selectedItem = this.flatList[this.selectedIndex];\n const currentPath = selectedItem ? selectedItem.node.path : \"$\";\n\n console.log(\"\\n\" + pc.dim(\"─\".repeat(Math.min(process.stdout.columns || 80, 80))));\n if (this.notification) {\n console.log(pc.green(pc.bold(` ${this.notification}`)));\n } else if (this.isSearching) {\n console.log(pc.yellow(pc.bold(` Search: /${this.searchInput}█`)));\n } else {\n console.log(pc.bold(pc.cyan(` Path: ${currentPath}`)));\n console.log(\n pc.dim(\" [↑/↓] Move [Enter/Space] Toggle [e] Expand All [c] Collapse All [p] Copy Path [y] Copy Val [/] Search [q] Exit\")\n );\n }\n }\n\n private expandAll(node: AnyNode): void {\n node.collapsed = false;\n if (node.children) node.children.forEach((c) => this.expandAll(c));\n }\n\n private collapseAll(node: AnyNode): void {\n if (node.depth > 0) node.collapsed = true;\n if (node.children) node.children.forEach((c) => this.collapseAll(c));\n }\n\n public async start(): Promise<void> {\n if (!process.stdin.isTTY) {\n return;\n }\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n this.render();\n\n return new Promise((resolve) => {\n const onKeypress = async (str: string, key: readline.Key) => {\n if (this.isSearching) {\n if (key.name === \"return\") {\n this.searchQuery = this.searchInput;\n this.isSearching = false;\n this.rebuildFlatList();\n this.render();\n return;\n }\n if (key.name === \"escape\") {\n this.isSearching = false;\n this.searchInput = \"\";\n this.render();\n return;\n }\n if (key.name === \"backspace\") {\n this.searchInput = this.searchInput.slice(0, -1);\n this.render();\n return;\n }\n if (str && str.length === 1) {\n this.searchInput += str;\n this.render();\n return;\n }\n }\n\n // Navigation\n if (key.name === \"up\" || key.name === \"k\") {\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.render();\n }\n } else if (key.name === \"down\" || key.name === \"j\") {\n if (this.selectedIndex < this.flatList.length - 1) {\n this.selectedIndex++;\n this.render();\n }\n } else if (key.name === \"return\" || key.name === \"space\" || key.name === \"right\" || key.name === \"left\") {\n const item = this.flatList[this.selectedIndex];\n if (item && item.node.children && item.node.children.length > 0) {\n item.node.collapsed = !item.node.collapsed;\n this.rebuildFlatList();\n this.render();\n }\n } else if (str === \"e\" || str === \"E\") {\n this.expandAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"c\" || str === \"C\") {\n this.collapseAll(this.root);\n this.rebuildFlatList();\n this.render();\n } else if (str === \"p\" || str === \"P\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n await copyToClipboard(item.node.path);\n this.setNotification(`✔ Copied JSONPath: ${item.node.path}`);\n }\n } else if (str === \"y\" || str === \"Y\") {\n const item = this.flatList[this.selectedIndex];\n if (item) {\n const val = \"value\" in item.node ? item.node.value : (item.node as DiffNode).newValue;\n const textToCopy = typeof val === \"object\" ? JSON.stringify(val, null, 2) : String(val);\n await copyToClipboard(textToCopy);\n this.setNotification(`✔ Copied value to clipboard!`);\n }\n } else if (str === \"/\") {\n this.isSearching = true;\n this.searchInput = \"\";\n this.render();\n } else if (key.ctrl && key.name === \"c\" || key.name === \"escape\" || str === \"q\" || str === \"Q\") {\n // Cleanup & Exit\n process.stdin.removeListener(\"keypress\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n process.stdout.write(\"\\x1b[?25h\\n\"); // show cursor\n resolve();\n }\n };\n\n process.stdin.on(\"keypress\", onKeypress);\n });\n }\n}\n","import { exec } from \"child_process\";\nimport os from \"os\";\n\n/**\n * Copy text to system clipboard across macOS, Linux, and Windows.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n const platform = os.platform();\n\n return new Promise((resolve) => {\n let proc;\n if (platform === \"darwin\") {\n proc = exec(\"pbcopy\", (err) => resolve(!err));\n } else if (platform === \"win32\") {\n proc = exec(\"clip\", (err) => resolve(!err));\n } else {\n // Linux: Try wl-copy then xclip\n proc = exec(\"wl-copy 2>/dev/null || xclip -selection clipboard 2>/dev/null || xsel --clipboard --input\", (err) => {\n resolve(!err);\n });\n }\n\n if (proc.stdin) {\n proc.stdin.write(text);\n proc.stdin.end();\n } else {\n resolve(false);\n }\n });\n}\n"],"mappings":"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","names":["pc","pc","pc","pc"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-term",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.",
5
5
  "keywords": [
6
6
  "json",