Qiitaの様なサービス作成中 マークダウンエディタ 連載(3)

## 基本情報

* [次に作りたいQiita、dev.toの様なサービスについて](http://alphabrend.hatenablog.com/entry/2018/05/07/090803) で書いたサービスを開発中です。
* [前回の記事](https://qiita.com/dala00/items/5c378c5cffd412d75267)
* できたサービス [Crieit](https://crieit.net)

## はじめに

前回ユーザー認証を作成してログインできるようにしたので、早速記事を投稿できるようにします。

掲示板等であれば普通にtextareaでいいのですが、エンジニアが記事を投稿するサービスはだいたいMarkdownで記述できるようになっているので、今回はMarkdownエディタを導入してMarkdownで記事を投稿できるようにします。
あとはタグ入力コンポーネントも導入します。

## Markdownエディタ

### 使用するライブラリ

[TOAST UI Editor](https://github.com/nhnent/tui.editor)
これを使うことにしました。下記は公式のイメージサンプルです。

![34356204-4c03be8a-ea7f-11e7-9aa9-0d84f9e912ec.gif](https://qiita-image-store.s3.amazonaws.com/0/136506/d0c5e92a-6d5d-2b88-5fc2-aa30b4955a87.gif)

QiitaライクなMarkdownエディタというだけでなく、グラフやUMLを書くこともできるとりあえずなんかすごいエディタっぽいです。公式サイトで実際に触ってみることも可能です。

[Tutorial: 1. Basic | Editor](https://nhnent.github.io/tui.editor/api/latest/tutorial-example01-basic.html)

元々他のサービスでSimpleMDEというのを使っていたのですが、それはデフォルトで画像のアップロードもできなかったので、TOAST UI Editorの方が色々と良さそうでした。

### TOAST UI Editorの導入

インストール

```sh
yarn add tui-editor
```

最初の方でCSSや拡張機能の読み込みを行います。（CSSはここで読まない方がよかったかも）

```javascript
require('codemirror/lib/codemirror.css') // codemirror
require('tui-editor/dist/tui-editor.css'); // editor ui
require('tui-editor/dist/tui-editor-contents.css'); // editor content
require('tui-editor/dist/tui-editor-extChart');
require('tui-editor/dist/tui-editor-extUML');
require('tui-editor/dist/tui-editor-extScrollSync');
require('tui-editor/dist/tui-editor-extTable');
require('highlight.js/styles/github.css'); // code block highlight
```

Vue.jsのコンポーネントとしてエディタを追加します。

```html
    <div ref="editSection" class="editor"></div>
```

script。エクステンションの読み込みや画像アップロードのフックを入れたりもしています。

```javascript
        this.editor = new Editor({
          el: this.$refs.editSection,
          initialEditType: 'markdown',
          initialValue: response.data.draft.body,
          previewStyle: 'vertical',
          height: 'inherit',
          hooks: {
            addImageBlobHook: this.addImageBlobHook.bind(this),
          },
          exts: ['chart', 'scrollSync', 'table', 'uml']
        });
```

画像アップロード処理。サーバー側も適宜処理を入れる必要があります。通常のアップロードファイルの取得処理で可能です。

```javascript
    addImageBlobHook: function(blob, callback) {
      const data = new FormData();
      data.append('image', blob);
      const config = {
        header: {
          'Content-Type': 'multipart/form-data'
        }
      };
      axios.post('/upload-images', data, config)
        .then(response => {
          callback(response.data.url, '');
        })
        .catch(error => {

        })
    },
```

あと保存時に本文を取得する処理。

```javascript
      data.body = this.editor.getMarkdown();
```

こんな感じで完成です。入れた拡張はグラフ、UML、テーブル編集、左右のスクロール同期です。

![Dcmf5ZBV0AcUFZz.jpg](https://qiita-image-store.s3.amazonaws.com/0/136506/9ec087c3-d94e-de5f-690b-e741c3ca9286.jpeg)

## タグ編集機能

### ライブラリの選定

タグ入力ですが、正直つい最近までVueで便利に使えるOSSのタグ入力コンポーネントというのはこの世に存在しませんでした。入力はできるけどオートコンプリートできないとか、色々どれも何かが不足していました。

ところが、改めて調べてみると去年の年末くらいに新たなライブラリが作られていたようです。

[JohMun/vue-tags-input: A tags input component for VueJs](https://github.com/JohMun/vue-tags-input)

![vue tags input   A tags input component for VueJs with autocompletion  custom validation  templating and much more.png](https://qiita-image-store.s3.amazonaws.com/0/136506/9b82b78a-75cc-538e-c602-3bccad9cde4f.png)

Vueのコンポーネントとして使用でき、オートコンプリートも標準で用意されており、且つ通信して候補を取得する処理のサンプルもありました。ドキュメントはまだ途中でしたが、全然不便しない感じで実装できました。今までタグは結構面倒だったのですが、これのおかげでかなり工数が削減できました。

[公式](http://www.vue-tags-input.com/#/)にサンプルもあるので是非試してみてください。

導入方法はほんとにドキュメント通りなので見てみてください。オートコンプリートのサンプルは[こちら](http://www.vue-tags-input.com/#/examples/autocomplete)です。

## まとめ

最終的にこんな感じになりました。完全にQiitaを真似ていてこれがベストかどうかは不明ですが、なんにしろ画面いっぱい使って編集＆プレビューできるのはいいなと思います。

![Laravel.png](https://qiita-image-store.s3.amazonaws.com/0/136506/cfc2babd-4b38-4f3d-8e91-fb2bfe141f6e.png)


## 次回

多分はてなブログからの記事インポート
もしくはアラビカ・エチオピアとロブスタ・ウガンダを試しての雑感について

ちなみに完成したサービスは下記です。
[Crieit](https://crieit.net)

興味を持たれたらぜひいいねをお願いします。