From 7d5cad0a1a200b6d1f5315539099c065bf116d8b Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Wed, 19 Apr 2023 11:38:39 +0200 Subject: [PATCH] feat(json-schema-2020-12): handle cycles in rendering Refs #8513 --- .../components/JSONSchema/JSONSchema.jsx | 68 +++++++++++-------- .../components/keywords/Type/Type.jsx | 14 +++- .../plugins/json-schema-2020-12/context.js | 2 + src/core/plugins/json-schema-2020-12/hooks.js | 14 ++++ 4 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx b/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx index 5a15e3ef..201d93ba 100644 --- a/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx +++ b/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx @@ -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 ( -
-
- {isExpandable ? ( - <> - - - - - - ) : ( - - )} - - -
- {expanded && ( -
- - + +
+
+ {isExpandable && !isCircular ? ( + <> + + + + + + ) : ( + + )} + +
- )} -
+ {expanded && ( +
+ + {!isCircular && isExpandable && ( + + )} +
+ )} +
+
) diff --git a/src/core/plugins/json-schema-2020-12/components/keywords/Type/Type.jsx b/src/core/plugins/json-schema-2020-12/components/keywords/Type/Type.jsx index b4f988a6..0d0d2d20 100644 --- a/src/core/plugins/json-schema-2020-12/components/keywords/Type/Type.jsx +++ b/src/core/plugins/json-schema-2020-12/components/keywords/Type/Type.jsx @@ -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 {fn.getType(schema)} + return ( + {`${type}${circularSuffix}`} + ) } Type.propTypes = { schema: schema.isRequired, + isCircular: PropTypes.bool, +} + +Type.defaultProps = { + isCircular: false, } export default Type diff --git a/src/core/plugins/json-schema-2020-12/context.js b/src/core/plugins/json-schema-2020-12/context.js index 99311595..0686b177 100644 --- a/src/core/plugins/json-schema-2020-12/context.js +++ b/src/core/plugins/json-schema-2020-12/context.js @@ -11,3 +11,5 @@ JSONSchemaLevelContext.displayName = "JSONSchemaLevelContext" export const JSONSchemaDeepExpansionContext = createContext(false) JSONSchemaDeepExpansionContext.displayName = "JSONSchemaDeepExpansionContext" + +export const JSONSchemaCyclesContext = createContext(new Set()) diff --git a/src/core/plugins/json-schema-2020-12/hooks.js b/src/core/plugins/json-schema-2020-12/hooks.js index 1d6c6596..0e433671 100644 --- a/src/core/plugins/json-schema-2020-12/hooks.js +++ b/src/core/plugins/json-schema-2020-12/hooks.js @@ -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) +}