feat(json-schema-2020-12): handle cycles in rendering

Refs #8513
This commit is contained in:
Vladimir Gorej
2023-04-19 11:38:39 +02:00
committed by Vladimír Gorej
parent fe181ede90
commit 7d5cad0a1a
4 changed files with 67 additions and 31 deletions

View File

@@ -12,10 +12,13 @@ import {
useFn, useFn,
useIsEmbedded, useIsEmbedded,
useIsExpandedDeeply, useIsExpandedDeeply,
useIsCircular,
useRenderedSchemas,
} from "../../hooks" } from "../../hooks"
import { import {
JSONSchemaLevelContext, JSONSchemaLevelContext,
JSONSchemaDeepExpansionContext, JSONSchemaDeepExpansionContext,
JSONSchemaCyclesContext,
} from "../../context" } from "../../context"
const JSONSchema = ({ schema, name }) => { const JSONSchema = ({ schema, name }) => {
@@ -26,6 +29,8 @@ const JSONSchema = ({ schema, name }) => {
const [level, nextLevel] = useLevel() const [level, nextLevel] = useLevel()
const isEmbedded = useIsEmbedded() const isEmbedded = useIsEmbedded()
const isExpandable = fn.isExpandable(schema) const isExpandable = fn.isExpandable(schema)
const isCircular = useIsCircular(schema)
const renderedSchemas = useRenderedSchemas(schema)
const Accordion = useComponent("Accordion") const Accordion = useComponent("Accordion")
const KeywordProperties = useComponent("KeywordProperties") const KeywordProperties = useComponent("KeywordProperties")
const KeywordType = useComponent("KeywordType") const KeywordType = useComponent("KeywordType")
@@ -59,14 +64,16 @@ const JSONSchema = ({ schema, name }) => {
return ( return (
<JSONSchemaLevelContext.Provider value={nextLevel}> <JSONSchemaLevelContext.Provider value={nextLevel}>
<JSONSchemaDeepExpansionContext.Provider value={expandedDeeply}> <JSONSchemaDeepExpansionContext.Provider value={expandedDeeply}>
<JSONSchemaCyclesContext.Provider value={renderedSchemas}>
<article <article
data-json-schema-level={level} data-json-schema-level={level}
className={classNames("json-schema-2020-12", { className={classNames("json-schema-2020-12", {
"json-schema-2020-12--embedded": isEmbedded, "json-schema-2020-12--embedded": isEmbedded,
"json-schema-2020-12--circular": isCircular,
})} })}
> >
<div className="json-schema-2020-12-head"> <div className="json-schema-2020-12-head">
{isExpandable ? ( {isExpandable && !isCircular ? (
<> <>
<Accordion expanded={expanded} onChange={handleExpansion}> <Accordion expanded={expanded} onChange={handleExpansion}>
<KeywordTitle title={name} schema={schema} /> <KeywordTitle title={name} schema={schema} />
@@ -79,16 +86,19 @@ const JSONSchema = ({ schema, name }) => {
) : ( ) : (
<KeywordTitle title={name} schema={schema} /> <KeywordTitle title={name} schema={schema} />
)} )}
<KeywordType schema={schema} /> <KeywordType schema={schema} isCircular={isCircular} />
<KeywordFormat schema={schema} /> <KeywordFormat schema={schema} />
</div> </div>
{expanded && ( {expanded && (
<div className="json-schema-2020-12-body"> <div className="json-schema-2020-12-body">
<KeywordDescription schema={schema} /> <KeywordDescription schema={schema} />
{!isCircular && isExpandable && (
<KeywordProperties schema={schema} /> <KeywordProperties schema={schema} />
)}
</div> </div>
)} )}
</article> </article>
</JSONSchemaCyclesContext.Provider>
</JSONSchemaDeepExpansionContext.Provider> </JSONSchemaDeepExpansionContext.Provider>
</JSONSchemaLevelContext.Provider> </JSONSchemaLevelContext.Provider>
) )

View File

@@ -2,18 +2,28 @@
* @prettier * @prettier
*/ */
import React from "react" import React from "react"
import PropTypes from "prop-types"
import { schema } from "../../../prop-types" import { schema } from "../../../prop-types"
import { useFn } from "../../../hooks" import { useFn } from "../../../hooks"
const Type = ({ schema }) => { const Type = ({ schema, isCircular }) => {
const fn = useFn() const fn = useFn()
const type = fn.getType(schema)
const circularSuffix = isCircular ? " [circular]" : ""
return <span className="json-schema-2020-12__type">{fn.getType(schema)}</span> return (
<span className="json-schema-2020-12__type">{`${type}${circularSuffix}`}</span>
)
} }
Type.propTypes = { Type.propTypes = {
schema: schema.isRequired, schema: schema.isRequired,
isCircular: PropTypes.bool,
}
Type.defaultProps = {
isCircular: false,
} }
export default Type export default Type

View File

@@ -11,3 +11,5 @@ JSONSchemaLevelContext.displayName = "JSONSchemaLevelContext"
export const JSONSchemaDeepExpansionContext = createContext(false) export const JSONSchemaDeepExpansionContext = createContext(false)
JSONSchemaDeepExpansionContext.displayName = "JSONSchemaDeepExpansionContext" JSONSchemaDeepExpansionContext.displayName = "JSONSchemaDeepExpansionContext"
export const JSONSchemaCyclesContext = createContext(new Set())

View File

@@ -7,6 +7,7 @@ import {
JSONSchemaContext, JSONSchemaContext,
JSONSchemaLevelContext, JSONSchemaLevelContext,
JSONSchemaDeepExpansionContext, JSONSchemaDeepExpansionContext,
JSONSchemaCyclesContext,
} from "./context" } from "./context"
export const useConfig = () => { export const useConfig = () => {
@@ -40,3 +41,16 @@ export const useIsEmbedded = () => {
export const useIsExpandedDeeply = () => { export const useIsExpandedDeeply = () => {
return useContext(JSONSchemaDeepExpansionContext) return useContext(JSONSchemaDeepExpansionContext)
} }
export const useRenderedSchemas = (schema = undefined) => {
if (typeof schema === "undefined") {
return useContext(JSONSchemaCyclesContext)
}
const renderedSchemas = useContext(JSONSchemaCyclesContext)
return new Set([...renderedSchemas, schema])
}
export const useIsCircular = (schema) => {
const renderedSchemas = useRenderedSchemas()
return renderedSchemas.has(schema)
}