Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ckeditor/ckeditor5-typing

Package Overview
Dependencies
Maintainers
1
Versions
708
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ckeditor/ckeditor5-typing - npm Package Compare versions

Comparing version 0.7.0 to 0.8.0

.github/PULL_REQUEST_TEMPLATE.md

22

package.json
{
"name": "@ckeditor/ckeditor5-typing",
"version": "0.7.0",
"version": "0.8.0",
"description": "Typing feature for CKEditor 5.",
"keywords": [],
"dependencies": {
"@ckeditor/ckeditor5-core": "*",
"@ckeditor/ckeditor5-engine": "*",
"@ckeditor/ckeditor5-utils": "*"
"@ckeditor/ckeditor5-core": "^0.7.0",
"@ckeditor/ckeditor5-engine": "^0.8.0",
"@ckeditor/ckeditor5-utils": "^0.8.0"
},
"devDependencies": {
"@ckeditor/ckeditor5-dev-lint": "^2.0.0",
"@ckeditor/ckeditor5-basic-styles": "*",
"@ckeditor/ckeditor5-editor-classic": "*",
"@ckeditor/ckeditor5-enter": "*",
"@ckeditor/ckeditor5-heading": "*",
"@ckeditor/ckeditor5-paragraph": "*",
"@ckeditor/ckeditor5-undo": "*",
"@ckeditor/ckeditor5-dev-lint": "^2.0.2",
"@ckeditor/ckeditor5-basic-styles": "^0.7.1",
"@ckeditor/ckeditor5-editor-classic": "^0.7.1",
"@ckeditor/ckeditor5-enter": "^0.8.0",
"@ckeditor/ckeditor5-heading": "^0.8.0",
"@ckeditor/ckeditor5-paragraph": "^0.6.1",
"@ckeditor/ckeditor5-undo": "^0.7.1",
"gulp": "^3.9.0",

@@ -20,0 +20,0 @@ "guppy-pre-commit": "^0.4.0"

@@ -11,3 +11,2 @@ /**

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ChangeBuffer from './changebuffer';
import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';

@@ -19,2 +18,3 @@ import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';

import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';
import InputCommand from './inputcommand';

@@ -24,3 +24,3 @@ /**

*
* @extends core.Plugin
* @extends module:core/plugin~Plugin
*/

@@ -34,15 +34,10 @@ export default class Input extends Plugin {

const editingView = editor.editing.view;
const inputCommand = new InputCommand( editor, editor.config.get( 'typing.undoStep' ) || 20 );
/**
* Typing's change buffer used to group subsequent changes into batches.
*
* @protected
* @member {typing.ChangeBuffer} #_buffer
*/
this._buffer = new ChangeBuffer( editor.document, editor.config.get( 'typing.undoStep' ) || 20 );
// TODO The above default configuration value should be defined using editor.config.define() once it's fixed.
editor.commands.set( 'input', inputCommand );
this.listenTo( editingView, 'keydown', ( evt, data ) => {
this._handleKeydown( data );
this._handleKeydown( data, inputCommand.buffer );
}, { priority: 'lowest' } );

@@ -56,12 +51,2 @@

/**
* @inheritDoc
*/
destroy() {
super.destroy();
this._buffer.destroy();
this._buffer = null;
}
/**
* Handles the keydown event. We need to guess whether such keystroke is going to result

@@ -80,4 +65,5 @@ * in typing. If so, then before character insertion happens, any selected content needs

* @param {module:engine/view/observer/keyobserver~KeyEventData} evtData
* @param {module:typing/changebuffer~ChangeBuffer} buffer
*/
_handleKeydown( evtData ) {
_handleKeydown( evtData, buffer ) {
const doc = this.editor.document;

@@ -90,3 +76,3 @@

doc.enqueueChanges( () => {
this.editor.data.deleteContent( doc.selection, this._buffer.batch );
this.editor.data.deleteContent( doc.selection, buffer.batch );
} );

@@ -98,9 +84,8 @@ }

*
* @param {Array.<engine.view.Document~MutatatedText|engine.view.Document~MutatatedChildren>} mutations
* @private
* @param {Array.<module:engine/view/document~MutatatedText|module:engine/view/document~MutatatedChildren>} mutations
* @param {module:engine/view/selection~Selection|null} viewSelection
*/
_handleMutations( mutations, viewSelection ) {
const doc = this.editor.document;
const handler = new MutationHandler( this.editor.editing, this._buffer );
doc.enqueueChanges( () => handler.handle( mutations, viewSelection ) );
new MutationHandler( this.editor ).handle( mutations, viewSelection );
}

@@ -118,26 +103,20 @@ }

*
* @param {module:engine/controller/editingcontroller~EditingController} editing
* @param {module:typing/changebuffer~ChangeBuffer} buffer
* @param {module:core/editor/editor~Editor} editor
*/
constructor( editing, buffer ) {
constructor( editor ) {
/**
* The editing controller.
* Editor instance for which mutations are handled.
*
* @member {engine.controller.EditingController} #editing
* @readonly
* @member {module:core/editor/editor~Editor} #editor
*/
this.editing = editing;
this.editor = editor;
/**
* The change buffer.
* The editing controller.
*
* @member {engine.controller.EditingController} #buffer
* @readonly
* @member {module:engine/controller/editingcontroller~EditingController} #editing
*/
this.buffer = buffer;
/**
* The number of inserted characters which need to be fed to the {@link #buffer change buffer}.
*
* @member {Number} #insertedCharacterCount
*/
this.insertedCharacterCount = 0;
this.editing = this.editor.editing;
}

@@ -148,3 +127,5 @@

*
* @param {Array.<engine.view.Document~MutatatedText|engine.view.Document~MutatatedChildren>} mutations
* @param {Array.<module:engine/view/observer/mutationobserver~MutatedText|
* module:engine/view/observer/mutationobserver~MutatatedChildren>} mutations
* @param {module:engine/view/selection~Selection|null} viewSelection
*/

@@ -157,4 +138,2 @@ handle( mutations, viewSelection ) {

}
this.buffer.input( Math.max( this.insertedCharacterCount, 0 ) );
}

@@ -224,17 +203,10 @@

const modelPos = this.editing.mapper.toModelPosition( viewPos );
const removeRange = ModelRange.createFromPositionAndShift( modelPos, deletions );
const insertText = newText.substr( firstChangeAt, insertions );
// Remove appropriate number of characters from the model text node.
if ( deletions > 0 ) {
const removeRange = ModelRange.createFromPositionAndShift( modelPos, deletions );
this._remove( removeRange, deletions );
}
// Insert appropriate characters basing on `mutation.text`.
const insertedText = mutation.newText.substr( firstChangeAt, insertions );
this._insert( modelPos, insertedText );
// If there was `viewSelection` and it got correctly mapped, collapse selection at found model position.
if ( modelSelectionPosition ) {
this.editing.model.selection.collapse( modelSelectionPosition );
}
this.editor.execute( 'input', {
text: insertText,
range: removeRange,
resultPosition: modelSelectionPosition
} );
}

@@ -270,26 +242,13 @@

const modelPos = this.editing.mapper.toModelPosition( viewPos );
let insertedText = change.values[ 0 ].data;
const insertedText = change.values[ 0 ].data;
// Replace &nbsp; inserted by the browser with normal space.
// See comment in `_handleTextMutation`.
// In this case we don't need to do this before `diff` because we diff whole nodes.
// Just change &nbsp; in case there are some.
insertedText = insertedText.replace( /\u00A0/g, ' ' );
this._insert( modelPos, insertedText );
this.editing.model.selection.collapse( modelPos.getShiftedBy( insertedText.length ) );
this.editor.execute( 'input', {
// Replace &nbsp; inserted by the browser with normal space.
// See comment in `_handleTextMutation`.
// In this case we don't need to do this before `diff` because we diff whole nodes.
// Just change &nbsp; in case there are some.
text: insertedText.replace( /\u00A0/g, ' ' ),
range: new ModelRange( modelPos )
} );
}
_insert( position, text ) {
this.buffer.batch.weakInsert( position, text );
this.insertedCharacterCount += text.length;
}
_remove( range, length ) {
this.buffer.batch.remove( range );
this.insertedCharacterCount -= length;
}
}

@@ -302,2 +261,3 @@

getCode( 'arrowLeft' ),
9, // Tab
16, // Shift

@@ -304,0 +264,0 @@ 17, // Ctrl

@@ -33,2 +33,4 @@ /**

doc.schema.allow( { name: '$text', inside: 'img' } );
doc.schema.objects.add( 'img' );
} );

@@ -35,0 +37,0 @@ } );

@@ -7,4 +7,5 @@ /*

import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import Input from '../src/input';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';

@@ -29,2 +30,4 @@ import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';

testUtils.createSinonSandbox();
before( () => {

@@ -70,18 +73,2 @@ listenter = Object.create( EmitterMixin );

it( 'has a buffer configured to default value of config.typing.undoStep', () => {
expect( editor.plugins.get( Input )._buffer ).to.have.property( 'limit', 20 );
} );
it( 'has a buffer configured to config.typing.undoStep', () => {
return VirtualTestEditor.create( {
plugins: [ Input ],
typing: {
undoStep: 5
}
} )
.then( editor => {
expect( editor.plugins.get( Input )._buffer ).to.have.property( 'limit', 5 );
} );
} );
describe( 'mutations handling', () => {

@@ -228,3 +215,3 @@ it( 'should handle text mutation', () => {

it( 'should use up to one insert and remove operations', () => {
it( 'should use up to one insert and remove operations (spellchecker)', () => {
// This test case emulates spellchecker correction.

@@ -235,4 +222,4 @@

sinon.spy( Batch.prototype, 'weakInsert' );
sinon.spy( Batch.prototype, 'remove' );
testUtils.sinon.spy( Batch.prototype, 'weakInsert' );
testUtils.sinon.spy( Batch.prototype, 'remove' );

@@ -252,2 +239,125 @@ view.fire( 'mutations',

} );
it( 'should place selection after when correcting to longer word (spellchecker)', () => {
// This test case emulates spellchecker correction.
editor.setData( '<p>Foo hous a</p>' );
const viewSelection = new ViewSelection();
viewSelection.collapse( viewRoot.getChild( 0 ).getChild( 0 ), 9 );
view.fire( 'mutations',
[ {
type: 'text',
oldText: 'Foo hous a',
newText: 'Foo house a',
node: viewRoot.getChild( 0 ).getChild( 0 )
} ],
viewSelection
);
expect( getModelData( model ) ).to.equal( '<paragraph>Foo house[] a</paragraph>' );
expect( getViewData( view ) ).to.equal( '<p>Foo house{} a</p>' );
} );
it( 'should place selection after when correcting to shorter word (spellchecker)', () => {
// This test case emulates spellchecker correction.
editor.setData( '<p>Bar athat foo</p>' );
const viewSelection = new ViewSelection();
viewSelection.collapse( viewRoot.getChild( 0 ).getChild( 0 ), 8 );
view.fire( 'mutations',
[ {
type: 'text',
oldText: 'Bar athat foo',
newText: 'Bar that foo',
node: viewRoot.getChild( 0 ).getChild( 0 )
} ],
viewSelection
);
expect( getModelData( model ) ).to.equal( '<paragraph>Bar that[] foo</paragraph>' );
expect( getViewData( view ) ).to.equal( '<p>Bar that{} foo</p>' );
} );
it( 'should place selection after when merging two words (spellchecker)', () => {
// This test case emulates spellchecker correction.
editor.setData( '<p>Foo hous e</p>' );
const viewSelection = new ViewSelection();
viewSelection.collapse( viewRoot.getChild( 0 ).getChild( 0 ), 9 );
view.fire( 'mutations',
[ {
type: 'text',
oldText: 'Foo hous e',
newText: 'Foo house',
node: viewRoot.getChild( 0 ).getChild( 0 )
} ],
viewSelection
);
expect( getModelData( model ) ).to.equal( '<paragraph>Foo house[]</paragraph>' );
expect( getViewData( view ) ).to.equal( '<p>Foo house{}</p>' );
} );
it( 'should replace last &nbsp; with space', () => {
model.enqueueChanges( () => {
model.selection.setRanges( [
ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 6, modelRoot.getChild( 0 ), 6 )
] );
} );
view.fire( 'mutations', [
{
type: 'text',
oldText: 'foobar',
newText: 'foobar\u00A0',
node: viewRoot.getChild( 0 ).getChild( 0 )
}
] );
expect( getModelData( model ) ).to.equal( '<paragraph>foobar []</paragraph>' );
expect( getViewData( view ) ).to.equal( '<p>foobar {}</p>' );
} );
it( 'should replace first &nbsp; with space', () => {
model.enqueueChanges( () => {
model.selection.setRanges( [
ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 0, modelRoot.getChild( 0 ), 0 )
] );
} );
view.fire( 'mutations', [
{
type: 'text',
oldText: 'foobar',
newText: '\u00A0foobar',
node: viewRoot.getChild( 0 ).getChild( 0 )
}
] );
expect( getModelData( model ) ).to.equal( '<paragraph> []foobar</paragraph>' );
expect( getViewData( view ) ).to.equal( '<p> {}foobar</p>' );
} );
it( 'should replace all &nbsp; with spaces', () => {
model.enqueueChanges( () => {
model.selection.setRanges( [
ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 6, modelRoot.getChild( 0 ), 6 )
] );
} );
view.fire( 'mutations', [
{
type: 'text',
oldText: 'foobar',
newText: 'foobar\u00A0\u00A0\u00A0baz',
node: viewRoot.getChild( 0 ).getChild( 0 )
}
] );
expect( getModelData( model ) ).to.equal( '<paragraph>foobar baz[]</paragraph>' );
expect( getViewData( view ) ).to.equal( '<p>foobar baz{}</p>' );
} );
} );

@@ -316,2 +426,14 @@

// #69
it( 'should do nothing on tab key', () => {
model.enqueueChanges( () => {
model.selection.setRanges( [
ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) ] );
} );
view.fire( 'keydown', { keyCode: 9 } ); // Tab
expect( getModelData( model ) ).to.equal( '<paragraph>fo[ob]ar</paragraph>' );
} );
it( 'should do nothing if selection is collapsed', () => {

@@ -323,17 +445,3 @@ view.fire( 'keydown', { ctrlKey: true, keyCode: getCode( 'c' ) } );

} );
describe( 'destroy', () => {
it( 'should destroy change buffer', () => {
const typing = new Input( new VirtualTestEditor() );
typing.init();
const destroy = typing._buffer.destroy = sinon.spy();
typing.destroy();
expect( destroy.calledOnce ).to.be.true;
expect( typing._buffer ).to.be.null;
} );
} );
} );

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc