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

View File

@@ -2,18 +2,28 @@
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
import { schema } from "../../../prop-types"
import { useFn } from "../../../hooks"
const Type = ({ schema }) => {
const Type = ({ schema, isCircular }) => {
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 = {
schema: schema.isRequired,
isCircular: PropTypes.bool,
}
Type.defaultProps = {
isCircular: false,
}
export default Type

View File

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

View File

@@ -7,6 +7,7 @@ import {
JSONSchemaContext,
JSONSchemaLevelContext,
JSONSchemaDeepExpansionContext,
JSONSchemaCyclesContext,
} from "./context"
export const useConfig = () => {
@@ -40,3 +41,16 @@ export const useIsEmbedded = () => {
export const useIsExpandedDeeply = () => {
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)
}