Tiptap React Editor:PageBuilder の HTML ブロックをシンプルにした方法
Tech
Tiptap
React
Next.js
E-commerce

Tiptap React Editor:PageBuilder の HTML ブロックをシンプルにした方法

EC サイトの PageBuilder に Tiptap React エディタを導入し、マーチャントが生のマークアップに触れることなく HTML ブロックを構築できるようにしました。

Uygar DuzgunUUygar Duzgun
Jun 17, 2026
更新日 2026年7月1日
8 min read

最高のエディタのアップグレードとは、コンテンツ作業から恐怖を取り除くものです。

私たちは EC サイトの PageBuilder に Tiptap React エディタを追加しました。生の HTML ブロックは編集コストが高くなりすぎていたからです。機能はしていましたが、マークアップを読むことに慣れた人だけが扱える状態でした。マーチャントは、製品ページのレイアウトを壊したり、安全でない HTML を配信したりすることなく、見出し、画像、ボタン、カラム、タブ、Instagram 埋め込みなどを追加できるべきです。

この作業は ecom テーマの `codex/htmlblock-wysiwyg-editor` ブランチで実装されました。最初の実装コミット `08692e2e` で HTML ブロック用の WYSIWYG エディタが追加されました。その後のコミットではインタラクションの洗練、ラベルの翻訳システムへの移行、メディア処理の強化、およびメディアライブラリ画像の ID による重複排除が行われました。

Tiptap が適していた理由は、閉じた CMS の形状を強制されなかったからです。既存の PageBuilder HTML 契約を維持しつつ、Tiptap を編集エンジンとして利用できました。

構築したもの

目に見える機能はシンプルです。PageBuilder の HTML ブロックが、生の HTML textarea から本物のエディタに変わりました。

しかし、その実装は言葉以上に有用です。このエディタは以下をサポートしています:

H2 から H6 までの見出し
段落、太字、斜体、下線、取り消し線、コード、引用、リスト、ハイライト、リンク
テキスト配置とクラスベースのフォントサイズ
クロール可能なアンカーとしてレンダリングされる CTA ボタン
レスポンシブなカラムレイアウト
代替テキスト、キャプション、遅延読み込み、メディアピッカーを備えた画像
スクリプトタグを保存コンテンツに持ち込まない Instagram 埋め込み
レイアウトのリズムを制御するためのスペーサー
2 から 20 パネルまでのタブ
古いコンテンツが存続する必要がある場合のためのテーブルとレガシー CMS マークアップ

最後の点が重要でした。これはグリーンフィールド(新規)のエディタではなかったのです。EC フロントエンドにはすでに Bootstrap スタイルのコンテンツ、レガシー CMS スニペット、PageBuilder ゾーン、PrestaShop メディアパス、SEO ルールが存在していました。サイトの既存の HTML モデルを平坦化することなくコンテンツを編集できる WYSIWYG レイヤーが必要だったのです。

Tiptap がシンプルに感じられた理由

Tiptap の React 設定は小規模です:`useEditor`、`EditorContent`、そして拡張機能の配列です。StarterKit が基本的な編集プリミティブを提供し、その後で製品に必要なピースを追加していきます。

私たちの場合、依存関係のセットは理解しやすいままでした:

`@tiptap/core`
`@tiptap/react`
`@tiptap/starter-kit`
`@tiptap/extension-link`
`@tiptap/extension-highlight`

これでエディタの表面を構築し、その上に独自の EC ブロックを層として追加するのに十分でした。標準的なエディタの動作には `StarterKit.configure()` を使用し、独自のルールが必要な場所ではデフォルトのリンク処理を無効にし、Link と Highlight を明示的に設定しました。

シンプルだったのは、Tiptap がすべての EC 問題を解決してくれたからではありません。そうではありません。シンプルだったのは拡張機能モデルです。ボタン、画像、レガシー画像、Instagram 埋め込み、カラム、タブ、スペーサー、テーブル、フォントサイズ、リストスタイル、テキスト配置といった独自のコンテンツノードを直接定義できました。

これは PageBuilder にきれいにマッピングされます。ボタンは単にスタイルされたテキストではありません。画像は単なる `img` タグではありません。タブコンポーネントにはラベル、パネル、ID、アクティブ状態、アクセシビリティロールがあります。Tiptap により、これらを後から textarea から推測しようとするのではなく、エディタのコンテンツとしてモデル化できました。

HTML の往復が重要な部分でした

多くの WYSIWYG 移行が失敗するのは、エディタがあるフォーマットを求め、サイトが別のフォーマットをレンダリングするためです。

私たちはそれを望みませんでした。フロントエンドはすでに、製品ページ、コンテンツページ、ホームページセクション、チェックアウト隣接スロット、その他の PageBuilder ゾーン全体で HTML ブロックをレンダリングしています。エディタは既存の HTML を読み込み、管理者が変更し、パブリックなストアフロントが安全にレンダリングできる HTML を保存できる必要がありました。

Tiptap はそのための変換ツールを提供してくれました。タブパネルについては、`generateJSON()` を使用して既存の HTML をエディタコンテンツに変換し、`generateHTML()` を使用してパネルコンテンツを HTML に戻します。これにより、サイトのパブリックな HTML 出力を維持しながら、編集表面を構造化されたままに保つことができます。

これは SEO にも重要です。CTA はアンカーのままです。見出しは見出しのままです。画像は代替テキストとキャプションを持つ意味論的な figure のままです。タブはクロール可能なパネルコンテンツを維持します。検索エンジンや支援技術が推測しなければならないクライアントのみのウィジェットの中に EC のコピーを埋没させることはありませんでした。

エディタはマーチャントにとってシンプル、コードにとって厳格

管理 UI は複雑さのほとんどを隠蔽しています。

編集者はツールバーボタン、ダイアログ、レイアウトカード、画像フィールド、メディアピッカーを目にします。テキストを選択してフローティング BubbleMenu を使用してフォーマットできます。Bootstrap クラスを覚えなくても、2 カラムまたは 3 カラムのレイアウトを選択できます。タブを追加し、保存前に最初のパネルをプレビューできます。

その下ではコードは厳格なままです:

リンクは許可されたプロトコルのみを受け入れる
画像 URL は挿入前に正規化される
Instagram 埋め込みは許可されたパーマリンクデータに還元される
タブの数は 2 から 20 の間に制限される
生成された ID は安定した安全な文字に正規化される
無効状態は Tiptap の editable フラグを通じて尊重される
貼り付けられた Instagram 埋め込みはスクリプトブロブではなくエディタノードに変換される

この分離こそが、私がこの実装を気に入っている理由です。UI は寛容に感じられますが、保存される出力は制御されています。

セキュリティは選択肢ではありませんでした

リッチテキストエディタは、保存パスがブラウザから返されるものを何でも信頼する場合、危険です。

私たちはパブリックレンダリングのために専用のリッチテキストサニタイザーを追加しました。これは DOMPurify を使用し、タグと属性の明示的な許可リストを用います。コンテンツが React の生 HTML シンクに到達する前に、スクリプト可能で実行可能なマークアップを削除します。また、Instagram 埋め込みデータを正規化し、URL 値を持つ属性からブロックされた URL プロトコルを削除します。

レンダリングテストは、EC ページビルダーにとって重要なケースをカバーしています:

レスポンシブなカラムはそのまま維持される
エディタで作成されたボタンはクロール可能のまま
画像は遅延読み込みされる意味論的な figure としてレンダリングされる
スペーサーとフォントサイズクラスはレンダリングを生き延びる
安全な Instagram 埋め込みはパーマリンクを保持し、スクリプトタグを失う
タブは `tablist` と `tabpanel` のセマンティクスを保持する
レガシー CMS 画像グリッドはタブ内で生存する
実行可能なマークアップはパブリックレンダリング前に削除される

これが、「WYSIWYG エディタを追加した」と「本番環境で使用できるようにした」の違いです。

ブランチ履歴が真の物語を語る

最初のコミットは大規模でした:18 ファイル変更、6,282 行追加、187 行削除。ストアフロントアプリ両方への Tiptap 依存関係の追加、3,000 行のエディタコンポーネント、1,100 行以上のエディタ SCSS、レンダリングテスト、管理コントロール、レイアウト処理、そしてサニタイザーパスが含まれていました。

その後、洗練が続きました。`d092141d` は HTML ブロックエディタとナビゲーションインタラクションを改善しました。`320591ec` は英語、スウェーデン語、フランス語での翻訳カバレッジを追加し、メディアピッカーフックを削除し、エディタの動作を強化し、タブをより柔軟にしました。`2c7928b9` はメディアライブラリ画像を ID で重複排除しました。

これがエディタ作業の真のパターンです。最初のバージョンはエディタが存在できることを証明します。その後のコミットがそれを使用可能にします。

Tiptap が最も役立った場所

Tiptap は 3 つの場所で役立ちました。

第一に、エディタのコアを退屈なもの(=安定したもの)にしました。選択、コマンド、元に戻す/やり直し、キーボード動作、フローティングメニューなどを発明する必要はありませんでした。React 統合と StarterKit が安定したベースを提供してくれました。

第二に、壊れやすい文字列操作の中に隠すことなく、EC 固有のブロックをモデル化できました。カスタムノードとコマンドにより、ボタン、画像、カラム、タブ、埋め込みに実体のある形状を与えました。

第三に、レンダリング契約を維持できました。パブリックなストアフロントがすでに HTML ブロックに依存しているため、HTML を保存およびレンダリングしつつ、意味のある場所では内部的に構造化されたエディタコンテンツを使用できました。

この組み合わせは稀です。多くのエディタはカスタム出力が必要になるまで簡単です。多くのカスタムエディタは通常の執筆体験が必要になるまで柔軟です。Tiptap は有用な中間に位置しています。

トレードオフ

Tiptap は製品の決定をなくすわけではありません。

どのコンテンツタイプを許可するか、どの HTML が存続するか、画像がどのように選択されるか、リンクがどのように検証されるか、貼り付けられたコンテンツがどのように振る舞うか、翻訳がどのように機能するか、パブリックレンダリングパスがどのようにコンテンツをサニタイズするか、マーチャントにどの程度の自由を与えるべきかを依然として決定する必要があります。

ブログエディタであれば、Tiptap は迅速かもしれません。しかし EC の PageBuilder 而言えば、作業の大部分は Tiptap の周囲にあります:レガシー互換性、レンダリングテスト、メディアワークフロー、アクセシビリティ、SEO、翻訳、ガードレールです。

それで問題ありません。優れたヘッドレスエディタは、ビジネスルールが存在しないふりをするのではなく、プリミティブを提供すべきなのです。

私の結論

私はこの種の作業で再び Tiptap を使用するでしょう。

この実装により、既存の PageBuilder システムを捨てることなく、実用的な Tiptap React エディタを手に入れることができました。マーチャントはより安全な編集表面を得られます。開発者は予測可能な HTML を維持できます。SEO に重要なコンテンツはクロール可能のままです。ストアフロントは壊れやすいクライアントのみのレンダリングトリックに依存しません。

それが私が EC 管理ツールに求める基準です:表面はシンプル、出力は厳格、そして最初のローンチ後にも信頼できるほど退屈(=安定)であること。

ソース