json-term 1.1.0 → 1.2.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 +18 -2
- package/dist/cli.js +35 -34
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +35 -34
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,8 +49,14 @@ npm install json-term
|
|
|
49
49
|
# View local JSON file
|
|
50
50
|
jsonx package.json
|
|
51
51
|
|
|
52
|
+
# Directly parse inline JSON string
|
|
53
|
+
jsonx '{"service": "auth-api", "port": 443, "active": true, "tags": ["prod", "v2"]}'
|
|
54
|
+
|
|
52
55
|
# View piped API response
|
|
53
56
|
curl -s https://api.github.com/repos/nodejs/node | jsonx
|
|
57
|
+
|
|
58
|
+
# Echo / pipe JSON string
|
|
59
|
+
echo '{"status": 200, "data": [1, 2, 3]}' | jsonx
|
|
54
60
|
```
|
|
55
61
|
|
|
56
62
|
### 2. Structural JSON Diffing
|
|
@@ -58,7 +64,10 @@ curl -s https://api.github.com/repos/nodejs/node | jsonx
|
|
|
58
64
|
# Compare two JSON configuration files
|
|
59
65
|
jsonx diff config.old.json config.new.json
|
|
60
66
|
|
|
61
|
-
# Diff
|
|
67
|
+
# Diff two direct inline JSON strings
|
|
68
|
+
jsonx diff '{"port": 8080, "debug": true}' '{"port": 8443, "debug": true, "ssl": true}'
|
|
69
|
+
|
|
70
|
+
# Diff file against piped stdin
|
|
62
71
|
curl -s https://api.com/v2/config | jsonx diff config.v1.json
|
|
63
72
|
|
|
64
73
|
# Hide unchanged lines in diff
|
|
@@ -67,9 +76,12 @@ jsonx diff a.json b.json --no-unchanged
|
|
|
67
76
|
|
|
68
77
|
### 3. Simple Colorized JSON View (jq-style with Bold Keys)
|
|
69
78
|
```bash
|
|
70
|
-
# Print syntax-highlighted standard JSON format
|
|
79
|
+
# Print syntax-highlighted standard JSON format from file
|
|
71
80
|
jsonx --raw data.json
|
|
72
81
|
|
|
82
|
+
# Print syntax-highlighted direct JSON string
|
|
83
|
+
jsonx --raw '{"user": "alice", "roles": ["admin", "developer"]}'
|
|
84
|
+
|
|
73
85
|
# Piped stream
|
|
74
86
|
curl -s https://api.github.com/users/octocat | jsonx --raw
|
|
75
87
|
```
|
|
@@ -79,11 +91,15 @@ curl -s https://api.github.com/users/octocat | jsonx --raw
|
|
|
79
91
|
# Print formatted tree to stdout
|
|
80
92
|
jsonx --print data.json
|
|
81
93
|
|
|
94
|
+
# Pretty print inline JSON string
|
|
95
|
+
jsonx --print '{"name": "test", "count": 42}'
|
|
96
|
+
|
|
82
97
|
# Set initial collapse depth (e.g. depth 2)
|
|
83
98
|
jsonx data.json --depth 2 --print
|
|
84
99
|
```
|
|
85
100
|
|
|
86
101
|
|
|
102
|
+
|
|
87
103
|
---
|
|
88
104
|
|
|
89
105
|
## ⌨️ Interactive TUI Keybindings
|
package/dist/cli.js
CHANGED
|
@@ -658,30 +658,41 @@ function parseJSON(raw, label = "Input") {
|
|
|
658
658
|
throw new Error(`Invalid JSON in ${label}: ${err.message}`);
|
|
659
659
|
}
|
|
660
660
|
}
|
|
661
|
+
async function resolveJSONInput(inputArg) {
|
|
662
|
+
if (inputArg) {
|
|
663
|
+
const trimmed = inputArg.trim();
|
|
664
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
665
|
+
return { raw: trimmed, label: "inline JSON" };
|
|
666
|
+
}
|
|
667
|
+
if (import_fs.default.existsSync(inputArg)) {
|
|
668
|
+
const raw = await import_fs.default.promises.readFile(inputArg, "utf-8");
|
|
669
|
+
return { raw, label: inputArg };
|
|
670
|
+
}
|
|
671
|
+
try {
|
|
672
|
+
JSON.parse(trimmed);
|
|
673
|
+
return { raw: trimmed, label: "inline JSON" };
|
|
674
|
+
} catch {
|
|
675
|
+
}
|
|
676
|
+
throw new Error(`File not found or invalid inline JSON: ${inputArg}`);
|
|
677
|
+
}
|
|
678
|
+
const stdinData = await readStdin();
|
|
679
|
+
return { raw: stdinData, label: "stdin" };
|
|
680
|
+
}
|
|
661
681
|
async function main() {
|
|
662
682
|
const program = new import_commander.Command();
|
|
663
|
-
program.name("json-term").description("High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.").version("1.
|
|
683
|
+
program.name("json-term").description("High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.").version("1.2.0", "-v, --version", "Output the current version").argument("[input]", "JSON file path, inline JSON string, or piped stdin").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 (inputArg, options) => {
|
|
664
684
|
try {
|
|
665
|
-
|
|
666
|
-
if (fileArg) {
|
|
667
|
-
if (!import_fs.default.existsSync(fileArg)) {
|
|
668
|
-
console.error(import_picocolors4.default.red(`Error: File not found: ${fileArg}`));
|
|
669
|
-
process.exit(1);
|
|
670
|
-
}
|
|
671
|
-
raw = await import_fs.default.promises.readFile(fileArg, "utf-8");
|
|
672
|
-
} else {
|
|
673
|
-
raw = await readStdin();
|
|
674
|
-
}
|
|
685
|
+
const { raw, label } = await resolveJSONInput(inputArg);
|
|
675
686
|
if (!raw) {
|
|
676
687
|
program.help();
|
|
677
688
|
process.exit(1);
|
|
678
689
|
}
|
|
679
|
-
const data = parseJSON(raw,
|
|
690
|
+
const data = parseJSON(raw, label);
|
|
680
691
|
if (options.raw || options.format === "json") {
|
|
681
692
|
console.log(colorizeJSON(data));
|
|
682
693
|
return;
|
|
683
694
|
}
|
|
684
|
-
const tree = buildTree(data,
|
|
695
|
+
const tree = buildTree(data, label, "$", 0, options.depth);
|
|
685
696
|
if (options.print || !process.stdin.isTTY) {
|
|
686
697
|
console.log(prettyPrintTree(tree));
|
|
687
698
|
} else {
|
|
@@ -693,31 +704,21 @@ async function main() {
|
|
|
693
704
|
process.exit(1);
|
|
694
705
|
}
|
|
695
706
|
});
|
|
696
|
-
program.command("diff <
|
|
707
|
+
program.command("diff <inputA> [inputB]").description("Structural JSON diff between files, inline JSON strings, or stdin").option("-p, --print", "Print formatted non-interactive diff to stdout", false).option("-d, --depth <number>", "Initial expansion depth", (val) => parseInt(val, 10), 3).option("--no-unchanged", "Hide unchanged nodes from the diff view", false).action(async (inputA, inputB, diffOptions) => {
|
|
697
708
|
try {
|
|
698
|
-
|
|
699
|
-
|
|
709
|
+
const itemA = await resolveJSONInput(inputA);
|
|
710
|
+
if (!itemA.raw) {
|
|
711
|
+
console.error(import_picocolors4.default.red("Error: Please provide valid first JSON input (file or string)."));
|
|
700
712
|
process.exit(1);
|
|
701
713
|
}
|
|
702
|
-
const
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
console.error(import_picocolors4.default.red(`Error: File not found: ${fileB}`));
|
|
708
|
-
process.exit(1);
|
|
709
|
-
}
|
|
710
|
-
const rawB = await import_fs.default.promises.readFile(fileB, "utf-8");
|
|
711
|
-
dataB = parseJSON(rawB, fileB);
|
|
712
|
-
} else {
|
|
713
|
-
const stdinData = await readStdin();
|
|
714
|
-
if (!stdinData) {
|
|
715
|
-
console.error(import_picocolors4.default.red("Error: Please specify second file or pipe JSON via stdin."));
|
|
716
|
-
process.exit(1);
|
|
717
|
-
}
|
|
718
|
-
dataB = parseJSON(stdinData, "stdin");
|
|
714
|
+
const dataA = parseJSON(itemA.raw, itemA.label);
|
|
715
|
+
const itemB = await resolveJSONInput(inputB);
|
|
716
|
+
if (!itemB.raw) {
|
|
717
|
+
console.error(import_picocolors4.default.red("Error: Please specify second JSON input (file, string, or piped stdin)."));
|
|
718
|
+
process.exit(1);
|
|
719
719
|
}
|
|
720
|
-
const
|
|
720
|
+
const dataB = parseJSON(itemB.raw, itemB.label);
|
|
721
|
+
const diffTree = diffJSON(dataA, dataB, `${itemA.label} \u2194 ${itemB.label}`, "$", 0, diffOptions.depth);
|
|
721
722
|
const stats = calculateDiffStats(diffTree);
|
|
722
723
|
if (diffOptions.print || !process.stdin.isTTY) {
|
|
723
724
|
console.log(
|
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, 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"]}
|
|
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 resolveJSONInput(inputArg?: string): Promise<{ raw: string; label: string }> {\n if (inputArg) {\n const trimmed = inputArg.trim();\n // 1. Direct inline JSON check\n if (\n (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"))\n ) {\n return { raw: trimmed, label: \"inline JSON\" };\n }\n // 2. Existing file check\n if (fs.existsSync(inputArg)) {\n const raw = await fs.promises.readFile(inputArg, \"utf-8\");\n return { raw, label: inputArg };\n }\n // 3. Try parsing as generic JSON value (number, boolean, string)\n try {\n JSON.parse(trimmed);\n return { raw: trimmed, label: \"inline JSON\" };\n } catch {}\n\n throw new Error(`File not found or invalid inline JSON: ${inputArg}`);\n }\n\n // 4. Stdin fallback\n const stdinData = await readStdin();\n return { raw: stdinData, label: \"stdin\" };\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.2.0\", \"-v, --version\", \"Output the current version\")\n .argument(\"[input]\", \"JSON file path, inline JSON string, or piped stdin\")\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 (inputArg, options) => {\n try {\n const { raw, label } = await resolveJSONInput(inputArg);\n\n if (!raw) {\n program.help();\n process.exit(1);\n }\n\n const data = parseJSON(raw, label);\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, label, \"$\", 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 <inputA> [inputB]\")\n .description(\"Structural JSON diff between files, inline JSON strings, 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 (inputA, inputB, diffOptions) => {\n try {\n const itemA = await resolveJSONInput(inputA);\n if (!itemA.raw) {\n console.error(pc.red(\"Error: Please provide valid first JSON input (file or string).\"));\n process.exit(1);\n }\n const dataA = parseJSON(itemA.raw, itemA.label);\n\n const itemB = await resolveJSONInput(inputB);\n if (!itemB.raw) {\n console.error(pc.red(\"Error: Please specify second JSON input (file, string, or piped stdin).\"));\n process.exit(1);\n }\n const dataB = parseJSON(itemB.raw, itemB.label);\n\n const diffTree = diffJSON(dataA, dataB, `${itemA.label} ↔ ${itemB.label}`, \"$\", 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
|
@@ -635,30 +635,41 @@ function parseJSON(raw, label = "Input") {
|
|
|
635
635
|
throw new Error(`Invalid JSON in ${label}: ${err.message}`);
|
|
636
636
|
}
|
|
637
637
|
}
|
|
638
|
+
async function resolveJSONInput(inputArg) {
|
|
639
|
+
if (inputArg) {
|
|
640
|
+
const trimmed = inputArg.trim();
|
|
641
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
642
|
+
return { raw: trimmed, label: "inline JSON" };
|
|
643
|
+
}
|
|
644
|
+
if (fs.existsSync(inputArg)) {
|
|
645
|
+
const raw = await fs.promises.readFile(inputArg, "utf-8");
|
|
646
|
+
return { raw, label: inputArg };
|
|
647
|
+
}
|
|
648
|
+
try {
|
|
649
|
+
JSON.parse(trimmed);
|
|
650
|
+
return { raw: trimmed, label: "inline JSON" };
|
|
651
|
+
} catch {
|
|
652
|
+
}
|
|
653
|
+
throw new Error(`File not found or invalid inline JSON: ${inputArg}`);
|
|
654
|
+
}
|
|
655
|
+
const stdinData = await readStdin();
|
|
656
|
+
return { raw: stdinData, label: "stdin" };
|
|
657
|
+
}
|
|
638
658
|
async function main() {
|
|
639
659
|
const program = new 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.
|
|
660
|
+
program.name("json-term").description("High-fidelity interactive terminal JSON viewer, collapsible tree explorer, type syntax highlighter, and structural diff tool.").version("1.2.0", "-v, --version", "Output the current version").argument("[input]", "JSON file path, inline JSON string, or piped stdin").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 (inputArg, options) => {
|
|
641
661
|
try {
|
|
642
|
-
|
|
643
|
-
if (fileArg) {
|
|
644
|
-
if (!fs.existsSync(fileArg)) {
|
|
645
|
-
console.error(pc4.red(`Error: File not found: ${fileArg}`));
|
|
646
|
-
process.exit(1);
|
|
647
|
-
}
|
|
648
|
-
raw = await fs.promises.readFile(fileArg, "utf-8");
|
|
649
|
-
} else {
|
|
650
|
-
raw = await readStdin();
|
|
651
|
-
}
|
|
662
|
+
const { raw, label } = await resolveJSONInput(inputArg);
|
|
652
663
|
if (!raw) {
|
|
653
664
|
program.help();
|
|
654
665
|
process.exit(1);
|
|
655
666
|
}
|
|
656
|
-
const data = parseJSON(raw,
|
|
667
|
+
const data = parseJSON(raw, label);
|
|
657
668
|
if (options.raw || options.format === "json") {
|
|
658
669
|
console.log(colorizeJSON(data));
|
|
659
670
|
return;
|
|
660
671
|
}
|
|
661
|
-
const tree = buildTree(data,
|
|
672
|
+
const tree = buildTree(data, label, "$", 0, options.depth);
|
|
662
673
|
if (options.print || !process.stdin.isTTY) {
|
|
663
674
|
console.log(prettyPrintTree(tree));
|
|
664
675
|
} else {
|
|
@@ -670,31 +681,21 @@ async function main() {
|
|
|
670
681
|
process.exit(1);
|
|
671
682
|
}
|
|
672
683
|
});
|
|
673
|
-
program.command("diff <
|
|
684
|
+
program.command("diff <inputA> [inputB]").description("Structural JSON diff between files, inline JSON strings, or stdin").option("-p, --print", "Print formatted non-interactive diff to stdout", false).option("-d, --depth <number>", "Initial expansion depth", (val) => parseInt(val, 10), 3).option("--no-unchanged", "Hide unchanged nodes from the diff view", false).action(async (inputA, inputB, diffOptions) => {
|
|
674
685
|
try {
|
|
675
|
-
|
|
676
|
-
|
|
686
|
+
const itemA = await resolveJSONInput(inputA);
|
|
687
|
+
if (!itemA.raw) {
|
|
688
|
+
console.error(pc4.red("Error: Please provide valid first JSON input (file or string)."));
|
|
677
689
|
process.exit(1);
|
|
678
690
|
}
|
|
679
|
-
const
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
console.error(pc4.red(`Error: File not found: ${fileB}`));
|
|
685
|
-
process.exit(1);
|
|
686
|
-
}
|
|
687
|
-
const rawB = await fs.promises.readFile(fileB, "utf-8");
|
|
688
|
-
dataB = parseJSON(rawB, fileB);
|
|
689
|
-
} else {
|
|
690
|
-
const stdinData = await readStdin();
|
|
691
|
-
if (!stdinData) {
|
|
692
|
-
console.error(pc4.red("Error: Please specify second file or pipe JSON via stdin."));
|
|
693
|
-
process.exit(1);
|
|
694
|
-
}
|
|
695
|
-
dataB = parseJSON(stdinData, "stdin");
|
|
691
|
+
const dataA = parseJSON(itemA.raw, itemA.label);
|
|
692
|
+
const itemB = await resolveJSONInput(inputB);
|
|
693
|
+
if (!itemB.raw) {
|
|
694
|
+
console.error(pc4.red("Error: Please specify second JSON input (file, string, or piped stdin)."));
|
|
695
|
+
process.exit(1);
|
|
696
696
|
}
|
|
697
|
-
const
|
|
697
|
+
const dataB = parseJSON(itemB.raw, itemB.label);
|
|
698
|
+
const diffTree = diffJSON(dataA, dataB, `${itemA.label} \u2194 ${itemB.label}`, "$", 0, diffOptions.depth);
|
|
698
699
|
const stats = calculateDiffStats(diffTree);
|
|
699
700
|
if (diffOptions.print || !process.stdin.isTTY) {
|
|
700
701
|
console.log(
|
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, 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"]}
|
|
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 resolveJSONInput(inputArg?: string): Promise<{ raw: string; label: string }> {\n if (inputArg) {\n const trimmed = inputArg.trim();\n // 1. Direct inline JSON check\n if (\n (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"))\n ) {\n return { raw: trimmed, label: \"inline JSON\" };\n }\n // 2. Existing file check\n if (fs.existsSync(inputArg)) {\n const raw = await fs.promises.readFile(inputArg, \"utf-8\");\n return { raw, label: inputArg };\n }\n // 3. Try parsing as generic JSON value (number, boolean, string)\n try {\n JSON.parse(trimmed);\n return { raw: trimmed, label: \"inline JSON\" };\n } catch {}\n\n throw new Error(`File not found or invalid inline JSON: ${inputArg}`);\n }\n\n // 4. Stdin fallback\n const stdinData = await readStdin();\n return { raw: stdinData, label: \"stdin\" };\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.2.0\", \"-v, --version\", \"Output the current version\")\n .argument(\"[input]\", \"JSON file path, inline JSON string, or piped stdin\")\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 (inputArg, options) => {\n try {\n const { raw, label } = await resolveJSONInput(inputArg);\n\n if (!raw) {\n program.help();\n process.exit(1);\n }\n\n const data = parseJSON(raw, label);\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, label, \"$\", 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 <inputA> [inputB]\")\n .description(\"Structural JSON diff between files, inline JSON strings, 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 (inputA, inputB, diffOptions) => {\n try {\n const itemA = await resolveJSONInput(inputA);\n if (!itemA.raw) {\n console.error(pc.red(\"Error: Please provide valid first JSON input (file or string).\"));\n process.exit(1);\n }\n const dataA = parseJSON(itemA.raw, itemA.label);\n\n const itemB = await resolveJSONInput(inputB);\n if (!itemB.raw) {\n console.error(pc.red(\"Error: Please specify second JSON input (file, string, or piped stdin).\"));\n process.exit(1);\n }\n const dataB = parseJSON(itemB.raw, itemB.label);\n\n const diffTree = diffJSON(dataA, dataB, `${itemA.label} ↔ ${itemB.label}`, \"$\", 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/package.json
CHANGED