Integración de editor Visual Studio (Monaco Editor)

Integración de editor Visual Studio (Monaco Editor)

Para la incorporación de nuevas funcionalidades o actualización de las existentes se ha incluido en los recursos de la plataforma el potente editor web Visual Studio, creado por Microsoft.

Está librería, se encuentra disponible como recurso en el controlpanel en su versión minimizada (/static/vendor/vs). Se está usando actualmente en el editor de las gadgets templates. Es una librería bastante más pesada que la anterior de codemirror, pero que ofrece por defecto una interfaz similar a la del Visual Studio desktop. Algunas características importantes:

  • Formateo de documentos automático, autocompletado de HTML, JS, CSS (con colorpicker integrado),… aunque sólo un modo posible a la vez, marcado de sintaxis en muchos lenguajes incluido JSON puro.
  • Buscar/Reemplazar, selector por columnas, formateo de código,… con el F1 se pueden ver todos los comandos.
  • Enable/Disable de código nativo.
  • Múltiples temas por defecto.
  • Capacidad de hacer diffs de texto en doble pantalla.
  • Minimapa del código con scroll.
  • Se permite probar diferentes configuraciones así como código, desde la web oficial: https://microsoft.github.io/monaco-editor/playground.html#creating-the-editor-editor-basic-options
  • Lanzamiento de comandos mediante acciones, un ejemplo sería recuperar los resultados de una query en string y formatearlos directamente en formato json.

Su integración es sencilla, basta con añadir una variable de configuración del loader (ruta base de la carpeta de recursos que podría ser otra o una absoluta) y después los recursos por defecto.

<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>


Existe una incompatibilidad con el plugin de jquery “jquery.validate.min.js” y el loader pero se solventa cargando después el 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>


Para la creación del editor basta con un div con altura:

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


Y una instanciación del editor en ese 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

});


Se pueden definir comandos custom para el editor. Por ejemplo un full-screen (con una clase definida para ello) podría ser así:

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;
});


Para recuperar el value se puede hacer puntualmente o por cada cambio:

var newtextvalue = myVSHTML.getValue());

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


También se puede gestionar drag&drop con destino el editor y hacer reemplazos sobre rangos, por ejemplo:

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)};