Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge cd364e1 into 139989c
Browse files Browse the repository at this point in the history
  • Loading branch information
panr committed Jan 27, 2020
2 parents 139989c + cd364e1 commit db29fcd
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 10 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@ckeditor/ckeditor5-list": "^16.0.0",
"@ckeditor/ckeditor5-paragraph": "^16.0.0",
"@ckeditor/ckeditor5-undo": "^16.0.0",
"@ckeditor/ckeditor5-code-block": "^16.0.0",
"eslint": "^5.5.0",
"eslint-config-ckeditor5": "^2.0.0",
"husky": "^1.3.1",
Expand Down
53 changes: 51 additions & 2 deletions src/texttransformation.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,44 @@ export default class TextTransformation extends Plugin {
include: DEFAULT_TRANSFORMATIONS
}
} );

this.editor = editor;
}

/**
* @inheritDoc
*/
init() {
const model = this.editor.model;
const modelDocument = model.document;
const modelSelection = modelDocument.selection;

/**
* Holds a set of active {@link module:typing/textwatcher~TextWatcher}
*
* @type {Set.<TextWatcher>}
* @private
*/
this._watchersStack = new Set();

this.on( 'change:isEnabled', () => {
this.isEnabled ? this._enableTransformationWatchers() : this._disableTransformationWatchers();
} );

this._enableTransformationWatchers();

this.listenTo( modelDocument, 'change:data', () => {
// Disable plugin when typing in code block.
this.isEnabled = !modelSelection.anchor.parent.is( 'codeBlock' );
} );
}

/**
* Create new set of TextWatchers listening to the editor for typing and selection events.
*
* @private
*/
_enableTransformationWatchers() {
const editor = this.editor;
const model = editor.model;
const input = editor.plugins.get( 'Input' );
Expand All @@ -110,7 +142,7 @@ export default class TextTransformation extends Plugin {

const watcher = new TextWatcher( editor.model, text => from.test( text ) );

watcher.on( 'matched:data', ( evt, data ) => {
const watcherCallback = ( evt, data ) => {
if ( !input.isInput( data.batch ) ) {
return;
}
Expand Down Expand Up @@ -142,9 +174,26 @@ export default class TextTransformation extends Plugin {
changeIndex += replaceWith.length;
}
} );
} );
};

this._watchersStack.add( watcher );

watcher.on( 'matched:data', watcherCallback );
}
}

/**
* Disable each running TextWatcher and clear the set of enabled watchers after all.
*
* @private
*/
_disableTransformationWatchers() {
this._watchersStack.forEach( watcher => {
watcher.stopListening();
} );

this._watchersStack.clear();
}
}

// Normalizes the configuration `from` parameter value.
Expand Down
5 changes: 2 additions & 3 deletions src/textwatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default class TextWatcher {
const model = this.model;
const document = model.document;

document.selection.on( 'change:range', ( evt, { directChange } ) => {
this.listenTo( document.selection, 'change:range', ( evt, { directChange } ) => {
// Indirect changes (i.e. when the user types or external changes are applied) are handled in the document's change event.
if ( !directChange ) {
return;
Expand All @@ -62,7 +62,7 @@ export default class TextWatcher {
this._evaluateTextBeforeSelection( 'selection' );
} );

document.on( 'change:data', ( evt, batch ) => {
this.listenTo( document, 'change:data', ( evt, batch ) => {
if ( batch.type == 'transparent' ) {
return;
}
Expand Down Expand Up @@ -128,4 +128,3 @@ export default class TextWatcher {
}

mix( TextWatcher, EmitterMixin );

68 changes: 63 additions & 5 deletions tests/texttransformation.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import TextTransformation from '../src/texttransformation';
import { getData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import CodeBlock from '@ckeditor/ckeditor5-code-block/src/codeblock';

describe( 'Text transformation feature', () => {
let editorElement, editor, model, doc;
Expand Down Expand Up @@ -40,6 +41,54 @@ describe( 'Text transformation feature', () => {
} );
} );

describe( 'plugin', () => {
let TextTransformationPlugin, enableWatchersSpy, disableWatchersSpy;

beforeEach( () => {
TextTransformationPlugin = new TextTransformation( editor );
enableWatchersSpy = sinon.spy( TextTransformationPlugin, '_enableTransformationWatchers' );
disableWatchersSpy = sinon.spy( TextTransformationPlugin, '_disableTransformationWatchers' );

TextTransformationPlugin.init();
} );

it( 'should be enabled after initialization', () => {
expect( TextTransformationPlugin.isEnabled ).to.be.true;
} );

it( 'should initialize watchers after initialization', () => {
sinon.assert.calledOnce( enableWatchersSpy );
} );

it( 'should initialize watchers again when is enabled', () => {
sinon.assert.calledOnce( enableWatchersSpy );

TextTransformationPlugin.isEnabled = false;
TextTransformationPlugin.isEnabled = true;

sinon.assert.calledTwice( enableWatchersSpy );
expect( TextTransformationPlugin._watchersStack.size ).to.be.at.least( 1 );
} );

it( 'should disable watchers when is disabled', () => {
TextTransformationPlugin.isEnabled = false;

sinon.assert.calledOnce( disableWatchersSpy );
} );

it( 'should have active watchers when is enabled', () => {
expect( TextTransformationPlugin.isEnabled ).to.be.true;
expect( TextTransformationPlugin._watchersStack.size ).to.be.at.least( 1 );
} );

it( 'should not have active watchers when is disabled', () => {
TextTransformationPlugin.isEnabled = false;

expect( TextTransformationPlugin.isEnabled ).to.be.false;
expect( TextTransformationPlugin._watchersStack.size ).to.be.equal( 0 );
} );
} );

describe( 'transformations', () => {
beforeEach( createEditorInstance );

Expand Down Expand Up @@ -155,6 +204,19 @@ describe( 'Text transformation feature', () => {
.to.equal( '<paragraph>"Foo <softBreak></softBreak>“Bar”</paragraph>' );
} );

it( 'should be disabled inside code blocks', () => {
setData( model, '<codeBlock language="plaintext">some [] code</codeBlock>' );

simulateTyping( '1/2' );

const plugin = editor.plugins.get( 'TextTransformation' );

expect( plugin.isEnabled ).to.be.false;
expect( plugin._watchersStack.size ).to.be.equal( 0 );
expect( getData( model, { withoutSelection: true } ) )
.to.equal( '<codeBlock language="plaintext">some 1/2 code</codeBlock>' );
} );

function testTransformation( transformFrom, transformTo, textInParagraph = 'A foo' ) {
it( `should transform "${ transformFrom }" to "${ transformTo }"`, () => {
setData( model, `<paragraph>${ textInParagraph }[]</paragraph>` );
Expand Down Expand Up @@ -355,18 +417,14 @@ describe( 'Text transformation feature', () => {
function createEditorInstance( additionalConfig = {} ) {
return ClassicTestEditor
.create( editorElement, Object.assign( {
plugins: [ Typing, Paragraph, Bold, TextTransformation ]
plugins: [ Typing, Paragraph, Bold, TextTransformation, CodeBlock ]
}, additionalConfig ) )
.then( newEditor => {
editor = newEditor;

model = editor.model;
doc = model.document;

model.schema.register( 'softBreak', {
allowWhere: '$text',
isInline: true
} );
editor.conversion.elementToElement( {
model: 'softBreak',
view: 'br'
Expand Down

0 comments on commit db29fcd

Please sign in to comment.