【Laravel Sail × Editor.js】リッチテキストエディタの導入〜出力まで

現在エンジニアを目指して勉強中です。

ポートフォリオ作品にリッチテキストエディタを導入しようと調べた結果、
[Editor.js](https://github.com/codex-team/editor.js/)なるものにたどり着きました。

長くなりそうだったので、
導入~出力 / [データ整形~保存](https://qiita.com/Oidon/items/3d06ef6b8e0dfc420c9a) / [画面表示・再編集](https://qiita.com/Oidon/items/3dbb3f6840fd65bda701) / 画像プラグイン /
の4部作にして、実装をまとめていきます。（現在進行中）

自分と同じ状況の方には参考になるかと思いますので、ぜひ。
今回は導入~出力までです。

## 環境

・macOS Monterey 12.6
・PHP 8.1.13
・Laravel 9.3.12
・MySQL 8.0.31
・Docker 20.10.2
・Laravel Sail

## Editor.jsとは

https://editorjs.io/

公式が掲げる主な特徴は以下の3つ
>It is a block-styled editor
It returns clean data output in JSON
Designed to be extendable and pluggable with a simple API



## 導入フロー
### インストール

方法としては3通り
1. Nodeパッケージ
2. CDN
3. プロジェクトにファイルを配置（[GitHubのソースコードはこちら](https://github.com/codex-team/editor.js/releases)）

Laravel Sailなので、今回は以下を実行
```terminal
sail npm i @editorjs/editorjs
```

インストール完了
```packege-lock.json
"dependencies": 
{
   "@editorjs/editorjs": "^2.26.4"
}
```

### 実装

実装もとても分かりやすかったです。
Laravelプロジェクトの`/resources/js`配下に`editor.js`ファイルを追加。
（ファイル名等は個人的な管理しやすさを優先してます。）

```resources/js/editor.js
import EditorJS from '@editorjs/editorjs';

// 以下のどちらかを書く。おそらく大体の人は、結局2番目の書き方になります。
const editor = new EditorJS('koko-wo-soroeru');
const editor = new EditorJS ({
  holderId: 'koko-wo-soroeru',
});
```
```editor.html
<!-- Laravelプロジェクトなので実際はeditor.blade.phpファイル -->
<div id="koko-wo-soroeru"></div>
```
これで画面にエディターが表示されます。

![editorjsデフォルト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535390/17f979ab-2f3f-ddaf-51bd-15cddabf1b64.png)
ただデフォルトでは、シンプルなテキスト入力と
太字・斜体・リンクに対応しているのみ。
プラグインでの拡張が基本のようなので、追加していきます。

### プラグインの導入

プラグインの導入も、基本的にEditor.js本体と同様に3通りで実装が可能。
導入できるプラグインは[こちらで確認](https://github.com/editor-js)してください。

今回自分が導入したのは以下のプラグイン。
・[header（見出し）](https://github.com/editor-js/header)
・[list（リスト）](https://github.com/editor-js/list)
・[paragraph（空行有効化）](https://github.com/editor-js/paragraph)
・[image（画像アップローダー）](https://github.com/editor-js/image)

```terminal
sail npm i @editorjs/header
sail npm i @editorjs/list
sail npm i @editorjs/paragraph
sail npm i @editorjs/image
```
各プラグインの設定はGitHubのREADMEを。
分かりやすくまとまっています。
（画像プラグインについては別途まとめます）
```resources/js/editor.js
const editor = new EditorJS ({
  holderId: 'editor',
  tools: {
      header: {
        class: Header,
        config: {
          levels: [2, 3, 4],
          defaultLevel: 2
        }
      },
      list: {
        class: List,
        inlineToolBar: true,
        config: {
          defaultStyle: 'unorderd'
        }
      },
      paragraph: {
        class: Paragraph,
        inlineToolBar: true,
        config: {
          preserveBlank: true
        }
      }
  }
});
```

## 入力データの出力

[エディタに入力されたデータはsave()メソッドで出力](https://editorjs.io/saving-data)できます。
あとは用途に合わせて煮るなり焼くなりというわけですね。

今回は、ボタンを押すと出力される処理をjQueryで実装しました。
`editor.save()`以下のコードは公式で紹介されているものの転用です。
```editor.html
<button id="get-editor-data" >editor.js出力！！</button>
```
```resources/js/editor.js
$(function() {
  // データ保存
  $('#get-editor-data').on('click', function() {
    editor.save()
      .then((outputData) => {console.log('Article data: ', outputData)})
      .catch((error) => {console.log('Saving failed: ', error)});
  });
});
```


```js
// outputData
// 出力されるJSONオブジェクトは以下のように3つのプロパティを含んでいる
{time: 1672207762160, blocks: Array(2), version: '2.26.4'}

// blocksのなかにテキスト情報が含まれる
blocks:[
    {
     id  : "J4ZvhsriKq",
     type:"paragraph",
     data:{
            text:"ああああああ"
           }
    },
    {
     id  :"El6S5s-QoM",
     type:"list",
     data:{
            style:"ordered",
            items:[
                    "ほほおほほほおほほほほh<br>ほほほほほほほほほほほ",
                    "ほほおほほほほほほほほほ"
                   ]
           }
    }
]
```

今回はここまで。
出力されたデータをどうDBへ保存するか
保存したデータをどう表示するか、再編集するか
といったことを知りたい方は、続きをどうぞ。（現在執筆中です）


## 参考

### 公式
https://editorjs.io/

https://github.com/codex-team/editor.js/

### その他
https://www.aizulab.com/blog/rich-text-editor-editorjs/

https://note.com/eveningmoon_lab/n/n5d53243df5a6

https://paiza.hatenablog.com/entry/2019/08/15/完全カスタマイズOK！ブロックスタイルのテキスト