2022年3月29日火曜日

monaco-editor で YAML の入力補完を行う

monaco-editor に入門する の続きから、 JSON Schema を読み込ませて YAML の入力補完を実現するところまで。

必要パッケージのインストール

monaco-yaml パッケージをインストールする。

npm install --save-dev monaco-yaml

JSON スキーマの作成

前回 と同じく、「タイトル」「URL」のプロパティを持った要素の配列を定義する。

dist/schema/Bookmarks.json

{
  "type": "array",
  "items": {
    "type": "object",
    "required": [
      "url"
    ],
    "properties": {
      "url": {
        "type": "string"
      },
      "title": {
        "type": "string"
      }
    },
    "$schema": "http://json-schema.org/schema#"
  },
  "$schema": "http://json-schema.org/schema#",
  "additionalProperties": false
}

YAML 補完機能の実装

MonacoWebpackPlugin の言語設定修正

前回のサンプルでは、 typescript, javascript, css が設定されていたが、 今回は YAML を編集したいので、 yaml のみとする。

diff --git a/js/monaco-editor/json/webpack.config.js b/js/monaco-editor/json/webpack.config.js
index 8b5ea53..1094993 100644
--- a/js/monaco-editor/json/webpack.config.js
+++ b/js/monaco-editor/json/webpack.config.js
@@ -28,7 +28,7 @@ module.exports = {
     },
     plugins: [
         new MonacoWebpackPlugin({
-            languages: ['typescript', 'javascript', 'css']
+            languages: ['json']
         })
     ]
 };

monaco-yaml のインポート

+import { setDiagnosticsOptions } from 'monaco-yaml';

スキーマファイルの読み込み

fetch で URL を指定子、ファイルの中身を取得する。

+async function init() {
+
+  const SCHEMA_URL = './schema/Bookmarks.json';
+
+  async function getJsonFromUri(jsonUri) {
+    const response = await fetch(jsonUri);
+    const json = await response.json();
+    return json;
+  }
+
+  const schema = await getJsonFromUri(SCHEMA_URL);
...(snip, 後述の YAML の Diag 設定処理)

fetch で async/await を使用するため、これ以降の処理をすべて init 関数として括る。

YAML の Diag 設定

先ほど取得した JSON スキーマの情報を使い、 Diagnostics Option の設定を行う。

...(snip, 前述のスキーマファイルの読み込み処理)
+  setDiagnosticsOptions({
+    enableSchemaRequest: true,
+    hover: true,
+    completion: true,
+    format: true,
+    validate: true,
+    schemas: [
+      {
+        uri: SCHEMA_URL,
+        fileMatch: ['*'],
+        schema: schema
+      }
+    ]
+  });
...(snip, 後述の monaco-editor の生成処理)
  • schemas.uri: JSON スキーマファイルの URI を指定
  • schemas.fileMatch: このスキーマを適用するファイル名のパターンを指定、今回は全ファイルにマッチさせたいので '*' とする
  • schemas.schema: JSON スキーマファイルの中身を指定

これで、このスキーマに則った候補の出力をしてくれるようになる。

monaco-editor の生成

   monaco.editor.create(document.getElementById('root'), {
-    value: `const foo = () => 0;`,
-    language: 'javascript',
-    theme: 'vs-dark'
+    value: "",
+    language: 'yaml',
   });
+}
  • language: エディタで開くファイルの言語、今回は YAML なので yaml を設定
  • value: エディタのテキスト初期値、今回は空にしたいので空文字を設定

init 関数を呼び出す処理追加

async/await の関係上 init 関数を作ったので、 DOMContentLoaded のタイミングでその関数を呼び出すように修正。

+document.addEventListener('DOMContentLoaded', () => {
+  init();
 });
■ index.js 全体
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { setDiagnosticsOptions } from 'monaco-yaml';

(function () {
    // create div to avoid needing a HtmlWebpackPlugin template
    const div = document.createElement('div');
    div.id = 'root';
    div.style = 'width:800px; height:600px; border:1px solid #ccc;';

    document.body.appendChild(div);
})();

async function init() {

  const SCHEMA_URL = './schema/Bookmarks.json';

  async function getJsonFromUri(jsonUri) {
    const response = await fetch(jsonUri);
    const json = await response.json();
    return json;
  }

  const schema = await getJsonFromUri(SCHEMA_URL);

  setDiagnosticsOptions({
    enableSchemaRequest: true,
    hover: true,
    completion: true,
    format: true,
    validate: true,
    schemas: [
      {
        uri: SCHEMA_URL,
        fileMatch: ['*'],
        schema: schema
      }
    ]
  });

  monaco.editor.create(document.getElementById('root'), {
    value: "",
    language: 'yaml',
  });
}

document.addEventListener('DOMContentLoaded', () => {
  init();
});

動作確認

npm start コマンドで実行し、 monaco-editor が開かれ、 <C-Space>title, url が補完されることを確認。 OK.

ここまでの修正内容を以下 Pull Request で実施しているので、必要に応じて参照してみてください。

参考資料

0 件のコメント:

コメントを投稿