【超簡単】Nuxtでシンタックスハイライト＋プレビュー付きのマークダウンエディタを作る

# はじめに
NuxtでQiitaのようなマークダウンエディター+プレビュー機能のブログを作ろうとした時に、
[markdown-it-vue](https://github.com/ravenq/markdown-it-vue)という便利なライブラリがあったので遊んでみました。
最終的にはこんな感じのシンタックスハイライト+プレビュー機能のついたマークダウンエディターを作ります。
![スクリーンショット 2021-05-12 2.42.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631045/08d4604a-2c03-f942-0d26-266a4655da42.png)

**コード挿入の黒い背景色やh1タグなどは個人的な好みで後から色を変えています。**

このライブラリを導入するだけででマークダウンとシンタックスハイライト、警告ボックスなど簡単に実装できるので、個人開発では試してみるのもアリです。
ただ少しマイナーなライブラリのため、不安な方は`marked.js`と`Highlight.js`を組み合わせる方式をとったほうがいいと思います。

# markdown-it-vue
 [markdown-it-vue](https://github.com/ravenq/markdown-it-vue)

対応言語は[こちら](https://github.com/ravenq/markdown-it-vue#support-hilight-lang)で確認できます。有名な言語には大抵対応しているので困ることはないです。
他にもサポートとして円グラフやシーケンス図が対応しています。
詳しくは[README](https://github.com/ravenq/markdown-it-vue#readme)をご覧ください。


# 実装
まずはnuxtで適当なプロジェクトを作りましょう。
初期設定などは割愛します。

````shell:ターミナル
$ create-nuxt-app markdown-app
```
`markdown-it-vue`をインストールします。

````shell:ターミナル
$ cd markdown-app
$ yarn add markdown-it-vue #yarnの場合
$ npm install markdown-it-vue #npmの場合
```

`pages/index.vue`をまるっと以下のように書き換えます。
まずは公式の[README](https://github.com/ravenq/markdown-it-vue#usage)に書かれてる簡単なサンプルで動作確認しましょう。

```vue:pages/index.vue
<template>
  <div>
    <markdown-it-vue class="md-body" :content="content" />
  </div>
</template>

<script>
import MarkdownItVue from 'markdown-it-vue'
import 'markdown-it-vue/dist/markdown-it-vue.css'
export default {
  components: {
    MarkdownItVue
  },
  data() {
    return {
      content: '# your markdown content'
    }
  }
}
</script>

```

```shell:ターミナル
yarn dev #yarnの場合
npm run dev #npmの場合
```
`http://localhost:3000`にアクセスすると、以下のようにマークダウンが反映されています。
若干見づらいですが、ボーダーもついていますね。
公式のスタイル一覧は[こちら](https://github.com/ravenq/markdown-it-vue#screenshot)

![スクリーンショット 2021-05-11 23.53.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631045/c419c0bd-c0da-51a7-e25e-bd1d287f4059.png)


## プレビュー機能を作る

簡単なサンプルを載せます。
細かいスタイルは各自で修正してください。

```vue:pages/index.vue
<template>
  <div class="wrap">
    <div class="editer">
      <textarea
        class="md-editer"
        v-model="content"
        placeholder="マークダウンで書く"
      ></textarea>
    </div>
    <div class="preview">
      <markdown-it-vue class="md-body" :content="content" />
    </div>
  </div>
</template>

<script>
import MarkdownItVue from "markdown-it-vue";
import "markdown-it-vue/dist/markdown-it-vue.css";
export default {
  components: {
    MarkdownItVue
  },
  data() {
    return {
      content: ""
    };
  }
};
</script>

<style lang="scss" scoped>
.wrap {
  width: 100%;
  height: 800px;
  display: flex;
  padding-top: 40px;
  .editer {
    width: 50%;
    .md-editer {
      width: 100%;
      height: 100%;
      border: solid 1px rgb(206, 205, 205);
      font-size: 1.1rem;
    }
  }
  .preview {
    width: 50%;
    height: 100%;
    border: solid 1px rgb(206, 205, 205);
    padding: 10px;
  }
}
</style>

```
**プレビュー機能は`textarea`と`content`を`v-model`で紐付けることが肝です。**
以下の画像の通り、半分より左がエディター、右がプレビューです。
実際にマークダウンで書くと即座に反映されると思います。

![スクリーンショット 2021-05-12 0.48.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631045/de0d6a09-dbb8-514b-bff8-863715ab2a50.png)



実際に[公式の書き方](https://github.com/ravenq/markdown-it-vue#screenshot)を参考に書いてみるとこんな感じ。

![スクリーンショット 2021-05-12 1.13.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631045/2ffbf113-8ac5-59c7-da73-31d2b5e456d0.png)

これが`markdown-it-vue`のデフォルトスタイルです。
これだけでも十分ですが、私はコード挿入の背景色をQiitaのように黒っぽくしたいと思ったので、独自のCSSを作ることにしました。
もし独自のCSSにしたいと思った方はこの先もお読みください。

## 独自のCSSを作る
`assets/markdown.scss`を作成して以下をコピペ。

```scss:assets/markdown.scss
$mainColor: #36cbfa;

.md-body {
  .markdown-body {
    h1,
    h2 {
      border-bottom: none;
      border-left: solid 10px $mainColor;
      padding: 5px;
    }
    h2 {
      border: none;
      color: $mainColor;
    }
    pre {
      background-color: #334146;
      code {
        color: rgb(236, 236, 236);
        font-family: inherit;
        line-height: 1.8;
        font-size: 0.9rem;
        .hljs-keyword {
          color: rgb(201, 146, 253);
        }
        .hljs-title {
          color: $mainColor;
        }
        .hljs-attr {
          color: rgb(247, 210, 0);
        }
        .hljs-attribute {
          color: palegreen;
        }
        .hljs-variable {
          color: orange;
        }
        .hljs-selector-class {
          color: rgb(214, 157, 50);
        }
        .hljs-built_in {
          color: #d19719;
        }
        .hljs-symbol {
          color: rgb(18, 167, 253);
        }
        .hljs-number {
          color: rgb(172, 255, 172);
        }
        .hljs-string {
          color: rgb(190, 228, 190);
        }
        .hljs-subst {
          color: rgb(250, 99, 89);
        }
        .hljs-meta {
          color: #6594fa;
        }
      }
    }
  }
}

```
```js:nuxt.config.js
css: ["@/assets/markdown.scss"]//追記
```
こんな感じで独自のスタイルが反映されたら成功です！
![スクリーンショット 2021-05-12 10.29.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631045/d7573061-9edb-60de-a0fc-325bbec92ef7.png)



# 最後に
`markdown-it-vue`を使えば簡単にマークダウンとシンタックスハイライトが実装できました。
プレビュー機能も実装するとマークダウンの反映が確認できて便利ですね。
皆さんも独自のCSSを割り当てて遊んでみてください。


## 参考

* [markdown-it-vue](https://github.com/ravenq/markdown-it-vue)