UNPKG

@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
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