@curveball/browser
Version:
Automatic API browser generator. A middleware that turns your JSON responses into HTML if accessed by a browser.
130 lines • 5.95 kB
JavaScript
import * as React from 'react';
export default function JsonViewer(props) {
const data = JSON.parse(props.data);
return React.createElement("code", { className: "hljs" }, renderJsonValue(data, undefined, props.schema ?? undefined));
}
function renderJsonValue(value, asLink, schema) {
if (value === null) {
return React.createElement("span", { className: "hljs-keyword" }, "null");
}
if (typeof value === 'boolean') {
return React.createElement("span", { className: "hljs-keyword" }, value ? 'true' : 'false');
}
if (typeof value === 'string') {
if (asLink && isLegalLink(value)) {
return React.createElement("span", { className: "hljs-string" },
"\"",
React.createElement("a", { href: value }, value),
"\"");
}
else {
return React.createElement("span", { className: "hljs-string" },
"\"",
value,
"\"");
}
}
if (typeof value === 'number') {
return React.createElement("span", { className: "hljs-number" }, value);
}
if (Array.isArray(value)) {
let arrayItemSchema = undefined;
if (schema?.items && !Array.isArray(schema.items)) {
arrayItemSchema = schema.items;
}
return React.createElement(React.Fragment, null,
React.createElement("span", { className: "hljs-punctuation" }, "["),
React.createElement("ul", null, (value.map((item, idx) => {
return React.createElement("li", { key: idx },
renderJsonValue(item, false, arrayItemSchema),
idx < value.length - 1 ? React.createElement("span", { className: "hljs-punctuation" }, ",") : null);
}))),
React.createElement("span", { className: "hljs-punctuation" }, "]"));
}
return renderJsonObject(value, false, schema);
}
function renderJsonObject(value, skipOpen = false, jsonSchema) {
return React.createElement(React.Fragment, null,
skipOpen ? null : React.createElement(React.Fragment, null,
React.createElement("span", { className: "hljs-punctuation" }, '{'),
React.createElement("br", null)),
React.createElement("ul", null, (Object.entries(value).map(([key, value], idx, arr) => {
return renderCollapsableRow(key, value, idx >= arr.length - 1, jsonSchema?.properties?.[key]);
}))),
React.createElement("span", { className: "hljs-punctuation" }, '}'));
}
function renderCollapsableRow(key, value, isLast, jsonSchema) {
const description = jsonSchema?.description ? React.createElement("li", { key: key + '-desc' },
React.createElement("span", { className: "hljs-comment" }, '// ' + jsonSchema.description)) : undefined;
if (isJsonObject(value)) {
// Open by default, unless the key starts with undescore
// This ensures that stuff like _links, _embedded starts closed
const open = !key.startsWith('_');
return React.createElement(React.Fragment, { key: key },
description,
React.createElement("li", { key: key },
React.createElement("details", { open: open },
React.createElement("summary", null,
React.createElement("span", { className: "hidden-copy-paste" }, "\""),
React.createElement("span", { className: "hljs-attr" }, key),
React.createElement("span", { className: "hidden-copy-paste" }, "\""),
React.createElement("span", { className: "hljs-punctuation" },
": ",
'{'),
React.createElement("span", { className: "hidden-when-open" },
React.createElement("span", { className: "hljs-punctuation" },
" ",
React.createElement("em", null,
Object.keys(value).length,
" properties"),
" ",
'}'))),
renderJsonObject(value, true, jsonSchema),
isLast ? null : React.createElement("span", { className: "hljs-punctuation" }, ","))));
}
else {
return React.createElement(React.Fragment, { key: key },
description,
React.createElement("li", { key: key },
React.createElement("span", { className: "hidden-copy-paste" }, "\""),
React.createElement("span", { className: "hljs-attr" }, key),
React.createElement("span", { className: "hidden-copy-paste" }, "\""),
React.createElement("span", { className: "hljs-punctuation" }, ": "),
renderJsonValue(value, isLikelyAUri(key), jsonSchema),
isLast ? null : React.createElement("span", { className: "hljs-punctuation" }, ",")));
}
}
/**
* Checks at a name of a property and returns true if it's probably a uri
*/
function isLikelyAUri(keyName) {
const key = keyName.toLowerCase();
return key.endsWith('href') || key.endsWith('uri') || key.endsWith('url');
}
const allowedSchemes = ['http', 'https', 'mailto', 'gopher'];
function isLegalLink(uri) {
if (uri.includes('{')) {
// Likely a templated URI
return false;
}
if (uri.startsWith('/')) {
return true;
}
for (const scheme of allowedSchemes) {
if (uri.startsWith(scheme + ':')) {
return true;
}
}
return false;
}
/**
* Ugly way to find out something is a JSON object
*/
function isJsonObject(value) {
if (typeof value !== 'object')
return false;
if (value === null || Array.isArray(value))
return false;
return true;
}
//# sourceMappingURL=json-viewer.js.map