|
1 | | -export default class JSONElement extends HTMLElement { |
2 | | - constructor() { |
3 | | - super(); |
4 | | - const shadow = this.attachShadow({ mode: "open" }); |
5 | | - this.value = {}; |
6 | | - } |
7 | | - |
8 | | - static get styles() { |
9 | | - return ` |
10 | | - :host { |
11 | | - font-family: monospace; |
12 | | - } |
13 | | -
|
14 | | - details > div { |
15 | | - padding-left: 15px; |
16 | | - } |
17 | | -
|
18 | | - .key { |
19 | | - color: purple; |
20 | | - } |
21 | | -
|
22 | | - .value { |
23 | | - color: green; |
24 | | - } |
25 | | -
|
26 | | - .less { |
27 | | - color: grey; |
28 | | - } |
29 | | -
|
30 | | - `; |
31 | | - } |
32 | | - |
33 | | - connectedCallback() { |
34 | | - this.render(); |
35 | | - } |
36 | | - |
37 | | - render() { |
38 | | - this.shadowRoot.innerHTML = ` |
39 | | - <style> |
40 | | - ${JSONElement.styles} |
41 | | - </style> |
42 | | - ${this.renderNode(undefined, this.value)}`; |
43 | | - } |
44 | | - |
45 | | - // |
46 | | - // Main Renders |
47 | | - // |
48 | | - |
49 | | - renderNode(key, obj) { |
50 | | - const type = JSONElement.objType(obj); |
51 | | - switch (type) { |
52 | | - case "Object": |
53 | | - case "Array": |
54 | | - return this.renderParent(type, key, obj); |
55 | | - default: |
56 | | - return this.renderKeyValue(key, this.renderValue(type, obj)); |
57 | | - } |
58 | | - } |
59 | | - |
60 | | - renderValue(type, value) { |
61 | | - switch (type) { |
62 | | - case "Boolean": |
63 | | - return `${value ? "true" : "false"}`; |
64 | | - case "String": |
65 | | - return `"${value}"`; |
66 | | - case "Number": |
67 | | - return `${value}`; |
68 | | - case "Date": |
69 | | - return `${value.toISOString()}`; |
70 | | - case "Null": |
71 | | - return "null"; |
72 | | - case "Undefined": |
73 | | - return "undefined"; |
74 | | - case "Function": |
75 | | - case "Symbol": |
76 | | - return `${value.toString()}`; |
77 | | - default: |
78 | | - return `###unsupported yet###`; |
79 | | - } |
80 | | - } |
81 | | - |
82 | | - renderParent(type, key, value) { |
83 | | - const summary = `<summary>${this.renderSummaryObject( |
84 | | - type, |
85 | | - key, |
86 | | - value |
87 | | - )}</summary>`; |
88 | | - |
89 | | - let details = ""; |
90 | | - const keys = Reflect.ownKeys(value); |
91 | | - keys.forEach(key => { |
92 | | - details += this.renderNode(key, value[key]); |
93 | | - }); |
94 | | - |
95 | | - return `<details>${summary}<div>${details}</div></details>`; |
96 | | - } |
97 | | - |
98 | | - renderKeyValue(key, value) { |
99 | | - return `<div>${this.renderSpanKey(key)}${this.renderSpanValue( |
100 | | - value |
101 | | - )}</div>`; |
102 | | - } |
103 | | - |
104 | | - renderSpanKey(key) { |
105 | | - return key ? `<span class="key">${key}: </span>` : ""; |
106 | | - } |
107 | | - |
108 | | - renderSpanValue(value) { |
109 | | - return value ? `<span class="value">${value}</span>` : ""; |
110 | | - } |
111 | | - |
112 | | - renderSpanLessImportant(value) { |
113 | | - return value ? `<span class="less">${value}</span>` : ""; |
114 | | - } |
115 | | - |
116 | | - // |
117 | | - // Summary renders |
118 | | - // |
119 | | - |
120 | | - renderSummaryObject(type, key, value) { |
121 | | - const frontkey = this.renderSpanKey(key); |
122 | | - |
123 | | - let openSummary = ""; |
124 | | - let closeSummary = ""; |
125 | | - |
126 | | - switch (type) { |
127 | | - case "Object": |
128 | | - openSummary = "Object: {"; |
129 | | - closeSummary = "}"; |
130 | | - break; |
131 | | - case "Array": |
132 | | - openSummary = "Array: ["; |
133 | | - closeSummary = "]"; |
134 | | - break; |
135 | | - } |
136 | | - |
137 | | - const keys = Reflect.ownKeys(value); |
138 | | - |
139 | | - const content = keys.reduce((accu, key, index) => { |
140 | | - if (index > 5) return accu; |
141 | | - if (index == 5) return accu + ` ${this.renderSpanLessImportant("...")}`; |
142 | | - // less than 5 items show in summary |
143 | | - const child = value[key]; |
144 | | - return ( |
145 | | - accu + ` ${this.renderSpanKey(key)}${this.renderSummaryValue(child)}` |
146 | | - ); |
147 | | - }, ""); |
148 | | - |
149 | | - return `${frontkey}${openSummary} ${content} ${closeSummary}`; |
150 | | - } |
151 | | - |
152 | | - renderSummaryValue(value) { |
153 | | - const type = JSONElement.objType(value); |
154 | | - switch (type) { |
155 | | - case "Object": |
156 | | - return this.renderSpanLessImportant("{...}"); |
157 | | - case "Array": |
158 | | - return this.renderSpanLessImportant("[...]"); |
159 | | - default: |
160 | | - return this.renderSpanValue(this.renderValue(type, value)); |
161 | | - } |
162 | | - } |
163 | | - |
164 | | - // |
165 | | - // Tools |
166 | | - // |
167 | | - |
168 | | - static objType(obj) { |
169 | | - const type = Object.prototype.toString.call(obj).slice(8, -1); |
170 | | - if (type === "Object") { |
171 | | - if (typeof obj[Symbol.iterator] === "function") { |
172 | | - return "Iterable"; |
173 | | - } |
174 | | - return obj.constructor.name; |
175 | | - } |
176 | | - |
177 | | - return type; |
178 | | - } |
179 | | -} |
| 1 | +import JSONElement from "./JSONElement"; |
| 2 | +export default JSONElement; |
0 commit comments