テーブル下部クリック時のカーソル位置を修正

basecamp/lexxy

WrappedTableNodecanInsertTextBefore()/canInsertTextAfter()のオーバーライドを追加することで、テーブル下部のクリックがテーブル外にカーソルを正しく配置するようになりました。

背景

テーブル周辺のクリック操作が正しく機能しない根本原因は、WrappedTableNodeが暫定段落システムに誤ったシグナルを送っていたことにありました。WrappedTableNodeElementNodeを継承しており、canInsertTextBefore()canInsertTextAfter()がデフォルトでtrueを返します。これはブラウザがテーブルの前後へのクリックをネイティブに解決できると暫定段落システムに伝えることを意味します。

しかし実際には、テーブル下部のクリックはブラウザによって最後のセル内に解決されてしまいます。この誤ったシグナルにより、ProvisionalParagraphExtensionがテーブルの周囲に隠しクリックターゲット(暫定段落)を挿入しないという問題が生じていました。その結果、テーブルの後ろをクリックしてもカーソルはテーブル内の最後のセルに移動し、テーブルの外側にテキストを入力できない状態でした。

技術的な変更

修正はWrappedTableNodeへの2メソッドの追加のみで完結しています。src/nodes/wrapped_table_node.jscanInsertTextBefore()canInsertTextAfter()をオーバーライドし、どちらもfalseを返すようにしました。

変更後:

export class WrappedTableNode extends TableNode {
  // ...

  canInsertTextBefore() {
    return false
  }

  canInsertTextAfter() {
    return false
  }

  exportDOM(editor) {
    // ...
  }
}

この変更により、ProvisionalParagraphExtensionはテーブルの前後にクリックターゲットとなる非表示段落を挿入するようになります。これでテーブル下部のクリックがその隠し段落に当たり、カーソルがテーブル外に正しく配置されます。

併せてtest/browser/tests/tables/click_target.test.jsがPlaywrightテストとして追加されました。テストはテーブルのみを含むコンテンツをロードし、テーブル下部の座標をクリックした後にテキストを入力し、そのテキストがテーブル内ではなくテーブル後の<p>要素に存在することを検証します。

設計判断

継承元の挙動をオーバーライドする方式が採用されています。ElementNodecanInsertTextBefore()/canInsertTextAfter()は汎用的にtrueを返しますが、テーブルはブラウザのネイティブなカーソル配置が機能しない特殊なノードです。新たな設定フラグや条件分岐をシステム全体に追加するのではなく、WrappedTableNode自身がその性質をfalseで宣言することで、暫定段落システムは既存のロジックのまま正しく動作します。変更箇所を最小限に抑えつつ、責任をノード自身に持たせた設計といえます。

まとめ

8行の追加で、テーブルノードがブラウザの制約を暫定段落システムに正しく伝えるようになりました。「ブラウザが解決できないクリック位置はノード自身が申告する」というシステムの契約を適切に満たすことで、テーブル周辺の編集体験が改善されています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
e3e8286a

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

「リード文→背景→技術的な変更→設計判断→まとめ」という理想的な3部構成が明確に守られています。各セクションの役割が明確で、論理的な流れが構築されています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```javascript:src/nodes/wrapped_table_node.js)とPR番号のリンク記法([PR #835]...)が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

フレームワークの内部実装に関する深い内容であり、専門知識を持つエンジニアという対象読者に完全に適合しています。冗長な説明がなく、的確です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクション、各パラグラフが「総論→各論」の構成になっており、トピックセンテンスが段落の冒頭に配置されているため、非常に読みやすいです。1段落1トピックの原則も守られています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているコードは、提供されたDiff情報と完全に一致しており、ファイルパスも正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「WrappedTableNode」「ProvisionalParagraphExtension」など、PRで使われている技術用語が正確に使用されており、誤用は見られません。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

問題の原因から解決策に至るまでの技術的な説明が、PRのDescriptionとDiffの内容に完全に基づいています。因果関係が論理的で正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張がPRのDescription、Diff、Titleで裏付けられており、ハルシネーション(捏造)は一切ありません。「設計判断」セクションはコードの意図を的確に解説しており、価値ある洞察を提供しています。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号「#835」が正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「テーブル下部クリック時のカーソル位置を修正」は、PRのタイトル「Clicking below a table now places cursor after the table」の内容を的確に要約しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PR情報に記載のないバージョン情報やリリース日程といった外部知識の追加はなく、事実に基づいた記述に徹しています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

PRが解決した問題について「...するようになりました」と記述しており、時間表現は正確です。