ノート共有型SNSの投稿フォーム実装についてご紹介

チーム開発ReactQuill
Tomu Obata
📅2020/8/16

eeNotes というサービスでテキストエディタライブラリ react-quillを使用してノート投稿フォームを作成しました。

今回は、技術選定の背景や使用感・工夫したことなどを書いていきたいと思います。

Quillって何が出来るの?

以下のようなリッチなテキストエディタを簡単に導入することが出来ます。

eeNotesでのQuillエディタの様子
eeNotesでのQuillエディタの様子

様々なテキストエディタに関するライブラリが公開されている中でどうしてreact-quillを選定したの?

GitHubでStar数が多かったライブラリを以下のような観点で比較し、判断していきました。

また、GitHubのCommit履歴などからメンテナンスが行われていることが確認でき、GitHubのStar数も3.7k(本家のQuillは27.4k)React製のテキストエディタライブラリで多かったことも理由の1つです。2020/08/23時点

比較したライブラリ郡

Quillの他に以下のライブラリも比較しました。

比較検討した詳細については、以下の記事を見てもらえると幸いです😄

次に導入する上で工夫した点の紹介をしていきたいと思います。

ToolBarのカスタマイズについて

QuillではToolBarを自由にカスタマイズすることが出来ます。eeNotesのToolBarは以下のように定義して組まれています。

import { Quill } from "react-quill";

export const previewModules = {
    toolbar: [
        [{ "background": "#F4FF81" }]
    ]
};

export const commentFormModules = {
    formula: true,
    // 空段落の挿入を無効化
    // https://stackoverflow.com/questions/43748108/how-to-keep-quill-from-inserting-blank-paragraphs-pbr-p-before-heading
    clipboard: {
        matchVisual: false
    },
    toolbar: [
        [{ "font": [] }],

        [{ "header": 1 }, { "header": 2 }], // custom button values
        [{ "header": [1, 2, 3, 4, 5, 6, false] }],

        ["bold", "italic", "underline", "strike"], // toggled buttons

        [{ "color": [] }, { "background": [] }],// dropdown with defaults from theme
        [{ "script": "sub"}, { "script": "super" }], // superscript/subscript
        [{ "indent": "-1"}, { "indent": "+1" }, "blockquote", "code-block"], // outdent/indent
        [{ "list": "ordered"}, { "list": "bullet" }],
        ["link", "formula", "image"],

        [{ "align": [] }],

        ["clean"] // remove formatting button
    ]
};

// https://quilljs.com/docs/formats/
export const formats = [
    "background", "bold", "color", "font", "code", "italic", "link", "size", "strike", "script", "underline",
    "blockquote", "header", "indent", "list", "align", "direction", "code-block",
    "image", "formula" // https://katex.org/ 数式
];

Quillのデータ構造 Deltaについて

QuillはDeltaというJSONのような独自形式で文字列の内容が管理されています。

Deltaフォーマット

{
  ops: [
    { insert: 'Gandalf', attributes: { bold: true } },
    { insert: ' the ' },
    { insert: 'Grey', attributes: { color: '#cccccc' } }
  ]
}

文字列の変更検知

text-changeイベントを登録することで、文字列に変更があるたびに以下のフォーマットで検知することが出来ます。

{
  ops: [
    { delete: 10 }  // Delete the next 10 characters
  ]
}

テーマについて

Quillには、BubbleSnowというテーマがあります。

Bubbleテーマ

theme="bubble" と指定すると以下のような表示になります。Bubbleテーマの特徴は、文字を選択した時にホップアップ表示で当てるスタイルを選ぶことが出来る点です。

Bubbleテーマの様子
Bubbleテーマの様子

Snowテーマ

theme="snow" と指定すると以下のような表示になります。私たちは、文字選択時にはマーカー機能を実装したかったこともあり、こちらのテーマを選定しました。

Snowテーマの様子
Snowテーマの様子

デフォルトのタグを変更する方法

Quillのデフォルトのタグは<p>で記述されています。

An image from Notion

任意のタグに変更する場合は、以下の設定を追記すれば良いです。

// デフォルトのタグを<p>から<div>に変更
const Block = Quill.import("blots/block");
Block.tagName = "DIV";
Quill.register(Block, true);

私たちのプロジェクトでは、Quillの設定ファイルをConfig/quill.jsに記述しています。

そして、divタグに変換したUI要素に対して以下のようなコードでCSSを当てています。デフォルトでは行間が狭く窮屈な感じだったためline-heightを指定したりしています。

import styled from "styled-components";

const FontStyle = styled.div`
    font-family: Roboto;
    font-style: normal;
    font-weight: normal;
    font-size: 24px;
    line-height: 16px;
    color: #000000;
`;
// CommentPreviewはReactQuillを使用しているコンポーネント
return (
    <FontStyle>
        <CommentPreview body={comment.body} />
    </FontStyle>
);

空段落が挿入される問題について

Quill Version: 1.3.7において、編集した文字列のDOMを更新した際などに<p><br></p>といった空段落が挿入されてしまう問題がありました。

以下の設定を追記することで解決出来ます。

clipboard: {
    matchVisual: false
},

参考

Quillに関するリポジトリ紹介

Quillに関するリポジトリが列挙されています。

Quillの形式変換module郡

さいごに

QuillはGitHubに公開されているmoduleも含めるとカスタマイズ性はかなり高く、良いライブラリだという所感です。最後まで読んでいただきありがとうございました😄

おまけ

eeNotesのチームメンバーがそれぞれ記事を書いてくれているので、ぜひ見てみてください!

インフラ基盤構成については @_tetsuya28 が

サーバーサイドについては @kozamurai

フロンドエンドについては @schktjm

チーム開発の流れについては @assassinEng

SHARE

スポンサーリンク