ぷろじぇくと、みすじら。

Visual Studio CodeのエディターをWebページに埋め込む

Created at:

Visual Studio CodeのシンタックスハイライトをWebページで使うという話を少し前に書きましたが、
今回はエディタ部分をWebページに埋め込んでみようという話です。

前にも少し触れましたが、Visual Studio Codeのエディター部分、いわゆるMonacoはVisual Studio Code以前からいろいろなところで埋め込まれて使われています。
Visual Studio Online “Monaco”を始め、TypeScript PlaygroundWinJS Playground、IE/EdgeのF12開発者ツールなどなど、
エディター部分の出来の良さというか埋め込んで使われることが念頭に置かれている感じがします。

動作サンプル

まずは動作するサンプルを貼り付けてみるので、触ってみてください。

適当なところでCtrl/Cmd + スペースを押せばきちんとコードの補完(IntelliSense)が表示されます。
Visual Studio Codeと同じようにJavaScriptモードはTypeScriptモードが元になっているので、型もちゃんと認識されています(helloメソッドの戻り値の型がstringになっています)。

hの後ろでコード補完を表示した

埋め込み方

肝心の埋め込み方ですが、エディター部分を埋め込むだけであればとても簡単です。

最初にエディターのJavaScriptファイルを用意する必要がありますが、
MimosaにあらかじめVisual Studio Codeからエディター部分をビルドしたものを同梱しているのでそれを使うと簡単です。
リポジトリの monaco-prebuilt 以下を引っこ抜いてきてもよいです。

ファイルの準備ができたらHTMLを書きます。エディターの領域をdiv要素で確保してください。

<div id="editor" style="height:200px;"></div>

エディターの表示サイズはエディターにしてほしい部分の要素のサイズによって確定するので、空の要素の場合、高さが0で何も表示できなくなります。
例えばコードの長さに応じた高さ、といったことはできないので注意が必要です。
また、このエディターとなりたい部分の要素の内容は空にしておいてください(エディターが実体化されても残るので)。

次にJavaScriptでMonacoエディターを生成します。

<script>
    require.config({
        baseUrl: '/mimosa/', // これは例によってMonaco(vsディレクトリ)が入っているディレクトリ
    });

    require(["vs/editor/editor.main"], function () {
        // エディター領域を取得する
        var editorE = document.querySelector('#editor');
        
        // エディターに表示する文字列を組み立てる
        var content = [
            '"use strict";',
            'const message = "コンニチハ!";',
            'class Greeter {',
            '    /** ハロー!! */',
            '    hello() {',
            '        return message;',
            '    }',
            '}',
            'new Greeter().h'
        ].join('\n');
        
        // エディターを生成する
        var editor = Monaco.Editor.create(editorE, {
            value: content,
            mode: "javascript",
            readOnly: false,
            //theme: "vs-dark",
            scrollBeyondLastLine: false,
            automaticLayout: true,
            autoSize: true,
            scrollbar: {
                handleMouseWheel: true
            }
        });
        
        // 何かイベントに応じて編集した文字列を取得する
        // console.log(editor.getValue());
    });
</script>

実質的にやることはrequire([“vs/editor/editor.main”])で読み込んで、Monaco.Editor.create メソッドでエディターを生成するということだけです。なんとお手軽。

Monaco.Editor.create メソッドの第二引数はオプションとなるオブジェクトです。
valueが初期文字列、modeが言語(csharpとかjavascriptとか)、readOnlyは編集可能かどうか、それ以外はICommonEditorOptions インターフェースあたりをご覧ください。

これだと表示するだけですので、最終的には編集結果を取得するというのが普通です。
Monaco.Editor.create メソッドの戻り値であるエディターのインスタンスに対して、
getValue メソッドを呼び出すことで編集中の文字列を取得できます。

まとめ

というわけで割と手軽に高性能エディターを自分のアプリケーションやWebページに組み込めるようになりました。
一部Visual Studio Codeの本体側に依存している機能(diagnostics)などもあるのでそういうものは使えなかったりするのですが、
それはそれとしても利用価値はあるのではと思います。

今回は単純に埋め込むところまでなので、次はこのエディターの拡張方法について書くかもしれません。