📝

WYSIWYGエディタに入門する

2021/03/17に公開

最近、QuillというWYSIWYGエディタのライブラリを触ったので忘れないうちに記事にしています。

https://quilljs.com/

Markdownに関する記事は比較的多いですが、WYSIWYGエディタはあまり見かけなかったです...
この記事では、以下のことについて解説していきます。

  • WYSIWYGエディタとMarkdownの違い
  • よく使われているWYSIWYGエディタ
  • WYSIWYGエディタの勘所
  • おまけ: pluginを作る

WYSIWYGエディタとは

WYSIWYG(アクロニム: ウィジウィグ)とは、コンピュータのユーザインタフェースに関する用語で、ディスプレイに現れるものと処理内容(特に印刷結果)が一致するように表現する技術。What You See Is What You Get(見たままが得られる)の頭文字をとったものであり、「is」を外したWYSWYG(ウィズウィグ)と呼ばれることもある。

https://ja.wikipedia.org/wiki/WYSIWYG

冒頭でも紹介しましたが、
Slackのように「エディタ上で表現されるコンテンツ」と「実際に表示されるコンテンツ」が一致するように作られるエディタをWYSIWYGエディタと呼びます。

WYSIWYGエディタはnoteWordPressのGutenberg, Googleドキュメント, Googleスライドなどが当てはまります。

Markdownとの違い

ちなみにWYSIWYGエディタと呼んでいるのにMarkdownエディタと呼んでいないのは、MarkdownはHTMLに変換するParserに焦点があたると思っているからです。

他には以下の違いがあります。

WYSIWYGエディタ Markdown
記法 定まっていない 定まっている
エディタと実際の見た目 一致する 一致しない
ライブラリの特徴 Parser + Editor Parser のみ
HTMLの記述 (たぶん)不可能 可能

これらの特徴を踏まえて使い分ける必要があると思いますが、
Zennのエディタのように、普段からMarkdownに慣れ親しんでいるユーザを対象にするのであればMarkdownのほうが使いやすさや拡張の面ではメリットが大きいでしょう。

e^{i\pi} = -1

(これはKaTeXを書きたかっただけです💦 )

逆に、noteなどのように幅広いユーザを対象にしている場合などは、誰にとっても書きやすく実際に表示されるコンテンツとのズレが少ないWYSIWYGエディタを選ぶほうが良さそうです。

よく使用されるライブラリ

調べていた中で人気そうだったライブラリを挙げてみました。

https://www.npmtrends.com/@editorjs/editorjs-vs-draft-js-vs-quill

Draft.jsはFacebook製ということやTwitterでも採用されている?いた?こともあり1番使われていそうです。

僕が使用したQuillも TRUSTED BY Microsoft, LinkedIn, salesforce, Slack となっており、Draft.jsほどではないですが有名そうです。

WYSIWYGエディタを用いてnoteのように記事を書くためなのか、それともSlackのようにメッセージを書くために使用するのか等によって使用するライブラリは異なると思うので、エディタを通してユーザーにどのような体験を提供する必要があるかで選ぶと良いと思います。

WYSIWYGエディタを用いた開発の勘所

普段はMarkdownを使用したり、ライブラリを作ってみたりしてるのですが

https://www.npmjs.com/package/react-markdown-heading

Quillを使用してみて、「WYSIWYGエディタを使用する時はここに注意したほうが良さそう」といった気づきもあったので紹介できたらと思います。

  • エディタのCSSと実際のコンテンツ表示のCSSを合わせる必要がある
  • エディタの実装がコンテンツ表示に影響する

エディタとコンテンツ表示のCSSを合わせる必要がある

Quillなどのライブラリでは、ライブラリが提供しているCSSを読み込んだ上でカスタマイズすることになります。
例として、Reactで用いるためのreact-quillでは以下のようにして提供されているCSSをimportします。

import 'react-quill/dist/quill.snow.css';

エディタに入力したテキストはpタグで囲まれ、部分的にBold, Italicなどを適用すると以下のような出力になります。

<p>This is <strong>Strong</strong>. This is <em>Emphasis</em>.</p>

これだけであればスタイルがあたっていないのでコンテンツ表示を気にする必要はありませんが、
例えばテキストのカラーを赤色にしたい、フォントサイズを20pxにしたいといった場合、直接styleを当てたり、該当するCSSが記述されたclass名を追加する必要があります。

<p>
  This is 
  <span style="color: rgb(230, 0, 0);">Red</span>
  . This is 
  <span class="ql-size-large">Large</span>
  .
</p>
.ql-size-large {
  font-size: 24px;
}

ここでの ql-size-large はライブラリが提供しているCSSに記述されていますが、エディタではなく実際にコンテンツとして表示する際、同じCSSを定義しておく必要があります。

色々試行錯誤してみましたが、この辺りは厄介でした...
CSS自体を上書きしたいというケースも発生しうるため、WYSIWYGエディタ周りのスタイルの管理はちょっと面倒だと思っておいてください。

class名を付与するのではなく全てstyle属性に直接記述するようになってると良いのかな🤔

エディタの実装がコンテンツ表示に影響する

例えば階層を持つリストを作成したい時、liの中にulを記述する形で小階層を表現するかと思います。

const NestedUnorderedList = () => {
  return (
    <ul>
      <li>
        1階層目
        <ul><li>2階層目</li></ul>
      </li>
    </ul>
  );
};

Quillではどうでしょうか。

const NestedUnorderedList = () => {
  return (
    <ul>
      <li>1階層目</li>
      <li class="ql-indent-1">2階層目</li>
    </ul>
  );
};
.ql-indent-1 {
  padding-left: 4.5em;
}

Quillでもリストを作成するときに入れ子になってると良いのですが、class名をあててpadding-left, margin-leftを使用して表現しています。

エディタ上では正しく表示されるのですが、1つ前での問題のように実際にコンテンツとして表示する際にはスタイルを用意する必要があります。


実際に触ってみると「Slackのこの機能こう実装してるんだ」と気づけるのでQuillのドキュメントも記載しておきますね。

https://quilljs.com/docs/quickstart/

おまけ: Quillのpluginを作成する

ここからは余談ですが、
SlackやTwitterとかでURLやメールアドレスを入力すると自動でリンクに変換してくれるアレを簡単に説明しようと思います。

想定される入力のパターンとしてはType, Pasteがあります。

処理の大まかな流れです。

  1. Type・Paste時にその行のテキストに正規表現でmatchをかる
  2. matchする箇所がリンクになるようにオブジェクトを作成

Quillのpluginを作成したので是非使用してみてください!
電話番号の自動リンクにも対応しています、Starもバグ報告やissue歓迎です✨

https://github.com/kyoncy/quill-linkify

https://www.npmjs.com/package/quill-linkify

脚注
  1. Editor.jsはIE11に対応していません... ↩︎

Discussion