Visual Studio editor integration (Monaco Editor)

The powerful Visual Studio web editor created by Microsoft has been included in the resources of the platform for the incorporation of new functionalities or for the update of the existing ones.

This library is available as a resource in the control panel in its minimized version (/static/vendor/vs). It is currently being used in the gadget templates editor. It is a much heavier library than the previous one about codemirror, but it offers by default an interface similar to that of the Visual Studio desktop. Some important features:

  • Automatic document formatting, autocomplete for HTML, JS, CSS (with integrated colorpicker), ... although only one possible mode at a time, syntax marking in many languages ​​including pure JSON.
  • Search/Replace, column selector, code formatting, ... with F1 you can see all the commands.
  • Enable/Disable native code.
  • Multiple default themes.
  • Ability to make text diffs on double screen.
  • Minimap of the code with scroll.
  • You can try different configurations as well as code, from the official website: https://microsoft.github.io/monaco-editor/playground.html#creating-the-editor-editor-basic-options
  • Launching commands through actions, See an example about retrieving the results of a query in string and format them directly in json format.

Its integration is easy: Just add a loader configuration variable (base path of the resources folder that could be another or an absolute one) and then the default resources.

<script>

	var require = { paths: { 'vs': '../../../static/vendor/vs' } };

</script>

<script th:src="@{/static/vendor/vs/loader.js}"></script>

<script th:src="@{/static/vendor/vs/editor/editor.main.nls.js}"></script>

<script th:src="@{/static/vendor/vs/editor/editor.main.js}"></script>


There is an incompatibility with the jquery plugin “jquery.validate.min.js” and the loader but it is solved by loading the vs

<script th:src="@{/static/vendor/jquery-validation/jquery.validate.min.js}" type="text/javascript"></script>

<script th:src="@{/static/vendor/jquery-validation/additional-methods.min.js}" type="text/javascript"></script>

<script th:if="${lang} == 'es'" th:src="@{/static/vendor/jquery-validation/localization/messages_es.min.js}" type="text/javascript"></script>

<script>

	var require = { paths: { 'vs': '../../../static/vendor/vs' } };

</script>

<script th:src="@{/static/vendor/vs/loader.js}"></script>

<script th:src="@{/static/vendor/vs/editor/editor.main.nls.js}"></script>

<script th:src="@{/static/vendor/vs/editor/editor.main.js}"></script>


For the creation of the editor, use a div with height:

<div style="height:400px" id="htmlcode"></div>


And an instantiation of the editor in that div:

var htmlelement = document.getElementById('htmlcode');

myVSHTML = monaco.editor.create(htmlelement, {

       value: myTextArea.value,

       language: 'html',

       readOnly: myTextArea.disabled,

       scrollBeyondLastLine: false,

       theme: "vs-dark",

       automaticLayout: true

});


You can define custom commands for the editor. For example a full-screen (with a class defined for it) could be like this:

myVSHTML.addCommand(monaco.KeyCode.F11, function() {
	if(!myVSHTML_isfullscreen){
		document.getElementById("htmlcode").classList.add(“fullscreen”);
		myVSHTML_isfullscreen=true;
	}
	else{
		document.getElementById("htmlcode").classList.remove(“fullscreen”);
		myVSHTML_isfullscreen=false;
	}
});

myVSHTML.addCommand(monaco.KeyCode.Escape, function() {
	document.getElementById("htmlcode").classList.remove(“fullscreen”);
	myVSHTML_isfullscreen=false;
});


To recover the value, you can do it for each point or for each change:

var newtextvalue = myVSHTML.getValue());

myVSHTML.onDidChangeModelContent(function() {
	var newtextvalue = myVSHTML.getValue());
})


You can also manage drag&drop to the editor and make replacements over ranges, for example:

var allowDrop = function(ev) {
	ev.preventDefault();
}

var dropParam = function(e,vsinstance){
	e.preventDefault();
	var data = e.dataTransfer.getData("content");  
	var line = vsinstance.getPosition();
	var range = new monaco.Range(line.lineNumber, line.column, line.lineNumber, line.column);
	var id = { major: 1, minor: 1 };            
	var text = dataFromId(data);
	var op = {identifier: id, range: range, text: text, forceMoveMarkers: true};
	vsinstance.executeEdits("my-source", [op]);
}

htmlelement.ondragover = function(e){allowDrop(e)};
htmlelement.ondrop = function(e){dropParam(e,myVSHTML)};