Skip to content

Commit

Permalink
Merge pull request #17197 from ckeditor/ck/10147-fix-inline-object-co…
Browse files Browse the repository at this point in the history
…ntent

Fix (engine): The content of an inline object should be handled as a flow root so whitespaces should be trimmed as the content of an inline object element is inside a block element. Closes #17199.
  • Loading branch information
niegowski authored Oct 9, 2024
2 parents 453f507 + d3feac0 commit 9c8f687
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 13 deletions.
5 changes: 4 additions & 1 deletion packages/ckeditor5-engine/src/view/domconverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export default class DomConverter {
this.document = document;
this.renderingMode = renderingMode;
this.blockFillerMode = blockFillerMode || ( renderingMode === 'editing' ? 'br' : 'nbsp' );
this.preElements = [ 'pre' ];
this.preElements = [ 'pre', 'textarea' ];
this.blockElements = [
'address', 'article', 'aside', 'blockquote', 'caption', 'center', 'dd', 'details', 'dir', 'div',
'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header',
Expand Down Expand Up @@ -1473,6 +1473,9 @@ export default class DomConverter {
// for inline objects can verify if the element is empty.
if ( this._isInlineObjectElement( viewElement ) ) {
inlineNodes.push( viewElement );

// Inline object content should be handled as a flow-root.
this._processDomInlineNodes( null, nestedInlineNodes, options );
} else {
// It's an inline element that is not an object (like <b>, <i>) or a block element.
for ( const inlineNode of nestedInlineNodes ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ describe( 'DomConverter – whitespace handling – integration', () => {
expect( editor.getData() ).to.equal( '<p>foo <img src="/assets/sample.png"> bar</p>' );
} );

it( 'white space around (and inside) inline object elements should not be trimmed', () => {
it( 'white space around inline object elements should not be trimmed', () => {
editor.model.schema.register( 'button', {
allowWhere: '$text',
isInline: true,
Expand All @@ -362,12 +362,53 @@ describe( 'DomConverter – whitespace handling – integration', () => {
editor.setData( '<p>foo <button> Button </button> bar</p>' );

expect( getData( editor.model, { withoutSelection: true } ) )
.to.equal( '<paragraph>foo <button> Button </button> bar</paragraph>' );
.to.equal( '<paragraph>foo <button>Button</button> bar</paragraph>' );

expect( editor.getData() ).to.equal( '<p>foo <button> Button </button> bar</p>' );
expect( editor.getData() ).to.equal( '<p>foo <button>Button</button> bar</p>' );
} );

it( 'white spaces around (and inside) successive inline object elements should not be trimmed', () => {
it( 'white spaces inside an inline object elements should be trimmed', () => {
editor.model.schema.register( 'button', {
allowWhere: '$text',
isInline: true,
allowChildren: [ '$text' ]
} );

editor.conversion.elementToElement( {
model: 'button',
view: 'button'
} );

editor.setData( '<p>foo <button>\n\t\t\t\t Some button \n\t\t</button> bar</p>' );

expect( getData( editor.model, { withoutSelection: true } ) )
.to.equal( '<paragraph>foo <button>Some button</button> bar</paragraph>' );

expect( editor.getData() ).to.equal( '<p>foo <button>Some button</button> bar</p>' );
} );

it( 'white spaces inside a textarea (as inline object element) should not be trimmed', () => {
editor.model.schema.register( 'textarea', {
allowWhere: '$text',
isInline: true,
allowChildren: [ '$text' ]
} );

editor.conversion.elementToElement( {
model: 'textarea',
view: 'textarea'
} );

editor.setData( '<p>foo <textarea>\n\t\t\t\t Some textarea \n\t\t</textarea> bar</p>' );

// Note that the first \n is trimmed by the DOMParser.
expect( getData( editor.model, { withoutSelection: true } ) )
.to.equal( '<paragraph>foo <textarea>\t\t\t\t Some textarea \n\t\t</textarea> bar</paragraph>' );

expect( editor.getData() ).to.equal( '<p>foo <textarea>\t\t\t\t Some textarea \n\t\t</textarea> bar</p>' );
} );

it( 'white spaces around successive inline object elements should not be trimmed', () => {
editor.model.schema.register( 'button', {
allowWhere: '$text',
isInline: true,
Expand All @@ -382,12 +423,12 @@ describe( 'DomConverter – whitespace handling – integration', () => {
editor.setData( '<p>foo <button> Button </button> <button> Another </button> bar</p>' );

expect( getData( editor.model, { withoutSelection: true } ) )
.to.equal( '<paragraph>foo <button> Button </button> <button> Another </button> bar</paragraph>' );
.to.equal( '<paragraph>foo <button>Button</button> <button>Another</button> bar</paragraph>' );

expect( editor.getData() ).to.equal( '<p>foo <button> Button </button> <button> Another </button> bar</p>' );
expect( editor.getData() ).to.equal( '<p>foo <button>Button</button> <button>Another</button> bar</p>' );
} );

it( 'white spaces around (and inside) nested inline object elements should not be trimmed', () => {
it( 'white spaces around nested inline object elements should not be trimmed', () => {
editor.model.schema.register( 'select', {
allowWhere: '$text',
isInline: true,
Expand Down Expand Up @@ -434,17 +475,29 @@ describe( 'DomConverter – whitespace handling – integration', () => {
.to.equal( '<paragraph>select ' +
'<select name="things">' +
'<optgroup label="FoosAndBars">' +
'<option value="foo"> Foo </option>' +
'<option value="bar"> Bar </option>' +
'<option value="foo">Foo</option>' +
'<option value="bar">Bar</option>' +
'</optgroup>' +
'<optgroup label="letters">' +
'<option value="a"> A </option>' +
'<option value="b"> B </option>' +
'<option value="a">A</option>' +
'<option value="b">B</option>' +
'</optgroup>' +
'</select>' +
' with some text</paragraph>' );

expect( editor.getData() ).to.equal( initialData );
expect( editor.getData() ).to.equal(
'<p>select <select name="things">' +
'<optgroup label="FoosAndBars">' +
'<option value="foo">Foo</option>' +
'<option value="bar">Bar</option>' +
'</optgroup>' +
'<optgroup label="letters">' +
'<option value="a">A</option>' +
'<option value="b">B</option>' +
'</optgroup>' +
'</select> with some text' +
'</p>'
);
} );

// All possible cases have been checked 👆. These are dummy tests only to verify this will work for all elements in the list.
Expand Down

0 comments on commit 9c8f687

Please sign in to comment.