How to Embed a Monaco Editor in a Browser as a Part of My First Task at TypeFox

Hi there, this is Akos. I am the new one at TypeFox, and within this post, I would like to describe you what was my first task after joining TypeFox. Namely, how to embed the Monaco Editor in the web browser and how to support a simple expression language from the browser using the Language Server Protocol (LSP).

monaco_example_add

I came from the Java world; I did Eclipse plug-in development in the last couple of years. Although I also worked with Java EE technologies and created rich web based applications with various frameworks such as JBoss Seam and Vaadin I never really had to deal with the JavaScript part because the currently used technology somehow magically took care of them under the hood and I had to deal rather with the Java code. Embedding the Monaco Editor was a bit more complicated task and required some additional JavaScript and TypeScript knowledge. Besides that, I also used Gradle, Webpack, and npm.

First and foremost, what is the Monaco Editor? The Monaco Editor is a browser-based code editor that powers VS Code. It supports cool features such as syntax and semantic validation, content assist, syntax coloring, parameter hints, hover, and much more out of the box. It is well-documented and relatively easy to connect with a language server and integrate into your projects.

The first thing I needed for this task is the Xtext implementation of the language server. This server is available from the 2.11.0.beta1 milestone version of Xtext and depends on a lightweight library: ls-api. This library is a simple Java binding for the LSP and is going to be replaced by the LSP4J Eclipse project in the future. By default, the Xtext language server supports various features, such as content proposals, hover, mark occurrences, and find references, which one can use for almost any kind of DSLs without any further customizations. Besides that, there are a couple of additional features that require custom implementation; for instance the signature helper which provides parameter hints. Usually, one single language is supported by one server; however, the Xtext server is capable of supporting multiple Xtext languages at the same time. The only requirement is that the actual implementation of the language should be available from the classpath of the server as a bundled jar.

I had to prepare some generic glue code that acts as a web socket server endpoint and handles the lifecycle of the Xtext language server instance associated with the web socket session. On session-open event, it creates a new server instance and caches it and indeed on the web socket session-close event it shuts down the server and removes it from the cache. Besides that, to be able to support Guice based dependency injection in RESTful web services I used the jersey2-guice library which supports DI within the Jersey 2.x implementation of the JAX-RS/JSR-311 specification.

Once the server-side was ready, and our DSL was available on the classpath, I had to implement a language-specific signature helper. I added some tests and switched to the client-side code. On the client-side, I used mostly TypeScript with some additional JavaScript code and invoked Webpack to compile TypeScript to JavaScript and to build the dependency graph with all of my static assets to create one single uglified JavaScript file for the browser. The client code is responsible for creating a web socket and connecting to the Xtext language server. Once the connection is successfully established between the client and server, the language gets registered into a new Monaco Editor instance. Right after the editor instantiation, both the syntax coloring and the auto-bracket insertion was configured in the client code. Currently, the LSP does not support syntax coloring, so this had to be added to the JavaScript code.

The last remaining part of this task was to build a web-archive file and deploy it. Since not all environments have installed Node.js on it, an individual Node.js task was added to the Gradle configuration to install Node.js with npm. Npm can install Webpack and Webpack can gather all modules and their direct and transitive dependencies reading the content of the package.json of our module. Finally, Gradle creates a war file which can be optionally deployed on a Tomcat server using the Gretty Gradle plug-in.

This example web-based Monaco Editor, which was presented at EclipseCon Europe last week, is available here. We are planning to make both the generic glue code (used for the server) and the Monaco Editor code accessible in the future. Once the code is available under the EPL 1.0 license, we’ll come back to you with another blog post with all the technical details and pitfalls. If you cannot wait, feel free to drop me a mail.

Try the Monaco Demo
By | 2017-05-17T13:21:38+00:00 November 2nd, 2016|Cloud IDE, Eclipse, Language Server, Xtext|12 Comments

About the Author:

Akos is a dedicated and down-to-earth software engineer at TypeFox. He is specialized in model-driven software development, and he is a great fan of several open-source Eclipse Modeling Projects such as CDO and Xtext. Alongside his software engineering passion, he is also interested in healthcare standards, terminologies and ontologies such as SNOMED CT.

12 Comments

  1. Markus November 17, 2016 at 09:57 - Reply

    That really sounds and looks awesome.

    Will this replace the “web-IDE” project in the future? (which you can tick when you create a new project in Eclipse)

    • Sven Efftinge November 17, 2016 at 11:50 - Reply

      Yes, long term the LSP support might replace the web support we have now. It is very similar in the underlying approach, but uses a more widely used protocol.

  2. Jesse Greenwald November 22, 2016 at 12:17 - Reply

    Neat demo. Is the source code available?

    • Sven Efftinge November 30, 2016 at 08:07 - Reply

      Not yet, but we plan to make it available in the near future.

      • Richard Ward February 9, 2017 at 14:54 - Reply

        Is there any update on the source for this becoming available? I am currently using the web support to allow users to use their dsls online, and would be very interested to see how this is achieved with the language server and monaco.

        • Sven Efftinge February 23, 2017 at 12:31 - Reply

          No, not yet. We are still in the process of making it fit for open-sourcing.
          The plan is to release it until Summer.

          • Daniel Kopp July 18, 2017 at 19:53

            Hi,
            I wanted to ask if the source code will be available in the near future ?

  3. […] seem to be working with the new Language Server Protocol doing interesting things like embedding a Monaco editor in a browser. Personally I am very interested in the idea behind the Language Server Protocol. I think it is […]

  4. Matthew White March 20, 2017 at 17:48 - Reply

    Would be very interested when this is available – as I’m attempting to write exactly the same thing at present! I’d like to connect Monaco to language server we have already as part of a VSCode plugin (https://github.com/fabric-composer/composer-vscode-plugin).

    Is there any possibility of a beta? Hate to re-invent the wheel 🙂

    • Sven Efftinge August 24, 2017 at 09:21 - Reply

      We have published the individual parts that are used in the example:
      https://github.com/TypeFox/monaco-languageclient

      The example itself however has not yet been published, as it would need to be reworked based on the new tools. And we didn’t find the time to do that yet. I would provide the source code and pointers via mail, though.

  5. Omer O December 5, 2017 at 15:54 - Reply

    Hey Akos, very interesting article! is the full source code available anywhere?

  6. Remichi Youcef Islam May 7, 2018 at 05:48 - Reply

    Is the example source code going to be available this week?

Leave A Comment