json-diff-viewer-component 0.6.3 → 0.6.4
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 +108 -43
- package/package.json +1 -1
- package/src/lib/styles.js +13 -8
- package/src/lib/viewer.js +20 -20
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/metaory/json-diff-viewer-component/master/public/logo.
|
|
2
|
+
<img src="https://raw.githubusercontent.com/metaory/json-diff-viewer-component/master/public/logo.png" alt="logo" height="128" />
|
|
3
3
|
<h2>json-diff-viewer</h2>
|
|
4
4
|
<h5>
|
|
5
5
|
Compare JSON side-by-side, visually
|
|
@@ -36,24 +36,50 @@ npm i json-diff-viewer-component
|
|
|
36
36
|
|
|
37
37
|
## Usage
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Every integration needs three things:
|
|
40
|
+
|
|
41
|
+
1. Import the package once to register the custom element.
|
|
42
|
+
2. Add `<json-diff-viewer>` to the page.
|
|
43
|
+
3. Provide both values using one of the data APIs below.
|
|
44
|
+
|
|
45
|
+
Import the package:
|
|
40
46
|
|
|
41
47
|
```js
|
|
42
48
|
import "json-diff-viewer-component";
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<json-diff-viewer></json-diff-viewer>
|
|
53
|
+
```
|
|
43
54
|
|
|
55
|
+
Choose one data API. Root values must be non-null.
|
|
56
|
+
|
|
57
|
+
### `setData(left, right)` (Recommended)
|
|
58
|
+
|
|
59
|
+
Use for dynamic data. Both values update in one render:
|
|
60
|
+
|
|
61
|
+
```js
|
|
44
62
|
const viewer = document.querySelector("json-diff-viewer");
|
|
45
|
-
viewer.setData(
|
|
63
|
+
viewer.setData(
|
|
64
|
+
{ name: "foo", enabled: true },
|
|
65
|
+
{ name: "bar", enabled: true },
|
|
66
|
+
);
|
|
46
67
|
```
|
|
47
68
|
|
|
48
|
-
|
|
69
|
+
### Properties (Alternative)
|
|
70
|
+
|
|
71
|
+
Use when assigning JavaScript values independently. Rendering starts once both sides are set:
|
|
49
72
|
|
|
50
73
|
```js
|
|
51
|
-
|
|
74
|
+
viewer.left = { name: "foo" };
|
|
75
|
+
viewer.right = { name: "bar" };
|
|
76
|
+
|
|
77
|
+
console.log(viewer.left, viewer.right);
|
|
52
78
|
```
|
|
53
79
|
|
|
54
|
-
### HTML Attributes
|
|
80
|
+
### HTML Attributes (Alternative)
|
|
55
81
|
|
|
56
|
-
|
|
82
|
+
Use only for small, static, inline JSON. Each value is parsed with `JSON.parse()`, so invalid JSON throws:
|
|
57
83
|
|
|
58
84
|
```html
|
|
59
85
|
<json-diff-viewer
|
|
@@ -62,33 +88,32 @@ Static JSON can be passed as attributes. Values must be valid JSON strings:
|
|
|
62
88
|
></json-diff-viewer>
|
|
63
89
|
```
|
|
64
90
|
|
|
65
|
-
|
|
66
|
-
- Prefer `setData()` or property setters for dynamic or object data
|
|
91
|
+
Prefer `setData()` or properties for objects already available in JavaScript.
|
|
67
92
|
|
|
68
|
-
###
|
|
93
|
+
### Class Export
|
|
69
94
|
|
|
70
|
-
|
|
95
|
+
The registered class is exported only when a class reference is needed for testing or extension:
|
|
71
96
|
|
|
72
97
|
```js
|
|
73
|
-
|
|
74
|
-
viewer.right = { name: "bar" };
|
|
75
|
-
|
|
76
|
-
viewer.left; // read current left value
|
|
77
|
-
viewer.right; // read current right value
|
|
98
|
+
import { JsonDiffViewer } from "json-diff-viewer-component";
|
|
78
99
|
```
|
|
79
100
|
|
|
80
101
|
### Built-in Controls
|
|
81
102
|
|
|
82
|
-
The component toolbar includes:
|
|
103
|
+
No setup is required. The component toolbar includes:
|
|
83
104
|
|
|
84
105
|
- **Show only changed**: filter toggle (default: **on**); hides unchanged nodes
|
|
85
106
|
- **Collapse all** / **Expand all**: bulk expand/collapse
|
|
86
107
|
- **Node toggles**: click any object/array line to expand/collapse (synced across both panels)
|
|
87
108
|
|
|
109
|
+
### Framework Usage
|
|
110
|
+
|
|
111
|
+
The component remains the same custom element and uses `setData()` for reactive values.
|
|
112
|
+
|
|
88
113
|
<details>
|
|
89
|
-
<summary>
|
|
114
|
+
<summary>React and Vue examples</summary>
|
|
90
115
|
|
|
91
|
-
|
|
116
|
+
#### React
|
|
92
117
|
|
|
93
118
|
```jsx
|
|
94
119
|
import { useEffect, useRef } from "react";
|
|
@@ -107,7 +132,7 @@ function DiffViewer({ left, right }) {
|
|
|
107
132
|
}
|
|
108
133
|
```
|
|
109
134
|
|
|
110
|
-
|
|
135
|
+
#### Vue
|
|
111
136
|
|
|
112
137
|
```vue
|
|
113
138
|
<template>
|
|
@@ -115,25 +140,15 @@ function DiffViewer({ left, right }) {
|
|
|
115
140
|
</template>
|
|
116
141
|
|
|
117
142
|
<script setup>
|
|
118
|
-
import { ref,
|
|
143
|
+
import { ref, watchEffect } from "vue";
|
|
119
144
|
import "json-diff-viewer-component";
|
|
120
145
|
|
|
121
|
-
const props = defineProps(
|
|
122
|
-
left: Object,
|
|
123
|
-
right: Object,
|
|
124
|
-
});
|
|
125
|
-
|
|
146
|
+
const props = defineProps(["left", "right"]);
|
|
126
147
|
const viewerRef = ref(null);
|
|
127
148
|
|
|
128
|
-
|
|
129
|
-
(
|
|
130
|
-
|
|
131
|
-
if (viewerRef.value) {
|
|
132
|
-
viewerRef.value.setData(props.left, props.right);
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
{ immediate: true },
|
|
136
|
-
);
|
|
149
|
+
watchEffect(() => {
|
|
150
|
+
viewerRef.value?.setData(props.left, props.right);
|
|
151
|
+
});
|
|
137
152
|
</script>
|
|
138
153
|
```
|
|
139
154
|
|
|
@@ -141,18 +156,20 @@ watch(
|
|
|
141
156
|
|
|
142
157
|
## Diff Types
|
|
143
158
|
|
|
144
|
-
| Type
|
|
145
|
-
|
|
|
146
|
-
| Added
|
|
147
|
-
| Removed
|
|
148
|
-
| Modified | Yellow |
|
|
159
|
+
| Type | Default | Description |
|
|
160
|
+
| --- | --- | --- |
|
|
161
|
+
| Added | Green | Key exists only on the right |
|
|
162
|
+
| Removed | Red | Key exists only on the left |
|
|
163
|
+
| Modified | Yellow | Values differ, or a container has changed descendants |
|
|
149
164
|
|
|
150
165
|
## Styling
|
|
151
166
|
|
|
152
|
-
Override CSS custom properties
|
|
167
|
+
The component is fully usable without style configuration. Override CSS custom properties on `json-diff-viewer`. They inherit through the host into its shadow DOM. State foreground tokens also drive their derived backgrounds unless those backgrounds are overridden separately.
|
|
153
168
|
|
|
154
169
|
### Design Tokens
|
|
155
170
|
|
|
171
|
+
Tokens inherit through the host. Override only the values your theme needs.
|
|
172
|
+
|
|
156
173
|
```css
|
|
157
174
|
json-diff-viewer {
|
|
158
175
|
/* Diff colors */
|
|
@@ -171,8 +188,18 @@ json-diff-viewer {
|
|
|
171
188
|
--txt: #fafafa; /* Primary text */
|
|
172
189
|
--dim: #a1a1aa; /* Dimmed/secondary text */
|
|
173
190
|
|
|
174
|
-
/*
|
|
175
|
-
--
|
|
191
|
+
/* State backgrounds */
|
|
192
|
+
--add-bg: color-mix(in srgb, var(--add) 15%, transparent);
|
|
193
|
+
--rem-bg: color-mix(in srgb, var(--rem) 15%, transparent);
|
|
194
|
+
--mod-bg: color-mix(in srgb, var(--mod) 15%, transparent);
|
|
195
|
+
|
|
196
|
+
/* Controls and interaction */
|
|
197
|
+
--hover: rgb(0 0 0 / 3%); /* Diff row hover */
|
|
198
|
+
--control-bg: var(--bg2); /* Action button background */
|
|
199
|
+
--control-hover: rgb(0 0 0 / 5%); /* Action button hover */
|
|
200
|
+
--control-bdr: var(--bdr); /* Action button border */
|
|
201
|
+
--slider: var(--bdr); /* Slider active track */
|
|
202
|
+
--slider-thumb: var(--br); /* Slider thumb */
|
|
176
203
|
|
|
177
204
|
/* Syntax highlighting */
|
|
178
205
|
--key: #38bdf8; /* Object keys */
|
|
@@ -206,6 +233,43 @@ json-diff-viewer {
|
|
|
206
233
|
}
|
|
207
234
|
```
|
|
208
235
|
|
|
236
|
+
### Shadow Parts
|
|
237
|
+
|
|
238
|
+
Use `::part()` for structural overrides that are not shared design tokens:
|
|
239
|
+
|
|
240
|
+
| Parts | Elements |
|
|
241
|
+
| --- | --- |
|
|
242
|
+
| `toolbar`, `legend`, `legend-item`, `legend-added`, `legend-removed`, `legend-modified` | Summary and state legend |
|
|
243
|
+
| `actions`, `filter`, `filter-track`, `action-button`, `collapse-button`, `expand-button` | Viewer controls |
|
|
244
|
+
| `content`, `panel`, `panel-left`, `panel-right` | Diff layout and panels |
|
|
245
|
+
| `node`, `node-added`, `node-removed`, `node-modified`, `line` | Diff nodes and rows |
|
|
246
|
+
| `toggle`, `marker`, `marker-added`, `marker-removed`, `marker-modified` | Node controls and state markers |
|
|
247
|
+
| `key`, `separator`, `value`, `value-string`, `value-number`, `value-boolean`, `value-null` | JSON content |
|
|
248
|
+
| `bracket`, `preview`, `empty` | Supporting content and empty state |
|
|
249
|
+
|
|
250
|
+
Elements can expose multiple parts, so generic and specific selectors compose:
|
|
251
|
+
|
|
252
|
+
```css
|
|
253
|
+
json-diff-viewer {
|
|
254
|
+
--add: lime;
|
|
255
|
+
--add-bg: color-mix(in srgb, lime 20%, transparent);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
json-diff-viewer::part(toolbar) {
|
|
259
|
+
border-block-end-width: 4px;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
json-diff-viewer::part(node-added) {
|
|
263
|
+
border-inline-start: 3px solid var(--add);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
json-diff-viewer::part(collapse-button) {
|
|
267
|
+
border-radius: 999px;
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Parts are the supported structural API. Internal classes and other shadow elements remain private. `::part()` cannot select descendants, so target each listed part directly. Changing layout, padding, or typography on `node` and `line` can desynchronize corresponding rows between panels.
|
|
272
|
+
|
|
209
273
|
### Sizing
|
|
210
274
|
|
|
211
275
|
Set a height to get scrolling. Without one, the viewer grows to fit all content. Default border-radius is `12px`.
|
|
@@ -237,6 +301,7 @@ json-diff-viewer {
|
|
|
237
301
|
```bash
|
|
238
302
|
npm run dev # start dev server
|
|
239
303
|
npm run build # build for production
|
|
304
|
+
npm run preview # preview the production build
|
|
240
305
|
```
|
|
241
306
|
|
|
242
307
|
## License
|
package/package.json
CHANGED
package/src/lib/styles.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
export default `
|
|
2
2
|
:host {
|
|
3
3
|
--add: #22c55e; --rem: #ef4444; --mod: #eab308;
|
|
4
|
+
--add-bg: color-mix(in srgb, var(--add) 15%, transparent);
|
|
5
|
+
--rem-bg: color-mix(in srgb, var(--rem) 15%, transparent);
|
|
6
|
+
--mod-bg: color-mix(in srgb, var(--mod) 15%, transparent);
|
|
4
7
|
--bg: #18181b; --bg2: #27272a; --bdr: #3f3f46;
|
|
5
8
|
--txt: #fafafa; --dim: #a1a1aa;
|
|
6
9
|
--key: #38bdf8; --str: #a78bfa; --num: #34d399; --bool: #fb923c; --nul: #f472b6; --br: #71717a;
|
|
7
|
-
--
|
|
10
|
+
--hover: rgb(0 0 0 / 3%);
|
|
11
|
+
--control-bg: var(--bg2); --control-hover: rgb(0 0 0 / 5%); --control-bdr: var(--bdr);
|
|
12
|
+
--slider: var(--bdr); --slider-thumb: var(--br);
|
|
8
13
|
display: flex; flex-direction: column; font: 13px 'JetBrains Mono', 'Fira Code', monospace;
|
|
9
14
|
background: var(--bg); color: var(--txt); border-radius: 12px; overflow: hidden;
|
|
10
15
|
}
|
|
@@ -15,7 +20,7 @@ export default `
|
|
|
15
20
|
.node { padding-left: 1.25rem; }
|
|
16
21
|
.node.root { padding-left: 0; }
|
|
17
22
|
.line { display: flex; align-items: flex-start; gap: 0.5rem; padding: 2px 4px; border-radius: 4px; cursor: pointer; transition: background .15s; }
|
|
18
|
-
.line:hover { background:
|
|
23
|
+
.line:hover { background: var(--hover); }
|
|
19
24
|
.line.placeholder { cursor: default; pointer-events: none; }
|
|
20
25
|
.line.placeholder:hover { background: transparent; }
|
|
21
26
|
.tog { width: 1rem; flex-shrink: 0; color: var(--br); user-select: none; }
|
|
@@ -28,9 +33,9 @@ export default `
|
|
|
28
33
|
.val-boolean { color: var(--bool); }
|
|
29
34
|
.val-null { color: var(--nul); font-style: italic; }
|
|
30
35
|
.br { color: var(--br); }
|
|
31
|
-
.node.diff-added { background:
|
|
32
|
-
.node.diff-removed { background:
|
|
33
|
-
.node.diff-modified { background:
|
|
36
|
+
.node.diff-added { background: var(--add-bg); }
|
|
37
|
+
.node.diff-removed { background: var(--rem-bg); }
|
|
38
|
+
.node.diff-modified { background: var(--mod-bg); }
|
|
34
39
|
.node.diff-added .key { color: var(--add); }
|
|
35
40
|
.node.diff-removed .key { color: var(--rem); }
|
|
36
41
|
.node.diff-modified .key { color: var(--mod); }
|
|
@@ -47,13 +52,13 @@ export default `
|
|
|
47
52
|
.switch { display: inline-block; cursor: pointer; }
|
|
48
53
|
.checkbox { display: none; }
|
|
49
54
|
.slider { width: 48px; height: 24px; background-color: var(--bdr); border-radius: 16px; overflow: hidden; display: flex; align-items: center; border: 3px solid transparent; transition: .3s; box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.25) inset; cursor: pointer; }
|
|
50
|
-
.slider::before { content: ''; display: block; width: 100%; height: 100%; background-color: var(--
|
|
55
|
+
.slider::before { content: ''; display: block; width: 100%; height: 100%; background-color: var(--slider-thumb); transform: translateX(-24px); border-radius: 16px; transition: .3s; box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.25); }
|
|
51
56
|
.checkbox:checked ~ .slider::before { transform: translateX(24px); box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.25); }
|
|
52
57
|
.checkbox:checked ~ .slider { background-color: var(--slider); }
|
|
53
58
|
.checkbox:active ~ .slider::before { transform: translate(0); }
|
|
54
|
-
.btn-collapse, .btn-expand { padding: 0.5rem; background: var(--
|
|
59
|
+
.btn-collapse, .btn-expand { padding: 0.5rem; background: var(--control-bg); border: 1px solid var(--control-bdr); border-radius: 10px; color: var(--txt); cursor: pointer; transition: background .15s, border-color .15s; display: flex; align-items: center; justify-content: center; }
|
|
55
60
|
.btn-collapse svg, .btn-expand svg { width: 18px; height: 18px; }
|
|
56
|
-
.btn-collapse:hover, .btn-expand:hover { background:
|
|
61
|
+
.btn-collapse:hover, .btn-expand:hover { background: var(--control-hover); box-shadow: 0 0 4px var(--control-bdr); }
|
|
57
62
|
.stat { display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: .35rem; }
|
|
58
63
|
.stat .dot { width: 8px; height: 8px; }
|
|
59
64
|
.stat-added .dot { background: var(--add); }
|
package/src/lib/viewer.js
CHANGED
|
@@ -22,7 +22,7 @@ const filterChildren = (children, showOnlyChanged) =>
|
|
|
22
22
|
const isExpanded = (proxy, path) => proxy[path] !== false;
|
|
23
23
|
|
|
24
24
|
const buildKeyHtml = (key, root, hidden = false) =>
|
|
25
|
-
root ? "" : `<span class="key"${hidden ? ' style="visibility: hidden;"' : ""}>${escapeHtml(key)}</span><span class="colon"${hidden ? ' style="visibility: hidden;"' : ""}>:</span>`;
|
|
25
|
+
root ? "" : `<span class="key" part="key"${hidden ? ' style="visibility: hidden;"' : ""}>${escapeHtml(key)}</span><span class="colon" part="separator"${hidden ? ' style="visibility: hidden;"' : ""}>:</span>`;
|
|
26
26
|
|
|
27
27
|
const buildRootClass = (root) => root ? " root" : "";
|
|
28
28
|
|
|
@@ -138,30 +138,30 @@ class JsonDiffViewer extends HTMLElement {
|
|
|
138
138
|
|
|
139
139
|
#render() {
|
|
140
140
|
if (!this.#tree) {
|
|
141
|
-
this.shadowRoot.innerHTML = `<style>${styles}</style><div class="empty">Provide left and right JSON</div>`;
|
|
141
|
+
this.shadowRoot.innerHTML = `<style>${styles}</style><div class="empty" part="empty">Provide left and right JSON</div>`;
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
const panel = this.shadowRoot.querySelector('.panel');
|
|
145
145
|
const scroll = { top: panel?.scrollTop || 0, left: panel?.scrollLeft || 0 };
|
|
146
146
|
this.shadowRoot.innerHTML = `
|
|
147
147
|
<style>${styles}</style>
|
|
148
|
-
<div class="stats">
|
|
149
|
-
<div class="stats-items">
|
|
150
|
-
${STAT_TYPES.map((t) => `<div class="stat stat-${t}"><span class="dot"></span>${this.#stats[t]} ${t.replace("_", " ")}</div>`).join("")}
|
|
148
|
+
<div class="stats" part="toolbar">
|
|
149
|
+
<div class="stats-items" part="legend">
|
|
150
|
+
${STAT_TYPES.map((t) => `<div class="stat stat-${t}" part="legend-item legend-${t}"><span class="dot" part="marker marker-${t}"></span>${this.#stats[t]} ${t.replace("_", " ")}</div>`).join("")}
|
|
151
151
|
</div>
|
|
152
|
-
<div class="stats-buttons">
|
|
153
|
-
<label class="switch" aria-label="Show only changed" title="Show only changed">
|
|
152
|
+
<div class="stats-buttons" part="actions">
|
|
153
|
+
<label class="switch" part="filter" aria-label="Show only changed" title="Show only changed">
|
|
154
154
|
<input type="checkbox" class="checkbox" data-action="filter" ${this.#showOnlyChanged ? "checked" : ""}>
|
|
155
|
-
<div class="slider"></div>
|
|
155
|
+
<div class="slider" part="filter-track"></div>
|
|
156
156
|
</label>
|
|
157
|
-
<button class="btn-collapse" data-action="collapse" title="Collapse all"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M9 15H6q-.425 0-.712-.288T5 14t.288-.712T6 13h4q.425 0 .713.288T11 14v4q0 .425-.288.713T10 19t-.712-.288T9 18zm6-6h3q.425 0 .713.288T19 10t-.288.713T18 11h-4q-.425 0-.712-.288T13 10V6q0-.425.288-.712T14 5t.713.288T15 6z"/></svg></button>
|
|
158
|
-
<button class="btn-expand" data-action="expand" title="Expand all"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M7 17h3q.425 0 .713.288T11 18t-.288.713T10 19H6q-.425 0-.712-.288T5 18v-4q0-.425.288-.712T6 13t.713.288T7 14zM17 7h-3q-.425 0-.712-.288T13 6t.288-.712T14 5h4q.425 0 .713.288T19 6v4q0 .425-.288.713T18 11t-.712-.288T17 10z"/></svg></button>
|
|
157
|
+
<button class="btn-collapse" part="action-button collapse-button" data-action="collapse" title="Collapse all"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M9 15H6q-.425 0-.712-.288T5 14t.288-.712T6 13h4q.425 0 .713.288T11 14v4q0 .425-.288.713T10 19t-.712-.288T9 18zm6-6h3q.425 0 .713.288T19 10t-.288.713T18 11h-4q-.425 0-.712-.288T13 10V6q0-.425.288-.712T14 5t.713.288T15 6z"/></svg></button>
|
|
158
|
+
<button class="btn-expand" part="action-button expand-button" data-action="expand" title="Expand all"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M7 17h3q.425 0 .713.288T11 18t-.288.713T10 19H6q-.425 0-.712-.288T5 18v-4q0-.425.288-.712T6 13t.713.288T7 14zM17 7h-3q-.425 0-.712-.288T13 6t.288-.712T14 5h4q.425 0 .713.288T19 6v4q0 .425-.288.713T18 11t-.712-.288T17 10z"/></svg></button>
|
|
159
159
|
</div>
|
|
160
160
|
</div>
|
|
161
|
-
<div class="container">
|
|
161
|
+
<div class="container" part="content">
|
|
162
162
|
${["left", "right"]
|
|
163
163
|
.map((side) => {
|
|
164
|
-
return `<div class="panel" data-side="${side}">${this.#renderNode(this.#tree, side, "")}</div>`;
|
|
164
|
+
return `<div class="panel" part="panel panel-${side}" data-side="${side}">${this.#renderNode(this.#tree, side, "")}</div>`;
|
|
165
165
|
})
|
|
166
166
|
.join("")}
|
|
167
167
|
</div>`;
|
|
@@ -184,18 +184,18 @@ class JsonDiffViewer extends HTMLElement {
|
|
|
184
184
|
const otherValue = side === 'left' ? node.right : node.left;
|
|
185
185
|
const [val, type] = format(otherValue);
|
|
186
186
|
const hiddenKey = buildKeyHtml(node.key, root, true);
|
|
187
|
-
return `<div class="node${rootClass}"><div class="line placeholder">${hiddenKey}<span class="val-${type}" style="visibility: hidden;">${escapeHtml(val)}</span></div></div>`;
|
|
187
|
+
return `<div class="node${rootClass}" part="node"><div class="line placeholder" part="line">${hiddenKey}<span class="val-${type}" part="value value-${type}" style="visibility: hidden;">${escapeHtml(val)}</span></div></div>`;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
if (value !== undefined && !node.isArray && !node.isObject) {
|
|
191
191
|
const [val, type] = format(value);
|
|
192
192
|
if (placeholder) {
|
|
193
|
-
return `<div class="node${rootClass}"><div class="line placeholder">${keyHtml}<span class="val-${type}"${hidden}>${escapeHtml(val)}</span></div></div>`;
|
|
193
|
+
return `<div class="node${rootClass}" part="node"><div class="line placeholder" part="line">${keyHtml}<span class="val-${type}" part="value value-${type}"${hidden}>${escapeHtml(val)}</span></div></div>`;
|
|
194
194
|
}
|
|
195
195
|
const hasDiff = node.hasDiff && node.type !== TYPE.UNCHANGED;
|
|
196
196
|
const diffClass = hasDiff ? `diff-${node.type}` : "";
|
|
197
197
|
const nodeDiffClass = hasDiff ? ` ${diffClass}` : "";
|
|
198
|
-
return `<div class="node${rootClass}${nodeDiffClass}"><div class="line"><span class="tog"></span>${keyHtml}<span class="val-${type}">${escapeHtml(val)}</span></div></div>`;
|
|
198
|
+
return `<div class="node${rootClass}${nodeDiffClass}" part="node${hasDiff ? ` node-${node.type}` : ""}"><div class="line" part="line"><span class="tog" part="toggle"></span>${keyHtml}<span class="val-${type}" part="value value-${type}">${escapeHtml(val)}</span></div></div>`;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
const [open, close] = getBrackets(node.isArray);
|
|
@@ -209,25 +209,25 @@ class JsonDiffViewer extends HTMLElement {
|
|
|
209
209
|
|
|
210
210
|
if (placeholder) {
|
|
211
211
|
if (!expanded) {
|
|
212
|
-
return `<div class="node${rootClass}"><div class="line placeholder">${keyHtml}<span class="br"${hidden}>${open}</span><span class="preview"${hidden}>${preview}</span><span class="br"${hidden}>${close}</span></div></div>`;
|
|
212
|
+
return `<div class="node${rootClass}" part="node"><div class="line placeholder" part="line">${keyHtml}<span class="br" part="bracket"${hidden}>${open}</span><span class="preview" part="preview"${hidden}>${preview}</span><span class="br" part="bracket"${hidden}>${close}</span></div></div>`;
|
|
213
213
|
}
|
|
214
|
-
return `<div class="node${rootClass}"><div class="line placeholder">${keyHtml}<span class="br"${hidden}>${open}</span></div>${childrenHtml}<div class="line placeholder"><span class="br"${hidden}>${close}</span></div></div>`;
|
|
214
|
+
return `<div class="node${rootClass}" part="node"><div class="line placeholder" part="line">${keyHtml}<span class="br" part="bracket"${hidden}>${open}</span></div>${childrenHtml}<div class="line placeholder" part="line"><span class="br" part="bracket"${hidden}>${close}</span></div></div>`;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
const hasDiff = node.hasDiff && node.type !== TYPE.UNCHANGED;
|
|
218
218
|
const diffClass = hasDiff ? `diff-${node.type}` : "";
|
|
219
219
|
const hasChildDiff = node.hasDiff && children.some((c) => c.hasDiff);
|
|
220
220
|
const dotType = node.type === TYPE.UNCHANGED ? "modified" : node.type;
|
|
221
|
-
const dot = hasChildDiff ? `<span class="dot dot-${dotType}"></span>` : "";
|
|
221
|
+
const dot = hasChildDiff ? `<span class="dot dot-${dotType}" part="marker marker-${dotType}"></span>` : "";
|
|
222
222
|
const nodeDiffClass = hasDiff && !hasChildDiff ? ` ${diffClass}` : "";
|
|
223
223
|
const toggle = expanded ? "▼" : "▶";
|
|
224
224
|
const dataPath = ` data-p="${escapeHtml(currentPath)}"`;
|
|
225
225
|
|
|
226
226
|
if (!expanded) {
|
|
227
|
-
return `<div class="node${rootClass}${nodeDiffClass}"><div class="line"${dataPath}><span class="tog">${toggle}</span>${dot}${keyHtml}<span class="br">${open}</span><span class="preview">${preview}</span><span class="br">${close}</span></div></div>`;
|
|
227
|
+
return `<div class="node${rootClass}${nodeDiffClass}" part="node${hasDiff ? ` node-${node.type}` : ""}"><div class="line" part="line"${dataPath}><span class="tog" part="toggle">${toggle}</span>${dot}${keyHtml}<span class="br" part="bracket">${open}</span><span class="preview" part="preview">${preview}</span><span class="br" part="bracket">${close}</span></div></div>`;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
return `<div class="node${rootClass}${nodeDiffClass}"><div class="line"${dataPath}><span class="tog">${toggle}</span>${dot}${keyHtml}<span class="br">${open}</span></div>${childrenHtml}<div class="line"><span class="tog"></span><span class="br">${close}</span></div></div>`;
|
|
230
|
+
return `<div class="node${rootClass}${nodeDiffClass}" part="node${hasDiff ? ` node-${node.type}` : ""}"><div class="line" part="line"${dataPath}><span class="tog" part="toggle">${toggle}</span>${dot}${keyHtml}<span class="br" part="bracket">${open}</span></div>${childrenHtml}<div class="line" part="line"><span class="tog" part="toggle"></span><span class="br" part="bracket">${close}</span></div></div>`;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
#bind() {
|