UNPKG

@discoveryjs/discovery

Version:

Frontend framework for rapid data (JSON) analysis, shareable serverless reports and dashboards

208 lines (207 loc) 6.42 kB
import { jsonStringifyAsJavaScript } from "../../core/utils/json.js"; function isTextNode(node) { return Boolean(node && node.nodeType === Node.TEXT_NODE); } function childrenHtml(node, level = "\n") { let res = ""; for (const child of node.childNodes) { if (!isTextNode(child) && child.previousSibling && !isTextNode(child.previousSibling)) { res += level; } res += nodeHtml(child, level); } return res; } function nodeHtml(node, level = "\n") { switch (node.nodeType) { case Node.ELEMENT_NODE: const [start, end = ""] = node.cloneNode().outerHTML.split(/(?=<\/[^>]+>$)/); return start + (node.firstChild && !isTextNode(node.firstChild) ? level + " " : "") + childrenHtml(node, level + " ") + (node.lastChild && !isTextNode(node.lastChild) ? level : "") + end; case Node.TEXT_NODE: return node.nodeValue; case Node.COMMENT_NODE: return "<!--" + node.nodeValue + "-->"; case Node.DOCUMENT_FRAGMENT_NODE: return childrenHtml(node, level); } return ""; } function highlightRefs(data, content) { const refs = []; const highlights = [ ...Array.isArray(data.highlight) ? data.highlight : data.highlight ? [data.highlight] : [] ]; if (Array.isArray(data.highlightProps)) { highlights.push(`(")?(?:${data.highlightProps.join("|")})\\1(?=:)`); } for (const highlight of highlights) { const rx = new RegExp(highlight, "gm"); let match = null; while (match = rx.exec(content)) { refs.push({ range: [match.index, match.index + match[0].length] }); } } return refs; } export const addModelViewsToContext = (host) => (_, context) => { const render = context.params?.render === "text" ? "text" : "web"; const webViews = [...host.view.values]; const textViews = [...host.textView.values]; return { ...context, render, views: { webViews, textViews, selected: render === "text" ? textViews : webViews } }; }; export function getUsageRenderConfig(host) { const renderDemo = { view: "context", modifiers: [ { view: "switch", when: "beforeDemo", content: [ { when: ({ beforeDemo }) => typeof beforeDemo === "string", content: 'html:"<p>" + beforeDemo + "</p>"' }, { content: { view: "render", config: "beforeDemo", context: "{ __demoContext: true, ...(viewDef | { name, group, options }) }" } } ] }, { view: "block", when: "demo or view", className: "usage-render", postRender(el, { onInit }, { demoFixed }, ctx) { if (demoFixed) { el.classList.add("demo-fixed"); el.style.height = demoFixed + "px"; } el.dataset.renderType = ctx.render; onInit(el, "root"); }, content: { view: "render", config: 'demo or view | #.render != "text" ?: [{ view: "text-render", content: $ }, { view: "text-render-tree", when: false, content: $ }]', data: "demoData", context: "{ __demoContext: true, ...(viewDef | { name, group, options }) }" } }, { view: "switch", when: "afterDemo", content: [ { when: ({ afterDemo }) => typeof afterDemo === "string", content: 'html:"<p>" + afterDemo + "</p>"' }, { content: { view: "render", config: "afterDemo", context: "{ __demoContext: true, ...(viewDef | { name, group, options }) }" } } ] } ], content: { view: "tabs", when: "source != false", className: "usage-sources", name: "code", tabs: [ { value: "config", text: "Config (JS)" }, { value: "config-json", text: "Config (JSON)" }, { value: "html", text: "Rendered HTML" } ], content: { view: "switch", content: [ { when: '#.code="config"', content: [{ view: "expand", when: '"demoData" in $', header: 'text:"Input data"', content: { view: "struct", expanded: 2, data: "demoData" } }, { view: "source", className: "first-tab", data: (data) => { const content = jsonStringifyAsJavaScript(data.demo || data.view); return { syntax: "discovery-view", content, refs: highlightRefs(data, content) }; } }] }, { when: '#.code="config-json"', content: [{ view: "expand", when: '"demoData" in $', header: 'text:"Input data"', content: { view: "struct", expanded: 2, data: "demoData" } }, { view: "source", data: (data) => { const content = JSON.stringify(data.demo || data.view, null, 4); return { syntax: "json", content, refs: highlightRefs(data, content) }; } }] }, { when: '#.code="html"', content: { view: "source", data: (data, context) => ({ syntax: "html", content: childrenHtml(context.root) }) } } ] } } }; return { view: "block", className: "discovery-view-usage", context: addModelViewsToContext(host), data({ name, options }, context) { const group = context.views.selected.filter((view) => view.options.usage === options.usage).map((view) => view.name); if (!group.includes(name)) { group.unshift(name); } return context.viewDef = { demo: { view: name, data: '"' + name + '"' }, ...typeof options.usage === "function" ? options.usage(name, group) : Array.isArray(options.usage) ? { examples: options.usage } : options.usage, name, group, options }; }, content: [ "h1:name", renderDemo, { view: "list", data: "examples", whenData: true, itemConfig: { className: "usage-section" }, item: [ "h2{ anchor: true, data: title }", renderDemo ] } ] }; }