SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

monaco-editorをelectron環境で使ってみた

前回に引き続き、monaco-editorネタです。
今回は、monaco-editorをelectron環境で使ってみました。

f:id:minami_SC:20160725001931p:plain

プロジェクト一式は以下のリポジトリに置いています。
github.com

参考リンク

monaco-editorのサンプル類が置かれた、以下のリポジトリを参考にやってみます。
https://github.com/Microsoft/monaco-editor-samples/tree/master/sample-electron

ベースのプロジェクト

以前作った、↓のelectron+typescriptなプロジェクトをベースにして、monaco-editorを組み込んでみます。
https://github.com/sourcechord/electron-typescript-sample

気を付ける点

loader.jsを読み込むタイミング

monaco-editorを使うときは、AMD方式のモジュールローダのloader.jsを読み込む必要があります。
しかし、このloader.jsを読み込むと、node.jsのrequire()・・・というモジュール読み込みができなくなってしまいます。

そのため、node.js/electron関連のモジュールや、npmでインストールしたモジュール類は先に読み込んでおき、
最後にloader.jsを読み込んで、monaco-editor関連のファイルをrequireする必要があります。

こんな風にbodyタグの最後の部分でloader.jsを読み込み、そのあとでmonaco-editor関連のモジュール読み込みを行います。

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <style type="text/css">
      * {
        box-sizing: border-box;
      }
      html, body{
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
    <script src="index.js"></script>
  </head>
  <body>
    <div id="container" style="width: 100%; height: calc(100% - 30px); border:1px solid #ccc"></div>
    <button onclick="showEditorText()">Show Text</button>

    <script>
      // node.js/electron関係のモジュールは、loader.jsを読み込む前にrequire()しておく必要がある。
      var path = require('path');
    </script>
    <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
    <script>
      function uriFromPath(_path) {
        var pathName = path.resolve(_path).replace(/\\/g, '/');
        if (pathName.length > 0 && pathName.charAt(0) !== '/') {
          pathName = '/' + pathName;
        }
        return encodeURI('file://' + pathName);
      }
      require.config({
        baseUrl: uriFromPath(path.join(__dirname, 'node_modules/monaco-editor/min'))
      });
      // workaround monaco-css not understanding the environment
      self.module = undefined;
      // workaround monaco-typescript not understanding the environment
      self.process.browser = true;
      require(['vs/editor/editor.main'], function() {
        onModuleLoaded();
      });
    </script>
  </body>
</html>

index.ts

/// <reference path="node_modules/monaco-editor/monaco.d.ts" />
import * as electron from 'electron';
import {remote} from 'electron';
const app = remote.app;
const BrowserWindow = remote.BrowserWindow;
const dialog = remote.dialog;

var editor: monaco.editor.IStandaloneCodeEditor;

function onModuleLoaded() {
    editor = monaco.editor.create(document.getElementById('container'), {
        value: [
        'function x() {',
        '\tconsole.log("Hello world!");',
        '}'
        ].join('\n'),
        language: 'typescript',
        automaticLayout: true,
        theme: "vs-dark"
    });
}

function showEditorText() {
    var text = editor.getValue();
    alert(text);
}
レイアウト

monaco.editor.createメソッドを呼び出す際に、以下のようにautomaticLayout: trueという指定を追加しています。

    editor = monaco.editor.create(document.getElementById('container'), {
        value: [
        'function x() {',
        '\tconsole.log("Hello world!");',
        '}'
        ].join('\n'),
        language: 'typescript',
        automaticLayout: true,
        theme: "vs-dark"
    });

この指定を加えておくと、テキストエディタ領域をリサイズした際に、monaco-editorのテキストエディタ部分が自動でレイアウト調整されるようになります。
(指定しないと、ウィンドウリサイズ時とかしても、エディタ部分がリサイズされず、そのままの状態で残ってしまいます)

今回はこの辺まで。