CKEditor5でclass付与するのが大変な話

掲載日
更新日

はじめに

このサイトはブログ記事を作成する際にCKEditor5というライブラリを使用しています。

CKEditor5でデフォルト機能以外で画像を本文に追加する等行う場合、最終的な処理は公式の提供しているimageプラグインに含まれるinsertImageコマンドを使用するのが楽です。

ただ、この追加する画像にclassを付与するのに地味にはまったので備忘録です。

前提条件

  • CKEditorのバージョンは5。
  • CKEditorにはImage関係のプラグインが入っている。

追加する要素にclassを付与する

insertImageコマンド

画像を追加する際のデフォルトのプラグインが「Image」で、この中にinsertImageコマンドがあります。
以下のように使うことで、入力欄のカーソルがあたっている箇所にimgタグが追加できます。

// ~~ この上でカスタム画像追加処理等 ~~

editor.execute('insertImage', {
    source: [
        {
            src: '/path/to/image.ext',
            alt: '適切なalt文章。',
            width: 100, // 画像の幅
            height: 100, // 画像の高さ
        },
    ],
})

source配下に設定したいattributeを追加すればOK。
それならclassを付与するのは以下で行けるだろうと思い実行。

// ~~ この上でカスタム画像追加処理等 ~~

editor.execute('insertImage', {
    source: [
        {
            src: '/path/to/image.ext',
            alt: '適切なalt文章。',
            width: 100, // 画像の幅
            height: 100, // 画像の高さ
            class: 'default-class',
            
        },
    ],
})

が、これだとclassは付与されず。

解決方法

General HTML Supportプラグインを入れ、ckeditor.tsに以下を追加します。

// 設定上部にimport追加
import { GeneralHtmlSupport } from '@ckeditor/ckeditor5-html-support';

// ~~ (中略) ~~
public static override builtinPlugins = [
        // 他プラグインは省略
		GeneralHtmlSupport,
        // 他プラグインは省略
];

public static override defaultConfig: EditorConfig = {
       // 他の設定は省略
		htmlSupport: {
			allow: [
				{
					name: /.*/,
					attributes: true,
					classes: true, // class追加するなら多分ここだけあればいい
					styles: true
				}
			],
		]
       // 他の設定は省略
}

insertコマンドのオプションの中でhtmlImgAttributesをプロパティに指定し、さらにその中でclassesを追加します。

editor.execute('insertImage', {
    source: [
        {
            src: '/path/to/image.ext',
            alt: '適切なalt文章。',
            width: 100, // 画像の幅
            height: 100, // 画像の高さ
            htmlImgAttributes: {
                classes: 'default-class' // 配列も可
            }
        },
    ],
})

原因

こういう設定が必要なのは、まずCKEditor5がviewだのmodelだのに分かれて入力内容や描画内容を良い感じにしていて複雑なのが原因です。

imgタグはCKEditor側でImageBlockやImageInlineといったmodelに変換され、その際使用できる属性もmodel毎に変化します。

この複雑な仕組みのおかげで不要な記述を良い感じに除去して綺麗にしてくれたり、
CKEditor4時代にあった同じリンクが連続する文字列の中でバラバラに配置されてしまう等の問題も解決してくれるのでメリットも大きいです。
(4時代は改行などで何故かリンクが分割されてしまい、「<a href="https://example.com">リンク先は<br></a><a href="https://example.com">こちら</a>」のように分割されることがありました。
これの何が不味いかというと、例えばリンク先のURLが変わって置換が必要になったとします。
編集者は「リンク先は」だけ直して全て直した気になってしまい、「こちら」のリンクは直ってない状態になります。
よって、新旧リンクがどっちもあり、ユーザーがクリックしたマウスの位置によって古いURL先の情報をもとに行動してしまう可能性があるという状態になります。

CKEditor5は同じリンクが連続していると勝手にくっつけてくれたりするので、適当に入力や編集をしていても最終的なHTMLが綺麗になり上記のような事故を防げます。)

 

話を戻すと、各modelにはschemaというものを登録できます
schemaを使って、「このmodelにはalt属性を持たせられる。」「このmodelは子要素にこのmodelを持つことが出来る。」みたいな設定が可能です。

しかし、どのmodelにどのschemaがあり、各schemaが何を意味するのか。これが分からない。
src, altタグみたいなimgタグでほぼ必須なattributeなどは公式のドキュメントのサンプルにも載っているので困りませんが、載ってないものは元のソースコードを掘って探しています。

(ドキュメントも自分が見方が分からないのと英語が出来ないのが原因でちゃんと書いてあるのかもしれません。書いてあったらすみません。)

探した結果、imgタグはデフォルトのImageプラグインだけだとclassを付与することは出来なさそう(そんなことある?)なので、その辺りのschema設定を良い感じにやってくれる「General HTML Supportプラグイン」を追加します。

コンフィグでclass付与を許可する設定を追加し、insertImageコマンドに戻ってsorceの設定に上記の通り「htmlImgAttributes」追加すればなんとかclassが付与出来ました。

しかしこの「htmlImgAttributes」schemaも公式ドキュメントからは見つけられずソースを掘り返して見つけたもの。

 

…classなんてどのタグにも付与出来て使用頻度が高いもの、もっと楽に追加できそうなもんでは?
自分が何か見落としてるだけな気がします。

おわりに

追加する画像にclassを付与したいだけなのにえらい大変でした。
ソースを掘り返しているとき、「htmlImgAttributes」以外にも「htmlA」等があったのでaタグにclassを付与したい場合はこっちのschemaを指定する等、この知識があればimgタグ以外でも応用が利きそうなので備忘録として残しておきます。

記事の作成者のA.W.のアイコン

この記事を書いた人

A.W.
茨城県在住Webエンジニアです。 PHPなどを業務で使用しています。 趣味ではGoやNuxt、Flutterをやってます。

Comment