テーブル下部クリック時のカーソル位置を修正
WrappedTableNodeにcanInsertTextBefore()/canInsertTextAfter()のオーバーライドを追加することで、テーブル下部のクリックがテーブル外にカーソルを正しく配置するようになりました。
背景
テーブル周辺のクリック操作が正しく機能しない根本原因は、WrappedTableNodeが暫定段落システムに誤ったシグナルを送っていたことにありました。WrappedTableNodeはElementNodeを継承しており、canInsertTextBefore()とcanInsertTextAfter()がデフォルトでtrueを返します。これはブラウザがテーブルの前後へのクリックをネイティブに解決できると暫定段落システムに伝えることを意味します。
しかし実際には、テーブル下部のクリックはブラウザによって最後のセル内に解決されてしまいます。この誤ったシグナルにより、ProvisionalParagraphExtensionがテーブルの周囲に隠しクリックターゲット(暫定段落)を挿入しないという問題が生じていました。その結果、テーブルの後ろをクリックしてもカーソルはテーブル内の最後のセルに移動し、テーブルの外側にテキストを入力できない状態でした。
技術的な変更
修正はWrappedTableNodeへの2メソッドの追加のみで完結しています。src/nodes/wrapped_table_node.jsにcanInsertTextBefore()と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>要素に存在することを検証します。
設計判断
継承元の挙動をオーバーライドする方式が採用されています。ElementNodeのcanInsertTextBefore()/canInsertTextAfter()は汎用的にtrueを返しますが、テーブルはブラウザのネイティブなカーソル配置が機能しない特殊なノードです。新たな設定フラグや条件分岐をシステム全体に追加するのではなく、WrappedTableNode自身がその性質をfalseで宣言することで、暫定段落システムは既存のロジックのまま正しく動作します。変更箇所を最小限に抑えつつ、責任をノード自身に持たせた設計といえます。
まとめ
8行の追加で、テーブルノードがブラウザの制約を暫定段落システムに正しく伝えるようになりました。「ブラウザが解決できないクリック位置はノード自身が申告する」というシステムの契約を適切に満たすことで、テーブル周辺の編集体験が改善されています。