Vue Codemirror6 日本語説明文

# Vue CodeMirror6日本語ガイド

この記事は以下の説明文の原文です。
https://github.com/logue/vue-codemirror6

Vue CodeMirror6は[CodeMirror6](https://codemirror.net/6/)用のVueコンポーネントです。[surmon-china氏のvue-codemirror](https://github.com/surmon-china/vue-codemirror)とは異なり、CodeMirror6用です。

## 使用方法

```
yarn add vue-codemirror6
```

基本的に、他のVueコンポーネントと同じように`v-model`を用いて透過的に使用できます。

Vue2で使用する場合は別途[@vue/composition-api](https://www.npmjs.com/package/@vue/composition-api)が必要になります。

```sh
yarn add vue-codemirror6 @vue/composition-api
```

## 利用できるプロップ

| プロップ    | 種別                              | 説明                                                                                                                                                      |
| ---------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| value      | string?                           | 初期のテキストの値                                                                                                                                              |
| dark       | boolean                           | ダークモードにします。Vuetifyを使っている場合は`$vuetify.theme.dark`と入れると良いでしょう。                                                                           |
| wrap       | boolean                           | 自動改行を有効にします。詳細は[lineWrapping](https://codemirror.net/6/docs/ref/#view.EditorView.lineWrapping).                                                                                                                         |
| tab        | boolean                           | タブ入力を有効にします。                                                                                                                                                                                                         |
| theme      | { [selector: string]: StyleSpec } | テーマ設定を入れます。例えば、[@codemirror/theme-one-dark](https://github.com/codemirror/theme-one-dark)を使用する場合は、`oneDark`を同ライブラリからインポートして、その値をこのプロップに指定します。|
| readonly   | boolean                           | 読み込み専用にします。`editable`を`false`にした場合と異なり、テキストカーソルが表示されます。                                                                                        |
| editable   | boolean                           | ここを`false`にしたときは、`readonly`と似ていますが、こちらの場合`<pre>`タグのような動作になります。                                         |
| lang       | LanguageSupport                   | シンタックスハイライトに使用する言語を指定します。利用可能な言語は以下を参照してください： <https://codemirror.net/6/#languages>                                                                     |
| phrases    | Record&lt;string, string&gt;      | CodeMirrorの表示テキストを変更します。通常はVue i18nと併用するといいでしょう。詳細は以下を参照してください： <https://codemirror.net/6/examples/translate/>                                 |
| extensions | Extension[]                       | [@codemirror/basic-setup](https://github.com/codemirror/basic-setup)のような機能拡張を指定します。                                        |
| linter     | LintSource                                              | リンターを指定します。（例：`@codemirror/lang-javascript`を使う場合、`esLint([arbitrary rule])`関数。`@codemirror/json`を使う場合、`jsonParseLinter()`関数などのように）詳細に関しては、各種言語ライブラリを参照してください。 |
| lint-gutter | boolean                           | リンターでエラーがあった行に🔴を表示します。`linter`が指定されていない場合は無効化されます。                                                                                                     |

注意：`lang` や`linter`などは`extensions`で指定しても動きます。これらはあくまでも旧バージョンのCodeMirrorと同じように使うための処置です。

### サポートされている言語

- [`@codemirror/lang-cpp`](https://www.npmjs.com/package/@codemirror/lang-cpp)
- [`@codemirror/lang-html`](https://www.npmjs.com/package/@codemirror/lang-html)
- [`@codemirror/lang-java`](https://www.npmjs.com/package/@codemirror/lang-java)
- [`@codemirror/lang-javascript`](https://www.npmjs.com/package/@codemirror/lang-javascript)
- [`@codemirror/lang-json`](https://www.npmjs.com/package/@codemirror/lang-json)
- [`@codemirror/lang-lezer`](https://www.npmjs.com/package/@codemirror/lang-lezer)
- [`@codemirror/lang-markdown`](https://www.npmjs.com/package/@codemirror/lang-markdown)
- [`@codemirror/lang-php`](https://www.npmjs.com/package/@codemirror/lang-php)
- [`@codemirror/lang-python`](https://www.npmjs.com/package/@codemirror/lang-python)
- [`@codemirror/lang-rust`](https://www.npmjs.com/package/@codemirror/lang-rust)
- [`@codemirror/lang-sql`](https://www.npmjs.com/package/@codemirror/lang-sql)
- [`@codemirror/lang-xml`](https://www.npmjs.com/package/@codemirror/lang-xml)

### サポートされているテーマ

- [`@codemirror/theme-one-dark`](https://github.com/codemirror/theme-one-dark)
- [`upleveled/theme-vs-code-dark-plus`](https://github.com/upleveled/theme-vs-code-dark-plus)

## 例

以下は最低限の例です。

```vue
<template>
  <code-mirror v-model="value" />
</template>

<script>
import { ref, defineComponent } from 'vue';

import CodeMirror from 'vue-codemirror6';

export default defineComponent({
  components: {
    CodeMirror,
  },
  setup() {
    const value = ref('色は匂えど　散りぬるを　我が世誰ぞ　常ならむ　有為の奥山　今日越えて　浅き夢見じ　酔ひもせず');

    return { value };
  },
});
</script>
```

### Slotを用いた例

スロットの内容は、既存の`v-model`を上書きします。 このため、`v-model`を使用せずに単に`readonly`プロパティで表示する場合に使用することをお勧めします。

また、スロット内のテキストが自動的にフォーマットされないように、`<pre>`タグを挿入して使用してください。

```vue
<template>
  <code-mirror :lang="lang" :linter="linter">
    <pre>
{
  "キー": "値"
}</pre
    >
  </code-mirror>
</template>

<script>
import { ref, defineComponent } from 'vue';

import { json, jsonParseLinter } from '@codemirror/lang-json';

import CodeMirror from 'vue-codemirror6';

export default defineComponent({
  components: {
    CodeMirror,
  },
  setup() {
    const lang = json();
    const linter = jsonParseLinter();
    return { lang, linter };
  },
});
</script>
```

### すべての機能を使った例


[vite-vue2-vuetify-ts-starter](https://github.com/logue/vite-vue2-vuetify-ts-starter)を使った例です。

```vue
<template>
  <code-mirror
    v-model="value"
    basic
    :dark="dark"
    :lang="lang"
    :phrases="phreses"
  />
</template>

<script lang="ts">
import { ref, defineComponent, type Ref } from 'vue';

// Load component
import CodeMirror from 'vue-codemirror6';

// CodeMirror extensions
import type { LanguageSupport } from '@codemirror/language';
import { markdown as md } from '@codemirror/lang-markdown';
import type { Extension } from '@codemirror/state';
import type { ViewUpdate } from '@codemirror/view';

export default defineComponent({
  components: {
    CodeMirror,
  },
  setup() {
    /**
     * Vuetifyのインスタンス
     * @see {@link https://github.com/logue/vite-vue2-vuetify-ts-starter | vite-vue2-vuetify-ts-starter}
     */
    const vuetify = useVuetify();

    /** テキスト */
    const value: Ref<string> = ref('');

    /**
     * CodeMirrorの言語
     *
     * @see {@link https://codemirror.net/6/docs/ref/#language | @codemirror/language}
     */
    const lang: LanguageSupport = md();

    /** ダークモード **/
    const dark = ref(window.matchMedia('(prefers-color-scheme: dark)').matches);

    // ダークモードとVuetifyのダークモードを同期させる
    watch(dark, v => (vuetify.theme.dark = v));

    /**
     * 多言語設定
     * この例ではメッセージを日本語化しています。実際使う場合は
     * vue-i18nと併用することを推奨します。
     *
     * @see {@link https://codemirror.net/6/examples/translate/ | Example: Internationalization}
     */
    const phrases: Ref<Record<string, string>> = ref({
      // @codemirror/view
      'Control character': '制御文字',
      // @codemirror/fold
      'Folded lines': '折り畳まれた行',
      'Unfolded lines': '折り畳める行',
      to: '行き先',
      'folded code': '折り畳まれたコード',
      unfold: '折り畳む解除',
      'Fold line': '行を折り畳む',
      'Unfold line': '行の折り畳む解除',
      // @codemirror/search
      'Go to line': '行き先の行',
      go: 'OK',
      Find: '検索',
      Replace: '置き換え',
      next: '▼',
      previous: '▲',
      all: 'すべて',
      'match case': '一致条件',
      regexp: '正規表現',
      replace: '置き換え',
      'replace all': 'すべてを置き換え',
      close: '閉じる',
      'current match': '現在の一致',
      'on line': 'した行',
      // @codemirror/lint
      Diagnostics: 'エラー',
      'No diagnostics': 'エラーなし',
    });

    return {
      dark,
      value,
      lang,
      phrases,
    };
  },
});
</script>
```

## 推奨事項

CodeMirrorは容量が大きいので、ビルド時に[`manualChunks`](https://vitejs.dev/guide/build.html#chunking-strategy)機能を使って本体から切り分けることを

```ts
const config: UserConfig = {
  // ...
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          // ...
          codemirror: [
            // Split CodeMirror code.
            '@codemirror/basic-setup',
            '@codemirror/commands',
            '@codemirror/language',
            '@codemirror/lint',
            '@codemirror/state',
            '@codemirror/view',
            // Add the following as needed.
            '@codemirror/lang-html',
            '@codemirror/lang-javascript',
            '@codemirror/lang-markdown',
          ],
          // ...
        },
      },
    },
  },
  // ...
};
```

## LICENSE

[MIT](LICENSE)