Skip to content

Commit 51eaabc

Browse files
authored
Merge pull request #18723 from ckeditor/ck/18722
Fix (typing): Typing over multiple selected blocks next to a code block or a block quote should not crash the editor. Closes #18722.
2 parents 170a9ed + 0e64a3a commit 51eaabc

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

packages/ckeditor5-typing/src/input.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ export default class Input extends Plugin {
114114
modelRanges = Array.from( modelSelection.getRanges() );
115115
}
116116

117+
// Browser must not modify multiple blocks selected as the result is unpredictable.
118+
if ( modelRanges.some( range => range.start.parent !== range.end.parent ) ) {
119+
data.preventDefault();
120+
}
121+
117122
let insertText = text;
118123

119124
// Typing in English on Android is firing composition events for the whole typed word.

packages/ckeditor5-typing/tests/input.js

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,68 @@ describe( 'Input', () => {
145145
it( 'should preventDefault() the original beforeinput event if target ranges match fake selection', () => {
146146
setModelData( editor.model, '[<widget></widget>]' );
147147

148-
const spy = sinon.spy();
148+
const eventData = {
149+
preventDefault: sinon.spy(),
150+
selection: viewDocument.selection,
151+
text: 'bar'
152+
};
149153

150-
viewDocument.fire( 'insertText', {
151-
preventDefault: spy,
154+
eventData.domEvent = {
155+
get defaultPrevented() {
156+
return eventData.preventDefault.called;
157+
}
158+
};
159+
160+
viewDocument.fire( 'insertText', eventData );
161+
162+
sinon.assert.calledOnce( eventData.preventDefault );
163+
sinon.assert.calledOnce( insertTextCommandSpy );
164+
} );
165+
166+
it( 'should preventDefault() the original beforeinput event if target ranges span across different blocks', () => {
167+
setModelData( editor.model,
168+
'<paragraph>[foo</paragraph>' +
169+
'<paragraph>]bar</paragraph>'
170+
);
171+
172+
const eventData = {
173+
preventDefault: sinon.spy(),
152174
selection: viewDocument.selection,
153-
text: 'bar',
175+
text: 'abc',
154176
domEvent: {}
155-
} );
177+
};
156178

157-
sinon.assert.calledOnce( spy );
179+
eventData.domEvent = {
180+
get defaultPrevented() {
181+
return eventData.preventDefault.called;
182+
}
183+
};
184+
185+
viewDocument.fire( 'insertText', eventData );
186+
187+
sinon.assert.calledOnce( eventData.preventDefault );
188+
sinon.assert.calledOnce( insertTextCommandSpy );
189+
} );
190+
191+
it( 'should not preventDefault() the original beforeinput event if target ranges span a single block', () => {
192+
setModelData( editor.model, '<paragraph>[foo]</paragraph>' );
193+
194+
const eventData = {
195+
preventDefault: sinon.spy(),
196+
selection: viewDocument.selection,
197+
text: 'abc',
198+
domEvent: {}
199+
};
200+
201+
eventData.domEvent = {
202+
get defaultPrevented() {
203+
return eventData.preventDefault.called;
204+
}
205+
};
206+
207+
viewDocument.fire( 'insertText', eventData );
208+
209+
sinon.assert.notCalled( eventData.preventDefault );
158210
sinon.assert.notCalled( insertTextCommandSpy );
159211
} );
160212

0 commit comments

Comments
 (0)