import { IRowRendererOptions, isParentNode, Tree } from '@stoplight/tree-list'; import cn from 'classnames'; import { JSONSchema4 } from 'json-schema'; import * as React from 'react'; import { getNodeMetadata, getSchemaNodeMetadata } from '../tree/metadata'; import { GoToRefHandler, SchemaKind, SchemaTreeListNode } from '../types'; import { getPrimaryType } from '../utils/getPrimaryType'; import { hasRefItems, isArrayNodeWithItems, isRefNode } from '../utils/guards'; import { Caret, Description, Divider, Format, Property, Validations } from './shared'; export interface ISchemaRow { className?: string; node: SchemaTreeListNode; rowOptions: IRowRendererOptions; onGoToRef?: GoToRefHandler; } const ICON_SIZE = 12; const ICON_DIMENSION = 20; const ROW_OFFSET = 7; function getRelevantSchemaForRequireCheck(treeNode: SchemaTreeListNode): JSONSchema4 | JSONSchema4[] | null { const metadata = getNodeMetadata(treeNode); if (!('schemaNode' in metadata)) return null; if (isArrayNodeWithItems(metadata.schemaNode)) { return metadata.schemaNode.items; } return metadata.schema; } function isRequired(treeNode: SchemaTreeListNode) { if (treeNode.parent === null) return false; try { const { path } = getSchemaNodeMetadata(treeNode); if (path.length === 0) { return false; } const schema = getRelevantSchemaForRequireCheck(treeNode.parent); return ( schema !== null && !Array.isArray(schema) && getPrimaryType(schema) === SchemaKind.Object && Array.isArray(schema.required) && schema.required.includes(String(path[path.length - 1])) ); } catch { return false; } } export const SchemaPropertyRow: typeof SchemaRow = ({ node, onGoToRef, rowOptions }) => { const metadata = getSchemaNodeMetadata(node); const { schemaNode } = metadata; const parentSchemaNode = (node.parent !== null && Tree.getLevel(node.parent) >= 0 && getSchemaNodeMetadata(node.parent)?.schemaNode) || null; const description = 'annotations' in schemaNode ? schemaNode.annotations.description : null; const has$Ref = isRefNode(schemaNode) || (getPrimaryType(schemaNode) === SchemaKind.Array && hasRefItems(schemaNode)); return ( <> {has$Ref || (isParentNode(node) && Tree.getLevel(node) > 0) ? ( ) : null} {node.parent !== null && node.parent.children.length > 0 && parentSchemaNode !== null && 'combiner' in parentSchemaNode && node.parent.children[0] !== node && }
{metadata.schema.type && typeof metadata.schema.format === 'string' && } {description && }
); }; SchemaPropertyRow.displayName = 'JsonSchemaViewer.SchemaPropertyRow'; export const SchemaErrorRow: React.FunctionComponent<{ message: string }> = ({ message }) => ( {message} ); SchemaErrorRow.displayName = 'JsonSchemaViewer.SchemaErrorRow'; export const SchemaRow: React.FunctionComponent = ({ className, node, rowOptions, onGoToRef }) => { const metadata = getNodeMetadata(node); return (
{'schema' in metadata ? ( ) : ( )}
); }; SchemaRow.displayName = 'JsonSchemaViewer.SchemaRow';