diff --git a/src/commands/mergecellcommand.js b/src/commands/mergecellcommand.js index f8449990..19f26e94 100644 --- a/src/commands/mergecellcommand.js +++ b/src/commands/mergecellcommand.js @@ -153,7 +153,10 @@ export default class MergeCellCommand extends Command { // @param {String} direction // @returns {module:engine/model/node~Node|null} function getHorizontalCell( tableCell, direction, tableUtils ) { + const tableRow = tableCell.parent; + const table = tableRow.parent; const horizontalCell = direction == 'right' ? tableCell.nextSibling : tableCell.previousSibling; + const headingColumns = table.getAttribute( 'headingColumns' ) || 0; if ( !horizontalCell ) { return; @@ -168,6 +171,15 @@ function getHorizontalCell( tableCell, direction, tableUtils ) { const { column: rightCellColumn } = tableUtils.getCellLocation( cellOnRight ); const leftCellSpan = parseInt( cellOnLeft.getAttribute( 'colspan' ) || 1 ); + const rightCellSpan = parseInt( cellOnRight.getAttribute( 'colspan' ) || 1 ); + + // We cannot merge cells if the result will extend over heading section. + const isMergeWithBodyCell = direction == 'right' && ( rightCellColumn + rightCellSpan > headingColumns ); + const isMergeWithHeadCell = direction == 'left' && ( leftCellColumn + leftCellSpan > headingColumns - 1 ); + + if ( headingColumns && ( isMergeWithBodyCell || isMergeWithHeadCell ) ) { + return; + } // The cell on the right must have index that is distant to the cell on the left by the left cell's width (colspan). const cellsAreTouching = leftCellColumn + leftCellSpan === rightCellColumn; diff --git a/tests/commands/mergecellcommand.js b/tests/commands/mergecellcommand.js index 694ff799..4c420bfa 100644 --- a/tests/commands/mergecellcommand.js +++ b/tests/commands/mergecellcommand.js @@ -93,6 +93,46 @@ describe( 'MergeCellCommand', () => { expect( command.isEnabled ).to.be.false; } ); + + it( 'should be false if mergeable cell is in other table section then current cell', () => { + setData( model, modelTable( [ + [ '00[]', '01' ] + ], { headingColumns: 1 } ) ); + + expect( command.isEnabled ).to.be.false; + } ); + + it( 'should be false if merged cell would cross heading section (mergeable cell with colspan)', () => { + setData( model, modelTable( [ + [ '00[]', { colspan: 2, contents: '01' }, '02', '03' ] + ], { headingColumns: 2 } ) ); + + expect( command.isEnabled ).to.be.false; + } ); + + it( 'should be true if merged cell would not cross heading section (mergeable cell with colspan)', () => { + setData( model, modelTable( [ + [ '00[]', { colspan: 2, contents: '01' }, '02', '03' ] + ], { headingColumns: 3 } ) ); + + expect( command.isEnabled ).to.be.true; + } ); + + it( 'should be false if merged cell would cross heading section (current cell with colspan)', () => { + setData( model, modelTable( [ + [ { colspan: 2, contents: '00[]' }, '01', '02', '03' ] + ], { headingColumns: 2 } ) ); + + expect( command.isEnabled ).to.be.false; + } ); + + it( 'should be true if merged cell would not cross heading section (current cell with colspan)', () => { + setData( model, modelTable( [ + [ { colspan: 2, contents: '00[]' }, '01', '02', '03' ] + ], { headingColumns: 3 } ) ); + + expect( command.isEnabled ).to.be.true; + } ); } ); describe( 'value', () => { @@ -273,6 +313,22 @@ describe( 'MergeCellCommand', () => { expect( command.isEnabled ).to.be.false; } ); + + it( 'should be false if mergeable cell is in other table section then current cell', () => { + setData( model, modelTable( [ + [ '00', '01[]' ], + ], { headingColumns: 1 } ) ); + + expect( command.isEnabled ).to.be.false; + } ); + + it( 'should be false if merged cell would cross heading section (mergeable cell with colspan)', () => { + setData( model, modelTable( [ + [ { colspan: 2, contents: '00' }, '02[]', '03' ] + ], { headingColumns: 2 } ) ); + + expect( command.isEnabled ).to.be.false; + } ); } ); describe( 'value', () => {