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

Commit

Permalink
Merge pull request #77 from ckeditor/i/5671
Browse files Browse the repository at this point in the history
Fix: `BlockAutoformat` should not react to text typed after inline element. Closes ckeditor/ckeditor5#5671.
  • Loading branch information
Reinmar authored Nov 5, 2019
2 parents 98d30f3 + c049bf5 commit 241c294
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 5 deletions.
12 changes: 7 additions & 5 deletions src/blockautoformatediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,23 +88,25 @@ export default class BlockAutoformatEditing {
return;
}

const item = entry.position.textNode || entry.position.nodeAfter;
const blockToFormat = entry.position.parent;

if ( !item.parent.is( 'paragraph' ) ) {
// Block formatting should trigger only if the entire content of a paragraph is a single text node... (see ckeditor5#5671).
if ( !blockToFormat.is( 'paragraph' ) || blockToFormat.childCount !== 1 ) {
return;
}

const match = pattern.exec( item.data );
const match = pattern.exec( blockToFormat.getChild( 0 ).data );

// ...and this text node's data match the pattern.
if ( !match ) {
return;
}

// Use enqueueChange to create new batch to separate typing batch from the auto-format changes.
editor.model.enqueueChange( writer => {
// Matched range.
const start = writer.createPositionAt( item.parent, 0 );
const end = writer.createPositionAt( item.parent, match[ 0 ].length );
const start = writer.createPositionAt( blockToFormat, 0 );
const end = writer.createPositionAt( blockToFormat, match[ 0 ].length );
const range = new LiveRange( start, end );

const wasChanged = callback( { match } );
Expand Down
36 changes: 36 additions & 0 deletions tests/autoformat.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ describe( 'Autoformat', () => {

expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="bulleted">- []</listItem>' );
} );

it( 'should not replace asterisk character after <softBreak>', () => {
setData( model, '<paragraph>Foo<softBreak></softBreak>*[]</paragraph>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<paragraph>Foo<softBreak></softBreak>* []</paragraph>' );
} );
} );

describe( 'Numbered list', () => {
Expand Down Expand Up @@ -128,6 +137,15 @@ describe( 'Autoformat', () => {

expect( getData( model ) ).to.equal( '<paragraph>3. []</paragraph>' );
} );

it( 'should not replace digit character after <softBreak>', () => {
setData( model, '<paragraph>Foo<softBreak></softBreak>1.[]</paragraph>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<paragraph>Foo<softBreak></softBreak>1. []</paragraph>' );
} );
} );

describe( 'Heading', () => {
Expand Down Expand Up @@ -212,6 +230,15 @@ describe( 'Autoformat', () => {

expect( getData( model ) ).to.equal( '<paragraph># []</paragraph>' );
} );

it( 'should not replace hash character after <softBreak>', () => {
setData( model, '<paragraph>Foo<softBreak></softBreak>#[]</paragraph>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<paragraph>Foo<softBreak></softBreak># []</paragraph>' );
} );
} );

describe( 'Block quote', () => {
Expand Down Expand Up @@ -250,6 +277,15 @@ describe( 'Autoformat', () => {

expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="bulleted">1. > []</listItem>' );
} );

it( 'should not replace greater-than character after <softBreak>', () => {
setData( model, '<paragraph>Foo<softBreak></softBreak>>[]</paragraph>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<paragraph>Foo<softBreak></softBreak>> []</paragraph>' );
} );
} );

describe( 'Inline autoformat', () => {
Expand Down
57 changes: 57 additions & 0 deletions tests/blockautoformatediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,63 @@ describe( 'BlockAutoformatEditing', () => {
sinon.assert.notCalled( spy );
} );

it( 'should not call callback when after inline element', () => {
// Configure the schema.
model.schema.register( 'softBreak', {
allowWhere: '$text',
isInline: true
} );
editor.conversion.for( 'upcast' )
.elementToElement( {
model: 'softBreak',
view: 'br'
} );
editor.conversion.for( 'downcast' )
.elementToElement( {
model: 'softBreak',
view: ( modelElement, viewWriter ) => viewWriter.createEmptyElement( 'br' )
} );

const spy = testUtils.sinon.spy();
new BlockAutoformatEditing( editor, /^[*]\s/, spy ); // eslint-disable-line no-new

setData( model, '<paragraph>*<softBreak></softBreak>[]</paragraph>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

sinon.assert.notCalled( spy );
} );

it( 'should not call callback when after inline element (typing after softBreak in a "matching" paragraph)', () => {
// Configure the schema.
model.schema.register( 'softBreak', {
allowWhere: '$text',
isInline: true
} );
editor.conversion.for( 'upcast' )
.elementToElement( {
model: 'softBreak',
view: 'br'
} );
editor.conversion.for( 'downcast' )
.elementToElement( {
model: 'softBreak',
view: ( modelElement, viewWriter ) => viewWriter.createEmptyElement( 'br' )
} );

const spy = testUtils.sinon.spy();
new BlockAutoformatEditing( editor, /^[*]\s/, spy ); // eslint-disable-line no-new

setData( model, '<paragraph>* <softBreak></softBreak>[]</paragraph>' );

model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

sinon.assert.notCalled( spy );
} );

it( 'should stop if callback returned false', () => {
new BlockAutoformatEditing( editor, /^[*]\s$/, () => false ); // eslint-disable-line no-new

Expand Down

0 comments on commit 241c294

Please sign in to comment.