はじめに
テキストを選択した瞬間に、ふわっと現れる太字・斜体・リンクのツールバー。Medium.comの執筆画面を触ったことがある人なら、あの操作感を自分のサイトにも取り入れたいと思ったことがあるのではないでしょうか。ところが一般的なWYSIWYGエディタは、常時表示のツールバーや専用のツールバー領域を前提にしたものが多く、あの「選択して初めて出てくる」体験をゼロから作るのは意外と手間がかかります。
Medium-Editorは、まさにそのMedium.com流のインライン編集体験を、フレームワーク非依存のバニラJavaScriptで再現するライブラリです。ブラウザ標準のcontenteditable属性をベースに、テキスト選択時のツールバー表示、アンカーリンクのプレビュー、見出し・引用への変換などを一通り実装しています。
とはいえ、読むより触った方が早いと思います。文章を選択するとツールバーが浮かび上がる挙動を実際に確認できるので、先に触ってみたい方はこちらからどうぞ。
Medium-Editorとは
Medium-Editorは、contenteditable属性を持つDOM要素に対して、テキスト選択時のインラインツールバーやキーボードショートカット、リンクのプレビュー機能などを付与するJavaScriptライブラリです。React・Vueのような特定フレームワークに依存せず、素のDOM要素に対してnew MediumEditor(...)を呼ぶだけで動作します。
主な特徴
- フレームワーク非依存 - jQueryや特定のUIフレームワークを必要とせず、
<div>や<textarea>にそのまま適用できる - 選択駆動のインラインツールバー - テキストを範囲選択したタイミングでのみツールバーが浮かび上がり、太字・斜体・下線・見出し・引用・リンクなどを即座に適用できる
- アンカープレビュー - 本文中のリンクにカーソルを合わせると、URLの確認や編集ができるプレビューが表示される
- 拡張機能(Extensions)によるカスタマイズ - ボタン構成やペースト処理、キーボードコマンドを
extensionsオプションで自由に差し替えられる
インストール
npmでインストールする場合は次のコマンドを実行します。
npm install medium-editor
CDN経由で読み込む場合は、本体のJSに加えてスタイルシート(medium-editor.cssとテーマCSS)も併せて読み込む必要があります。
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/medium-editor/dist/css/medium-editor.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/medium-editor/dist/css/themes/default.min.css">
<script src="https://cdn.jsdelivr.net/npm/medium-editor/dist/js/medium-editor.min.js"></script>
Medium-Editorのサンプルを動かす
以下はnew MediumEditor(selector, options)で.editableクラスを持つ要素を初期化し、toolbar.buttonsで太字・斜体・下線・見出し・引用・リンクのボタンを表示するサンプルです。本文中の文章をドラッグして選択すると、Medium.com風のインラインツールバーがふわっと表示されます。
const editor = new MediumEditor('.editable', {
toolbar: {
buttons: ['bold', 'italic', 'underline', 'h2', 'quote', 'anchor'],
},
placeholder: {
text: 'ここに文章を入力...',
},
});
実際に動かして選択→ツールバー表示の流れを確認してみてください。buttons配列の中身を['bold', 'italic']のように減らすと、ツールバーに出るボタンの数がその場で変わります。
選択した範囲だけに書式が適用される点、リンクボタン(anchor)を押すとURL入力欄がその場に展開される点も確認できます。ツールバーに出したいボタンを取捨選択するだけで、エディタの見た目が大きく変わるのがMedium-Editorの扱いやすさです。
基本的な使い方
最小構成であれば、対象要素にCSSクラスを付けてコンストラクタを呼ぶだけで動作します。
import MediumEditor from 'medium-editor';
// .editable クラスを持つ要素をすべてエディタ化する
const editor = new MediumEditor('.editable');
textarea要素を渡した場合は、自動的に編集可能なdivに変換されるため、フォーム部品として使っていた要素をそのままリッチテキスト化できます。
const editor = new MediumEditor('#my-textarea');
初期化後はeditor.getContent()で現在のHTMLを取得でき、フォーム送信時などに本文を保存する処理に組み込めます。
実践的なユースケース
プレースホルダーとツールバー配置のカスタマイズ
空の状態で何を書けばいいか分からないエディタは離脱されやすいものです。placeholderオプションで案内文を出しつつ、toolbar.staticをtrueにすると、選択の有無に関わらずツールバーを常時上部に固定表示できます。
static: trueでツールバーが常時表示に切り替わり、sticky: trueを組み合わせるとスクロールしても画面上部に張り付くようになります。ブログの下書き画面や社内向けのメモ帳のように、常にどのボタンが使えるかを示したい場面に向いた設定です。
アンカープレビューでリンクを確認・編集する
本文中に貼ったリンクが正しいURLを指しているかを、リンクを開かずにその場で確認したい場面は多くあります。Medium-EditorはanchorPreview拡張機能を通じて、リンク付きテキストにカーソルを合わせるだけでURLプレビューを表示します。
new MediumEditor('.editable', {
anchorPreview: {
showWhenToolbarIsVisible: false,
previewValueSelector: 'a',
},
toolbar: {
buttons: ['bold', 'anchor'],
},
});
上記のanchorボタンでリンクを作成したあと、そのリンクにマウスを重ねるとURLがプレビュー表示されます。
previewValueSelectorやhideDelayといったオプションを調整すると、プレビューの表示対象や消えるまでの時間を細かく制御できます。編集中のリンク切れに気づきやすくなるため、社内ドキュメントツールのようにリンクを多用する用途で役立ちます。
まとめ
Medium-Editorは、Medium.comのインライン編集という特徴的なUXを、contenteditableベースのシンプルなAPIで再現できるライブラリです。toolbar.buttonsでボタン構成を選び、placeholderやanchorPreviewといった拡張機能を組み合わせるだけで、フレームワークに依存しないリッチテキスト編集画面を短時間で用意できます。
まずは今回のサンプルのように最小構成で動かしてみて、必要に応じてextensionsオプションでボタンを追加したり、ペースト時のフィルタリングを設定したりと、自分のプロダクトに合わせて調整していくとよいでしょう。
