@@ -79,6 +79,15 @@ const alphabetsContainingSpaces = new RegExp(
7979 ')$' ,
8080) ;
8181
82+ /**
83+ * Spell-checking on mobile devices does not stop at inline tags like b, i, u
84+ * but it hits a barrier on different nodes like div for example. The code
85+ * below constructs a crude selector to match if the node is such a barrier.
86+ */
87+ const spellCheckingIgnoredTags = [ 'a' , 'b' , 'i' , 'u' , 'span' , 'font' , 'superscript' , 'subscript' ] ;
88+ const spellCheckingBarrier = spellCheckingIgnoredTags . map ( t => `:not(${ t } )` ) . join ( '' ) ;
89+ console . log ( spellCheckingBarrier ) ;
90+
8291/**
8392 * These javascript event types might, in case of safari or spell-checking
8493 * keyboard, trigger dom events in multiple javascript stacks. They will require
@@ -941,8 +950,11 @@ export class EventNormalizer {
941950 | DeleteWordAction
942951 | DeleteHardLineAction
943952 | DeleteContentAction {
944- const isInsertOrRemoveAction = hasMutatedElements && ! inputTypeCommands . has ( inputType ) ;
945- if ( isInsertOrRemoveAction ) {
953+ const isMutationAction = hasMutatedElements && ! inputTypeCommands . has ( inputType ) ;
954+ // These two particular keys might have been defaultPrevented to avoid
955+ // flickering and thus trigger no mutation but still need to be handled.
956+ const isRemoveAction = key === 'Backspace' || key === 'Delete' ;
957+ if ( isMutationAction || isRemoveAction ) {
946958 if ( key === 'Backspace' || key === 'Delete' ) {
947959 return this . _getRemoveAction ( key , inputType ) ;
948960 } else if ( key === 'Enter' ) {
@@ -1599,6 +1611,27 @@ export class EventNormalizer {
15991611 const selection = this . _getSelection ( ) ;
16001612 const [ offsetNode , offset ] = targetDeepest ( selection . anchorNode , selection . anchorOffset ) ;
16011613 this . _initialCaretPosition = { offsetNode, offset } ;
1614+
1615+ // Backspace cannot always be prevented as preventing a backspace in a
1616+ // text node would throw off spell-checking on mobile for example.
1617+ if ( ev . key === 'Backspace' ) {
1618+ const forward = selection . direction === Direction . FORWARD ;
1619+ const start = forward ? selection . anchorNode : selection . focusNode ;
1620+ const startOffset = forward ? selection . anchorOffset : selection . focusOffset ;
1621+ if (
1622+ ( startOffset === 0 && ! start . previousSibling ) ||
1623+ selection . anchorNode . parentElement . closest ( spellCheckingBarrier ) !==
1624+ selection . focusNode . parentElement . closest ( spellCheckingBarrier )
1625+ ) {
1626+ console . log ( 'prevented' ) ;
1627+ // Allowed cases for preventing is:
1628+ // 1. At the start of the node
1629+ // 2. When the anchor and focus of the selection are set in
1630+ // nodes that are separated of each other by a node that is
1631+ // considered to be a barrier for spell-checking purposes.
1632+ ev . preventDefault ( ) ;
1633+ }
1634+ }
16021635 }
16031636 /**
16041637 * Set internal properties of the pointer down event to retrieve them later
0 commit comments