Skip to content

エディタの画像形式を増やす(WebP・BMP・SVG・AVIF) ​

第1版作成 最終更新 (日本時間)
確認バージョン1.5.1.01.5.8.1

リッチテキストエディタに貼り付け・アップロードできる画像は JPEG・PNG・GIF の 3 形式だけで、Markdown エディタ(JPEG・PNG・GIF・WebP・BMP)より狭くなっています。この差をなくし、さらに SVG・AVIF を扱う場合に、どこを改修すればよいかの設計メモです。本体の標準機能ではありません。 調査は 1.5.1.0 で行い、前提にした部分を 1.5.8.1 のソースで確かめています。

前提にした現行実装 ​

図を読み込み中…

ブラウザ側のチェック ​

エディタ受け付ける形式判定合わないとき
リッチテキストエディタ(rt-editor)image/jpeg・image/png・image/gifMIME タイプと拡張子(.jpg・.jpeg・.png・.gif)の両方何も起きない
Markdown エディタ(markdown-field)上の 3 つ+image/webp・image/bmpMIME タイプだけ。ファイル選択の accept 属性にも同じリストを使う何も起きない

根拠は richTextEditor.ts#L65-L66・#L559-L565 と markdownField.ts#L15・#L484-L487 です。リッチテキストエディタ(SunEditor)のファイル選択ダイアログ自体はすべての画像形式を選べますが、選んだ後のチェックで 3 形式以外は捨てられます。

リッチテキストエディタは 1.4.21.0、Markdown エディタのこの実装は 1.5.0.0 で入りました。リッチテキストエディタの形式を 3 つに絞った理由は、コミットメッセージやコメントには書かれていません。

どちらのエディタも、形式のチェックの後に $p.validateImageUploadFileSize でファイルサイズを見ます。上限は Hidden 要素 #ImageUploadFileSizeLimit から読み、超えると TooLargeFile のエラーを出します(util.js#L39-L49)。

サーバー側のチェック ​

BinaryValidators.OnUploadingImage は次の順に確かめます(BinaryValidators.cs#L116-L190)。形式を名指しで絞る処理はありません。

  1. 契約で添付ファイルが使えるか。
  2. 中身が空でないか。
  3. BinaryStorage.json の ImageUploadFileSizeLimit(MB、既定 10)を超えていないか。
  4. Content-Type が image/ で始まるか。
  5. ImageSharp の Image.Identify で画像として読めるか(読めなければ IncorrectFileFormat)。
  6. ImageDecodedSizeLimit(MB、既定 256)が正なら、幅 × 高さ × フレーム数 × 4 バイトがそれを超えないか。
  7. テナントの容量と、項目の「画像の挿入を許可」(AllowImage)。

1.5.1.0 では 4 の Content-Type のチェックしかありませんでした。5・6 は 1.5.8.1 までに入ったもので、ImageSharp が読めない形式(SVG・AVIF)はここで拒否されます。

保存・サムネイル・表示 ​

処理内容
画像処理のライブラリSixLabors.ImageSharp 3.1.12(Implem.Pleasanter.csproj#L83)。JPEG・PNG・GIF・BMP・WebP・TIFF・TGA・PBM を読み書きでき、SVG(ベクター)と AVIF は扱えない
リサイズ・サムネイルImage.Load<Rgba32> で読み、PngEncoder で保存する。サムネイルは常に PNG(ImageData.cs#L52、#L184)
配信時の Content-Typeサムネイルは image/png。元画像は保存時の Content-Type(FileContentResults.cs#L297-L305)
ブラウザで開く形式BinaryStorage.json の BrowserAllowMimeTypes(既定は PDF・テキスト・JPEG・PNG・GIF・WebP)。BMP は入っていないので、show ではダウンロードになる(BinaryStorage.json#L33-L40)

改修の範囲 ​

形式優先度ブラウザ側サーバー側設定
WebP高リッチテキストエディタのリストに足す変更不要(ImageSharp が読める)変更不要
BMP高リッチテキストエディタのリストに足す変更不要ブラウザで開くなら BrowserAllowMimeTypes に image/bmp
SVG中両エディタのリストに足すImage.Identify を通らないので、SVG だけ別の経路で保存する処理と、スクリプトを取り除くサニタイズが要る同上
AVIF低両エディタのリストに足すImageSharp 3 は非対応。別のライブラリが要る同上

WebP・BMP(ブラウザ側だけ) ​

ts
// richTextEditor.ts
const VALID_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/bmp'];
const VALID_IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp'];
json
// BinaryStorage.json(BMP をブラウザで開く場合)
"BrowserAllowMimeTypes": [
    "application/pdf",
    "text/plain",
    "image/jpeg",
    "image/png",
    "image/gif",
    "image/webp",
    "image/bmp"
]

BrowserAllowMimeTypes はパラメータなので、本体を改修しなくても変えられます。

SVG の課題 ​

課題内容
ImageSharp で読めないImage.Identify で IncorrectFileFormat になり、リサイズ・サムネイルも作れない。SVG のときは ImageSharp を通さずにそのまま保存する分岐が要る
XSSSVG は XML で、<script> や onload 属性で JavaScript を埋め込める。保存前に DOMPurify などで取り除く必要がある
サムネイル?thumbnail=1 で PNG を返す仕組みに乗らないので、SVG は元画像をそのまま返すなどの扱いを決める

AVIF の課題 ​

ImageSharp 3 は AVIF を読み書きできません。対応するには別のライブラリ(libavif のバインディングなど)を組み込むか、ImageSharp の対応を待つ必要があります。

関連ページ ​

変更履歴

第1版Markdown の描画の仕組み・ショートカットキー・アイコン・公式マニュアルに無い $p 関数の解説と、Markdown 拡張・画像形式・ファビコン・テーマ・和暦などの改修・設計メモを追加