jsondiffpatch-html 1.0.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 ADDED
@@ -0,0 +1,28 @@
1
+ # jsondiffpatch-html
2
+
3
+ CLI tool to generate HTML diff reports from JSON files using `jsondiffpatch`.
4
+
5
+ ## Install Dependecies
6
+
7
+ ```bash
8
+ npm install
9
+ ```
10
+
11
+ ## Add execute permission
12
+
13
+ ```
14
+ chmod +x bin/jsondiffpatch-html.js
15
+ ```
16
+
17
+ ## Link the command
18
+
19
+ ```
20
+ npm link
21
+ ```
22
+
23
+ ## Run the command
24
+
25
+ ```
26
+ jsondiffpatch-html left.json right.json -o diff.html
27
+ ```
28
+
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'fs';
3
+ import { create } from 'jsondiffpatch';
4
+ import * as htmlFormatter from 'jsondiffpatch/formatters/html';
5
+
6
+ /**
7
+ * 统计 jsondiffpatch delta 中「第一级属性」的差异
8
+ *
9
+ * @param {object} delta jsondiffpatch.diff(left, right) 的结果
10
+ * @returns {{
11
+ * added: string[],
12
+ * removed: string[],
13
+ * updated: string[]
14
+ * }}
15
+ */
16
+ function statTopLevelDiff(delta) {
17
+ const result = {
18
+ added: [],
19
+ removed: [],
20
+ updated: [],
21
+ };
22
+
23
+ if (!delta || typeof delta !== 'object') {
24
+ return result;
25
+ }
26
+
27
+ for (const key of Object.keys(delta)) {
28
+ if (key === '_t') continue; // 忽略数组标记
29
+
30
+ const value = delta[key];
31
+
32
+ // 情况 1:数组形式(新增 / 删除 / 替换)
33
+ if (Array.isArray(value)) {
34
+ // 新增:[newValue]
35
+ if (value.length === 1) {
36
+ result.added.push(key);
37
+ continue;
38
+ }
39
+
40
+ // 删除:[oldValue, 0, 0]
41
+ if (value.length === 3 && value[1] === 0 && value[2] === 0) {
42
+ result.removed.push(key);
43
+ continue;
44
+ }
45
+
46
+ // 替换:[oldValue, newValue]
47
+ if (value.length === 2) {
48
+ result.updated.push(key);
49
+ continue;
50
+ }
51
+ }
52
+
53
+ // 情况 2:对象形式 → 子属性发生变化
54
+ if (typeof value === 'object') {
55
+ result.updated.push(key);
56
+ }
57
+ }
58
+
59
+ return result;
60
+ }
61
+
62
+ // 创建实例
63
+ const jdp = create();
64
+
65
+ // CLI 参数解析
66
+ const args = process.argv.slice(2);
67
+ if (args.length < 2) {
68
+ console.error(`Usage: jsondiffpatch-html old.json new.json [-o output.html]`);
69
+ process.exit(1);
70
+ }
71
+
72
+ const oldFile = args[0];
73
+ const newFile = args[1];
74
+
75
+ let outFile = 'diff.html';
76
+ const oIdx = args.indexOf('-o');
77
+ if (oIdx >= 0 && args[oIdx + 1]) {
78
+ outFile = args[oIdx + 1];
79
+ }
80
+
81
+ // 读取 JSON
82
+ const left = JSON.parse(fs.readFileSync(oldFile, 'utf8'));
83
+ const right = JSON.parse(fs.readFileSync(newFile, 'utf8'));
84
+
85
+ // 生成 delta
86
+ const delta = jdp.diff(left, right);
87
+
88
+ const diffContent = delta ? htmlFormatter.format(delta, left) : "No diff";
89
+ const statistics = statTopLevelDiff(delta);
90
+
91
+ // 生成 HTML
92
+ // 通过实例访问 jdp.formatters.html
93
+ const releasedPkgUrl = "https://esm.sh/jsondiffpatch@0.6.0";
94
+ const htmlContent = `
95
+ <!DOCTYPE html>
96
+ <html lang="en">
97
+ <head>
98
+ <meta charset="UTF-8">
99
+ <title>JSON Diff Report</title>
100
+ <link
101
+ rel="stylesheet"
102
+ href="${releasedPkgUrl}/lib/formatters/styles/html.css"
103
+ type="text/css"
104
+ />
105
+ <link
106
+ rel="stylesheet"
107
+ href="${releasedPkgUrl}/lib/formatters/styles/annotated.css"
108
+ type="text/css"
109
+ />
110
+ <script type="text/javascript">
111
+
112
+ const showUnchanged = (show, node, delay) => {
113
+ const el = node || document.body;
114
+ const prefix = 'jsondiffpatch-unchanged-';
115
+ const classes = {
116
+ showing: prefix + 'showing',
117
+ hiding: prefix + 'hiding',
118
+ visible: prefix + 'visible',
119
+ hidden: prefix + 'hidden',
120
+ };
121
+ const list = el.classList;
122
+ if (!list) {
123
+ return;
124
+ }
125
+ if (!delay) {
126
+ list.remove(classes.showing);
127
+ list.remove(classes.hiding);
128
+ list.remove(classes.visible);
129
+ list.remove(classes.hidden);
130
+ if (show === false) {
131
+ list.add(classes.hidden);
132
+ }
133
+ return;
134
+ }
135
+ if (show === false) {
136
+ list.remove(classes.showing);
137
+ list.add(classes.visible);
138
+ setTimeout(() => {
139
+ list.add(classes.hiding);
140
+ }, 10);
141
+ }
142
+ else {
143
+ list.remove(classes.hiding);
144
+ list.add(classes.showing);
145
+ list.remove(classes.hidden);
146
+ }
147
+ const intervalId = setInterval(() => {
148
+ adjustArrows(el);
149
+ }, 100);
150
+ setTimeout(() => {
151
+ list.remove(classes.showing);
152
+ list.remove(classes.hiding);
153
+ if (show === false) {
154
+ list.add(classes.hidden);
155
+ list.remove(classes.visible);
156
+ }
157
+ else {
158
+ list.add(classes.visible);
159
+ list.remove(classes.hidden);
160
+ }
161
+ setTimeout(() => {
162
+ list.remove(classes.visible);
163
+ clearInterval(intervalId);
164
+ }, delay + 400);
165
+ }, delay);
166
+ };
167
+ const hideUnchanged = (node, delay) => showUnchanged(false, node, delay);
168
+
169
+ </script>
170
+ </head>
171
+ <body>
172
+ <input type="checkbox" id="hide-unchanged"><label>Hide unchanged<label>
173
+ <div>
174
+ <span>Added: ${statistics.added.length} ${statistics.added}</span><br/>
175
+ <span>Removed: ${statistics.removed.length} ${statistics.removed}</span><br/>
176
+ <span>Updated: ${statistics.updated.length} ${statistics.updated}</span>
177
+ </div>
178
+ <div id='the-diff'>
179
+ ${diffContent}
180
+ </div>
181
+ <script type="text/javascript">
182
+ document.getElementById('hide-unchanged').addEventListener("change", (e) => {
183
+ const checked = e.target.checked;
184
+ if (checked) {
185
+ hideUnchanged();
186
+ } else {
187
+ showUnchanged(true);
188
+ }
189
+ });
190
+ </script>
191
+ </body>
192
+ </html>
193
+ `;
194
+
195
+ fs.writeFileSync(outFile, htmlContent, 'utf8');
196
+ console.log(`HTML diff report generated: ${outFile}`);
package/left.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "Tom",
3
+ "age": 20,
4
+ "city": "SG",
5
+ "tags": ["a", "b"],
6
+ "nochange": 1
7
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "jsondiffpatch-html",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool to generate HTML diff reports from JSON files using jsondiffpatch",
5
+ "main": "bin/jsondiffpatch-html.js",
6
+ "bin": {
7
+ "jsondiffpatch-html": "bin/jsondiffpatch-html.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "start": "node bin/jsondiffpatch-html.js",
12
+ "build": "pkg . --targets node18-macos,node18-win,node18-linux --output dist/jsondiffpatch-html"
13
+ },
14
+ "keywords": [
15
+ "json",
16
+ "diff",
17
+ "html",
18
+ "cli",
19
+ "jsondiffpatch"
20
+ ],
21
+ "author": "Yaohui Wu",
22
+ "license": "MIT",
23
+ "devDependencies": {
24
+ "pkg": "^5.3.1"
25
+ },
26
+ "dependencies": {
27
+ "jsondiffpatch": "^0.6.1"
28
+ }
29
+ }
package/right.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "Tom",
3
+ "age": 21,
4
+ "tags": ["a", "c"],
5
+ "country": "USA",
6
+ "nochange": 1
7
+ }