nuxt3.0環境でEditor.jsを動作させてみる

## 動作環境
- Nuxt3.0 + TailwindCSS


## 導入
以下コマンドでNuxt3を導入します。
`npx nuxi init <projectName>`

editor.jsをインストールします。
`npm install @editorjs/editorjs --save`
paragraphプラグインも導入します。
`npm install @editorjs/paragraph`

## 使用方法
エラーパターン
``` index.vue
<script setup lang="ts">
import EditorJS from '@editorjs/editorjs'
const editor =  new EditorJS({
  holder: 'editorjs'
})
</script>

<template>
  <div id="editorjs" />
</template>
```
そのままEditor.jsを使用しようとすると、`window is not defined`エラーが出ます。

そのため、Editor.jsのインポートを`onMounted`内で実施します。
``` index.vue
<script setup lang="ts">
onMounted(async () => {
  const EditorJS = (await import('@editorjs/editorjs')).default
  const editor = () => {
    new EditorJS({
      holder: 'editorjs'
    })
  }
  editor()
})
</script>

<template>
  <div id="editorjs" />
</template>

```

## pluginsにエディタを登録して使用するパターン
`useEditor()`でアクセスできるようにcomposablesに登録します。
```composables/ useEditor.ts
export const useEditor = () => {
    return useNuxtApp()?.$editor
 }
```
`plugins`にエディタを登録します。
使用する型を`models`に追加します。

``` models/ editor.ts
import EditorJS, { OutputData, API, BlockAPI } from '@editorjs/editorjs'

export type EditorConfig = {
  id: string
  data?: OutputData
  onChange?: (api: API, block: BlockAPI) => void
}

export interface Editor {
  create: (config: EditorConfig) => Promise<EditorManager>
}

```

``` models/ index.ts
export * from './editor'
```

Editor.jsのimport時にエラーが発生するため、`const create`内でインポートを実施します。


``` plugins/ editor.ts
import { Editor } from '~~/models'

const editor : Editor = {
  create: async({ id, data, onChange }) => {
    const EditorJS = (await import('@editorjs/editorjs')).default
    const Paragraph = (await import('@editorjs/paragraph')).default
    return new Promise((resolve, reject) => {
      // ツールの設定
      const tools = {
        paragraph: {
          class: Paragraph,
          inlineToolbar: ['link', 'bold', 'italic'],
          config: {
            placeholder: '本文を入力'
          }
        }
      }
      // Editor.js のインスタンス生成
      const editor = new EditorJS({
        holder: id,
        tools,
        data,
        minHeight: 0,
        onReady: () => resolve({
          id,
          element,
          instance: editor
        }),
        onChange
      })
    })
  }
}

  export default defineNuxtPlugin(() => {
    return {
      provide: {
        editor
      }
    }
  })
```

pagesから`useEditor().create`でクリエイトを呼び出します。


```index.vue
<script setup lang="ts">
onMounted(async () => {
  const editor = await useEditor().create({id: 'editorjs'})
})
</script>

<template>
  <div id="editorjs" />
</template>
```
これで最低限Editor.jsを使用する準備ができました。

## Editor.jsで書き込まれたデータの管理
editor上で作成されたデータは`onChange`で検知します。
データを保存する`const blocks`を作成し、データを保存します。
``` index.vue
<script setup lang="ts">
const blocks = ref({})
onMounted(async () => {
  const editor = await useEditor().create({
    id: 'editorjs',
    data: blocks.value
    onChange: (api, block) => {
      blocks.value = api.saver.save()
    }
  })
})
.
.
.
.

```
こうすることでblocksにデータが保存されます。
保存されたデータを`const blocks`に格納することで上書き編集や途中編集が可能になります。

## まとめ
今回はNuxt2系で稼働していたEditor.jsをNuxt3にて稼働できないかの検証をしていたため、ほとんどは現状のシステムからの流用でしたが問題なく稼働しました。
プラグインのロード場所、インポート方法を変更することでNuxt3でも問題なく使用できるようです。