【Rails】TinyMCE を使用してワードプレスのような高機能エディタを導入してみた

つい最近、Railsで自作ブログを作って公開したのですが、ブログで重要な機能の一つ「エディタ」をどうしようか考えていたところ、

ワードプレスのような使い勝手の良いリッチテキストエディタが欲しいなと思っていました。

そこで、目をつけたのが以前ワードプレスでも使われていたWYSIWYGエディタの一つである「TinyMCE」。

今回は、その TinyMCE をRails自作ブログに導入してみたので、導入方法についてのメモ書きを残そうと思います。

どなたかの参考になれば幸いです。

目次

開発環境

  • Ruby 3.1.2
  • Ruby on Rails 7.0.4.3
  • Bootstrap 5.2.3
  • M1 Macbook Air 2020
  • mac OS Monterey (ver. 12.4)

TinyMCEを設置する方法

TinyMCEを設置する前に、Postモデルを作成して記事投稿機能を作成しておきましょう。(説明は省きます)

ここでは、記事投稿フォームのcontent(記事のコンテンツ)を編集する部分に、TinyMCEを設置していく流れを説明します。

Gemをインストールする

TinyMCEのGemをインストールしておきます。

gem "tinymce-rails"

Gemfileに上記を追記したら$ bundle installを実行してインストールを完了させます。

TinyMCE 公式サイトでAPIキーを取得する

TinyMCEを利用するためには、公式サイトからAPIキーを取得する必要があります。(無料で利用できます。一部有料オプションあり)

まず、公式サイトに入って「Get Started」をクリック↓

アカウント登録画面が表示されるので、登録します。

Googleアカウントを持っているのであれば、「Continue with Google」で登録してしまった方が楽です。

登録が完了すると、以下のような画面が表示されるかと思います↓

ここに、APIキーが含まれたスクリプトや、TinyMCEオプション設定用のスクリプトが表示されているので、スクリプト部分をapplication.html.erbに貼り付けます(次項を参照)。

取得したコードをapplication.html.erbに貼り付ける

先ほどの、APIキーを含むスクリプトは<head>タグ内に、オプション設定用のスクリプトは<body>閉じタグ(</body>)の直前にそれぞれ追記します。

<!DOCTYPE html>
<html>
<head>
  <title>ブログ</title>
 <meta name="viewport" content="width=device-width,initial-scale=1">
  <meta name="turbo-visit-control" content="reload">
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
  <!-- ↓ APIキー入りのスクリプトを読み込む -->
  <script src="https://cdn.tiny.cloud/1/○○○○○○○○○○○○○○○○○○○○○○○/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
</head>
<body>
  <%= yield %>
  <!-- ↓ <body>閉じタグの直前にオプション設定用のスクリプトを記述 -->
  <script>
    tinymce.init({
      selector: 'textarea',
      plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount',
      toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat',
    });
  </script>
</body>
</html>

入力フォーム(text_area)にTinyMCEを適用させる

TinyMCEを適用させるため、記事投稿の入力フォーム(contentカラムの入力欄)にclass: "tinymce"を追記します。

# class: "tinymce" を記述することで TinyMCE が適用される
<%= form.text_area :content, class: "tinymce", rows: 28 %>

row: ○○オプションを指定すると、エディタの高さを変更できます。

TinyMCEが適用されると、エディタが以下のように変更されるかと思います↓

ただ、デフォルトだと英語表記になるので、気になる方は次項で日本語化すると良いでしょう。

TinyMCE を日本語化する

TinyMCEの日本語化用のGemをインストールします。

gem "tinymce-rails"
gem "tinymce-rails-langs" # ←追記

$ bundle installでインストールし終えたら、application.html.erbのTinyMCEオプション設定のスクリプト欄にlanguage: 'ja'を追記します。

<!DOCTYPE html>
<html>
<head>
  <!-- 省略 -->
  <script src="https://cdn.tiny.cloud/1/○○○○○○○○○○○○○○○○○○○○○○○/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
</head>
<body>
  <%= yield %>
  <script>
    tinymce.init({
      selector: 'textarea',
      plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount',
      toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat',
      // ↓language を 'ja' に設定
      language: 'ja', 
    });
  </script>
</body>
</html>

すると、以下のように日本語表記になります↓

これで、最低限ではありますがTinyMCEが使えるようになりました。

画像をペーストできないようにする

TinyMCEには便利な機能があり、その一つに画像をエディタ内にドラッグ&ドロップすると、そのまま画像を挿入してくれます。

しかし、画像はデータベースに保存される訳ではなく、文字列としてcontentカラムに保存されてしまうため、contentの文字情報が莫大になってしまいます(データベースによってはtext型でも文字数オーバーになってしまう)。

なので、できればこのドラッグ&ドロップ機能は使わない方がベターです。

このドラッグ&ドロップ機能を停止させるためには、paste_data_images: falseを以下のように追記します↓

<!DOCTYPE html>
<html>
<head>
  <!-- 省略 -->
  <script src="https://cdn.tiny.cloud/1/○○○○○○○○○○○○○○○○○○○○○○○/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
</head>
<body>
  <%= yield %>
  <script>
    tinymce.init({
      selector: 'textarea',
      plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount',
      toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat',
      language: 'ja', 
      // ↓ 画像のペースト設定を false にする
      paste_data_images: false,
    });
  </script>
</body>
</html>

これでドラッグ&ドロップしても画像が挿入されなくなります。

基本的に画像ファイルはactive_storageなどに保存し、content内ではimageタグを使用して画像を呼び出す形にした方が良いでしょう。

active_storageにアップロードした画像を、TinyMCEのテキストエディタ内にimageタグで呼び出す方法についてはまたいつか記事にしようと思います(気が向いたらw)。

showページのコンテンツ(post.content)を正しく表示する(sanitizeメソッド)

記事投稿フォームで作成した記事(content カラムに保存した文字列)を表示したい場合、showページに以下のように記述するかと思います。

<%= post.content %>

しかし、このままの状態で表示しようとすると、contentカラムに保存されたhtmlタグがそのまま表示されてしまいます。

記事コンテンツにhtmlタグが表示されると邪魔ですし、画像を用いる場合は<img>タグのみが表示され、肝心の画像が表示されません。

そこで、不要なhtmlタグのみを非表示にする、Railsのメソッドであるsimple_formatを使うのが一般的ですが、simple_formatだと一つ問題がありまして、、

それは全てのタグに改行タグ<br>が挿入されてしまい、二重改行になり見栄えが悪くなってしまいます。

そこで、もう一つのメソッドであるsanitizeを用います。(sanitaizeでは<br>が挿入されないので二重改行は起こりません)

sanitizeは、tagsやattributesで指定されていないタグや属性をすべて除去するメソッドです。

showページでは以下のように記述します↓

<%= sanitize post.content %>

ただし、sanitizeメソッドはデフォルトで指定されていない重要タグ(例えば<table><tr><td><span>など)や属性(src, hrefなど)があるため、

例えばテーブルを作成したり、imgタグを挿入(src属性で画像のURLを指定)したとしても、指定していないタグや属性は除去されてしまうため、これらが反映されません。

そこで、デフォルトで指定されていないタグや属性を指定してやる必要があります。

sanitizeでタグや属性を指定するには、config/application.rbに以下のように指定したいタグや属性を記述すればOKです。

config.action_view.sanitized_allowed_tags = %w(h1 h2 h3 h4 h5 h6 ul ol li p span a img table tbody th tr td em br b strong s)
config.action_view.sanitized_allowed_attributes = %w(id class href style src target rel)

保存したら、一旦Railsサーバーを再起動すると反映されます。

Rails7 を使用している場合(Turbo Drive を有効化している場合)

TinyMCEはどうやらRails7 のTurbo と相性が悪い(?)みたいなので、入力フォームのページを開いてもTinyMCEのエディタがうまく読み込まれないことが多々あります。

(TinyMCEが読み込まれなかった場合、リロードすると読み込まれる)

そこで、Turboを有効化している場合でも、入力フォームのページを強制的にリロードすることでこの問題を解決できます。

指定のページを強制的にリロードするためには、<head>タグ内に<meta name=”turbo-visit-control” content=”reload”>を記述します。

<!DOCTYPE html>
<html>
<head>
  <!-- ↓ ページを強制的にリロードするよう設定 -->
  <meta name="turbo-visit-control" content="reload">
  <!-- 省略 -->
  <script src="https://cdn.tiny.cloud/1/○○○○○○○○○○○○○○○○○○○○○○○/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
</head>
<body>
  <%= yield %>
  <script>
    tinymce.init({
      // 省略
    });
  </script>
</body>
</html>

これで、TinyMCEが読み込まれないという問題はなくなるはずです。

以上です。

参考資料

AgoHack
WYSIWYGエディタ TinyMCE の設置と使い方 タグを使わずに、文字の装飾やテーブルの挿入ができる HTML エディタを探しいて見つけた javaScript ライブラリ TinyMCE の使い方。 TinyMCE は、 WYS...
https://sites.google.com/site/railssiryou/gem/ritchieditanotinymcewo-shi-yongsuru
Stack Overflow
Insert an image into a tinymce editor I have a tinymce text box on my html page. Under this text box I have a table with my file system in which I can navigate to locate my images. I would like to b...
あわせて読みたい
Rails で raw HTML を sanitize する - FIVETEESIXONE ブログのようなアプリケーションを作ろうとしていて、フォームのテキストエリアをリッチテキストエディタ化するために tinymce-rails ...
GitHub
GitHub - spohlenz/tinymce-rails: Integration of TinyMCE with the Rails asset pipeline Integration of TinyMCE with the Rails asset pipeline - spohlenz/tinymce-rails
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

愛知の34歳。無職で暇になり始めたプログラミング(Ruby on Rails)の忘備録をまとめたブログです。最近は別にやりたいことができたのでプログラミングほぼやっていません。気が向いたらまた再開するかも。僕の日常はメインブログの方で更新しています。

コメント

コメントする

目次