@ckeditor/ckeditor5-typing
Advanced tools
Comparing version 12.0.2 to 12.1.0
Changelog | ||
========= | ||
## [12.1.0](https://github.com/ckeditor/ckeditor5-typing/compare/v12.0.2...v12.1.0) (2019-07-04) | ||
### Features | ||
* Introduced the text transformation feature. Additionally, the `TextWatcher` util was moved to this package from `@ckeditor/ckeditor5-mention`. Closes [ckeditor/ckeditor5#1490](https://github.com/ckeditor/ckeditor5/issues/1490). ([dafd16e](https://github.com/ckeditor/ckeditor5-typing/commit/dafd16e)) | ||
### Bug fixes | ||
* Improved typing on Android devices by handling `beforeinput` event instead of mutations. Introduced `options.selection` in the `DeleteCommand#execute()` params. Introduced `selectionToRemove` parameter in the `view.Document#event:delete` data. Closes [#167](https://github.com/ckeditor/ckeditor5-typing/issues/167). ([92ab3ff](https://github.com/ckeditor/ckeditor5-typing/commit/92ab3ff)) | ||
## [12.0.2](https://github.com/ckeditor/ckeditor5-typing/compare/v12.0.1...v12.0.2) (2019-06-05) | ||
@@ -5,0 +16,0 @@ |
{ | ||
"name": "@ckeditor/ckeditor5-typing", | ||
"version": "12.0.2", | ||
"version": "12.1.0", | ||
"description": "Typing feature for CKEditor 5.", | ||
@@ -13,18 +13,18 @@ "keywords": [ | ||
"dependencies": { | ||
"@ckeditor/ckeditor5-core": "^12.1.1", | ||
"@ckeditor/ckeditor5-engine": "^13.1.1", | ||
"@ckeditor/ckeditor5-utils": "^12.1.1" | ||
"@ckeditor/ckeditor5-core": "^12.2.0", | ||
"@ckeditor/ckeditor5-engine": "^13.2.0", | ||
"@ckeditor/ckeditor5-utils": "^13.0.0" | ||
}, | ||
"devDependencies": { | ||
"@ckeditor/ckeditor5-basic-styles": "^11.1.1", | ||
"@ckeditor/ckeditor5-block-quote": "^11.1.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^12.1.1", | ||
"@ckeditor/ckeditor5-enter": "^11.0.2", | ||
"@ckeditor/ckeditor5-essentials": "^11.0.2", | ||
"@ckeditor/ckeditor5-heading": "^11.0.2", | ||
"@ckeditor/ckeditor5-image": "^13.1.0", | ||
"@ckeditor/ckeditor5-link": "^11.0.2", | ||
"@ckeditor/ckeditor5-list": "^12.0.2", | ||
"@ckeditor/ckeditor5-paragraph": "^11.0.2", | ||
"@ckeditor/ckeditor5-undo": "^11.0.2", | ||
"@ckeditor/ckeditor5-basic-styles": "^11.1.2", | ||
"@ckeditor/ckeditor5-block-quote": "^11.1.1", | ||
"@ckeditor/ckeditor5-editor-classic": "^12.1.2", | ||
"@ckeditor/ckeditor5-enter": "^11.0.3", | ||
"@ckeditor/ckeditor5-essentials": "^11.0.3", | ||
"@ckeditor/ckeditor5-heading": "^11.0.3", | ||
"@ckeditor/ckeditor5-image": "^13.1.1", | ||
"@ckeditor/ckeditor5-link": "^11.1.0", | ||
"@ckeditor/ckeditor5-list": "^12.0.3", | ||
"@ckeditor/ckeditor5-paragraph": "^11.0.3", | ||
"@ckeditor/ckeditor5-undo": "^11.0.3", | ||
"eslint": "^5.5.0", | ||
@@ -31,0 +31,0 @@ "eslint-config-ckeditor5": "^1.0.11", |
@@ -7,3 +7,2 @@ CKEditor 5 typing feature | ||
[![Build Status](https://travis-ci.org/ckeditor/ckeditor5-typing.svg?branch=master)](https://travis-ci.org/ckeditor/ckeditor5-typing) | ||
[![BrowserStack Status](https://automate.browserstack.com/automate/badge.svg?badge_key=d3hvenZqQVZERFQ5d09FWXdyT0ozVXhLaVltRFRjTTUyZGpvQWNmWVhUUT0tLUZqNlJ1YWRUd0RvdEVOaEptM1B2Q0E9PQ==--c9d3dee40b9b4471ff3fb516d9ecf8d09292c7e0)](https://automate.browserstack.com/public-build/d3hvenZqQVZERFQ5d09FWXdyT0ozVXhLaVltRFRjTTUyZGpvQWNmWVhUUT0tLUZqNlJ1YWRUd0RvdEVOaEptM1B2Q0E9PQ==--c9d3dee40b9b4471ff3fb516d9ecf8d09292c7e0) | ||
[![Coverage Status](https://coveralls.io/repos/github/ckeditor/ckeditor5-typing/badge.svg?branch=master)](https://coveralls.io/github/ckeditor/ckeditor5-typing?branch=master) | ||
@@ -10,0 +9,0 @@ <br> |
@@ -13,5 +13,4 @@ /** | ||
import DeleteObserver from './deleteobserver'; | ||
import env from '@ckeditor/ckeditor5-utils/src/env'; | ||
import injectAndroidBackspaceMutationsHandling from './utils/injectandroidbackspacemutationshandling'; | ||
/** | ||
@@ -41,9 +40,60 @@ * The delete and backspace feature. Handles the <kbd>Delete</kbd> and <kbd>Backspace</kbd> keys in the editor. | ||
this.listenTo( viewDocument, 'delete', ( evt, data ) => { | ||
editor.execute( data.direction == 'forward' ? 'forwardDelete' : 'delete', { unit: data.unit, sequence: data.sequence } ); | ||
const deleteCommandParams = { unit: data.unit, sequence: data.sequence }; | ||
// If a specific (view) selection to remove was set, convert it to a model selection and set as a parameter for `DeleteCommand`. | ||
if ( data.selectionToRemove ) { | ||
const modelSelection = editor.model.createSelection(); | ||
const ranges = []; | ||
for ( const viewRange of data.selectionToRemove.getRanges() ) { | ||
ranges.push( editor.editing.mapper.toModelRange( viewRange ) ); | ||
} | ||
modelSelection.setTo( ranges ); | ||
deleteCommandParams.selection = modelSelection; | ||
} | ||
editor.execute( data.direction == 'forward' ? 'forwardDelete' : 'delete', deleteCommandParams ); | ||
data.preventDefault(); | ||
view.scrollToTheSelection(); | ||
} ); | ||
injectAndroidBackspaceMutationsHandling( editor ); | ||
// Android IMEs have a quirk - they change DOM selection after the input changes were performed by the browser. | ||
// This happens on `keyup` event. Android doesn't know anything about our deletion and selection handling. Even if the selection | ||
// was changed during input events, IME remembers the position where the selection "should" be placed and moves it there. | ||
// | ||
// To prevent incorrect selection, we save the selection after deleting here and then re-set it on `keyup`. This has to be done | ||
// on DOM selection level, because on `keyup` the model selection is still the same as it was just after deletion, so it | ||
// wouldn't be changed and the fix would do nothing. | ||
// | ||
/* istanbul ignore if */ | ||
if ( env.isAndroid ) { | ||
let domSelectionAfterDeletion = null; | ||
this.listenTo( viewDocument, 'delete', ( evt, data ) => { | ||
const domSelection = data.domTarget.ownerDocument.defaultView.getSelection(); | ||
domSelectionAfterDeletion = { | ||
anchorNode: domSelection.anchorNode, | ||
anchorOffset: domSelection.anchorOffset, | ||
focusNode: domSelection.focusNode, | ||
focusOffset: domSelection.focusOffset | ||
}; | ||
}, { priority: 'lowest' } ); | ||
this.listenTo( viewDocument, 'keyup', ( evt, data ) => { | ||
if ( domSelectionAfterDeletion ) { | ||
const domSelection = data.domTarget.ownerDocument.defaultView.getSelection(); | ||
domSelection.collapse( domSelectionAfterDeletion.anchorNode, domSelectionAfterDeletion.anchorOffset ); | ||
domSelection.extend( domSelectionAfterDeletion.focusNode, domSelectionAfterDeletion.focusOffset ); | ||
domSelectionAfterDeletion = null; | ||
} | ||
} ); | ||
} | ||
} | ||
} |
@@ -69,2 +69,4 @@ /** | ||
* See the {@link module:engine/view/document~Document#event:delete} event data. | ||
* @param {module:engine/model/selection~Selection} [options.selection] Selection to remove. If not set, current model selection | ||
* will be used. | ||
*/ | ||
@@ -78,3 +80,3 @@ execute( options = {} ) { | ||
const selection = writer.createSelection( doc.selection ); | ||
const selection = writer.createSelection( options.selection || doc.selection ); | ||
@@ -81,0 +83,0 @@ // Do not replace the whole selected content if selection was collapsed. |
@@ -50,2 +50,36 @@ /** | ||
fireViewDeleteEvent( evt, data.domEvent, deleteData ); | ||
} ); | ||
// `beforeinput` is handled only for Android devices. Desktop Chrome and iOS are skipped because they are working fine now. | ||
/* istanbul ignore if */ | ||
if ( env.isAndroid ) { | ||
document.on( 'beforeinput', ( evt, data ) => { | ||
// If event type is other than `deleteContentBackward` then this is not deleting. | ||
if ( data.domEvent.inputType != 'deleteContentBackward' ) { | ||
return; | ||
} | ||
const deleteData = { | ||
unit: 'codepoint', | ||
direction: 'backward', | ||
sequence: 1 | ||
}; | ||
// Android IMEs may change the DOM selection on `beforeinput` event so that the selection contains all the text | ||
// that the IME wants to remove. We will pass this information to `delete` event so proper part of the content is removed. | ||
// | ||
// Sometimes it is only expanding by a one character (in case of collapsed selection). In this case we don't need to | ||
// set a different selection to remove, it will work just fine. | ||
const domSelection = data.domTarget.ownerDocument.defaultView.getSelection(); | ||
if ( domSelection.anchorNode == domSelection.focusNode && domSelection.anchorOffset + 1 != domSelection.focusOffset ) { | ||
deleteData.selectionToRemove = view.domConverter.domSelectionToView( domSelection ); | ||
} | ||
fireViewDeleteEvent( evt, data.domEvent, deleteData ); | ||
} ); | ||
} | ||
function fireViewDeleteEvent( originalEvent, domEvent, deleteData ) { | ||
// Save the event object to check later if it was stopped or not. | ||
@@ -55,11 +89,10 @@ let event; | ||
const domEvtData = new DomEventData( document, data.domEvent, deleteData ); | ||
document.fire( 'delete', domEvtData ); | ||
document.fire( 'delete', new DomEventData( document, domEvent, deleteData ) ); | ||
// Stop `keydown` event if `delete` event was stopped. | ||
// Stop the original event if `delete` event was stopped. | ||
// https://github.com/ckeditor/ckeditor5/issues/753 | ||
if ( event && event.stop.called ) { | ||
evt.stop(); | ||
originalEvent.stop(); | ||
} | ||
} ); | ||
} | ||
} | ||
@@ -85,2 +118,4 @@ | ||
* If it's 2 or more it means that the key was pressed and hold. | ||
* @param {module:engine/view/selection~Selection} [data.selectionToRemove] View selection which content should be removed. If not set, | ||
* current selection should be used. | ||
*/ |
@@ -11,2 +11,3 @@ /** | ||
import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard'; | ||
import env from '@ckeditor/ckeditor5-utils/src/env'; | ||
@@ -26,3 +27,9 @@ /** | ||
view.document.on( 'keydown', ( evt, evtData ) => handleKeydown( evtData ), { priority: 'lowest' } ); | ||
// For Android, we want to handle keystrokes on `beforeinput` to be sure that code in `DeleteObserver` already had a chance to be fired. | ||
/* istanbul ignore if */ | ||
if ( env.isAndroid ) { | ||
view.document.on( 'beforeinput', ( evt, evtData ) => handleUnsafeKeystroke( evtData ), { priority: 'lowest' } ); | ||
} else { | ||
view.document.on( 'keydown', ( evt, evtData ) => handleUnsafeKeystroke( evtData ), { priority: 'lowest' } ); | ||
} | ||
@@ -47,3 +54,3 @@ view.document.on( 'compositionstart', handleCompositionStart, { priority: 'lowest' } ); | ||
// @param {module:engine/view/observer/keyobserver~KeyEventData} evtData | ||
function handleKeydown( evtData ) { | ||
function handleUnsafeKeystroke( evtData ) { | ||
const doc = model.document; | ||
@@ -50,0 +57,0 @@ const isComposing = view.document.isComposing; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83085
17
1578
21
- Removed@ckeditor/ckeditor5-utils@12.1.1(transitive)