@@ -737,6 +737,42 @@ class InputGuard {
737737 }
738738 }
739739
740+ /**
741+ * 変更前後の文字列から置換範囲と挿入文字列を推測
742+ * @param {string } beforeText
743+ * @param {string } afterText
744+ * @returns {{ replaceStart: number, replaceEnd: number, insertedText: string } }
745+ */
746+ detectTextDiff ( beforeText , afterText ) {
747+ let start = 0 ;
748+
749+ while (
750+ start < beforeText . length &&
751+ start < afterText . length &&
752+ beforeText [ start ] === afterText [ start ]
753+ ) {
754+ start ++ ;
755+ }
756+
757+ let beforeEnd = beforeText . length ;
758+ let afterEnd = afterText . length ;
759+
760+ while (
761+ beforeEnd > start &&
762+ afterEnd > start &&
763+ beforeText [ beforeEnd - 1 ] === afterText [ afterEnd - 1 ]
764+ ) {
765+ beforeEnd -- ;
766+ afterEnd -- ;
767+ }
768+
769+ return {
770+ replaceStart : start ,
771+ replaceEnd : beforeEnd ,
772+ insertedText : afterText . slice ( start , afterEnd )
773+ } ;
774+ }
775+
740776 /**
741777 * ルール実行に渡すコンテキストを作る(pushErrorで errors に積める)
742778 * @returns {GuardContext }
@@ -786,7 +822,9 @@ class InputGuard {
786822 baseSel = lastSel ;
787823 }
788824
789- // beforeinput がない環境では、差分再構成の基準が「前回の受理値」しかないため、そこから今回の編集内容を推測する必要がある。
825+ // オートコンプリートの処理
826+ // inputType が取得できないため existBeforeInputEvent 情報で判断
827+ // 差分再構成の基準が「前回の受理値」しかないため、そこから今回の編集内容を推測する必要がある。
790828 if ( beforeText . length === 0 || ! this . existBeforeInputEvent ) {
791829 // 前回の値がとれないものの、何かしら入力情報がある状態
792830 if ( afterText . length > 0 ) {
@@ -819,10 +857,10 @@ class InputGuard {
819857 let replaceStart = baseSel . start ?? 0 ;
820858 let replaceEnd = baseSel . end ?? 0 ;
821859
860+ // 削除操作の特殊処理
822861 // Backspace / Delete は「挿入文字がない(dataがnull)」ことが多い。
823862 // そのままだと差分再構成で “何も変わらない” 扱いになって削除が効かなくなるため、
824863 // 選択範囲が無い場合は「削除される1文字ぶん」の置換範囲をここで作る。
825- //
826864 // ※ 選択範囲がある削除は replaceStart!=replaceEnd なので補正不要(その範囲を消すだけでよい)
827865 if ( replaceStart === replaceEnd ) {
828866 if ( inputType === "deleteContentBackward" ) {
@@ -838,6 +876,14 @@ class InputGuard {
838876 // deleteWordBackward / deleteWordForward / deleteByCut / deleteSoftLineBackward ... etc
839877 }
840878
879+ // アンドゥリドゥの特殊処理
880+ if ( inputType === "historyUndo" || inputType === "historyRedo" ) {
881+ const diff = this . detectTextDiff ( beforeText , afterText ) ;
882+ replaceStart = diff . replaceStart ;
883+ replaceEnd = diff . replaceEnd ;
884+ insertedText = diff . insertedText ;
885+ }
886+
841887 return {
842888 hostElement : this . hostElement ,
843889 displayElement : this . displayElement ,
0 commit comments