AttachmentNodeキャプション入力のSafariバグ回避策を削除
Provisional Paragraphs機能の導入により、Safari特有のキャプション入力バグへの回避策が不要になりました。DecoratorNodeが単独のノードではなくなったことで、エディタのフォーカス管理がシンプルかつ堅牢になっています。
背景
Safariでは、ドキュメント内に AttachmentNode(DecoratorNode)しか存在しない場合、その前後にテキストを入力できないという問題がありました。#726で導入された Provisional Paragraphs は、DecoratorNodeやElementNodeの隣に選択可能な仮想的な段落ノードを自動挿入する仕組みです。この機能により、エディタ境界での選択が常に可能になり、Safariでの回避策が不要になりました。
従来の回避策は Selection クラスの #handleInputWhenDecoratorNodesSelected メソッドで実装されており、DecoratorNodeの前後に入力があった際に段落を手動で挿入していました。Provisional Paragraphsはこの処理を自動化し、より一般的な解決策を提供します。
技術的な変更
本PRでは、2つの主要な変更が行われました。
Safari回避策の削除
src/editor/selection.js から57行のコードが削除されました。
削除されたメソッド:
#handleInputWhenDecoratorNodesSelected() {
this.editor.getRootElement().addEventListener("keydown", (event) => {
if (isPrintableCharacter(event)) {
this.editor.update(() => {
const selection = $getSelection()
if ($isRangeSelection(selection) && selection.isCollapsed()) {
const anchorNode = selection.anchor.getNode()
const offset = selection.anchor.offset
const nodeBefore = this.#getNodeBeforePosition(anchorNode, offset)
const nodeAfter = this.#getNodeAfterPosition(anchorNode, offset)
if (nodeBefore instanceof DecoratorNode && !nodeBefore.isInline()) {
event.preventDefault()
// ... 段落挿入処理
}
}
})
}
})
}
このメソッドは Selection の初期化時に呼ばれていましたが、Provisional Paragraphsが自動的に選択可能なノードを保証するため削除されました。src/helpers/lexical_helper.js の isPrintableCharacter ヘルパー関数も同時に削除されています。
キャプションテキストエリアのイベントハンドリング改善
src/nodes/action_text_attachment_node.js の #handleCaptionInputKeydown メソッドが再設計されました。
変更前:
#handleCaptionInputKeydown(event) {
if (event.key === "Enter") {
this.#updateCaptionValueFromInput(event.target)
event.preventDefault()
this.editor.update(() => {
this.selectNext()
}, { tag: HISTORY_MERGE_TAG })
}
event.stopPropagation()
}
変更後:
#handleCaptionInputKeydown(event) {
if (event.key === "Enter") {
event.preventDefault()
event.stopPropagation()
event.target.blur()
this.editor.update(() => {
// Place the cursor after the current image
this.selectNext(0, 0)
}, {
tag: HISTORY_MERGE_TAG
})
}
}
主な変更点は以下の3つです:
-
event.target.blur()を追加し、キャプションテキストエリアから明示的にフォーカスを外す -
this.selectNext(0, 0)の引数指定により、カーソル位置を明確に指定 -
event.stopPropagation()をEnterキー処理の内部に移動し、他のキーイベントの伝播は許可
this.#updateCaptionValueFromInput の呼び出しは削除されましたが、キャプションの保存は blur イベントで処理されます。test/system/attachments_test.rb に追加された3つのテストケースが、Enter・クリック・Tabによるフォーカス遷移でキャプションが正しく保存されることを検証しています。
設計判断
Provisional Paragraphsへの移行 により、ブラウザ固有の問題への対処が構造的な解決に置き換えられました。
PR内の説明によれば、Provisional Paragraphsは DecoratorNodeやElementNodeの隣に自動的に仮想段落を挿入し、空のエディタにも段落を提供します。これらの仮想段落は編集時に通常の段落に変換され、不要になると自動削除されます。この仕組みにより、選択可能なノードが常に存在することが保証され、Safari固有のキーボード入力処理が不要になりました。
キャプションのフォーカス管理では、blur() を明示的に呼び出すアプローチが採用されました。これは、Enterキー押下時にキャプション入力を終了し、エディタ本体にフォーカスを戻す意図を明確にしています。Provisional Paragraphsがカーソル移動先を保証するため、フォーカス遷移の信頼性が向上しています。
まとめ
本PRは、Provisional Paragraphs機能を活用してSafari特有のバグ回避策を削除し、エディタのフォーカス管理をシンプル化しました。ブラウザ固有の問題への対処を構造的な解決に置き換えることで、コードの保守性が向上し、将来的なバグのリスクが軽減されています。57行のコード削除と8行の改善により、より堅牢なキャプション入力体験が実現されました。