📝

Webページで使用可能なコードエディター Ace

2022/08/27に公開

markdown の純粋なハイライトエディターを探していて見つけた。
とても質が良かったので紹介する。

https://ace.c9.io/

License は BSD。
利用するときはどこかに出典を明記する。

環境構築

Vue のもので紹介するが、元は純粋な javascript なので他FWでも実装可能。

vue テンプレの作成

vite + vue3 + typescript

https://ja.vitejs.dev/guide/

$ yarn cerate vite test-vue3-ace-editor
√ Select a framework: » vue
√ Select a variant: » vue-ts

$ cd test-vue3-ace-editor
$ yarn install
$ yarn dev

で開けるかを確認。

ace エディタの導入

ace のエディタを vue3 に落とし込んでくれているライブラリがあるので、使用する。

https://github.com/CarterLi/vue3-ace-editor

$ yarn add ace-builds vue3-ace-editor

App.vue

App.vue
<template>
  <div>
    <v-ace-editor
      v-model:value="content"
      lang="markdown"
      theme="chrome"
      style="width: 300px; height: 200px;"
      @init="editorInit"
    />

    <div>
      <button @click="onGetSelected">
        getSelected
      </button>
      {{ selected }}
    </div>

    <div>
      <button @click="onBold">
        BOLD
      </button>
    </div>

    <div>
      <button @click="onInsert">
        Insert Text
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Ace } from 'ace-builds'
import { VAceEditor } from 'vue3-ace-editor'

import 'ace-builds/src-noconflict/mode-markdown'
import 'ace-builds/src-noconflict/theme-chrome.js'

const content = ref<string>(
`# テスト

## こんにちは

- AAA
- BBB
- CCC

てきすと
**asd**
`)

const editor = ref<Ace.Editor>()
const editorInit = (e: Ace.Editor) => {
  editor.value = e
}

const selected = ref<string>()
const onGetSelected = () => {
  const text = editor.value?.getSelectedText()
  selected.value = text
}

const onBold = () => {
  const range = editor.value?.getSelectionRange()

  const text = editor.value?.getSelectedText()
  if (range && text?.trim()) {
    editor.value?.session.replace(range, `**${text}**`)
  }
}

const onInsert = () => {
  editor.value?.insert('Insert text')
}
</script>

※レイアウトが崩れる場合、./style.css が邪魔をしているため、削除する。

ででん!とてもお手軽。

Ace について

Ace API

@init イベントで ace エディタ本体のインスタンスが取得可能。
そのインスタンスを ref に記録しておいて、様々な動作を実装可能である。
以下リンクの editor がこのインスタンスに相当する。

Ace - How-To Guide

テキストの選択、置換や検索、ショートカットキーなど、エディタに欲しそうなものは大体揃っているからすごい。
追加機能で、構文チェック機能もあるらしい。
上記サンプルでは以下のものを実装した。

  • 選択した箇所を取得
  • 選択した箇所を bold 属性に書き換える
  • カーソルの位置に文字を挿入する

これだけできれば、やりたいことは実現できる気がする。

テーマとハイライト

上記サンプルの langtheme でデザインを変更することができる。

<v-ace-editor
  v-model:value="content"
  lang="markdown"
  theme="chrome"
/>
    
import 'ace-builds/src-noconflict/mode-markdown'
import 'ace-builds/src-noconflict/theme-chrome.js'

使用可能なファイルは node_modules/ace-builds/src-noconflict/ にある。
import したファイル名と lang theme を一致させると反映させられる。
いくつか読み込んで、セレクトボックスで選択させることがお手軽に可能!


リアルタイムでのデザイン確認は以下のページが参考になる。
相当数用意されていて、独自に組むことも可能なため、文句はないだろう。
https://ace.c9.io/build/kitchen-sink.html

事前読み込みによる更新は ace.config.setModuleUrl を使うようだ。
こちらはURLを指定することも可能なので、ビルドに含めずともユーザーに入力させる手段も取れる。
詳しくは書かない。

Option について

v-ace-editor は特にドキュメントが無いため、以下ソースから解読する必要がある。

https://github.com/CarterLi/vue3-ace-editor/blob/master/index.ts

v-bind

props: {
  value: {
    type: String,
    required: true,
  },
  lang: {
    type: String,
    default: 'text',
  },
  theme: {
    type: String,
    default: 'chrome',
  },
  options: Object,
  placeholder: String,
  readonly: Boolean,
  wrap: Boolean,
  printMargin: {
    type: [Boolean, Number],
    default: true,
  },
  minLines: Number,
  maxLines: Number,
},

v-on

- update: value
- init
- input
- change
- changeSelectionStyle
- changeSession
- copy
- focus
- paste

ビルドサイズ

vite 標準でそのままビルドして、500KB程度。
上等なのではと。

おわりに

web 上のエディタは他にも色々あるが、純粋な syntax highlight を行ってくれるものは少ない印象を受けた。
見つけたものを備忘録を兼ねて紹介する。
(WISWIGのほうが需要が高いのか、メンテナンスが行き届いている気がした。)

milkdown はお気に入り。
どこかで使ってみたい。

実装考察

textarea はそのままではハイライトを行うことができない。
textarea の文字を透明にして、ハイライト用のdivを重ね合わせる実装をよく見かけた。
しかし、IMEがあるCJK系では入力中の文字も消えるのでNG。

次に特定の単語に背景色を付ける実装を見かけた。
これも二枚のパネルを重ね合わせる、とてもお手軽実装だった。
単純用途なら十分使い勝手が良いと感じた。

最後は上に列挙したエディタ系。
これらは行ごとにdiv、更にはspanで記号を区切って、擬似的に textarea を構築していた。
そもそも textarea を捨てる方向性だ。
このクラスになると個人の実装は難しいので、神のおこぼれに預かったほうが楽だ。

ace もそうだが、cloud9 (AWS) と Mojila 様がメンテを行ってるので、やはり資本があるプロジェクトは質が良いな、という感想。

webエディタから辿る検索も強そう。
VSCode Web とか Stackblitz とか実装はあるわけでね。

Discussion