YAML validation for Monaco Editor
For YAML seems like we have indentation and code highlighting, but unfortunately, we can't validate the code (indentation format or naming, duplications of the fields).
I found a library (https://github.com/pengx17/monaco-yaml) that can maybe help, but I have issues to integrate with create-react-app.
I also tried this solution (https://github.com/suren-atoyan/monaco-react/issues/68#issuecomment-770205419) but unfortunately nothing works for create-react-app application.
Maybe someone integrated YAML validations and can share some knowledge.
this can be helpful. I'll try to find some time to make a working example
It's hard to understand something in this example and how to integrate with monaco-react. Seems like all the code should be placed in public/index.html and we don't need monaco-react at all.
An update on this would be greatly appreciated
@suren-atoyan could you please provide an update on this.
@suren-atoyan Did you manage to get some time to look into it? :)
@Nivl @Chethannp @efreila guys sorry, but this package isn't compatible with this yaml-monaco implmenetation. To avoid using webpack configuration in this package we download monaco sources from CDN. The mentioned yaml-monaco implementation heavily depends on the ESM version of monaco, which requires a specific webpack configuration
@suren-atoyan Is there a workaround that let us use https://github.com/remcohaszing/monaco-yaml with https://github.com/suren-atoyan/monaco-react ?
is there any example with monaco-yaml?
this might make it possible to use monaco-yaml with monaco-react
@suren-atoyan Cheers for the suggestion. I did manage to get it working using the webpack config from https://github.com/remcohaszing/monaco-yaml and the following component:
import React, {FC, useEffect} from 'react';
import * as monaco from "monaco-editor";
import Editor, { loader } from "@monaco-editor/react";
loader.config({ monaco });
import {setDiagnosticsOptions} from 'monaco-yaml';
// @ts-ignore
window.MonacoEnvironment = {
getWorker(moduleId: any, label: string) {
switch (label) {
case 'editorWorkerService':
// @ts-ignore
return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url));
case 'css':
case 'less':
case 'scss':
// @ts-ignore
return new Worker(new URL('monaco-editor/esm/vs/language/css/css.worker', import.meta.url));
case 'handlebars':
case 'html':
case 'razor':
return new Worker(
// @ts-ignore
new URL('monaco-editor/esm/vs/language/html/html.worker', import.meta.url),
);
case 'json':
return new Worker(
// @ts-ignore
new URL('monaco-editor/esm/vs/language/json/json.worker', import.meta.url),
);
case 'javascript':
case 'typescript':
return new Worker(
// @ts-ignore
new URL('monaco-editor/esm/vs/language/typescript/ts.worker', import.meta.url),
);
case 'yaml':
// @ts-ignore
return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url));
default:
throw new Error(`Unknown label ${label}`);
}
},
};
interface CodeEditorProps {
language: string;
value: any;
disabled?: boolean;
onChange(value: string|undefined): void;
className?: string;
width?: string;
height?: string;
}
export const CodeEditor: FC<CodeEditorProps> = (props) => {
const {language, value, disabled, onChange, className, width, height} = props;
const handleOnChange = (value: string|undefined) => {
onChange(value);
}
const handleEditorValidation = (markers: any) => {
// model markers
markers.forEach((marker: any) => console.log("onValidate:", marker.message));
}
useEffect(() => {
setDiagnosticsOptions({
// Have to set an empty Diagnostics options to get syntax checking
});
}, [])
return (
<div style={{border: "1px solid #ccc"}} className={className}>
<Editor
options={{
readOnly: disabled,
lineDecorationsWidth: 5,
lineNumbersMinChars: 0,
glyphMargin: false,
folding: false,
lineNumbers: 'off',
minimap: {
enabled: false
},
fontSize: 11,
}}
width={width}
height={height}
language={language}
value={value}
onValidate={handleEditorValidation}
onChange={handleOnChange}
/>
</div>
);
}
@suren-atoyan Cheers for the suggestion. I did manage to get it working using the webpack config from https://github.com/remcohaszing/monaco-yaml and the following component:
import React, {FC, useEffect} from 'react'; import * as monaco from "monaco-editor"; import Editor, { loader } from "@monaco-editor/react"; loader.config({ monaco }); import {setDiagnosticsOptions} from 'monaco-yaml'; // @ts-ignore window.MonacoEnvironment = { getWorker(moduleId: any, label: string) { switch (label) { case 'editorWorkerService': // @ts-ignore return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url)); case 'css': case 'less': case 'scss': // @ts-ignore return new Worker(new URL('monaco-editor/esm/vs/language/css/css.worker', import.meta.url)); case 'handlebars': case 'html': case 'razor': return new Worker( // @ts-ignore new URL('monaco-editor/esm/vs/language/html/html.worker', import.meta.url), ); case 'json': return new Worker( // @ts-ignore new URL('monaco-editor/esm/vs/language/json/json.worker', import.meta.url), ); case 'javascript': case 'typescript': return new Worker( // @ts-ignore new URL('monaco-editor/esm/vs/language/typescript/ts.worker', import.meta.url), ); case 'yaml': // @ts-ignore return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url)); default: throw new Error(`Unknown label ${label}`); } }, }; interface CodeEditorProps { language: string; value: any; disabled?: boolean; onChange(value: string|undefined): void; className?: string; width?: string; height?: string; } export const CodeEditor: FC<CodeEditorProps> = (props) => { const {language, value, disabled, onChange, className, width, height} = props; const handleOnChange = (value: string|undefined) => { onChange(value); } const handleEditorValidation = (markers: any) => { // model markers markers.forEach((marker: any) => console.log("onValidate:", marker.message)); } useEffect(() => { setDiagnosticsOptions({ // Have to set an empty Diagnostics options to get syntax checking }); }, []) return ( <div style={{border: "1px solid #ccc"}} className={className}> <Editor options={{ readOnly: disabled, lineDecorationsWidth: 5, lineNumbersMinChars: 0, glyphMargin: false, folding: false, lineNumbers: 'off', minimap: { enabled: false }, fontSize: 11, }} width={width} height={height} language={language} value={value} onValidate={handleEditorValidation} onChange={handleOnChange} /> </div> ); }
Throws:
Error: Target container is not a DOM element.
In a Next.js app :(