patternfly / patternfly-react

A set of React components for the PatternFly project.
https://react-staging.patternfly.org/
MIT License
763 stars 349 forks source link

Code Editor - add documentation how to use JSON Schemas #10647

Open nicolethoen opened 2 months ago

nicolethoen commented 2 months ago

It is not super straight forward to get the beforeMount call to cooperate with yaml parsing and many people using our code editor are using it for parsing/editing yaml files.

it might be wise to add an example which includes yaml parsing. A working example in a codebase is in this PR: https://github.com/KaotoIO/kaoto/pull/1179/files#diff-c64390323d50afca275373be6b4e3da7e76d1faefb849499e4aa47ae537c7b36

This request originates from this slack thread.

lordrip commented 1 month ago

The process to load a JSON Schema in the code editor (used for both JSON and YAML autocompletion) looks like the following:

  1. create a beforeMount callback that will receive the monaco instance and use the configureMonacoYaml function from the monaco-yaml package to set the desired JSON Schema.
  2. Capture the output of the configureMonacoYaml function into a Ref so we can dispose of it when the component is unmounted, otherwise the yaml worker is not released and a duplicated autocompletion appears in addition to the memory leak
  3. Provide an empty useEffect that returns a dispose function, so we ensure it executes when leaving the component.

For reference:

Setting the schema

const editorProps = useRef({
    beforeMount: (monaco) => {
      if (currentSchema) {
        // Keep the output of the `configureMonacoYaml` function
        const monacoYamlHandler = configureMonacoYaml(monaco, {
          enableSchemaRequest: true,
          hover: true,
          completion: true,
          validate: true,
          format: true,
          schemas: [
            {
              schema: '<your schema goes here>',
              uri: '<your schema URI>',
              fileMatch: ['*'],
            },
          ],
        });

        /** Capturing the monacoYamlHandlerRef so we can dispose it when unmounting this component */
        monacoYamlHandlerRef.current = monacoYamlHandler;
      }
    },
  });

Disposing the workers

 useEffect(() => {
    /**
     * This useEffect acts as an unmount hook for the CodeEditor component
     * It disposes the monacoYamlHandlerRef.current when the component is unmounted
     */
    return () => {
      monacoYamlHandlerRef.current?.dispose();
    };
  }, []);

Setting the editorProps

return (
    <CodeEditor
      language={Language.yaml}
      editorProps={editorProps.current!}
    />