Test on https://embeddable-monaco.lukasbach.com.
Monaco Editor is an code editor that powers VS Code and can be reused in other apps. Compared to other frontend libraries, setup is a bit harder with Monaco since it uses webworkers and requires a more complicated build setup. In most use cases it can be implemented with build plugins, but in some use cases, there are harder restrictions on the availability of the build system or the use of web workers, where this is not possible.
This project provides a pre-built version of Monaco Editor that can be embedded in an iframe and controlled via a simple messaging API. It is a drop-in replacement for the Monaco Editor, but it can be used in environments where the build system is not available or where web workers are not allowed.
<iframe src="https://embeddable-monaco.lukasbach.com?code=initial_code&language=javascript&theme=vs-dark" id="iframe"></iframe>
const iframe = document.getElementById("iframe");
window.addEventListener("message", ({ data }) => {
switch(data.type) {
case "ready": {
iframe.contentWindow?.postMessage({
type: "change-value",
value: "new initial value"
}, "*");
break;
}
case "change": {
console.log("current value is", data.value)
break;
}
}
});
To use, just embed the URL https://embeddable-monaco.lukasbach.com in an iframe.
There are two primary ways to configure and communicate with the editor. First, configuration can be passed through URL query parameters. Second, the editor can be controlled via a simple messaging API, so that configuration can be changed during runtime, and changes to the editor can be passed back to the parent frame.
The implementation is not complicated, so an easy way to understand what is possible is to just look into the implementation file src/embed.ts.
The following query parameters are supported:
code
: Initial code, defaults to emptylang
: Initial language, defaults to javascripttheme
: Initial theme, defaults to vs-light
contextmenu
: boolean, "true" or "false"folding
: boolean, "true" or "false"readonly
: boolean, "true" or "false"lineNumbers
: boolean, "on" or "off"minimap
: boolean, "true" or "false"background
: custom background color, can also be transparentjavascriptDefaults
: set javascript language properties, required to use:
javascriptDefaultsNoSemanticValidation
javascriptDefaultsNoSyntaxValidation
typescriptDefaults
: set typescript language properties, required to use:
typescriptDefaultsNoSemanticValidation
typescriptDefaultsNoSyntaxValidation
dontPostValueOnChange
: In the change
handler, don't post the value back to the parent frame every time the model is changedcontext
: a string that is passed back in every message sent back from the iframeReceive messages via
iframe.addEventListener('message', (e) => {
console.log(`message type is ${e.data.type}, payload is in`, e.data);
});
Messages sent by the iframe:
{ type: "ready" }
: Sent when the editor is ready{ type: "change", value: string }
: Sent everytime the editor value changes{ type: "content", value: string }
: Sent when the editor content is requested via get-content
messageSend messages to the iframe via
iframe.contentWindow.postMessage({ type: "type", ...parameters }, "*");
Messages that can be sent to the iframe
{ type: "change-options", options: IEditorOptions }
: Change editor options{ type: "change-value", value: string }
: Change editor value{ type: "change-language", language: string }
: Change editor language{ type: "change-theme", theme: string }
: Change editor theme{ type: "change-background", background: string, theme?: string }
: Change editor background color. Can also be transparent{ type: "change-javascript-defaults", javascriptDefaults: IJavaScriptDefaults }
: Change javascript language defaults{ type: "change-typescript-defaults", typescriptDefaults: ITypeScriptDefaults }
: Change typescript language defaults{ type: "get-content }
: IFrame will dispatch a content
message with the current editor value