Vue 3 × Tiptap(ProseMirror) で​作る​メールブロックエディタ ── ノーコードで​HTMLメールを​組み立てる​仕組み

SKYPCE Blog
Vue 3 × Tiptap(ProseMirror) で​作る​メールブロックエディタ ── ノーコードで​HTMLメールを​組み立てる​仕組み

SKYPCEのメール配信機能に搭載された「ブロックエディタ」の技術的な仕組みを解説します。編集データは3階層のデータ構造で管理され、ドラッグ&ドロップ操作はvuedraggableとHTML Drag and Drop APIを併用して実装。リッチテキスト部分にはTiptapを採用し、フォントサイズやインデント機能はカスタムExtensionで独自に拡張しています。最終的なHTMLメールは、クライアント間の互換性を考慮し、<table>タグベースで出力されます。


1. ​はじめに

SKYPCEでは、お客様の営業活動を支援するために「メール配信機能」をご用意しています。
「メール配信機能」では、営業担当者様がご自身でリッチなHTMLメールを作成できる必要があります。
しかし「HTMLを直接書いてもらう」のは現実的ではなく、かといって固定テンプレートだけでは表現の自由度が足りません。
そこで、コードを書かずにメール本文を組み立てられる「ブロックエディタ」を機能実装いたしました。
本記事では、この「ブロックエディタ」の仕組み・技術を説明させていただきます。

2. 全体​構成

ブロックエディタは6つのエリアで構成されています。

番号 項目 説明
テキスト/画像/線 コンテンツグループに文字・画像・線を配置します。
コンテンツグループ メールの文面にコンテンツグループを配置します。
コンテンツグループ領域 コンテンツグループを配置します。また、配置したコンテンツグループにテキスト、画像、線を配置します。
[コンテンツ]タブ/[全体設定]タブ 「コンテンツ」タブでは、コンテンツグループ、およびコンテンツグループに配置している要素についての設定ができます。コンテンツグループを選択しているときは、コンテンツグループを最大6個のブロックに分けることができ、ブロックの色や幅などを設定できます。テキストを選択しているときは、文字のフォントや大きさ、配置などを設定できます。画像を選択しているときは、画像のサイズや配置などを設定できます。線を選択しているときは、線の種類や太さなどを設定できます。「全体設定」タブでは、コンテンツグループの幅や配置、背景色などを設定できます。
プレビュー 編集している内容をプレビュー画面で確認できます。
ガイドを非表示 コンテンツグループの周りに表示されている破線が非表示になります。

3. コンポーネント設計:3階層の​データ構造

エディタの編集データは以下の3階層で表現されます。

  • メール本体
    • └─ コンテンツグループ // 行(セクション)
      • └─ ブロック // 列(カラム)
        • └─ [テキスト / 画像 / 区切り線]

コンテンツグループは「行」、ブロックは「列」に相当し、1行を最大6カラムまで分割できます。各レイヤーに背景色・ボーダー・パディング・角丸を個別設定できます。

4. ドラッグ&ドロップの​実装

ドラッグ操作は2種類あります。

  • コンテンツグループの並び替え:vuedraggable を使用
  • コンテンツの追加・移動:HTML Drag and Drop API と vuedraggable を組み合わせ

コンテンツグループの並び替えは、既存のリスト内での順序変更のみです。これは vuedraggable が最も得意とするユースケースであり、ライブラリだけで完結することができます。
コンテンツの追加・移動は、以下の2つの操作を含みます。

  • パーツ選択エリア(別エリア)からのドロップによる新規追加
  • 編集エリア内でのブロックをまたいだ移動

「別エリアから別エリアへ」という操作は vuedraggable 単体では制御しきれないため、HTML Drag and Drop API で開始元・移動先・挿入位置を独自に管理しつつ、アニメーションや並び替えの部分は vuedraggable に委ねる構成になっています。
つまり「ライブラリで済む操作はライブラリに任せ、ライブラリの範囲を超える操作だけ独自実装する」という役割分担としています。

5. Tiptap​(ProseMirror)​ の​カスタム Extension

テキストコンテンツのリッチエディタには Tiptap(ProseMirror)を採用しました。メール用途に必要な機能のうち、標準では提供されていないものを独自 Extension として実装しています。

  • フォントサイズ:textStyle マークに font-size 属性を追加する Extension を自作
  • インデント:Transaction を直接操作し、段落・リストに margin-left を付与。最大10段階に制限し、コピー貼り付け時のパース処理も考慮

6. HTMLメールの​出力

エディタで編集したデータからHTMLメールを生成します。
メールクライアントごとにHTMLやCSSの解釈エンジンが異なるため、完全に同じ表示にはなりませんが、一定の互換性を保てるように考慮してレイアウトはtableタグベースで出力しています。
出力処理もデータ構造に対応した階層で分割されており、各レイヤーが独立してHTML文字列を生成するようにしています。
モバイル対応のレスポンシブCSSもstyleタグ内に埋め込むことで、ブロック幅を基準に表示するように工夫されています。

7. まとめ

今回のブロックエディタ実装を通じて、いくつかの技術的な工夫と知見が得られました。

番号 内容
エディタ自身の状態管理は、グローバルストアを使用せずにコンポーネント間の状態共有を実現できるように設計しており、機能ごとに Composable を分割しつつファサードで一元化しました。各コンポーネントは必要なメソッドだけを取り出して使えるため、依存関係が明確になりテストや保守がしやすい構造になっています。
「別エリアからのドロップによる新規追加」や「ブロックをまたいだコンテンツ移動」を実現するために、vuedraggable と HTML Drag and Drop API の併用をしています。ライブラリの挙動を壊さずに独自ロジックを組み込めるように、開発チームでは様々な工夫をしています。
Tiptap のカスタム Extension については、メール配信という特定ドメインの要件(フォントサイズ指定、インデント、メール互換リンク等)に合わせて拡張できる利点で、Tiptapへの理解も深まりました。
HTMLメールの出力をtableベースで行う設計は、古いメールクライアントへの対応という制約の中で、編集データの階層構造をそのまま出力処理の階層に対応させることで、保守性と拡張性を両立しています。

「ノーコードで使いやすく、かつ開発者が保守しやすい」という相反しがちな要件を、Vue 3 の Composition API が持つ柔軟な設計力によって両立した事例になったと考えています。

名刺管理 SKYPCEについてお問い合わせ

名刺管理「SKYPCE」について詳しくはこちらから
名刺管理「SKYPCE」について詳しくはこちらから商品サイト
導入のご相談から料金まで、お気軽にお問い合わせくださいお問い合わせ
商品カタログ、活用例などの各種資料をご用意資料ダウンロード
SKYPCE Cloud Editionを2か月無料でお試しいただけます評価版のお申し込み
ホームに戻る
Categoryカテゴリー