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 #1173 from ckeditor/t/1170
Browse files Browse the repository at this point in the history
Fix: Prevent adding inline filler to non-editable content. Closes #1170.
  • Loading branch information
Piotr Jasiun committed Oct 30, 2017
2 parents d55dd3e + 8832628 commit 07a01b1
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/view/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,12 @@ export default class Renderer {
return false;
}

// Prevent adding inline filler inside elements with contenteditable=false.
// https://github.com/ckeditor/ckeditor5-engine/issues/1170
if ( !_isEditable( selectionParent ) ) {
return false;
}

// We have block filler, we do not need inline one.
if ( selectionOffset === selectionParent.getFillerOffset() ) {
return false;
Expand Down Expand Up @@ -708,3 +714,18 @@ export default class Renderer {
}

mix( Renderer, ObservableMixin );

// Checks if provided element is editable.
//
// @private
// @param {module:engine/view/element~Element} element
// @returns {Boolean}
function _isEditable( element ) {
if ( element.getAttribute( 'contenteditable' ) == 'false' ) {
return false;
}

const parent = element.findAncestor( element => element.hasAttribute( 'contenteditable' ) );

return !parent || parent.getAttribute( 'contenteditable' ) == 'true';
}
44 changes: 44 additions & 0 deletions tests/view/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,50 @@ describe( 'Renderer', () => {
expect( viewRoot ).to.be.ok;
} );

it( 'should not add filler when inside contenteditable=false parent', () => {
const { view: viewP, selection: newSelection } = parse(
'<container:p>foo<attribute:b contenteditable="false">[]</attribute:b>bar</container:p>' );

viewRoot.appendChildren( viewP );
selection.setTo( newSelection );

renderer.markToSync( 'children', viewRoot );
renderer.render();

expect( domRoot.childNodes.length ).to.equal( 1 );
expect( domRoot.childNodes[ 0 ].tagName.toLowerCase() ).to.equal( 'p' );

const domP = domRoot.childNodes[ 0 ];

expect( domP.childNodes.length ).to.equal( 3 );
expect( domP.childNodes[ 0 ].data ).to.equal( 'foo' );
expect( domP.childNodes[ 2 ].data ).to.equal( 'bar' );
expect( domP.childNodes[ 1 ].tagName.toLowerCase() ).to.equal( 'b' );
expect( domP.childNodes[ 1 ].childNodes.length ).to.equal( 0 );
} );

it( 'should not add filler when inside contenteditable=false ancestor', () => {
const { view: viewP, selection: newSelection } = parse(
'<container:p contenteditable="false">foo<attribute:b>[]</attribute:b>bar</container:p>' );

viewRoot.appendChildren( viewP );
selection.setTo( newSelection );

renderer.markToSync( 'children', viewRoot );
renderer.render();

expect( domRoot.childNodes.length ).to.equal( 1 );
expect( domRoot.childNodes[ 0 ].tagName.toLowerCase() ).to.equal( 'p' );

const domP = domRoot.childNodes[ 0 ];

expect( domP.childNodes.length ).to.equal( 3 );
expect( domP.childNodes[ 0 ].data ).to.equal( 'foo' );
expect( domP.childNodes[ 2 ].data ).to.equal( 'bar' );
expect( domP.childNodes[ 1 ].tagName.toLowerCase() ).to.equal( 'b' );
expect( domP.childNodes[ 1 ].childNodes.length ).to.equal( 0 );
} );

it( 'should add and remove inline filler in case <p>foo<b>[]</b>bar</p>', () => {
const domSelection = document.getSelection();

Expand Down

0 comments on commit 07a01b1

Please sign in to comment.