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,36 +64,41 @@ const JSONSchema = ({ schema, name }) => {
return ( return (
<JSONSchemaLevelContext.Provider value={nextLevel}> <JSONSchemaLevelContext.Provider value={nextLevel}>
<JSONSchemaDeepExpansionContext.Provider value={expandedDeeply}> <JSONSchemaDeepExpansionContext.Provider value={expandedDeeply}>
<article <JSONSchemaCyclesContext.Provider value={renderedSchemas}>
data-json-schema-level={level} <article
className={classNames("json-schema-2020-12", { data-json-schema-level={level}
"json-schema-2020-12--embedded": isEmbedded, 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 ? ( >
<> <div className="json-schema-2020-12-head">
<Accordion expanded={expanded} onChange={handleExpansion}> {isExpandable && !isCircular ? (
<KeywordTitle title={name} schema={schema} /> <>
</Accordion> <Accordion expanded={expanded} onChange={handleExpansion}>
<ExpandDeepButton <KeywordTitle title={name} schema={schema} />
expanded={expanded} </Accordion>
onClick={handleExpansionDeep} <ExpandDeepButton
/> expanded={expanded}
</> onClick={handleExpansionDeep}
) : ( />
<KeywordTitle title={name} schema={schema} /> </>
)} ) : (
<KeywordType schema={schema} /> <KeywordTitle title={name} schema={schema} />
<KeywordFormat schema={schema} /> )}
</div> <KeywordType schema={schema} isCircular={isCircular} />
{expanded && ( <KeywordFormat schema={schema} />
<div className="json-schema-2020-12-body">
<KeywordDescription schema={schema} />
<KeywordProperties schema={schema} />
</div> </div>
)} {expanded && (
</article> <div className="json-schema-2020-12-body">
<KeywordDescription schema={schema} />
{!isCircular && isExpandable && (
<KeywordProperties schema={schema} />
)}
</div>
)}
</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)
}