CodeMirrorでオリジナルのエディタを作る

# はじめに
[**福島高専アドベンドカレンダー**](https://qiita.com/advent-calendar/2020/nitfc)11日目に飛び込みました[@cyan](https://qiita.com/cyan)です！
初めてのアドベントカレンダーの参加ですが、私自身、技術的に詳しく書けることは無いので以前利用したライブラリについて紹介したいと思います。

# 目標
**CodeMirror** というライブラリを使って、オリジナルのエディタを作っていきます。
エディタなんて「VSCodeで十分！」と思いませんか？
その通りで、さすがに強力な補完機能やアドオンを持っているVSCodeやAtomのようなものは作れないです :sweat:
なので、今回は表示用のコードビューアとして作っていきます。

↓こんな感じです↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/d59a7218-65d9-d603-f694-292f4bcf4764.png)

しかし、CodeMirrorはかなりのカスタマイズ性があり、やろうと思えばかなり本格的なエディタを作ることも可能です!

実際、

- [CodePen](https://codepen.io/)
- [JetBrains](https://www.jetbrains.com/)

などでも使われています。

# 開発環境

- ブラウザ（なんでも）
- HTML , JavaScript

# 1. 前準備
## CodeMirrorのライブラリをダウンロード
↓こちらからzipファイルをダウンロードし、解凍してください。
https://codemirror.net/codemirror.zip

今回は単純化のためzipファイルをダウンロードしますが、npmでもパッケージをインストールできます。

```shell
npm install codemirror
```

## プロジェクト構成
- 適当なプロジェクトフォルダを作成
- index.htmlファイルを作成
- 先ほどダウンロードしたCodeMirrorのライブラリから `lib` フォルダをプロジェクトフォルダにコピペ

↓こんな感じ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/812bee99-f2ef-1633-7318-bf78b01e282e.png)

# 2. エディタを表示
それでは開発に入っていきましょう！
CodeMirrorはブラウザ上で動きます。なので基本はJavaScriptで処理を書いていきます。
まずは、**index.html** を以下のようにしましょう。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="lib/codemirror.css">
  <script src="lib/codemirror.js"></script>
</head>
<body>
  <script>
    var editor = CodeMirror(document.body, {
      value: 'console.log("Hello World")\n',
      lineNumbers: true,
    });
  </script>
</body>
</html>
```

では、 **index.html** をブラウザで開いてください。

どうでしょうか？
行番号が入ったエディタが表示されたら成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/bfc52113-1acb-9b74-ea03-905780a2f3c8.png)

## 説明
先に進む前に、先ほどのコードの説明を軽くします。
### ライブラリのインポート
以下のコードで、最初に`lib` フォルダにあるCodeMirrorのファイルを指定します。

```html
<link rel="stylesheet" href="lib/codemirror.css">
<script src="lib/codemirror.js"></script>
```

### エディターの作成
スクリプトタグでエディタを作成します。 `CodeMirror.fromTextArea` メソッドの第一引数にエディターにさせるDOM（今回は`body`）を指定し、第二引数に設定項目を記述します。

```js
var editor = CodeMirror(document.body, {
  value: "console.log\n",
  lineNumbers: true,
});
```

今回の設定は `lineNumbers` で行番号の表示、`value`でエディターの初期値を指定しています。

# 3. 装飾
エディタを表示させることはできましたが、このままじゃ味気ない感じになってしまうのでテーマを適用させていきたいと思います。

## テーマファイルの取得
１からテーマを作成することも可能ですが、今回はすでに用意されているテーマを利用します。
CodeMirrorの解凍フォルダのthemeフォルダに各テーマのcssファイルがあると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/e6a5e14d-da59-d299-1407-fdbbbf52869c.png)

この中からお好きなテーマをプロジェクトフォルダのthemeフォルダに入れましょう。
説明では**monokai.css**を入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/28081023-ab82-9cf4-ad94-f3ddbb937075.png)

## CodeMirrorの設定
では、エディタにテーマを適応させていきます。

先ほど入れたテーマファイルをインポートします。

```html
<link rel="stylesheet" href="theme/monokai.css">
```

CodeMirrorの設定項目に `theme` を追加します。値は追加したテーマの名前です。

```js
var editor = CodeMirror(document.body, {
  value: 'console.log("Hello World")\n',
  lineNumbers: true,
  theme: 'monokai'  // <- テーマの名前
});
```

## 全体コード

```html:index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="lib/codemirror.css">
  <link rel="stylesheet" href="theme/monokai.css">  <!-- ADD -->
  <script src="lib/codemirror.js"></script>
</head>
<body>
  <script>
    var editor = CodeMirror(document.body, {
      value: 'console.log("Hello World")\n',
      lineNumbers: true,
      theme: 'monokai'  // ADD
    });
  </script>
</body>
</html>
```

## プレビュー
どうでしょうか？指定したテーマ色にエディタが変化したと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/0ec105f9-0a06-08d1-9e88-753c6ad45997.png)

# 4. 言語対応
エディタの装飾はできましたが文字がまだ単色の状態です。これを解決するには、設定でどの言語仕様で装飾するかを指定する必要があります。
今回はエディタを `javascript` の仕様にします。

## 設定ファイルの取得
CodeMirrorの解凍フォルダのmodeフォルダに各言語ごとの設定ファイルがあります。ここから自分が使いたい言語を持っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/ec97b948-8016-3435-38e9-fa9069916ebe.png)

今回は`javascript`の記述にするため、 **javascriptフォルダ**を取得します。プロジェクトフォルダのmodeフォルダに持ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/bedb8e2d-794b-494c-6160-b1c6240ea51c.png)


持ってきたフォルダの中身にはいくつかファイルが入ってますが使うのは `言語名.js` というファイルです。
今回の場合だと、 `javascript.js` ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/20d7b342-a35d-2429-213b-76ef36443aa6.png)

## CodeMirrorの設定
テーマを適用した時と同じように設定していきます。
まず、先ほど持ってきた設定ファイルをインポートしましょう。

```html
<script src="mode/javascript/javascript.js"></script>
```

CodeMirrorの設定項目に `mode` を追加します。値には言語名を入れます。

```js
var editor = CodeMirror(document.body, {
  value: 'console.log("Hello World")\n',
  lineNumbers: true,
  theme: 'monokai',
  mode: 'javascript'  // 言語名
});
```

## 全体コード
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="lib/codemirror.css">
  <link rel="stylesheet" href="theme/monokai.css">
  <script src="lib/codemirror.js"></script>
  <script src="mode/javascript/javascript.js"></script>  <!-- ADD -->
</head>
<body>
  <script>
    var editor = CodeMirror(document.body, {
      value: 'console.log("Hello World")\n',
      lineNumbers: true,
      theme: 'monokai',
      mode: 'javascript'  // ADD
    });
  </script>
</body>
</html>
```

## プレビュー
かなりエディタっぽくなってきたのではないでしょうか？
言語仕様に沿って、単語ごとに装飾が入ると思います。

自分でコードを記述して試してみてください！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/f94d6a3e-19dc-0fb0-e0ac-35636a8bfb97.png)

# テーマをカスタマイズ
では最後にテーマを自分好みにカスタマイズしてみましょう！
テーマはCSSで定義されており、各単語の色や背景を自由に変えることができます。

## テーマ作成
今回は文字列の色を変えていきます。
新しくindex.cssというファイルをプロジェクトフォルダに作成し、以下のコードを入れてください。

```css:index.css
.cm-s-custom span.cm-string {
  color: #489748;
}
```

細かい説明が省きますが、CSSのクラス名は `.cm-s-{テーマ名}` と定義する必要があり、セレクタでどの要素を対象にするかを決めます。上記のコードは `span.cm-string` で文字列(`""`)の色を変えています。

## テーマの適用
それでは、自分で作成したテーマを適応させていきます。index.html の `head` タグに新しく index.css を追加しましょう。

```html
<link rel="stylesheet" href="index.css">
```

あとは `CodeMirror` に適応させます。 `theme` 属性に追加したいテーマ名を記述します。
テーマ名はindex.cssで記述した **custom** ですね。

```js
var editor = CodeMirror(document.body, {
  value: 'console.log("Hello World")\n',
  lineNumbers: true,
  theme: 'monokai custom',
  mode: 'javascript'
});
```

## 全体コード
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="lib/codemirror.css">
  <link rel="stylesheet" href="theme/monokai.css">
  <link rel="stylesheet" href="index.css">
  <script src="lib/codemirror.js"></script>
  <script src="mode/javascript/javascript.js"></script>
</head>
<body>
  <script>
    var editor = CodeMirror(document.body, {
      value: 'console.log("Hello World")\n',
      lineNumbers: true,
      theme: 'monokai custom',
      mode: 'javascript'
    });
  </script>
</body>
</html>
```

## プレビュー
文字列の色が変われば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/0d621a67-9200-f4e8-f109-54ddb299618d.png)

カスタマイズは他にもできることがたくさんあるので是非試して欲しいです！
（GIF画像を入れることだってできます）
![ezgif-5-7400f3b7869f.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278251/c33ab201-119f-007c-176d-bed0a5c01c0f.gif)



# 最後に
CodeMirrorを使えば、少し知識でかなり良いエディタが作れるのではないかと思います。
自分のサイトなどでコードを見せたいときに利用してみてはいかがでしょうか？

# 宣伝
CodeMirrorを使ってWebアプリを作ってみたので良かったら使ってみてください。
画面共有時やプレゼン中にコードを他人に見せるときに、簡単に説明したい部分を強調できるツールです。
完成度はかなり低いので「こんな機能があったらな〜」という意見があれば是非お願いします！

↓こちらから↓
<a href="https://attention-0fbcf9.an.r.appspot.com/" target="_blank"><img src="https://raw.githubusercontent.com/cyan-0fbcf9/Attention/develop/static/icon.png" width=128></a>

# Github
今回使ったコード
https://github.com/cyan-0fbcf9/codemirror-sample

# 参考文献
https://codemirror.net/