Webページで使用可能なコードエディター Ace
markdown の純粋なハイライトエディターを探していて見つけた。
とても質が良かったので紹介する。
License は BSD。
利用するときはどこかに出典を明記する。
環境構築
Vue のもので紹介するが、元は純粋な javascript なので他FWでも実装可能。
vue テンプレの作成
vite + vue3 + typescript
$ 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 に落とし込んでくれているライブラリがあるので、使用する。
$ yarn add ace-builds vue3-ace-editor
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
がこのインスタンスに相当する。
テキストの選択、置換や検索、ショートカットキーなど、エディタに欲しそうなものは大体揃っているからすごい。
追加機能で、構文チェック機能もあるらしい。
上記サンプルでは以下のものを実装した。
- 選択した箇所を取得
- 選択した箇所を bold 属性に書き換える
- カーソルの位置に文字を挿入する
これだけできれば、やりたいことは実現できる気がする。
テーマとハイライト
上記サンプルの lang
と theme
でデザインを変更することができる。
<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
を一致させると反映させられる。
いくつか読み込んで、セレクトボックスで選択させることがお手軽に可能!
リアルタイムでのデザイン確認は以下のページが参考になる。
相当数用意されていて、独自に組むことも可能なため、文句はないだろう。
事前読み込みによる更新は ace.config.setModuleUrl
を使うようだ。
こちらはURLを指定することも可能なので、ビルドに含めずともユーザーに入力させる手段も取れる。
詳しくは書かない。
Option について
v-ace-editor
は特にドキュメントが無いため、以下ソースから解読する必要がある。
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のほうが需要が高いのか、メンテナンスが行き届いている気がした。)
- Syntax Editor
- WISWIG
milkdown はお気に入り。
どこかで使ってみたい。
実装考察
textarea
はそのままではハイライトを行うことができない。
textarea の文字を透明にして、ハイライト用のdivを重ね合わせる実装をよく見かけた。
しかし、IMEがあるCJK系では入力中の文字も消えるのでNG。
次に特定の単語に背景色を付ける実装を見かけた。
これも二枚のパネルを重ね合わせる、とてもお手軽実装だった。
単純用途なら十分使い勝手が良いと感じた。
最後は上に列挙したエディタ系。
これらは行ごとにdiv、更にはspanで記号を区切って、擬似的に textarea を構築していた。
そもそも textarea を捨てる方向性だ。
このクラスになると個人の実装は難しいので、神のおこぼれに預かったほうが楽だ。
ace もそうだが、cloud9 (AWS) と Mojila 様がメンテを行ってるので、やはり資本があるプロジェクトは質が良いな、という感想。
webエディタから辿る検索も強そう。
VSCode Web とか Stackblitz とか実装はあるわけでね。
Discussion