cyberchef 9.38.6 → 9.38.9
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/package.json +2 -1
- package/src/core/config/OperationConfig.json +8 -3
- package/src/core/lib/Base64.mjs +8 -7
- package/src/core/lib/PublicKey.mjs +12 -22
- package/src/core/operations/JSONBeautify.mjs +193 -27
- package/src/core/operations/PEMToHex.mjs +1 -1
- package/src/core/operations/ParseX509Certificate.mjs +5 -5
- package/src/web/stylesheets/index.css +3 -0
- package/src/web/stylesheets/operations/json.css +78 -0
- package/tests/operations/tests/JSONBeautify.mjs +26 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyberchef",
|
|
3
|
-
"version": "9.38.
|
|
3
|
+
"version": "9.38.9",
|
|
4
4
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
|
5
5
|
"author": "n1474335 <n1474335@gmail.com>",
|
|
6
6
|
"homepage": "https://gchq.github.io/CyberChef",
|
|
@@ -122,6 +122,7 @@
|
|
|
122
122
|
"js-crc": "^0.2.0",
|
|
123
123
|
"js-sha3": "^0.8.0",
|
|
124
124
|
"jsesc": "^3.0.2",
|
|
125
|
+
"json5": "^2.2.1",
|
|
125
126
|
"jsonpath": "^1.1.1",
|
|
126
127
|
"jsonwebtoken": "^8.5.1",
|
|
127
128
|
"jsqr": "^1.4.0",
|
|
@@ -7637,10 +7637,10 @@
|
|
|
7637
7637
|
},
|
|
7638
7638
|
"JSON Beautify": {
|
|
7639
7639
|
"module": "Code",
|
|
7640
|
-
"description": "Indents and
|
|
7640
|
+
"description": "Indents and pretty prints JavaScript Object Notation (JSON) code.<br><br>Tags: json viewer, prettify, syntax highlighting",
|
|
7641
7641
|
"infoURL": null,
|
|
7642
7642
|
"inputType": "string",
|
|
7643
|
-
"outputType": "
|
|
7643
|
+
"outputType": "html",
|
|
7644
7644
|
"flowControl": false,
|
|
7645
7645
|
"manualBake": false,
|
|
7646
7646
|
"args": [
|
|
@@ -7653,6 +7653,11 @@
|
|
|
7653
7653
|
"name": "Sort Object Keys",
|
|
7654
7654
|
"type": "boolean",
|
|
7655
7655
|
"value": false
|
|
7656
|
+
},
|
|
7657
|
+
{
|
|
7658
|
+
"name": "Formatted",
|
|
7659
|
+
"type": "boolean",
|
|
7660
|
+
"value": true
|
|
7656
7661
|
}
|
|
7657
7662
|
]
|
|
7658
7663
|
},
|
|
@@ -8580,7 +8585,7 @@
|
|
|
8580
8585
|
"PEM to Hex": {
|
|
8581
8586
|
"module": "Default",
|
|
8582
8587
|
"description": "Converts PEM (Privacy Enhanced Mail) format to a hexadecimal DER (Distinguished Encoding Rules) string.",
|
|
8583
|
-
"infoURL": "https://
|
|
8588
|
+
"infoURL": "https://wikipedia.org/wiki/Privacy-Enhanced_Mail#Format",
|
|
8584
8589
|
"inputType": "string",
|
|
8585
8590
|
"outputType": "string",
|
|
8586
8591
|
"flowControl": false,
|
package/src/core/lib/Base64.mjs
CHANGED
|
@@ -130,10 +130,11 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
|
|
|
130
130
|
i = 0;
|
|
131
131
|
|
|
132
132
|
while (i < data.length) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
// Including `|| null` forces empty strings to null so that indexOf returns -1 instead of 0
|
|
134
|
+
enc1 = alphabet.indexOf(data.charAt(i++) || null);
|
|
135
|
+
enc2 = alphabet.indexOf(data.charAt(i++) || null);
|
|
136
|
+
enc3 = alphabet.indexOf(data.charAt(i++) || null);
|
|
137
|
+
enc4 = alphabet.indexOf(data.charAt(i++) || null);
|
|
137
138
|
|
|
138
139
|
if (strictMode && (enc1 < 0 || enc2 < 0 || enc3 < 0 || enc4 < 0)) {
|
|
139
140
|
throw new OperationError("Error: Base64 input contains non-alphabet char(s)");
|
|
@@ -143,13 +144,13 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
|
|
|
143
144
|
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
|
144
145
|
chr3 = ((enc3 & 3) << 6) | enc4;
|
|
145
146
|
|
|
146
|
-
if (chr1 < 256) {
|
|
147
|
+
if (chr1 >= 0 && chr1 < 256) {
|
|
147
148
|
output.push(chr1);
|
|
148
149
|
}
|
|
149
|
-
if (chr2 < 256 && enc3 !== 64) {
|
|
150
|
+
if (chr2 >= 0 && chr2 < 256 && enc3 !== 64) {
|
|
150
151
|
output.push(chr2);
|
|
151
152
|
}
|
|
152
|
-
if (chr3 < 256 && enc4 !== 64) {
|
|
153
|
+
if (chr3 >= 0 && chr3 < 256 && enc4 !== 64) {
|
|
153
154
|
output.push(chr3);
|
|
154
155
|
}
|
|
155
156
|
}
|
|
@@ -9,35 +9,25 @@
|
|
|
9
9
|
import { toHex, fromHex } from "./Hex.mjs";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Formats Distinguished Name (DN) strings.
|
|
12
|
+
* Formats Distinguished Name (DN) objects to strings.
|
|
13
13
|
*
|
|
14
|
-
* @param {
|
|
14
|
+
* @param {Object} dnObj
|
|
15
15
|
* @param {number} indent
|
|
16
16
|
* @returns {string}
|
|
17
17
|
*/
|
|
18
|
-
export function
|
|
19
|
-
|
|
20
|
-
let output = "",
|
|
21
|
-
maxKeyLen = 0,
|
|
22
|
-
key,
|
|
23
|
-
value,
|
|
24
|
-
i,
|
|
25
|
-
str;
|
|
26
|
-
|
|
27
|
-
for (i = 0; i < fields.length; i++) {
|
|
28
|
-
if (!fields[i].length) continue;
|
|
29
|
-
|
|
30
|
-
key = fields[i].split("=")[0];
|
|
18
|
+
export function formatDnObj(dnObj, indent) {
|
|
19
|
+
let output = "";
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
const maxKeyLen = dnObj.array.reduce((max, item) => {
|
|
22
|
+
return item[0].type.length > max ? item[0].type.length : max;
|
|
23
|
+
}, 0);
|
|
34
24
|
|
|
35
|
-
for (i = 0; i <
|
|
36
|
-
if (!
|
|
25
|
+
for (let i = 0; i < dnObj.array.length; i++) {
|
|
26
|
+
if (!dnObj.array[i].length) continue;
|
|
37
27
|
|
|
38
|
-
key =
|
|
39
|
-
value =
|
|
40
|
-
str = key.padEnd(maxKeyLen, " ")
|
|
28
|
+
const key = dnObj.array[i][0].type;
|
|
29
|
+
const value = dnObj.array[i][0].value;
|
|
30
|
+
const str = `${key.padEnd(maxKeyLen, " ")} = ${value}\n`;
|
|
41
31
|
|
|
42
32
|
output += str.padStart(indent + str.length, " ");
|
|
43
33
|
}
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
* @license Apache-2.0
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import JSON5 from "json5";
|
|
9
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
9
10
|
import Operation from "../Operation.mjs";
|
|
11
|
+
import Utils from "../Utils.mjs";
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* JSON Beautify operation
|
|
@@ -21,19 +23,25 @@ class JSONBeautify extends Operation {
|
|
|
21
23
|
|
|
22
24
|
this.name = "JSON Beautify";
|
|
23
25
|
this.module = "Code";
|
|
24
|
-
this.description = "Indents and
|
|
26
|
+
this.description = "Indents and pretty prints JavaScript Object Notation (JSON) code.<br><br>Tags: json viewer, prettify, syntax highlighting";
|
|
25
27
|
this.inputType = "string";
|
|
26
28
|
this.outputType = "string";
|
|
29
|
+
this.presentType = "html";
|
|
27
30
|
this.args = [
|
|
28
31
|
{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
name: "Indent string",
|
|
33
|
+
type: "binaryShortString",
|
|
34
|
+
value: " "
|
|
32
35
|
},
|
|
33
36
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
name: "Sort Object Keys",
|
|
38
|
+
type: "boolean",
|
|
39
|
+
value: false
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "Formatted",
|
|
43
|
+
type: "boolean",
|
|
44
|
+
value: true
|
|
37
45
|
}
|
|
38
46
|
];
|
|
39
47
|
}
|
|
@@ -44,35 +52,193 @@ class JSONBeautify extends Operation {
|
|
|
44
52
|
* @returns {string}
|
|
45
53
|
*/
|
|
46
54
|
run(input, args) {
|
|
55
|
+
if (!input) return "";
|
|
56
|
+
|
|
47
57
|
const [indentStr, sortBool] = args;
|
|
58
|
+
let json = null;
|
|
48
59
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
60
|
+
try {
|
|
61
|
+
json = JSON5.parse(input);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
throw new OperationError("Unable to parse input as JSON.\n" + err);
|
|
52
64
|
}
|
|
53
|
-
return vkbeautify.json(input, indentStr);
|
|
54
|
-
}
|
|
55
65
|
|
|
66
|
+
if (sortBool) json = sortKeys(json);
|
|
67
|
+
|
|
68
|
+
return JSON.stringify(json, null, indentStr);
|
|
69
|
+
}
|
|
56
70
|
|
|
57
71
|
/**
|
|
58
|
-
*
|
|
72
|
+
* Adds various dynamic features to the JSON blob
|
|
59
73
|
*
|
|
60
|
-
* @
|
|
61
|
-
* @
|
|
62
|
-
* @
|
|
63
|
-
* @returns {object}
|
|
74
|
+
* @param {string} data
|
|
75
|
+
* @param {Object[]} args
|
|
76
|
+
* @returns {html}
|
|
64
77
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
present(data, args) {
|
|
79
|
+
const formatted = args[2];
|
|
80
|
+
if (!formatted) return Utils.escapeHtml(data);
|
|
81
|
+
|
|
82
|
+
const json = JSON5.parse(data);
|
|
83
|
+
const options = {
|
|
84
|
+
withLinks: true,
|
|
85
|
+
bigNumbers: true
|
|
86
|
+
};
|
|
87
|
+
let html = '<div class="json-document">';
|
|
88
|
+
|
|
89
|
+
if (isCollapsable(json)) {
|
|
90
|
+
const isArr = json instanceof Array;
|
|
91
|
+
html += '<details open class="json-details">' +
|
|
92
|
+
`<summary class="json-summary ${isArr ? "json-arr" : "json-obj"}"></summary>` +
|
|
93
|
+
json2html(json, options) +
|
|
94
|
+
"</details>";
|
|
95
|
+
} else {
|
|
96
|
+
html += json2html(json, options);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
html += "</div>";
|
|
100
|
+
return html;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Sort keys in a JSON object
|
|
106
|
+
*
|
|
107
|
+
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
|
|
108
|
+
* @param {object} o
|
|
109
|
+
* @returns {object}
|
|
110
|
+
*/
|
|
111
|
+
function sortKeys(o) {
|
|
112
|
+
if (Array.isArray(o)) {
|
|
113
|
+
return o.map(sortKeys);
|
|
114
|
+
} else if ("[object Object]" === Object.prototype.toString.call(o)) {
|
|
115
|
+
return Object.keys(o).sort().reduce(function(a, k) {
|
|
116
|
+
a[k] = sortKeys(o[k]);
|
|
117
|
+
return a;
|
|
118
|
+
}, {});
|
|
119
|
+
}
|
|
120
|
+
return o;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Check if arg is either an array with at least 1 element, or a dict with at least 1 key
|
|
126
|
+
* @returns {boolean}
|
|
127
|
+
*/
|
|
128
|
+
function isCollapsable(arg) {
|
|
129
|
+
return arg instanceof Object && Object.keys(arg).length > 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check if a string looks like a URL, based on protocol
|
|
134
|
+
* @returns {boolean}
|
|
135
|
+
*/
|
|
136
|
+
function isUrl(string) {
|
|
137
|
+
const protocols = ["http", "https", "ftp", "ftps"];
|
|
138
|
+
for (let i = 0; i < protocols.length; i++) {
|
|
139
|
+
if (string.startsWith(protocols[i] + "://")) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Transform a json object into html representation
|
|
148
|
+
*
|
|
149
|
+
* Adapted for CyberChef by @n1474335 from jQuery json-viewer
|
|
150
|
+
* @author Alexandre Bodelot <alexandre.bodelot@gmail.com>
|
|
151
|
+
* @link https://github.com/abodelot/jquery.json-viewer
|
|
152
|
+
* @license MIT
|
|
153
|
+
*
|
|
154
|
+
* @returns {string}
|
|
155
|
+
*/
|
|
156
|
+
function json2html(json, options) {
|
|
157
|
+
let html = "";
|
|
158
|
+
if (typeof json === "string") {
|
|
159
|
+
// Escape tags and quotes
|
|
160
|
+
json = Utils.escapeHtml(json);
|
|
161
|
+
|
|
162
|
+
if (options.withLinks && isUrl(json)) {
|
|
163
|
+
html += `<a href="${json}" class="json-string" target="_blank">${json}</a>`;
|
|
164
|
+
} else {
|
|
165
|
+
// Escape double quotes in the rendered non-URL string.
|
|
166
|
+
json = json.replace(/"/g, "\\"");
|
|
167
|
+
html += `<span class="json-string">"${json}"</span>`;
|
|
168
|
+
}
|
|
169
|
+
} else if (typeof json === "number" || typeof json === "bigint") {
|
|
170
|
+
html += `<span class="json-literal">${json}</span>`;
|
|
171
|
+
} else if (typeof json === "boolean") {
|
|
172
|
+
html += `<span class="json-literal">${json}</span>`;
|
|
173
|
+
} else if (json === null) {
|
|
174
|
+
html += '<span class="json-literal">null</span>';
|
|
175
|
+
} else if (json instanceof Array) {
|
|
176
|
+
if (json.length > 0) {
|
|
177
|
+
html += '<span class="json-bracket">[</span><ol class="json-array">';
|
|
178
|
+
for (let i = 0; i < json.length; i++) {
|
|
179
|
+
html += "<li>";
|
|
180
|
+
|
|
181
|
+
// Add toggle button if item is collapsable
|
|
182
|
+
if (isCollapsable(json[i])) {
|
|
183
|
+
const isArr = json[i] instanceof Array;
|
|
184
|
+
html += '<details open class="json-details">' +
|
|
185
|
+
`<summary class="json-summary ${isArr ? "json-arr" : "json-obj"}"></summary>` +
|
|
186
|
+
json2html(json[i], options) +
|
|
187
|
+
"</details>";
|
|
188
|
+
} else {
|
|
189
|
+
html += json2html(json[i], options);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Add comma if item is not last
|
|
193
|
+
if (i < json.length - 1) {
|
|
194
|
+
html += '<span class="json-comma">,</span>';
|
|
195
|
+
}
|
|
196
|
+
html += "</li>";
|
|
197
|
+
}
|
|
198
|
+
html += '</ol><span class="json-bracket">]</span>';
|
|
199
|
+
} else {
|
|
200
|
+
html += '<span class="json-bracket">[]</span>';
|
|
201
|
+
}
|
|
202
|
+
} else if (typeof json === "object") {
|
|
203
|
+
// Optional support different libraries for big numbers
|
|
204
|
+
// json.isLosslessNumber: package lossless-json
|
|
205
|
+
// json.toExponential(): packages bignumber.js, big.js, decimal.js, decimal.js-light, others?
|
|
206
|
+
if (options.bigNumbers && (typeof json.toExponential === "function" || json.isLosslessNumber)) {
|
|
207
|
+
html += `<span class="json-literal">${json.toString()}</span>`;
|
|
208
|
+
} else {
|
|
209
|
+
let keyCount = Object.keys(json).length;
|
|
210
|
+
if (keyCount > 0) {
|
|
211
|
+
html += '<span class="json-brace">{</span><ul class="json-dict">';
|
|
212
|
+
for (const key in json) {
|
|
213
|
+
if (Object.prototype.hasOwnProperty.call(json, key)) {
|
|
214
|
+
const safeKey = Utils.escapeHtml(key);
|
|
215
|
+
html += "<li>";
|
|
216
|
+
|
|
217
|
+
// Add toggle button if item is collapsable
|
|
218
|
+
if (isCollapsable(json[key])) {
|
|
219
|
+
const isArr = json[key] instanceof Array;
|
|
220
|
+
html += '<details open class="json-details">' +
|
|
221
|
+
`<summary class="json-summary ${isArr ? "json-arr" : "json-obj"}">${safeKey}<span class="json-colon">:</span> </summary>` +
|
|
222
|
+
json2html(json[key], options) +
|
|
223
|
+
"</details>";
|
|
224
|
+
} else {
|
|
225
|
+
html += safeKey + '<span class="json-colon">:</span> ' + json2html(json[key], options);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Add comma if item is not last
|
|
229
|
+
if (--keyCount > 0) {
|
|
230
|
+
html += '<span class="json-comma">,</span>';
|
|
231
|
+
}
|
|
232
|
+
html += "</li>";
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
html += '</ul><span class="json-brace">}</span>';
|
|
236
|
+
} else {
|
|
237
|
+
html += '<span class="json-brace">{}</span>';
|
|
238
|
+
}
|
|
73
239
|
}
|
|
74
|
-
return o;
|
|
75
240
|
}
|
|
241
|
+
return html;
|
|
76
242
|
}
|
|
77
243
|
|
|
78
244
|
export default JSONBeautify;
|
|
@@ -24,7 +24,7 @@ class PEMToHex extends Operation {
|
|
|
24
24
|
this.name = "PEM to Hex";
|
|
25
25
|
this.module = "Default";
|
|
26
26
|
this.description = "Converts PEM (Privacy Enhanced Mail) format to a hexadecimal DER (Distinguished Encoding Rules) string.";
|
|
27
|
-
this.infoURL = "https://
|
|
27
|
+
this.infoURL = "https://wikipedia.org/wiki/Privacy-Enhanced_Mail#Format";
|
|
28
28
|
this.inputType = "string";
|
|
29
29
|
this.outputType = "string";
|
|
30
30
|
this.args = [];
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import r from "jsrsasign";
|
|
8
8
|
import { fromBase64 } from "../lib/Base64.mjs";
|
|
9
9
|
import { toHex } from "../lib/Hex.mjs";
|
|
10
|
-
import { formatByteStr,
|
|
10
|
+
import { formatByteStr, formatDnObj } from "../lib/PublicKey.mjs";
|
|
11
11
|
import Operation from "../Operation.mjs";
|
|
12
12
|
import Utils from "../Utils.mjs";
|
|
13
13
|
|
|
@@ -76,8 +76,8 @@ class ParseX509Certificate extends Operation {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
const sn = cert.getSerialNumberHex(),
|
|
79
|
-
issuer = cert.
|
|
80
|
-
subject = cert.
|
|
79
|
+
issuer = cert.getIssuer(),
|
|
80
|
+
subject = cert.getSubject(),
|
|
81
81
|
pk = cert.getPublicKey(),
|
|
82
82
|
pkFields = [],
|
|
83
83
|
sig = cert.getSignatureValueHex();
|
|
@@ -170,10 +170,10 @@ class ParseX509Certificate extends Operation {
|
|
|
170
170
|
extensions = cert.getInfo().split("X509v3 Extensions:\n")[1].split("signature")[0];
|
|
171
171
|
} catch (err) {}
|
|
172
172
|
|
|
173
|
-
const issuerStr =
|
|
173
|
+
const issuerStr = formatDnObj(issuer, 2),
|
|
174
174
|
nbDate = formatDate(cert.getNotBefore()),
|
|
175
175
|
naDate = formatDate(cert.getNotAfter()),
|
|
176
|
-
subjectStr =
|
|
176
|
+
subjectStr = formatDnObj(subject, 2);
|
|
177
177
|
|
|
178
178
|
return `Version: ${cert.version} (0x${Utils.hex(cert.version - 1)})
|
|
179
179
|
Serial number: ${new r.BigInteger(sn, 16).toString()} (0x${sn})
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON styles
|
|
3
|
+
*
|
|
4
|
+
* @author n1474335 [n1474335@gmail.com]
|
|
5
|
+
* @copyright Crown Copyright 2022
|
|
6
|
+
* @license Apache-2.0
|
|
7
|
+
*
|
|
8
|
+
* Adapted for CyberChef by @n1474335 from jQuery json-viewer
|
|
9
|
+
* @author Alexandre Bodelot <alexandre.bodelot@gmail.com>
|
|
10
|
+
* @link https://github.com/abodelot/jquery.json-viewer
|
|
11
|
+
* @license MIT
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* Root element */
|
|
15
|
+
.json-document {
|
|
16
|
+
padding: .5em 1.5em;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Syntax highlighting for JSON objects */
|
|
20
|
+
ul.json-dict, ol.json-array {
|
|
21
|
+
list-style-type: none;
|
|
22
|
+
margin: 0 0 0 1px;
|
|
23
|
+
border-left: 1px dotted #ccc;
|
|
24
|
+
padding-left: 2em;
|
|
25
|
+
}
|
|
26
|
+
.json-string {
|
|
27
|
+
color: green;
|
|
28
|
+
}
|
|
29
|
+
.json-literal {
|
|
30
|
+
color: red;
|
|
31
|
+
}
|
|
32
|
+
.json-brace,
|
|
33
|
+
.json-bracket,
|
|
34
|
+
.json-colon,
|
|
35
|
+
.json-comma {
|
|
36
|
+
color: gray;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Collapse */
|
|
40
|
+
.json-details {
|
|
41
|
+
display: inline;
|
|
42
|
+
}
|
|
43
|
+
.json-details[open] {
|
|
44
|
+
display: contents;
|
|
45
|
+
}
|
|
46
|
+
.json-summary {
|
|
47
|
+
display: contents;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Display object and array brackets when closed */
|
|
51
|
+
.json-summary.json-obj::after {
|
|
52
|
+
color: gray;
|
|
53
|
+
content: "{ ... }"
|
|
54
|
+
}
|
|
55
|
+
.json-summary.json-arr::after {
|
|
56
|
+
color: gray;
|
|
57
|
+
content: "[ ... ]"
|
|
58
|
+
}
|
|
59
|
+
.json-details[open] > .json-summary.json-obj::after,
|
|
60
|
+
.json-details[open] > .json-summary.json-arr::after {
|
|
61
|
+
content: "";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Show arrows, even in inline mode */
|
|
65
|
+
.json-summary::before {
|
|
66
|
+
content: "\25BC";
|
|
67
|
+
color: #c0c0c0;
|
|
68
|
+
margin-left: -12px;
|
|
69
|
+
margin-right: 5px;
|
|
70
|
+
display: inline-block;
|
|
71
|
+
transform: rotate(-90deg);
|
|
72
|
+
}
|
|
73
|
+
.json-summary:hover::before {
|
|
74
|
+
color: #aaa;
|
|
75
|
+
}
|
|
76
|
+
.json-details[open] > .json-summary::before {
|
|
77
|
+
transform: rotate(0deg);
|
|
78
|
+
}
|
|
@@ -16,7 +16,7 @@ TestRegister.addTests([
|
|
|
16
16
|
recipeConfig: [
|
|
17
17
|
{
|
|
18
18
|
op: "JSON Beautify",
|
|
19
|
-
args: [" ", false],
|
|
19
|
+
args: [" ", false, false],
|
|
20
20
|
},
|
|
21
21
|
],
|
|
22
22
|
},
|
|
@@ -27,7 +27,7 @@ TestRegister.addTests([
|
|
|
27
27
|
recipeConfig: [
|
|
28
28
|
{
|
|
29
29
|
op: "JSON Beautify",
|
|
30
|
-
args: [" ", false],
|
|
30
|
+
args: [" ", false, false],
|
|
31
31
|
},
|
|
32
32
|
],
|
|
33
33
|
},
|
|
@@ -38,8 +38,12 @@ TestRegister.addTests([
|
|
|
38
38
|
recipeConfig: [
|
|
39
39
|
{
|
|
40
40
|
op: "JSON Beautify",
|
|
41
|
-
args: [" ", false],
|
|
41
|
+
args: [" ", false, false],
|
|
42
42
|
},
|
|
43
|
+
{
|
|
44
|
+
op: "HTML To Text",
|
|
45
|
+
args: []
|
|
46
|
+
}
|
|
43
47
|
],
|
|
44
48
|
},
|
|
45
49
|
{
|
|
@@ -49,7 +53,7 @@ TestRegister.addTests([
|
|
|
49
53
|
recipeConfig: [
|
|
50
54
|
{
|
|
51
55
|
op: "JSON Beautify",
|
|
52
|
-
args: [" ", false],
|
|
56
|
+
args: [" ", false, false],
|
|
53
57
|
},
|
|
54
58
|
],
|
|
55
59
|
},
|
|
@@ -60,7 +64,7 @@ TestRegister.addTests([
|
|
|
60
64
|
recipeConfig: [
|
|
61
65
|
{
|
|
62
66
|
op: "JSON Beautify",
|
|
63
|
-
args: [" ", false],
|
|
67
|
+
args: [" ", false, false],
|
|
64
68
|
},
|
|
65
69
|
],
|
|
66
70
|
},
|
|
@@ -71,7 +75,7 @@ TestRegister.addTests([
|
|
|
71
75
|
recipeConfig: [
|
|
72
76
|
{
|
|
73
77
|
op: "JSON Beautify",
|
|
74
|
-
args: [" ", false],
|
|
78
|
+
args: [" ", false, false],
|
|
75
79
|
},
|
|
76
80
|
],
|
|
77
81
|
},
|
|
@@ -82,7 +86,7 @@ TestRegister.addTests([
|
|
|
82
86
|
recipeConfig: [
|
|
83
87
|
{
|
|
84
88
|
op: "JSON Beautify",
|
|
85
|
-
args: ["\t", false],
|
|
89
|
+
args: ["\t", false, false],
|
|
86
90
|
},
|
|
87
91
|
],
|
|
88
92
|
},
|
|
@@ -93,8 +97,12 @@ TestRegister.addTests([
|
|
|
93
97
|
recipeConfig: [
|
|
94
98
|
{
|
|
95
99
|
op: "JSON Beautify",
|
|
96
|
-
args: [" ", false],
|
|
100
|
+
args: [" ", false, false],
|
|
97
101
|
},
|
|
102
|
+
{
|
|
103
|
+
op: "HTML To Text",
|
|
104
|
+
args: []
|
|
105
|
+
}
|
|
98
106
|
],
|
|
99
107
|
},
|
|
100
108
|
{
|
|
@@ -104,8 +112,12 @@ TestRegister.addTests([
|
|
|
104
112
|
recipeConfig: [
|
|
105
113
|
{
|
|
106
114
|
op: "JSON Beautify",
|
|
107
|
-
args: ["\t", false],
|
|
115
|
+
args: ["\t", false, false],
|
|
108
116
|
},
|
|
117
|
+
{
|
|
118
|
+
op: "HTML To Text",
|
|
119
|
+
args: []
|
|
120
|
+
}
|
|
109
121
|
],
|
|
110
122
|
},
|
|
111
123
|
{
|
|
@@ -115,8 +127,12 @@ TestRegister.addTests([
|
|
|
115
127
|
recipeConfig: [
|
|
116
128
|
{
|
|
117
129
|
op: "JSON Beautify",
|
|
118
|
-
args: ["\t", true],
|
|
130
|
+
args: ["\t", true, false],
|
|
119
131
|
},
|
|
132
|
+
{
|
|
133
|
+
op: "HTML To Text",
|
|
134
|
+
args: []
|
|
135
|
+
}
|
|
120
136
|
],
|
|
121
137
|
},
|
|
122
138
|
]);
|