import React from "react" // Utility functions to know which case we have import { detectedTypes } from "@theme/JSONSchemaViewer/utils" import { TypeLabelSwitch } from "@theme/JSONSchemaViewer/components" import { AndLabel, NotLabel, OrLabel, XorLabel, } from "@theme/JSONSchemaViewer/labels" import type { JSONSchema, JSONSchemaNS, TypeValues, } from "@theme/JSONSchemaViewer/types" import type { JSX } from "react" // common function I need below function shouldAddSeparator(idx: number, length: number): boolean { // Not useful to add an separator for [], [item] situations if (length <= 1) { return false } // Otherwise return idx !== length - 1 } // generate a friendly name for the schema // It has to cover nasty cases like omit the "type" that usually helps to know what we have here export default function GenerateFriendlyName({ schema, }: { schema: JSONSchema }): JSX.Element { // In case the schema is always valid or not if (typeof schema === "boolean") { return } // Some people maintaining schemas provide a friendly name by themself if (schema.title) { return <>{schema.title} } // See which types are available const foundTypes = detectedTypes(schema) // If no types were found, let's use fallback trick if (foundTypes.length === 0) { return } // Return types, and customize them if needed return ( <> {foundTypes.map((type, idx) => ( {shouldAddSeparator(idx, foundTypes.length) && } ))} ) } // generate a friendly name when no type is present function FallbackFriendlyName({ schema, }: { schema: Exclude }): JSX.Element { // 1. we have a Schema Composition case (not, allOf, ...) // 1A) the "not" case if (schema.not !== undefined) { return ( <> {" ( "} {" ) "} ) } // the "allOf" / "oneOf" / "anyOf" if (schema.anyOf || schema.oneOf || schema.allOf) { // The linkword for the result const LINKWORD = schema.anyOf ? ( ) : schema.oneOf ? ( ) : ( ) // Generify the process const elements = schema.allOf || schema.anyOf || schema.oneOf! // In order to have unique elements // Return result return ( <> {elements.map((elem, idx) => ( {shouldAddSeparator(idx, elements.length) && LINKWORD} ))} ) } // 2. Assume it is "any" by default return } // Customize type display to human friendly way type CustomizeProps = { schema: Exclude type: TypeValues | string } function CustomizeType({ schema, type }: CustomizeProps): JSX.Element { // Use format when used with string // handle both predefined formats (e.g. "time", "date-time" ,...) & additional if (type === "string" && schema.format !== undefined) { return } // For "array" if (type === "array") { return } // For constant values if (!["array", "object"].includes(type)) { if (schema.const !== undefined) { return {`${JSON.stringify(schema.const)}`} } if (schema.enum !== undefined && schema.enum.length === 1) { return {`${JSON.stringify(schema.enum[0])}`} } } // By default, render the type as it return } // Customize array display function CustomizeArray({ schema, }: { schema: JSONSchemaNS.Array }): JSX.Element { // No clear specifications about the contents of the array ? // KISS return the generic type if ( [undefined, false].includes(schema.items as any) && [undefined, false].includes(schema.prefixItems as any) && schema.contains === undefined ) { return } // Now, we know that at least something exists to guess array type // The hardest part is that we could have some combinations let elements: JSX.Element[] = [] // 1) "prefixItems" if (Array.isArray(schema.prefixItems)) { // Prefix items are the first entries in the array elements.push( ...schema.prefixItems.map((subSchema, idx) => ( )), ) } // 2) "items" if (schema.items !== undefined && typeof schema.items !== "boolean") { // Generify the process for both cases let items = Array.isArray(schema.items) ? schema.items : [schema.items!] // add items to entries elements.push( ...items.map((subSchema, idx) => ( )), ) } // 2B) "additionalItems" (to cover cases for specs below the draft-2020-12 version) if ( schema.additionalItems !== undefined && typeof schema.additionalItems !== "boolean" ) { // add items to entries elements.push( , ) } // 2C) "unevaluatedItems" (to cover cases specs >= draft-2020-12 version) if ( schema.unevaluatedItems !== undefined && typeof schema.unevaluatedItems !== "boolean" ) { // add items to entries elements.push( , ) } // 3) "contains" if (schema.contains !== undefined) { // add contains to entries elements.push( ...[ {"..."}, , ], ) } // 4) Is it a open tuple ? if ( !( (schema as JSONSchemaNS.Array).unevaluatedItems === false || schema.items === false || schema.additionalItems === false ) ) { // notify the user elements.push( ...[{"..."}], ) } // result time return ( <> {"("} {elements.map((elem, idx) => ( {elem} {shouldAddSeparator(idx, elements.length) && ","} ))} {")[]"} ) }