{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/insertcolumncommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/selectcolumncommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/mergecellcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/converters/table-layout-post-fixer.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/inserttablecommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/converters/table-heading-rows-refresh-post-fixer.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/setheadercolumncommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/removerowcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/converters/upcasttable.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/converters/downcast.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/mergecellscommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-select-all/src/selectallcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-select-all/src/selectallediting.js","webpack:///./node_modules/@ckeditor/ckeditor5-select-all/src/selectallui.js","webpack:///./node_modules/@ckeditor/ckeditor5-select-all/src/selectall.js","webpack:///./node_modules/@ckeditor/ckeditor5-select-all/src/index.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/converters/tableproperties.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/splitcellcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/selectrowcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/converters/table-cell-refresh-post-fixer.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/removecolumncommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/insertrowcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/commands/setheaderrowcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-table/src/converters/table-cell-paragraph-post-fixer.js","webpack:///./node_modules/@ckeditor/ckeditor5-select-all/theme/icons/select-all.svg"],"names":["InsertColumnCommand","editor","options","order","selection","this","model","document","tableParent","getFirstPosition","findAncestor","isEnabled","tableUtils","plugins","get","insertBefore","affectedTableCells","getSelectionAffectedTableCells","columnIndexes","getColumnIndexes","column","first","last","table","insertColumns","columns","at","Command","SelectColumnCommand","selectedCells","length","referenceCells","firstCell","lastCell","pop","startLocation","getCellLocation","endLocation","startColumn","Math","min","endColumn","max","rangesToSelect","TableWalker","cellInfo","push","createRangeOn","cell","change","writer","setSelection","MergeCellCommand","direction","isHorizontal","cellToMerge","_getMergeableCell","value","doc","tableCell","getTableCellsContainingSelection","isMergeNext","cellToExpand","cellToRemove","removedTableCellRow","parent","mergeTableCells","spanAttribute","cellSpan","parseInt","getAttribute","cellToMergeSpan","setAttribute","createRangeIn","removeEmptyRowsColumns","getHorizontalCell","getVerticalCell","span","tableRow","horizontalCell","nextSibling","previousSibling","hasHeadingColumns","cellOnLeft","cellOnRight","leftCellColumn","rightCellColumn","leftCellSpan","isCellOnLeftInHeadingColumn","isHeadingColumnCell","isCellOnRightInHeadingColumn","cellsAreTouching","undefined","rowIndex","getChildIndex","childCount","rowspan","headingRows","isMergeWithBodyCell","isMergeWithHeadCell","currentCellRowSpan","rowOfCellToMerge","tableMap","endRow","currentCellData","find","mergeColumn","cellToMergeData","row","cellHeight","isEmpty","remove","move","createPositionAt","getChild","is","injectTableLayoutPostFixer","registerPostFixer","tableLayoutPostFixer","changes","differ","getChanges","wasFixed","analyzedTables","Set","entry","name","type","position","nodeAfter","isTableAttributeEntry","range","start","has","fixTableCellsRowspan","fixTableRowsSizes","add","cellsToTrim","findCellsToTrim","data","updateNumericAttribute","rowsLengths","getRowsLengths","rowsToRemove","entries","size","reverse","splice","tableSize","isValid","every","maxColumns","reduce","prev","current","columnsToInsert","i","createEmptyTableCell","maxRows","isInHeader","rowLimit","newRowspan","lengths","Array","fill","includeAllSlots","isAttributeType","key","attributeKey","InsertTableCommand","schema","isAllowedInParent","checkSelectionOnObject","insertPosition","findOptimalInsertionPosition","createTable","insertContent","getNodeByPath","positionParent","validParent","root","checkChild","injectTableHeadingRowsRefreshPostFixer","tableHeadingRowsRefreshPostFixer","tablesToRefresh","element","values","refreshItem","SetHeaderColumnCommand","isInTable","forceValue","headingColumnsToSet","overlappingCells","getHorizontallyOverlappingCells","splitVertically","RemoveRowCommand","tableRowCount","getRows","lastRowIndex","selectedRowIndexes","getRowIndexes","areAllRowsSelected","removedRowIndexes","columnIndexToFocus","removeRows","rows","cellToFocus","getCellToFocus","removedRowIndex","columnToFocus","getChildren","upcastTable","dispatcher","on","evt","conversionApi","viewTable","viewItem","consumable","test","scanTable","headingColumns","attributes","createElement","safeInsert","modelCursor","consume","forEach","convertItem","insert","updateConversionResult","skipEmptyTableRow","index","stop","priority","ensureParagraphInTableCell","elementName","modelRange","insertElement","firstTheadElement","tableMeta","headRows","bodyRows","from","tableChild","trs","filter","el","tr","headingCols","scanRowForHeadingColumns","children","child","th","colspan","downcastInsertTable","item","tableWidget","asWidget","figureElement","createContainerElement","class","tableElement","toTableWidget","tableWalker","tableAttributes","viewRows","Map","tableSlot","trElement","createTr","set","createViewTableCellElement","viewPosition","mapper","toViewPosition","bindElements","downcastInsertRow","toViewElement","getViewTable","downcastInsertCell","downcastTableHeadingColumnsChange","oldColumns","attributeOldValue","newColumns","attributeNewValue","lastColumnToCheck","renameViewTableCellIfRequired","downcastRemoveRow","viewWriter","viewStart","getLastMatchingPosition","tableSection","removeRange","removed","getItems","unbindViewElement","removeTableSectionIfEmpty","convertParagraphInTableCell","modelElement","isSingleParagraphWithoutAttributes","style","isSingleParagraph","hasAnyAttribute","viewElement","setCustomProperty","toWidget","hasSelectionHandle","renameViewTableCell","desiredCellElementName","viewCell","editable","createEditableElement","getAttributes","renamedCell","toWidgetEditable","setHighlightHandling","descriptor","addClass","toArray","classes","removeClass","createPositionAfter","getCellElementName","cellElementName","cellElement","firstChild","innerParagraph","createEmptyElement","getOrCreateTableSection","getSectionName","offset","isColumnHeading","isRowHeading","sectionName","viewTableSection","getExistingTableSectionElement","createTableSection","tableChildElement","viewFigure","getAttributeKeys","MergeCellsCommand","selectedTableCells","getSelectedTableCells","isSelectionRectangular","TableUtils","firstTableCell","shift","getMergeDimensions","mergeWidth","mergeHeight","cellBeingMerged","targetCell","maxWidthOffset","maxHeightOffset","getMaxOffset","firstCellRow","firstCellColumn","currentMaxOffset","which","dimensionValue","SelectAllCommand","scopeElement","getLimitElement","containsEntireContent","isSelectAllScope","isLimit","SELECT_ALL_KEYSTROKE","parseKeystroke","SelectAllEditing","view","editing","viewDocument","commands","listenTo","eventInfo","domEventData","getCode","execute","preventDefault","Plugin","SelectAllUI","ui","componentFactory","locale","command","ButtonView","t","label","icon","selectAllIcon","keystroke","tooltip","bind","to","focus","SelectAll","upcastStyleToAttribute","conversion","modelAttribute","styleName","for","attributeToAttribute","styles","getNormalizedStyle","upcastBorderStyles","viewElementName","stylesToConsume","hasStyle","matcherPattern","shallow","downcastAttributeToStyle","modelAttributeValue","downcastTableAttribute","setStyle","removeStyle","SplitCellCommand","splitCellHorizontally","splitCellVertically","SelectRowCommand","rowIndexes","injectTableCellRefreshPostFixer","tableCellRefreshPostFixer","cellsToCheck","shouldRefresh","paragraph","RemoveColumnCommand","tableColumnCount","getColumns","getBoundaryCells","removedColumnIndexes","columnsToRemove","removeColumns","returnValue","isBefore","InsertRowCommand","insertAbove","insertRows","copyStructureFromAbove","SetHeaderRowCommand","_isInHeading","headingRowsToSet","currentHeadingRows","startRow","getVerticallyOverlappingCells","splitHorizontally","injectTableCellParagraphPostFixer","tableCellContentsPostFixer","fixTable","fixTableRow","fixTableCellContent","checkTableCellChange","textNodes","wrap","module","exports"],"mappings":"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","file":"js/chunk-vendors~2bd5423c.b5d66161.js","sourcesContent":["/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/insertcolumncommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport { getColumnIndexes, getSelectionAffectedTableCells } from '../utils/selection';\n\n/**\n * The insert column command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'insertTableColumnLeft'` and\n * `'insertTableColumnRight'` editor commands.\n *\n * To insert a column to the left of the selected cell, execute the following command:\n *\n *\t\teditor.execute( 'insertTableColumnLeft' );\n *\n * To insert a column to the right of the selected cell, execute the following command:\n *\n *\t\teditor.execute( 'insertTableColumnRight' );\n *\n * @extends module:core/command~Command\n */\nexport default class InsertColumnCommand extends Command {\n\t/**\n\t * Creates a new `InsertColumnCommand` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor An editor on which this command will be used.\n\t * @param {Object} options\n\t * @param {String} [options.order=\"right\"] The order of insertion relative to the column in which the caret is located.\n\t * Possible values: `\"left\"` and `\"right\"`.\n\t */\n\tconstructor( editor, options = {} ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The order of insertion relative to the column in which the caret is located.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} module:table/commands/insertcolumncommand~InsertColumnCommand#order\n\t\t */\n\t\tthis.order = options.order || 'right';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selection = this.editor.model.document.selection;\n\n\t\tconst tableParent = selection.getFirstPosition().findAncestor( 'table' );\n\n\t\tthis.isEnabled = !!tableParent;\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * Depending on the command's {@link #order} value, it inserts a column to the `'left'` or `'right'` of the column\n\t * in which the selection is set.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\t\tconst tableUtils = editor.plugins.get( 'TableUtils' );\n\t\tconst insertBefore = this.order === 'left';\n\n\t\tconst affectedTableCells = getSelectionAffectedTableCells( selection );\n\t\tconst columnIndexes = getColumnIndexes( affectedTableCells );\n\n\t\tconst column = insertBefore ? columnIndexes.first : columnIndexes.last;\n\t\tconst table = affectedTableCells[ 0 ].findAncestor( 'table' );\n\n\t\ttableUtils.insertColumns( table, { columns: 1, at: insertBefore ? column : column + 1 } );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/selectcolumncommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\n\nimport TableWalker from '../tablewalker';\nimport { getSelectionAffectedTableCells } from '../utils/selection';\n\n/**\n * The select column command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'selectTableColumn'` editor command.\n *\n * To select the columns containing the selected cells, execute the command:\n *\n *\t\teditor.execute( 'selectTableColumn' );\n *\n * @extends module:core/command~Command\n */\nexport default class SelectColumnCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selectedCells = getSelectionAffectedTableCells( this.editor.model.document.selection );\n\n\t\tthis.isEnabled = selectedCells.length > 0;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst referenceCells = getSelectionAffectedTableCells( model.document.selection );\n\t\tconst firstCell = referenceCells[ 0 ];\n\t\tconst lastCell = referenceCells.pop();\n\t\tconst table = firstCell.findAncestor( 'table' );\n\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\t\tconst startLocation = tableUtils.getCellLocation( firstCell );\n\t\tconst endLocation = tableUtils.getCellLocation( lastCell );\n\n\t\tconst startColumn = Math.min( startLocation.column, endLocation.column );\n\t\tconst endColumn = Math.max( startLocation.column, endLocation.column );\n\n\t\tconst rangesToSelect = [];\n\n\t\tfor ( const cellInfo of new TableWalker( table, { startColumn, endColumn } ) ) {\n\t\t\trangesToSelect.push( model.createRangeOn( cellInfo.cell ) );\n\t\t}\n\n\t\tmodel.change( writer => {\n\t\t\twriter.setSelection( rangesToSelect );\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/mergecellcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport TableWalker from '../tablewalker';\nimport { getTableCellsContainingSelection } from '../utils/selection';\nimport { isHeadingColumnCell } from '../utils/common';\nimport { removeEmptyRowsColumns } from '../utils/structure';\n\n/**\n * The merge cell command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'mergeTableCellRight'`, `'mergeTableCellLeft'`,\n * `'mergeTableCellUp'` and `'mergeTableCellDown'` editor commands.\n *\n * To merge a table cell at the current selection with another cell, execute the command corresponding with the preferred direction.\n *\n * For example, to merge with a cell to the right:\n *\n *\t\teditor.execute( 'mergeTableCellRight' );\n *\n * **Note**: If a table cell has a different [`rowspan`](https://www.w3.org/TR/html50/tabular-data.html#attr-tdth-rowspan)\n * (for `'mergeTableCellRight'` and `'mergeTableCellLeft'`) or [`colspan`](https://www.w3.org/TR/html50/tabular-data.html#attr-tdth-colspan)\n * (for `'mergeTableCellUp'` and `'mergeTableCellDown'`), the command will be disabled.\n *\n * @extends module:core/command~Command\n */\nexport default class MergeCellCommand extends Command {\n\t/**\n\t * Creates a new `MergeCellCommand` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor on which this command will be used.\n\t * @param {Object} options\n\t * @param {String} options.direction Indicates which cell to merge with the currently selected one.\n\t * Possible values are: `'left'`, `'right'`, `'up'` and `'down'`.\n\t */\n\tconstructor( editor, options ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The direction that indicates which cell will be merged with the currently selected one.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} #direction\n\t\t */\n\t\tthis.direction = options.direction;\n\n\t\t/**\n\t\t * Whether the merge is horizontal (left/right) or vertical (up/down).\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} #isHorizontal\n\t\t */\n\t\tthis.isHorizontal = this.direction == 'right' || this.direction == 'left';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst cellToMerge = this._getMergeableCell();\n\n\t\tthis.value = cellToMerge;\n\t\tthis.isEnabled = !!cellToMerge;\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * Depending on the command's {@link #direction} value, it will merge the cell that is to the `'left'`, `'right'`, `'up'` or `'down'`.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst tableCell = getTableCellsContainingSelection( doc.selection )[ 0 ];\n\n\t\tconst cellToMerge = this.value;\n\t\tconst direction = this.direction;\n\n\t\tmodel.change( writer => {\n\t\t\tconst isMergeNext = direction == 'right' || direction == 'down';\n\n\t\t\t// The merge mechanism is always the same so sort cells to be merged.\n\t\t\tconst cellToExpand = isMergeNext ? tableCell : cellToMerge;\n\t\t\tconst cellToRemove = isMergeNext ? cellToMerge : tableCell;\n\n\t\t\t// Cache the parent of cell to remove for later check.\n\t\t\tconst removedTableCellRow = cellToRemove.parent;\n\n\t\t\tmergeTableCells( cellToRemove, cellToExpand, writer );\n\n\t\t\tconst spanAttribute = this.isHorizontal ? 'colspan' : 'rowspan';\n\t\t\tconst cellSpan = parseInt( tableCell.getAttribute( spanAttribute ) || 1 );\n\t\t\tconst cellToMergeSpan = parseInt( cellToMerge.getAttribute( spanAttribute ) || 1 );\n\n\t\t\t// Update table cell span attribute and merge set selection on merged contents.\n\t\t\twriter.setAttribute( spanAttribute, cellSpan + cellToMergeSpan, cellToExpand );\n\t\t\twriter.setSelection( writer.createRangeIn( cellToExpand ) );\n\n\t\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\t\t\tconst table = removedTableCellRow.findAncestor( 'table' );\n\n\t\t\t// Remove empty rows and columns after merging.\n\t\t\tremoveEmptyRowsColumns( table, tableUtils );\n\t\t} );\n\t}\n\n\t/**\n\t * Returns a cell that can be merged with the current cell depending on the command's direction.\n\t *\n\t * @returns {module:engine/model/element~Element|undefined}\n\t * @private\n\t */\n\t_getMergeableCell() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst tableCell = getTableCellsContainingSelection( doc.selection )[ 0 ];\n\n\t\tif ( !tableCell ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\n\t\t// First get the cell on proper direction.\n\t\tconst cellToMerge = this.isHorizontal ?\n\t\t\tgetHorizontalCell( tableCell, this.direction, tableUtils ) :\n\t\t\tgetVerticalCell( tableCell, this.direction );\n\n\t\tif ( !cellToMerge ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If found check if the span perpendicular to merge direction is equal on both cells.\n\t\tconst spanAttribute = this.isHorizontal ? 'rowspan' : 'colspan';\n\t\tconst span = parseInt( tableCell.getAttribute( spanAttribute ) || 1 );\n\n\t\tconst cellToMergeSpan = parseInt( cellToMerge.getAttribute( spanAttribute ) || 1 );\n\n\t\tif ( cellToMergeSpan === span ) {\n\t\t\treturn cellToMerge;\n\t\t}\n\t}\n}\n\n// Returns the cell that can be merged horizontally.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @param {String} direction\n// @returns {module:engine/model/node~Node|null}\nfunction getHorizontalCell( tableCell, direction, tableUtils ) {\n\tconst tableRow = tableCell.parent;\n\tconst table = tableRow.parent;\n\tconst horizontalCell = direction == 'right' ? tableCell.nextSibling : tableCell.previousSibling;\n\tconst hasHeadingColumns = ( table.getAttribute( 'headingColumns' ) || 0 ) > 0;\n\n\tif ( !horizontalCell ) {\n\t\treturn;\n\t}\n\n\t// Sort cells:\n\tconst cellOnLeft = direction == 'right' ? tableCell : horizontalCell;\n\tconst cellOnRight = direction == 'right' ? horizontalCell : tableCell;\n\n\t// Get their column indexes:\n\tconst { column: leftCellColumn } = tableUtils.getCellLocation( cellOnLeft );\n\tconst { column: rightCellColumn } = tableUtils.getCellLocation( cellOnRight );\n\n\tconst leftCellSpan = parseInt( cellOnLeft.getAttribute( 'colspan' ) || 1 );\n\n\tconst isCellOnLeftInHeadingColumn = isHeadingColumnCell( tableUtils, cellOnLeft, table );\n\tconst isCellOnRightInHeadingColumn = isHeadingColumnCell( tableUtils, cellOnRight, table );\n\n\t// We cannot merge heading columns cells with regular cells.\n\tif ( hasHeadingColumns && isCellOnLeftInHeadingColumn != isCellOnRightInHeadingColumn ) {\n\t\treturn;\n\t}\n\n\t// The cell on the right must have index that is distant to the cell on the left by the left cell's width (colspan).\n\tconst cellsAreTouching = leftCellColumn + leftCellSpan === rightCellColumn;\n\n\t// If the right cell's column index is different it means that there are rowspanned cells between them.\n\treturn cellsAreTouching ? horizontalCell : undefined;\n}\n\n// Returns the cell that can be merged vertically.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @param {String} direction\n// @returns {module:engine/model/node~Node|null}\nfunction getVerticalCell( tableCell, direction ) {\n\tconst tableRow = tableCell.parent;\n\tconst table = tableRow.parent;\n\n\tconst rowIndex = table.getChildIndex( tableRow );\n\n\t// Don't search for mergeable cell if direction points out of the table.\n\tif ( ( direction == 'down' && rowIndex === table.childCount - 1 ) || ( direction == 'up' && rowIndex === 0 ) ) {\n\t\treturn;\n\t}\n\n\tconst rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );\n\tconst headingRows = table.getAttribute( 'headingRows' ) || 0;\n\n\tconst isMergeWithBodyCell = direction == 'down' && ( rowIndex + rowspan ) === headingRows;\n\tconst isMergeWithHeadCell = direction == 'up' && rowIndex === headingRows;\n\n\t// Don't search for mergeable cell if direction points out of the current table section.\n\tif ( headingRows && ( isMergeWithBodyCell || isMergeWithHeadCell ) ) {\n\t\treturn;\n\t}\n\n\tconst currentCellRowSpan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );\n\tconst rowOfCellToMerge = direction == 'down' ? rowIndex + currentCellRowSpan : rowIndex;\n\n\tconst tableMap = [ ...new TableWalker( table, { endRow: rowOfCellToMerge } ) ];\n\n\tconst currentCellData = tableMap.find( value => value.cell === tableCell );\n\tconst mergeColumn = currentCellData.column;\n\n\tconst cellToMergeData = tableMap.find( ( { row, cellHeight, column } ) => {\n\t\tif ( column !== mergeColumn ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( direction == 'down' ) {\n\t\t\t// If merging a cell below the mergeRow is already calculated.\n\t\t\treturn row === rowOfCellToMerge;\n\t\t} else {\n\t\t\t// If merging a cell above calculate if it spans to mergeRow.\n\t\t\treturn rowOfCellToMerge === row + cellHeight;\n\t\t}\n\t} );\n\n\treturn cellToMergeData && cellToMergeData.cell;\n}\n\n// Merges two table cells. It will ensure that after merging cells with an empty paragraph, the resulting table cell will only have one\n// paragraph. If one of the merged table cells is empty, the merged table cell will have the contents of the non-empty table cell.\n// If both are empty, the merged table cell will have only one empty paragraph.\n//\n// @param {module:engine/model/element~Element} cellToRemove\n// @param {module:engine/model/element~Element} cellToExpand\n// @param {module:engine/model/writer~Writer} writer\nfunction mergeTableCells( cellToRemove, cellToExpand, writer ) {\n\tif ( !isEmpty( cellToRemove ) ) {\n\t\tif ( isEmpty( cellToExpand ) ) {\n\t\t\twriter.remove( writer.createRangeIn( cellToExpand ) );\n\t\t}\n\n\t\twriter.move( writer.createRangeIn( cellToRemove ), writer.createPositionAt( cellToExpand, 'end' ) );\n\t}\n\n\t// Remove merged table cell.\n\twriter.remove( cellToRemove );\n}\n\n// Checks if the passed table cell contains an empty paragraph.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @returns {Boolean}\nfunction isEmpty( tableCell ) {\n\treturn tableCell.childCount == 1 && tableCell.getChild( 0 ).is( 'element', 'paragraph' ) && tableCell.getChild( 0 ).isEmpty;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/converters/table-layout-post-fixer\n */\n\nimport TableWalker from './../tablewalker';\nimport { createEmptyTableCell, updateNumericAttribute } from '../utils/common';\n\n/**\n * Injects a table layout post-fixer into the model.\n *\n * The role of the table layout post-fixer is to ensure that the table rows have the correct structure\n * after a {@link module:engine/model/model~Model#change `change()`} block was executed.\n *\n * The correct structure means that:\n *\n * * All table rows have the same size.\n * * None of the table cells extend vertically beyond their section (either header or body).\n * * A table cell has always at least one element as a child.\n *\n * If the table structure is not correct, the post-fixer will automatically correct it in two steps:\n *\n * 1. It will clip table cells that extend beyond their section.\n * 2. It will add empty table cells to the rows that are narrower than the widest table row.\n *\n * ## Clipping overlapping table cells\n *\n * Such situation may occur when pasting a table (or a part of a table) to the editor from external sources.\n *\n * For example, see the following table which has a cell (FOO) with the rowspan attribute (2):\n *\n *\t\t\n *\t\t\t\n *\t\t\t\tFOO\n *\t\t\t\tBAR\n *\t\t\t\n *\t\t\t\n *\t\t\t\tBAZ\n *\t\t\t\tXYZ\n *\t\t\t\n *\t\t
\n *\n * It will be rendered in the view as:\n *\n *\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
FOOBAR
BAZXYZ
\n *\n * In the above example the table will be rendered as a table with two rows: one in the header and second one in the body.\n * The table cell (FOO) cannot span over multiple rows as it would extend from the header to the body section.\n * The `rowspan` attribute must be changed to (1). The value (1) is the default value of the `rowspan` attribute\n * so the `rowspan` attribute will be removed from the model.\n *\n * The table cell with BAZ in the content will be in the first column of the table.\n *\n * ## Adding missing table cells\n *\n * The table post-fixer will insert empty table cells to equalize table row sizes (the number of columns).\n * The size of a table row is calculated by counting column spans of table cells, both horizontal (from the same row) and\n * vertical (from the rows above).\n *\n * In the above example, the table row in the body section of the table is narrower then the row from the header: it has two cells\n * with the default colspan (1). The header row has one cell with colspan (1) and the second with colspan (2).\n * The table cell (FOO) does not extend beyond the head section (and as such will be fixed in the first step of this post-fixer).\n * The post-fixer will add a missing table cell to the row in the body section of the table.\n *\n * The table from the above example will be fixed and rendered to the view as below:\n *\n *\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
FOOBAR
BAZXYZ
\n *\n * ## Collaboration and undo - Expectations vs post-fixer results\n *\n * The table post-fixer only ensures proper structure without a deeper analysis of the nature of the change. As such, it might lead\n * to a structure which was not intended by the user. In particular, it will also fix undo steps (in conjunction with collaboration)\n * in which the editor content might not return to the original state.\n *\n * This will usually happen when one or more users change the size of the table.\n *\n * As an example see the table below:\n *\n *\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
1112
2122
\n *\n * and the user actions:\n *\n * 1. Both users have a table with two rows and two columns.\n * 2. User A adds a column at the end of the table. This will insert empty table cells to two rows.\n * 3. User B adds a row at the end of the table. This will insert a row with two empty table cells.\n * 4. Both users will have a table as below:\n *\n *\n *\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
1112(empty, inserted by A)
2122(empty, inserted by A)
(empty, inserted by B)(empty, inserted by B)
\n *\n * The last row is shorter then others so the table post-fixer will add an empty row to the last row:\n *\n *\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
1112(empty, inserted by A)
2122(empty, inserted by A)
(empty, inserted by B)(empty, inserted by B)(empty, inserted by the post-fixer)
\n *\n * Unfortunately undo does not know the nature of the changes and depending on which user applies the post-fixer changes, undoing them\n * might lead to a broken table. If User B undoes inserting the column to the table, the undo engine will undo only the operations of\n * inserting empty cells to rows from the initial table state (row 1 and 2) but the cell in the post-fixed row will remain:\n *\n *\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
1112
2122
(empty, inserted by B)(empty, inserted by B)(empty, inserted by a post-fixer)
\n *\n * After undo, the table post-fixer will detect that two rows are shorter than others and will fix the table to:\n *\n *\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
1112(empty, inserted by a post-fixer after undo)
2122(empty, inserted by a post-fixer after undo)
(empty, inserted by B)(empty, inserted by B)(empty, inserted by a post-fixer)
\n * @param {module:engine/model/model~Model} model\n */\nexport default function injectTableLayoutPostFixer( model ) {\n\tmodel.document.registerPostFixer( writer => tableLayoutPostFixer( writer, model ) );\n}\n\n// The table layout post-fixer.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/model~Model} model\nfunction tableLayoutPostFixer( writer, model ) {\n\tconst changes = model.document.differ.getChanges();\n\n\tlet wasFixed = false;\n\n\t// Do not analyze the same table more then once - may happen for multiple changes in the same table.\n\tconst analyzedTables = new Set();\n\n\tfor ( const entry of changes ) {\n\t\tlet table;\n\n\t\tif ( entry.name == 'table' && entry.type == 'insert' ) {\n\t\t\ttable = entry.position.nodeAfter;\n\t\t}\n\n\t\t// Fix table on adding/removing table cells and rows.\n\t\tif ( entry.name == 'tableRow' || entry.name == 'tableCell' ) {\n\t\t\ttable = entry.position.findAncestor( 'table' );\n\t\t}\n\n\t\t// Fix table on any table's attribute change - including attributes of table cells.\n\t\tif ( isTableAttributeEntry( entry ) ) {\n\t\t\ttable = entry.range.start.findAncestor( 'table' );\n\t\t}\n\n\t\tif ( table && !analyzedTables.has( table ) ) {\n\t\t\t// Step 1: correct rowspans of table cells if necessary.\n\t\t\t// The wasFixed flag should be true if any of tables in batch was fixed - might be more then one.\n\t\t\twasFixed = fixTableCellsRowspan( table, writer ) || wasFixed;\n\t\t\t// Step 2: fix table rows sizes.\n\t\t\twasFixed = fixTableRowsSizes( table, writer ) || wasFixed;\n\n\t\t\tanalyzedTables.add( table );\n\t\t}\n\t}\n\n\treturn wasFixed;\n}\n\n// Fixes the invalid value of the `rowspan` attribute because a table cell cannot vertically extend beyond the table section it belongs to.\n//\n// @param {module:engine/model/element~Element} table\n// @param {module:engine/model/writer~Writer} writer\n// @returns {Boolean} Returns `true` if the table was fixed.\nfunction fixTableCellsRowspan( table, writer ) {\n\tlet wasFixed = false;\n\n\tconst cellsToTrim = findCellsToTrim( table );\n\n\tif ( cellsToTrim.length ) {\n\t\t// @if CK_DEBUG_TABLE // console.log( `Post-fixing table: trimming cells row-spans (${ cellsToTrim.length }).` );\n\n\t\twasFixed = true;\n\n\t\tfor ( const data of cellsToTrim ) {\n\t\t\tupdateNumericAttribute( 'rowspan', data.rowspan, data.cell, writer, 1 );\n\t\t}\n\t}\n\n\treturn wasFixed;\n}\n\n// Makes all table rows in a table the same size.\n//\n// @param {module:engine/model/element~Element} table\n// @param {module:engine/model/writer~Writer} writer\n// @returns {Boolean} Returns `true` if the table was fixed.\nfunction fixTableRowsSizes( table, writer ) {\n\tlet wasFixed = false;\n\n\tconst rowsLengths = getRowsLengths( table );\n\tconst rowsToRemove = [];\n\n\t// Find empty rows.\n\tfor ( const [ rowIndex, size ] of rowsLengths.entries() ) {\n\t\tif ( !size ) {\n\t\t\trowsToRemove.push( rowIndex );\n\t\t}\n\t}\n\n\t// Remove empty rows.\n\tif ( rowsToRemove.length ) {\n\t\t// @if CK_DEBUG_TABLE // console.log( `Post-fixing table: remove empty rows (${ rowsToRemove.length }).` );\n\n\t\twasFixed = true;\n\n\t\tfor ( const rowIndex of rowsToRemove.reverse() ) {\n\t\t\twriter.remove( table.getChild( rowIndex ) );\n\t\t\trowsLengths.splice( rowIndex, 1 );\n\t\t}\n\t}\n\n\t// Verify if all the rows have the same number of columns.\n\tconst tableSize = rowsLengths[ 0 ];\n\tconst isValid = rowsLengths.every( length => length === tableSize );\n\n\tif ( !isValid ) {\n\t\t// @if CK_DEBUG_TABLE // console.log( 'Post-fixing table: adding missing cells.' );\n\n\t\t// Find the maximum number of columns.\n\t\tconst maxColumns = rowsLengths.reduce( ( prev, current ) => current > prev ? current : prev, 0 );\n\n\t\tfor ( const [ rowIndex, size ] of rowsLengths.entries() ) {\n\t\t\tconst columnsToInsert = maxColumns - size;\n\n\t\t\tif ( columnsToInsert ) {\n\t\t\t\tfor ( let i = 0; i < columnsToInsert; i++ ) {\n\t\t\t\t\tcreateEmptyTableCell( writer, writer.createPositionAt( table.getChild( rowIndex ), 'end' ) );\n\t\t\t\t}\n\n\t\t\t\twasFixed = true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn wasFixed;\n}\n\n// Searches for table cells that extend beyond the table section to which they belong to. It will return an array of objects\n// that stores table cells to be trimmed and the correct value of the `rowspan` attribute to set.\n//\n// @param {module:engine/model/element~Element} table\n// @returns {Array.<{{cell, rowspan}}>}\nfunction findCellsToTrim( table ) {\n\tconst headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );\n\tconst maxRows = table.childCount;\n\n\tconst cellsToTrim = [];\n\n\tfor ( const { row, cell, cellHeight } of new TableWalker( table ) ) {\n\t\t// Skip cells that do not expand over its row.\n\t\tif ( cellHeight < 2 ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst isInHeader = row < headingRows;\n\n\t\t// Row limit is either end of header section or whole table as table body is after the header.\n\t\tconst rowLimit = isInHeader ? headingRows : maxRows;\n\n\t\t// If table cell expands over its limit reduce it height to proper value.\n\t\tif ( row + cellHeight > rowLimit ) {\n\t\t\tconst newRowspan = rowLimit - row;\n\n\t\t\tcellsToTrim.push( { cell, rowspan: newRowspan } );\n\t\t}\n\t}\n\n\treturn cellsToTrim;\n}\n\n// Returns an array with lengths of rows assigned to the corresponding row index.\n//\n// @param {module:engine/model/element~Element} table\n// @returns {Array.}\nfunction getRowsLengths( table ) {\n\t// TableWalker will not provide items for the empty rows, we need to pre-fill this array.\n\tconst lengths = new Array( table.childCount ).fill( 0 );\n\n\tfor ( const { row } of new TableWalker( table, { includeAllSlots: true } ) ) {\n\t\tlengths[ row ]++;\n\t}\n\n\treturn lengths;\n}\n\n// Checks if the differ entry for an attribute change is one of the table's attributes.\n//\n// @param entry\n// @returns {Boolean}\nfunction isTableAttributeEntry( entry ) {\n\tconst isAttributeType = entry.type === 'attribute';\n\tconst key = entry.attributeKey;\n\n\treturn isAttributeType && ( key === 'headingRows' || key === 'colspan' || key === 'rowspan' );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/inserttablecommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport { findOptimalInsertionPosition, checkSelectionOnObject } from 'ckeditor5/src/widget';\n\n/**\n * The insert table command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'insertTable'` editor command.\n *\n * To insert a table at the current selection, execute the command and specify the dimensions:\n *\n *\t\teditor.execute( 'insertTable', { rows: 20, columns: 5 } );\n *\n * @extends module:core/command~Command\n */\nexport default class InsertTableCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\tconst schema = model.schema;\n\n\t\tthis.isEnabled = isAllowedInParent( selection, schema ) &&\n\t\t\t!checkSelectionOnObject( selection, schema );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * Inserts a table with the given number of rows and columns into the editor.\n\t *\n\t * @param {Object} options\n\t * @param {Number} [options.rows=2] The number of rows to create in the inserted table.\n\t * @param {Number} [options.columns=2] The number of columns to create in the inserted table.\n\t * @param {Number} [options.headingRows=0] The number of heading rows.\n\t * @param {Number} [options.headingColumns=0] The number of heading columns.\n\t * @fires execute\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\n\t\tconst insertPosition = findOptimalInsertionPosition( selection, model );\n\n\t\tmodel.change( writer => {\n\t\t\tconst table = tableUtils.createTable( writer, options );\n\n\t\t\tmodel.insertContent( table, insertPosition );\n\n\t\t\twriter.setSelection( writer.createPositionAt( table.getNodeByPath( [ 0, 0, 0 ] ), 0 ) );\n\t\t} );\n\t}\n}\n\n// Checks if the table is allowed in the parent.\n//\n// @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n// @param {module:engine/model/schema~Schema} schema\n// @returns {Boolean}\nfunction isAllowedInParent( selection, schema ) {\n\tconst positionParent = selection.getFirstPosition().parent;\n\tconst validParent = positionParent === positionParent.root ? positionParent : positionParent.parent;\n\n\treturn schema.checkChild( validParent, 'table' );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/converters/table-heading-rows-refresh-post-fixer\n */\n\n/**\n * Injects a table post-fixer into the model which marks the table in the differ to have it re-rendered.\n *\n * Table heading rows are represented in the model by a `headingRows` attribute. However, in the view, it's represented as separate\n * sections of the table (`` or ``) and changing `headingRows` attribute requires moving table rows between two sections.\n * This causes problems with structural changes in a table (like adding and removing rows) thus atomic converters cannot be used.\n *\n * When table `headingRows` attribute changes, the entire table is re-rendered.\n *\n * @param {module:engine/model/model~Model} model\n */\nexport default function injectTableHeadingRowsRefreshPostFixer( model ) {\n\tmodel.document.registerPostFixer( () => tableHeadingRowsRefreshPostFixer( model ) );\n}\n\nfunction tableHeadingRowsRefreshPostFixer( model ) {\n\tconst differ = model.document.differ;\n\n\t// Stores tables to be refreshed so the table will be refreshed once for multiple changes.\n\tconst tablesToRefresh = new Set();\n\n\tfor ( const change of differ.getChanges() ) {\n\t\tif ( change.type != 'attribute' ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst element = change.range.start.nodeAfter;\n\n\t\tif ( element && element.is( 'element', 'table' ) && change.attributeKey == 'headingRows' ) {\n\t\t\ttablesToRefresh.add( element );\n\t\t}\n\t}\n\n\tif ( tablesToRefresh.size ) {\n\t\t// @if CK_DEBUG_TABLE // console.log( `Post-fixing table: refreshing heading rows (${ tablesToRefresh.size }).` );\n\n\t\tfor ( const table of tablesToRefresh.values() ) {\n\t\t\t// Should be handled by a `triggerBy` configuration. See: https://github.com/ckeditor/ckeditor5/issues/8138.\n\t\t\tdiffer.refreshItem( table );\n\t\t}\n\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/setheadercolumncommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\n\nimport {\n\tisHeadingColumnCell,\n\tupdateNumericAttribute\n} from '../utils/common';\nimport { getColumnIndexes, getSelectionAffectedTableCells } from '../utils/selection';\nimport { getHorizontallyOverlappingCells, splitVertically } from '../utils/structure';\n\n/**\n * The header column command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'setTableColumnHeader'` editor command.\n *\n * You can make the column containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element)\n * by executing:\n *\n *\t\teditor.execute( 'setTableColumnHeader' );\n *\n * **Note:** All preceding columns will also become headers. If the current column is already a header, executing this command\n * will make it a regular column back again (including the following columns).\n *\n * @extends module:core/command~Command\n */\nexport default class SetHeaderColumnCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst selectedCells = getSelectionAffectedTableCells( model.document.selection );\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\t\tconst isInTable = selectedCells.length > 0;\n\n\t\tthis.isEnabled = isInTable;\n\n\t\t/**\n\t\t * Flag indicating whether the command is active. The command is active when the\n\t\t * {@link module:engine/model/selection~Selection} is in a header column.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #value\n\t\t */\n\t\tthis.value = isInTable && selectedCells.every( cell => isHeadingColumnCell( tableUtils, cell ) );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * When the selection is in a non-header column, the command will set the `headingColumns` table attribute to cover that column.\n\t *\n\t * When the selection is already in a header column, it will set `headingColumns` so the heading section will end before that column.\n\t *\n\t * @fires execute\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.forceValue] If set, the command will set (`true`) or unset (`false`) the header columns according to\n\t * the `forceValue` parameter instead of the current model state.\n\t */\n\texecute( options = {} ) {\n\t\tif ( options.forceValue === this.value ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst model = this.editor.model;\n\t\tconst selectedCells = getSelectionAffectedTableCells( model.document.selection );\n\t\tconst table = selectedCells[ 0 ].findAncestor( 'table' );\n\n\t\tconst { first, last } = getColumnIndexes( selectedCells );\n\t\tconst headingColumnsToSet = this.value ? first : last + 1;\n\n\t\tmodel.change( writer => {\n\t\t\tif ( headingColumnsToSet ) {\n\t\t\t\t// Changing heading columns requires to check if any of a heading cell is overlapping horizontally the table head.\n\t\t\t\t// Any table cell that has a colspan attribute > 1 will not exceed the table head so we need to fix it in columns before.\n\t\t\t\tconst overlappingCells = getHorizontallyOverlappingCells( table, headingColumnsToSet );\n\n\t\t\t\tfor ( const { cell, column } of overlappingCells ) {\n\t\t\t\t\tsplitVertically( cell, column, headingColumnsToSet, writer );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tupdateNumericAttribute( 'headingColumns', headingColumnsToSet, table, writer, 0 );\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/removerowcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\n\nimport { getRowIndexes, getSelectionAffectedTableCells } from '../utils/selection';\n\n/**\n * The remove row command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'removeTableRow'` editor command.\n *\n * To remove the row containing the selected cell, execute the command:\n *\n *\t\teditor.execute( 'removeTableRow' );\n *\n * @extends module:core/command~Command\n */\nexport default class RemoveRowCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selectedCells = getSelectionAffectedTableCells( this.editor.model.document.selection );\n\t\tconst firstCell = selectedCells[ 0 ];\n\n\t\tif ( firstCell ) {\n\t\t\tconst table = firstCell.findAncestor( 'table' );\n\t\t\tconst tableRowCount = this.editor.plugins.get( 'TableUtils' ).getRows( table );\n\t\t\tconst lastRowIndex = tableRowCount - 1;\n\n\t\t\tconst selectedRowIndexes = getRowIndexes( selectedCells );\n\n\t\t\tconst areAllRowsSelected = selectedRowIndexes.first === 0 && selectedRowIndexes.last === lastRowIndex;\n\n\t\t\t// Disallow selecting whole table -> delete whole table should be used instead.\n\t\t\tthis.isEnabled = !areAllRowsSelected;\n\t\t} else {\n\t\t\tthis.isEnabled = false;\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst referenceCells = getSelectionAffectedTableCells( model.document.selection );\n\t\tconst removedRowIndexes = getRowIndexes( referenceCells );\n\n\t\tconst firstCell = referenceCells[ 0 ];\n\t\tconst table = firstCell.findAncestor( 'table' );\n\n\t\tconst columnIndexToFocus = this.editor.plugins.get( 'TableUtils' ).getCellLocation( firstCell ).column;\n\n\t\tmodel.change( writer => {\n\t\t\tconst rowsToRemove = removedRowIndexes.last - removedRowIndexes.first + 1;\n\n\t\t\tthis.editor.plugins.get( 'TableUtils' ).removeRows( table, {\n\t\t\t\tat: removedRowIndexes.first,\n\t\t\t\trows: rowsToRemove\n\t\t\t} );\n\n\t\t\tconst cellToFocus = getCellToFocus( table, removedRowIndexes.first, columnIndexToFocus );\n\n\t\t\twriter.setSelection( writer.createPositionAt( cellToFocus, 0 ) );\n\t\t} );\n\t}\n}\n\n// Returns a cell that should be focused before removing the row, belonging to the same column as the currently focused cell.\n// * If the row was not the last one, the cell to focus will be in the row that followed it (before removal).\n// * If the row was the last one, the cell to focus will be in the row that preceded it (before removal).\nfunction getCellToFocus( table, removedRowIndex, columnToFocus ) {\n\tconst row = table.getChild( removedRowIndex ) || table.getChild( table.childCount - 1 );\n\n\t// Default to first table cell.\n\tlet cellToFocus = row.getChild( 0 );\n\tlet column = 0;\n\n\tfor ( const tableCell of row.getChildren() ) {\n\t\tif ( column > columnToFocus ) {\n\t\t\treturn cellToFocus;\n\t\t}\n\n\t\tcellToFocus = tableCell;\n\t\tcolumn += parseInt( tableCell.getAttribute( 'colspan' ) || 1 );\n\t}\n\n\treturn cellToFocus;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/converters/upcasttable\n */\n\nimport { createEmptyTableCell } from '../utils/common';\n\n/**\n * View table element to model table element conversion helper.\n *\n * This conversion helper converts the table element as well as table rows.\n *\n * @returns {Function} Conversion helper.\n */\nexport default function upcastTable() {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'element:table', ( evt, data, conversionApi ) => {\n\t\t\tconst viewTable = data.viewItem;\n\n\t\t\t// When element was already consumed then skip it.\n\t\t\tif ( !conversionApi.consumable.test( viewTable, { name: true } ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst { rows, headingRows, headingColumns } = scanTable( viewTable );\n\n\t\t\t// Only set attributes if values is greater then 0.\n\t\t\tconst attributes = {};\n\n\t\t\tif ( headingColumns ) {\n\t\t\t\tattributes.headingColumns = headingColumns;\n\t\t\t}\n\n\t\t\tif ( headingRows ) {\n\t\t\t\tattributes.headingRows = headingRows;\n\t\t\t}\n\n\t\t\tconst table = conversionApi.writer.createElement( 'table', attributes );\n\n\t\t\tif ( !conversionApi.safeInsert( table, data.modelCursor ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconversionApi.consumable.consume( viewTable, { name: true } );\n\n\t\t\t// Upcast table rows in proper order (heading rows first).\n\t\t\trows.forEach( row => conversionApi.convertItem( row, conversionApi.writer.createPositionAt( table, 'end' ) ) );\n\n\t\t\t// Create one row and one table cell for empty table.\n\t\t\tif ( table.isEmpty ) {\n\t\t\t\tconst row = conversionApi.writer.createElement( 'tableRow' );\n\t\t\t\tconversionApi.writer.insert( row, conversionApi.writer.createPositionAt( table, 'end' ) );\n\n\t\t\t\tcreateEmptyTableCell( conversionApi.writer, conversionApi.writer.createPositionAt( row, 'end' ) );\n\t\t\t}\n\n\t\t\tconversionApi.updateConversionResult( table, data );\n\t\t} );\n\t};\n}\n\n/**\n * A conversion helper that skips empty elements from upcasting at the beginning of the table.\n *\n * An empty row is considered a table model error but when handling clipboard data there could be rows that contain only row-spanned cells\n * and empty TR-s are used to maintain the table structure (also {@link module:table/tablewalker~TableWalker} assumes that there are only\n * rows that have related `tableRow` elements).\n *\n * *Note:* Only the first empty rows are removed because they have no meaning and it solves the issue\n * of an improper table with all empty rows.\n *\n * @returns {Function} Conversion helper.\n */\nexport function skipEmptyTableRow() {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'element:tr', ( evt, data ) => {\n\t\t\tif ( data.viewItem.isEmpty && data.modelCursor.index == 0 ) {\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\t};\n}\n\n/**\n * A converter that ensures an empty paragraph is inserted in a table cell if no other content was converted.\n *\n * @returns {Function} Conversion helper.\n */\nexport function ensureParagraphInTableCell( elementName ) {\n\treturn dispatcher => {\n\t\tdispatcher.on( `element:${ elementName }`, ( evt, data, conversionApi ) => {\n\t\t\t// The default converter will create a model range on converted table cell.\n\t\t\tif ( !data.modelRange ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Ensure a paragraph in the model for empty table cells for converted table cells.\n\t\t\tif ( data.viewItem.isEmpty ) {\n\t\t\t\tconst tableCell = data.modelRange.start.nodeAfter;\n\t\t\t\tconst modelCursor = conversionApi.writer.createPositionAt( tableCell, 0 );\n\n\t\t\t\tconversionApi.writer.insertElement( 'paragraph', modelCursor );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\t};\n}\n\n// Scans table rows and extracts required metadata from the table:\n//\n// headingRows - The number of rows that go as table headers.\n// headingColumns - The maximum number of row headings.\n// rows - Sorted `` elements as they should go into the model - ie. if `` is inserted after `` in the view.\n//\n// @param {module:engine/view/element~Element} viewTable\n// @returns {{headingRows, headingColumns, rows}}\nfunction scanTable( viewTable ) {\n\tconst tableMeta = {\n\t\theadingRows: 0,\n\t\theadingColumns: 0\n\t};\n\n\t// The `` and `` sections in the DOM do not have to be in order `` -> `` and there might be more than one\n\t// of them.\n\t// As the model does not have these sections, rows from different sections must be sorted.\n\t// For example, below is a valid HTML table:\n\t//\n\t//\t\t\n\t//\t\t\t\n\t//\t\t\t\n\t//\t\t\t\n\t//\t\t
2
1
3
\n\t//\n\t// But browsers will render rows in order as: 1 as the heading and 2 and 3 as the body.\n\tconst headRows = [];\n\tconst bodyRows = [];\n\n\t// Currently the editor does not support more then one section.\n\t// Only the first from the view will be used as a heading row and the others will be converted to body rows.\n\tlet firstTheadElement;\n\n\tfor ( const tableChild of Array.from( viewTable.getChildren() ) ) {\n\t\t// Only ``, `` & `` from allowed table children can have ``s.\n\t\t// The else is for future purposes (mainly ``).\n\t\tif ( tableChild.name === 'tbody' || tableChild.name === 'thead' || tableChild.name === 'tfoot' ) {\n\t\t\t// Save the first `` in the table as table header - all other ones will be converted to table body rows.\n\t\t\tif ( tableChild.name === 'thead' && !firstTheadElement ) {\n\t\t\t\tfirstTheadElement = tableChild;\n\t\t\t}\n\n\t\t\t// There might be some extra empty text nodes between the ``s.\n\t\t\t// Make sure further code operates on `tr`s only. (#145)\n\t\t\tconst trs = Array.from( tableChild.getChildren() ).filter( el => el.is( 'element', 'tr' ) );\n\n\t\t\tfor ( const tr of trs ) {\n\t\t\t\t// This is a child of a first element.\n\t\t\t\tif ( tr.parent.name === 'thead' && tr.parent === firstTheadElement ) {\n\t\t\t\t\ttableMeta.headingRows++;\n\t\t\t\t\theadRows.push( tr );\n\t\t\t\t} else {\n\t\t\t\t\tbodyRows.push( tr );\n\t\t\t\t\t// For other rows check how many column headings this row has.\n\n\t\t\t\t\tconst headingCols = scanRowForHeadingColumns( tr, tableMeta, firstTheadElement );\n\n\t\t\t\t\tif ( headingCols > tableMeta.headingColumns ) {\n\t\t\t\t\t\ttableMeta.headingColumns = headingCols;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\ttableMeta.rows = [ ...headRows, ...bodyRows ];\n\n\treturn tableMeta;\n}\n\n// Scans a `` element and its children for metadata:\n// - For heading row:\n// - Adds this row to either the heading or the body rows.\n// - Updates the number of heading rows.\n// - For body rows:\n// - Calculates the number of column headings.\n//\n// @param {module:engine/view/element~Element} tr\n// @returns {Number}\nfunction scanRowForHeadingColumns( tr ) {\n\tlet headingColumns = 0;\n\tlet index = 0;\n\n\t// Filter out empty text nodes from tr children.\n\tconst children = Array.from( tr.getChildren() )\n\t\t.filter( child => child.name === 'th' || child.name === 'td' );\n\n\t// Count starting adjacent elements of a .\n\twhile ( index < children.length && children[ index ].name === 'th' ) {\n\t\tconst th = children[ index ];\n\n\t\t// Adjust columns calculation by the number of spanned columns.\n\t\tconst colspan = parseInt( th.getAttribute( 'colspan' ) || 1 );\n\n\t\theadingColumns = headingColumns + colspan;\n\t\tindex++;\n\t}\n\n\treturn headingColumns;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/converters/downcast\n */\n\nimport TableWalker from './../tablewalker';\nimport { setHighlightHandling, toWidget, toWidgetEditable } from 'ckeditor5/src/widget';\nimport { toArray } from 'ckeditor5/src/utils';\n\n/**\n * Model table element to view table element conversion helper.\n *\n * This conversion helper creates the whole table element with child elements.\n *\n * @param {Object} options\n * @param {Boolean} options.asWidget If set to `true`, the downcast conversion will produce a widget.\n * @returns {Function} Conversion helper.\n */\nexport function downcastInsertTable( options = {} ) {\n\treturn dispatcher => dispatcher.on( 'insert:table', ( evt, data, conversionApi ) => {\n\t\tconst table = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( table, 'insert' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Consume attributes if present to not fire attribute change downcast\n\t\tconversionApi.consumable.consume( table, 'attribute:headingRows:table' );\n\t\tconversionApi.consumable.consume( table, 'attribute:headingColumns:table' );\n\n\t\tconst asWidget = options && options.asWidget;\n\n\t\tconst figureElement = conversionApi.writer.createContainerElement( 'figure', { class: 'table' } );\n\t\tconst tableElement = conversionApi.writer.createContainerElement( 'table' );\n\t\tconversionApi.writer.insert( conversionApi.writer.createPositionAt( figureElement, 0 ), tableElement );\n\n\t\tlet tableWidget;\n\n\t\tif ( asWidget ) {\n\t\t\ttableWidget = toTableWidget( figureElement, conversionApi.writer );\n\t\t}\n\n\t\tconst tableWalker = new TableWalker( table );\n\n\t\tconst tableAttributes = {\n\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t};\n\n\t\t// Cache for created table rows.\n\t\tconst viewRows = new Map();\n\n\t\tfor ( const tableSlot of tableWalker ) {\n\t\t\tconst { row, cell } = tableSlot;\n\n\t\t\tconst tableRow = table.getChild( row );\n\t\t\tconst trElement = viewRows.get( row ) || createTr( tableElement, tableRow, row, tableAttributes, conversionApi );\n\t\t\tviewRows.set( row, trElement );\n\n\t\t\t// Consume table cell - it will be always consumed as we convert whole table at once.\n\t\t\tconversionApi.consumable.consume( cell, 'insert' );\n\n\t\t\tconst insertPosition = conversionApi.writer.createPositionAt( trElement, 'end' );\n\n\t\t\tcreateViewTableCellElement( tableSlot, tableAttributes, insertPosition, conversionApi, options );\n\t\t}\n\n\t\t// Insert empty TR elements if there are any rows without anchored cells. Since the model is always normalized\n\t\t// this can happen only in the document fragment that only part of the table is down-casted.\n\t\tfor ( const tableRow of table.getChildren() ) {\n\t\t\tconst rowIndex = tableRow.index;\n\n\t\t\tif ( !viewRows.has( rowIndex ) ) {\n\t\t\t\tviewRows.set( rowIndex, createTr( tableElement, tableRow, rowIndex, tableAttributes, conversionApi ) );\n\t\t\t}\n\t\t}\n\n\t\tconst viewPosition = conversionApi.mapper.toViewPosition( data.range.start );\n\n\t\tconversionApi.mapper.bindElements( table, asWidget ? tableWidget : figureElement );\n\t\tconversionApi.writer.insert( viewPosition, asWidget ? tableWidget : figureElement );\n\t} );\n}\n\n/**\n * Model row element to view `` element conversion helper.\n *\n * This conversion helper creates the whole `` element with child elements.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastInsertRow() {\n\treturn dispatcher => dispatcher.on( 'insert:tableRow', ( evt, data, conversionApi ) => {\n\t\tconst tableRow = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( tableRow, 'insert' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst table = tableRow.parent;\n\n\t\tconst figureElement = conversionApi.mapper.toViewElement( table );\n\t\tconst tableElement = getViewTable( figureElement );\n\n\t\tconst row = table.getChildIndex( tableRow );\n\n\t\tconst tableWalker = new TableWalker( table, { row } );\n\n\t\tconst tableAttributes = {\n\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t};\n\n\t\t// Cache for created table rows.\n\t\tconst viewRows = new Map();\n\n\t\tfor ( const tableSlot of tableWalker ) {\n\t\t\tconst trElement = viewRows.get( row ) || createTr( tableElement, tableRow, row, tableAttributes, conversionApi );\n\t\t\tviewRows.set( row, trElement );\n\n\t\t\t// Consume table cell - it will be always consumed as we convert whole row at once.\n\t\t\tconversionApi.consumable.consume( tableSlot.cell, 'insert' );\n\n\t\t\tconst insertPosition = conversionApi.writer.createPositionAt( trElement, 'end' );\n\n\t\t\tcreateViewTableCellElement( tableSlot, tableAttributes, insertPosition, conversionApi, { asWidget: true } );\n\t\t}\n\t} );\n}\n\n/**\n * Model table cell element to view `` or `` element conversion helper.\n *\n * This conversion helper will create proper `` elements for table cells that are in the heading section (heading row or column)\n * and `` otherwise.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastInsertCell() {\n\treturn dispatcher => dispatcher.on( 'insert:tableCell', ( evt, data, conversionApi ) => {\n\t\tconst tableCell = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( tableCell, 'insert' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\t\tconst rowIndex = table.getChildIndex( tableRow );\n\n\t\tconst tableWalker = new TableWalker( table, { row: rowIndex } );\n\n\t\tconst tableAttributes = {\n\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t};\n\n\t\t// We need to iterate over a table in order to get proper row & column values from a walker\n\t\tfor ( const tableSlot of tableWalker ) {\n\t\t\tif ( tableSlot.cell === tableCell ) {\n\t\t\t\tconst trElement = conversionApi.mapper.toViewElement( tableRow );\n\t\t\t\tconst insertPosition = conversionApi.writer.createPositionAt( trElement, tableRow.getChildIndex( tableCell ) );\n\n\t\t\t\tcreateViewTableCellElement( tableSlot, tableAttributes, insertPosition, conversionApi, { asWidget: true } );\n\n\t\t\t\t// No need to iterate further.\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t} );\n}\n\n/**\n * Conversion helper that acts on heading column table attribute change.\n *\n * Depending on changed attributes this converter will rename `` elements or vice versa depending on the cell column index.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastTableHeadingColumnsChange() {\n\treturn dispatcher => dispatcher.on( 'attribute:headingColumns:table', ( evt, data, conversionApi ) => {\n\t\tconst table = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst tableAttributes = {\n\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t};\n\n\t\tconst oldColumns = data.attributeOldValue;\n\t\tconst newColumns = data.attributeNewValue;\n\n\t\tconst lastColumnToCheck = ( oldColumns > newColumns ? oldColumns : newColumns ) - 1;\n\n\t\tfor ( const tableSlot of new TableWalker( table, { endColumn: lastColumnToCheck } ) ) {\n\t\t\trenameViewTableCellIfRequired( tableSlot, tableAttributes, conversionApi );\n\t\t}\n\t} );\n}\n\n/**\n * Conversion helper that acts on a removed row.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastRemoveRow() {\n\treturn dispatcher => dispatcher.on( 'remove:tableRow', ( evt, data, conversionApi ) => {\n\t\t// Prevent default remove converter.\n\t\tevt.stop();\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst mapper = conversionApi.mapper;\n\n\t\tconst viewStart = mapper.toViewPosition( data.position ).getLastMatchingPosition( value => !value.item.is( 'element', 'tr' ) );\n\t\tconst viewItem = viewStart.nodeAfter;\n\t\tconst tableSection = viewItem.parent;\n\t\tconst viewTable = tableSection.parent;\n\n\t\t// Remove associated from the view.\n\t\tconst removeRange = viewWriter.createRangeOn( viewItem );\n\t\tconst removed = viewWriter.remove( removeRange );\n\n\t\tfor ( const child of viewWriter.createRangeIn( removed ).getItems() ) {\n\t\t\tmapper.unbindViewElement( child );\n\t\t}\n\n\t\t// Cleanup: Ensure that thead & tbody sections are removed if left empty after removing rows. See #6437, #6391.\n\t\tremoveTableSectionIfEmpty( 'thead', viewTable, conversionApi );\n\t\tremoveTableSectionIfEmpty( 'tbody', viewTable, conversionApi );\n\t}, { priority: 'higher' } );\n}\n\n/**\n * Overrides paragraph inside table cell conversion.\n *\n * This converter:\n * * should be used to override default paragraph conversion in the editing view.\n * * It will only convert placed directly inside .\n * * For a single paragraph without attributes it returns `` to simulate data table.\n * * For all other cases it returns `

` element.\n *\n * @param {module:engine/model/element~Element} modelElement\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n * @returns {module:engine/view/containerelement~ContainerElement|undefined}\n */\nexport function convertParagraphInTableCell( modelElement, conversionApi ) {\n\tconst { writer } = conversionApi;\n\n\tif ( !modelElement.parent.is( 'element', 'tableCell' ) ) {\n\t\treturn;\n\t}\n\n\tif ( isSingleParagraphWithoutAttributes( modelElement ) ) {\n\t\t// Use display:inline-block to force Chrome/Safari to limit text mutations to this element.\n\t\t// See #6062.\n\t\treturn writer.createContainerElement( 'span', { style: 'display:inline-block' } );\n\t} else {\n\t\treturn writer.createContainerElement( 'p' );\n\t}\n}\n\n/**\n * Checks if given model `` is an only child of a parent (``) and if it has any attribute set.\n *\n * The paragraph should be converted in the editing view to:\n *\n * * If returned `true` - to a ``\n * * If returned `false` - to a `

`\n *\n * @param {module:engine/model/element~Element} modelElement\n * @returns {Boolean}\n */\nexport function isSingleParagraphWithoutAttributes( modelElement ) {\n\tconst tableCell = modelElement.parent;\n\n\tconst isSingleParagraph = tableCell.childCount === 1;\n\n\treturn isSingleParagraph && !hasAnyAttribute( modelElement );\n}\n\n// Converts a given {@link module:engine/view/element~Element} to a table widget:\n// * Adds a {@link module:engine/view/element~Element#_setCustomProperty custom property} allowing to recognize the table widget element.\n// * Calls the {@link module:widget/utils~toWidget} function with the proper element's label creator.\n//\n// @param {module:engine/view/element~Element} viewElement\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer An instance of the view writer.\n// @param {String} label The element's label. It will be concatenated with the table `alt` attribute if one is present.\n// @returns {module:engine/view/element~Element}\nfunction toTableWidget( viewElement, writer ) {\n\twriter.setCustomProperty( 'table', true, viewElement );\n\n\treturn toWidget( viewElement, writer, { hasSelectionHandle: true } );\n}\n\n// Renames an existing table cell in the view to a given element name.\n//\n// **Note** This method will not do anything if a view table cell has not been converted yet.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @param {String} desiredCellElementName\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction renameViewTableCell( tableCell, desiredCellElementName, conversionApi ) {\n\tconst viewWriter = conversionApi.writer;\n\tconst viewCell = conversionApi.mapper.toViewElement( tableCell );\n\n\tconst editable = viewWriter.createEditableElement( desiredCellElementName, viewCell.getAttributes() );\n\tconst renamedCell = toWidgetEditable( editable, viewWriter );\n\n\tsetHighlightHandling(\n\t\trenamedCell,\n\t\tviewWriter,\n\t\t( element, descriptor, writer ) => writer.addClass( toArray( descriptor.classes ), element ),\n\t\t( element, descriptor, writer ) => writer.removeClass( toArray( descriptor.classes ), element )\n\t);\n\n\tviewWriter.insert( viewWriter.createPositionAfter( viewCell ), renamedCell );\n\tviewWriter.move( viewWriter.createRangeIn( viewCell ), viewWriter.createPositionAt( renamedCell, 0 ) );\n\tviewWriter.remove( viewWriter.createRangeOn( viewCell ) );\n\n\tconversionApi.mapper.unbindViewElement( viewCell );\n\tconversionApi.mapper.bindElements( tableCell, renamedCell );\n}\n\n// Renames a table cell element in the view according to its location in the table.\n//\n// @param {module:table/tablewalker~TableSlot} tableSlot\n// @param {{headingColumns, headingRows}} tableAttributes\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction renameViewTableCellIfRequired( tableSlot, tableAttributes, conversionApi ) {\n\tconst { cell } = tableSlot;\n\n\t// Check whether current columnIndex is overlapped by table cells from previous rows.\n\tconst desiredCellElementName = getCellElementName( tableSlot, tableAttributes );\n\n\tconst viewCell = conversionApi.mapper.toViewElement( cell );\n\n\t// If in single change we're converting attribute changes and inserting cell the table cell might not be inserted into view\n\t// because of child conversion is done after parent.\n\tif ( viewCell && viewCell.name !== desiredCellElementName ) {\n\t\trenameViewTableCell( cell, desiredCellElementName, conversionApi );\n\t}\n}\n\n// Creates a table cell element in the view.\n//\n// @param {module:table/tablewalker~TableSlot} tableSlot\n// @param {module:engine/view/position~Position} insertPosition\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction createViewTableCellElement( tableSlot, tableAttributes, insertPosition, conversionApi, options ) {\n\tconst asWidget = options && options.asWidget;\n\tconst cellElementName = getCellElementName( tableSlot, tableAttributes );\n\n\tconst cellElement = asWidget ?\n\t\ttoWidgetEditable( conversionApi.writer.createEditableElement( cellElementName ), conversionApi.writer ) :\n\t\tconversionApi.writer.createContainerElement( cellElementName );\n\n\tif ( asWidget ) {\n\t\tsetHighlightHandling(\n\t\t\tcellElement,\n\t\t\tconversionApi.writer,\n\t\t\t( element, descriptor, writer ) => writer.addClass( toArray( descriptor.classes ), element ),\n\t\t\t( element, descriptor, writer ) => writer.removeClass( toArray( descriptor.classes ), element )\n\t\t);\n\t}\n\n\tconst tableCell = tableSlot.cell;\n\n\tconst firstChild = tableCell.getChild( 0 );\n\tconst isSingleParagraph = tableCell.childCount === 1 && firstChild.name === 'paragraph';\n\n\tconversionApi.writer.insert( insertPosition, cellElement );\n\n\tconversionApi.mapper.bindElements( tableCell, cellElement );\n\n\t// Additional requirement for data pipeline to have backward compatible data tables.\n\tif ( !asWidget && isSingleParagraph && !hasAnyAttribute( firstChild ) ) {\n\t\tconst innerParagraph = tableCell.getChild( 0 );\n\n\t\tconversionApi.consumable.consume( innerParagraph, 'insert' );\n\n\t\tconversionApi.mapper.bindElements( innerParagraph, cellElement );\n\t}\n}\n\n// Creates a `` view element.\n//\n// @param {module:engine/view/element~Element} tableElement\n// @param {module:engine/model/element~Element} tableRow\n// @param {Number} rowIndex\n// @param {{headingColumns, headingRows}} tableAttributes\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @returns {module:engine/view/element~Element}\nfunction createTr( tableElement, tableRow, rowIndex, tableAttributes, conversionApi ) {\n\t// Will always consume since we're converting element from a parent .\n\tconversionApi.consumable.consume( tableRow, 'insert' );\n\n\tconst trElement = tableRow.isEmpty ?\n\t\tconversionApi.writer.createEmptyElement( 'tr' ) :\n\t\tconversionApi.writer.createContainerElement( 'tr' );\n\n\tconversionApi.mapper.bindElements( tableRow, trElement );\n\n\tconst headingRows = tableAttributes.headingRows;\n\tconst tableSection = getOrCreateTableSection( getSectionName( rowIndex, tableAttributes ), tableElement, conversionApi );\n\n\tconst offset = headingRows > 0 && rowIndex >= headingRows ? rowIndex - headingRows : rowIndex;\n\tconst position = conversionApi.writer.createPositionAt( tableSection, offset );\n\n\tconversionApi.writer.insert( position, trElement );\n\n\treturn trElement;\n}\n\n// Returns `th` for heading cells and `td` for other cells for the current table walker value.\n//\n// @param {module:table/tablewalker~TableSlot} tableSlot\n// @param {{headingColumns, headingRows}} tableAttributes\n// @returns {String}\nfunction getCellElementName( tableSlot, tableAttributes ) {\n\tconst { row, column } = tableSlot;\n\tconst { headingColumns, headingRows } = tableAttributes;\n\n\t// Column heading are all tableCells in the first `columnHeading` rows.\n\tconst isColumnHeading = headingRows && headingRows > row;\n\n\t// So a whole row gets ` or `` element with caching.\n//\n// @param {String} sectionName\n// @param {module:engine/view/element~Element} viewTable\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @param {Object} cachedTableSection An object that stores cached elements.\n// @returns {module:engine/view/containerelement~ContainerElement}\nfunction getOrCreateTableSection( sectionName, viewTable, conversionApi ) {\n\tconst viewTableSection = getExistingTableSectionElement( sectionName, viewTable );\n\n\treturn viewTableSection ? viewTableSection : createTableSection( sectionName, viewTable, conversionApi );\n}\n\n// Finds an existing `` or `` element or returns undefined.\n//\n// @param {String} sectionName\n// @param {module:engine/view/element~Element} tableElement\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction getExistingTableSectionElement( sectionName, tableElement ) {\n\tfor ( const tableSection of tableElement.getChildren() ) {\n\t\tif ( tableSection.name == sectionName ) {\n\t\t\treturn tableSection;\n\t\t}\n\t}\n}\n\n// Creates a table section at the end of the table.\n//\n// @param {String} sectionName\n// @param {module:engine/view/element~Element} tableElement\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @returns {module:engine/view/containerelement~ContainerElement}\nfunction createTableSection( sectionName, tableElement, conversionApi ) {\n\tconst tableChildElement = conversionApi.writer.createContainerElement( sectionName );\n\n\tconst insertPosition = conversionApi.writer.createPositionAt( tableElement, sectionName == 'tbody' ? 'end' : 0 );\n\n\tconversionApi.writer.insert( insertPosition, tableChildElement );\n\n\treturn tableChildElement;\n}\n\n// Removes an existing `` or `` element if it is empty.\n//\n// @param {String} sectionName\n// @param {module:engine/view/element~Element} tableElement\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction removeTableSectionIfEmpty( sectionName, tableElement, conversionApi ) {\n\tconst tableSection = getExistingTableSectionElement( sectionName, tableElement );\n\n\tif ( tableSection && tableSection.childCount === 0 ) {\n\t\tconversionApi.writer.remove( conversionApi.writer.createRangeOn( tableSection ) );\n\t}\n}\n\n// Finds a '
element.\n\tif ( isColumnHeading ) {\n\t\treturn 'th';\n\t}\n\n\t// Row heading are tableCells which columnIndex is lower then headingColumns.\n\tconst isRowHeading = headingColumns && headingColumns > column;\n\n\treturn isRowHeading ? 'th' : 'td';\n}\n\n// Returns the table section name for the current table walker value.\n//\n// @param {Number} row\n// @param {{headingColumns, headingRows}} tableAttributes\n// @returns {String}\nfunction getSectionName( row, tableAttributes ) {\n\treturn row < tableAttributes.headingRows ? 'thead' : 'tbody';\n}\n\n// Creates or returns an existing `
' element inside the `
` widget.\n//\n// @param {module:engine/view/element~Element} viewFigure\nfunction getViewTable( viewFigure ) {\n\tfor ( const child of viewFigure.getChildren() ) {\n\t\tif ( child.name === 'table' ) {\n\t\t\treturn child;\n\t\t}\n\t}\n}\n\n// Checks if an element has any attributes set.\n//\n// @param {module:engine/model/element~Element element\n// @returns {Boolean}\nfunction hasAnyAttribute( element ) {\n\treturn !![ ...element.getAttributeKeys() ].length;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/mergecellscommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport TableUtils from '../tableutils';\nimport { getSelectedTableCells, isSelectionRectangular } from '../utils/selection';\nimport { updateNumericAttribute } from '../utils/common';\nimport { removeEmptyRowsColumns } from '../utils/structure';\n\n/**\n * The merge cells command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'mergeTableCells'` editor command.\n *\n * For example, to merge selected table cells:\n *\n *\t\teditor.execute( 'mergeTableCells' );\n *\n * @extends module:core/command~Command\n */\nexport default class MergeCellsCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selectedTableCells = getSelectedTableCells( this.editor.model.document.selection );\n\t\tthis.isEnabled = isSelectionRectangular( selectedTableCells, this.editor.plugins.get( TableUtils ) );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst tableUtils = this.editor.plugins.get( TableUtils );\n\n\t\tmodel.change( writer => {\n\t\t\tconst selectedTableCells = getSelectedTableCells( model.document.selection );\n\n\t\t\t// All cells will be merged into the first one.\n\t\t\tconst firstTableCell = selectedTableCells.shift();\n\n\t\t\t// Update target cell dimensions.\n\t\t\tconst { mergeWidth, mergeHeight } = getMergeDimensions( firstTableCell, selectedTableCells, tableUtils );\n\t\t\tupdateNumericAttribute( 'colspan', mergeWidth, firstTableCell, writer );\n\t\t\tupdateNumericAttribute( 'rowspan', mergeHeight, firstTableCell, writer );\n\n\t\t\tfor ( const tableCell of selectedTableCells ) {\n\t\t\t\tmergeTableCells( tableCell, firstTableCell, writer );\n\t\t\t}\n\n\t\t\tconst table = firstTableCell.findAncestor( 'table' );\n\n\t\t\t// Remove rows and columns that become empty (have no anchored cells).\n\t\t\tremoveEmptyRowsColumns( table, tableUtils );\n\n\t\t\twriter.setSelection( firstTableCell, 'in' );\n\t\t} );\n\t}\n}\n\n// Merges two table cells. It will ensure that after merging cells with empty paragraphs the resulting table cell will only have one\n// paragraph. If one of the merged table cells is empty, the merged table cell will have contents of the non-empty table cell.\n// If both are empty, the merged table cell will have only one empty paragraph.\n//\n// @param {module:engine/model/element~Element} cellBeingMerged\n// @param {module:engine/model/element~Element} targetCell\n// @param {module:engine/model/writer~Writer} writer\nfunction mergeTableCells( cellBeingMerged, targetCell, writer ) {\n\tif ( !isEmpty( cellBeingMerged ) ) {\n\t\tif ( isEmpty( targetCell ) ) {\n\t\t\twriter.remove( writer.createRangeIn( targetCell ) );\n\t\t}\n\n\t\twriter.move( writer.createRangeIn( cellBeingMerged ), writer.createPositionAt( targetCell, 'end' ) );\n\t}\n\n\t// Remove merged table cell.\n\twriter.remove( cellBeingMerged );\n}\n\n// Checks if the passed table cell contains an empty paragraph.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @returns {Boolean}\nfunction isEmpty( tableCell ) {\n\treturn tableCell.childCount == 1 && tableCell.getChild( 0 ).is( 'element', 'paragraph' ) && tableCell.getChild( 0 ).isEmpty;\n}\n\nfunction getMergeDimensions( firstTableCell, selectedTableCells, tableUtils ) {\n\tlet maxWidthOffset = 0;\n\tlet maxHeightOffset = 0;\n\n\tfor ( const tableCell of selectedTableCells ) {\n\t\tconst { row, column } = tableUtils.getCellLocation( tableCell );\n\n\t\tmaxWidthOffset = getMaxOffset( tableCell, column, maxWidthOffset, 'colspan' );\n\t\tmaxHeightOffset = getMaxOffset( tableCell, row, maxHeightOffset, 'rowspan' );\n\t}\n\n\t// Update table cell span attribute and merge set selection on a merged contents.\n\tconst { row: firstCellRow, column: firstCellColumn } = tableUtils.getCellLocation( firstTableCell );\n\n\tconst mergeWidth = maxWidthOffset - firstCellColumn;\n\tconst mergeHeight = maxHeightOffset - firstCellRow;\n\n\treturn { mergeWidth, mergeHeight };\n}\n\nfunction getMaxOffset( tableCell, start, currentMaxOffset, which ) {\n\tconst dimensionValue = parseInt( tableCell.getAttribute( which ) || 1 );\n\n\treturn Math.max( currentMaxOffset, start + dimensionValue );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module select-all/selectallcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\n/**\n * The select all command.\n *\n * It is used by the {@link module:select-all/selectallediting~SelectAllEditing select all editing feature} to handle\n * the Ctrl/⌘+A keystroke.\n *\n * Executing this command changes the {@glink framework/guides/architecture/editing-engine#model model}\n * selection so it contains the entire content of the editable root of the editor the selection is\n * {@link module:engine/model/selection~Selection#anchor anchored} in.\n *\n * If the selection was anchored in a {@glink framework/guides/tutorials/implementing-a-block-widget nested editable}\n * (e.g. a caption of an image), the new selection will contain its entire content. Successive executions of this command\n * will expand the selection to encompass more and more content up to the entire editable root of the editor.\n *\n * @extends module:core/command~Command\n */\nexport default class SelectAllCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\tlet scopeElement = model.schema.getLimitElement( selection );\n\n\t\t// If an entire scope is selected, or the selection's ancestor is not a scope yet,\n\t\t// browse through ancestors to find the enclosing parent scope.\n\t\tif ( selection.containsEntireContent( scopeElement ) || !isSelectAllScope( model.schema, scopeElement ) ) {\n\t\t\tdo {\n\t\t\t\tscopeElement = scopeElement.parent;\n\n\t\t\t\t// Do nothing, if the entire `root` is already selected.\n\t\t\t\tif ( !scopeElement ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} while ( !isSelectAllScope( model.schema, scopeElement ) );\n\t\t}\n\n\t\tmodel.change( writer => {\n\t\t\twriter.setSelection( scopeElement, 'in' );\n\t\t} );\n\t}\n}\n\n// Checks whether the element is a valid select-all scope.\n// Returns true, if the element is a {@link module:engine/model/schema~Schema#isLimit limit},\n// and can contain any text or paragraph.\n//\n// @param {module:engine/model/schema~Schema} schema The schema to check against.\n// @param {module:engine/model/element~Element} element\n// @return {Boolean}\nfunction isSelectAllScope( schema, element ) {\n\treturn schema.isLimit( element ) && ( schema.checkChild( element, '$text' ) || schema.checkChild( element, 'paragraph' ) );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module select-all/selectallediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport { getCode, parseKeystroke } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport SelectAllCommand from './selectallcommand';\n\nconst SELECT_ALL_KEYSTROKE = parseKeystroke( 'Ctrl+A' );\n\n/**\n * The select all editing feature.\n *\n * It registers the `'selectAll'` {@link module:select-all/selectallcommand~SelectAllCommand command}\n * and the Ctrl/⌘+A keystroke listener which executes it.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class SelectAllEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'SelectAllEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\n\t\teditor.commands.add( 'selectAll', new SelectAllCommand( editor ) );\n\n\t\tthis.listenTo( viewDocument, 'keydown', ( eventInfo, domEventData ) => {\n\t\t\tif ( getCode( domEventData ) === SELECT_ALL_KEYSTROKE ) {\n\t\t\t\teditor.execute( 'selectAll' );\n\t\t\t\tdomEventData.preventDefault();\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module select-all/selectallui\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport selectAllIcon from '../theme/icons/select-all.svg';\n\n/**\n * The select all UI feature.\n *\n * It registers the `'selectAll'` UI button in the editor's\n * {@link module:ui/componentfactory~ComponentFactory component factory}. When clicked, the button\n * executes the {@link module:select-all/selectallcommand~SelectAllCommand select all command}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class SelectAllUI extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'SelectAllUI';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\teditor.ui.componentFactory.add( 'selectAll', locale => {\n\t\t\tconst command = editor.commands.get( 'selectAll' );\n\t\t\tconst view = new ButtonView( locale );\n\t\t\tconst t = locale.t;\n\n\t\t\tview.set( {\n\t\t\t\tlabel: t( 'Select all' ),\n\t\t\t\ticon: selectAllIcon,\n\t\t\t\tkeystroke: 'Ctrl+A',\n\t\t\t\ttooltip: true\n\t\t\t} );\n\n\t\t\tview.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );\n\n\t\t\t// Execute the command.\n\t\t\tthis.listenTo( view, 'execute', () => {\n\t\t\t\teditor.execute( 'selectAll' );\n\t\t\t\teditor.editing.view.focus();\n\t\t\t} );\n\n\t\t\treturn view;\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module select-all/selectall\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport SelectAllEditing from './selectallediting';\nimport SelectAllUI from './selectallui';\n\n/**\n * The select all feature.\n *\n * This is a \"glue\" plugin which loads the {@link module:select-all/selectallediting~SelectAllEditing select all editing feature}\n * and the {@link module:select-all/selectallui~SelectAllUI select all UI feature}.\n *\n * Please refer to the documentation of individual features to learn more.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class SelectAll extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ SelectAllEditing, SelectAllUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'SelectAll';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module select-all\n */\n\nexport { default as SelectAll } from './selectall';\nexport { default as SelectAllEditing } from './selectallediting';\nexport { default as SelectAllUI } from './selectallui';\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/converters/tableproperites\n */\n\n/**\n * Conversion helper for upcasting attributes using normalized styles.\n *\n * @param {module:engine/conversion/conversion~Conversion} conversion\n * @param {String} modelElement\n * @param {String} modelAttribute\n * @param {String} styleName\n */\nexport function upcastStyleToAttribute( conversion, modelElement, modelAttribute, styleName ) {\n\tconversion.for( 'upcast' ).attributeToAttribute( {\n\t\tview: {\n\t\t\tstyles: {\n\t\t\t\t[ styleName ]: /[\\s\\S]+/\n\t\t\t}\n\t\t},\n\t\tmodel: {\n\t\t\tname: modelElement,\n\t\t\tkey: modelAttribute,\n\t\t\tvalue: viewElement => viewElement.getNormalizedStyle( styleName )\n\t\t}\n\t} );\n}\n\n/**\n * Conversion helper for upcasting border styles for view elements.\n *\n * @param {module:engine/conversion/conversion~Conversion} conversion\n * @param {String} viewElementName\n */\nexport function upcastBorderStyles( conversion, viewElementName ) {\n\tconversion.for( 'upcast' ).add( dispatcher => dispatcher.on( 'element:' + viewElementName, ( evt, data, conversionApi ) => {\n\t\t// If the element was not converted by element-to-element converter,\n\t\t// we should not try to convert the style. See #8393.\n\t\tif ( !data.modelRange ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// TODO: this is counter-intuitive: ie.: if only `border-top` is defined then `hasStyle( 'border' )` also returns true.\n\t\t// TODO: this might needs to be fixed in styles normalizer.\n\t\tconst stylesToConsume = [\n\t\t\t'border-top',\n\t\t\t'border-right',\n\t\t\t'border-bottom',\n\t\t\t'border-left'\n\t\t].filter( styleName => data.viewItem.hasStyle( styleName ) );\n\n\t\tif ( !stylesToConsume.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst matcherPattern = {\n\t\t\tstyles: stylesToConsume\n\t\t};\n\n\t\t// Try to consume appropriate values from consumable values list.\n\t\tif ( !conversionApi.consumable.test( data.viewItem, matcherPattern ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelElement = [ ...data.modelRange.getItems( { shallow: true } ) ].pop();\n\n\t\tconversionApi.consumable.consume( data.viewItem, matcherPattern );\n\n\t\tconversionApi.writer.setAttribute( 'borderStyle', data.viewItem.getNormalizedStyle( 'border-style' ), modelElement );\n\t\tconversionApi.writer.setAttribute( 'borderColor', data.viewItem.getNormalizedStyle( 'border-color' ), modelElement );\n\t\tconversionApi.writer.setAttribute( 'borderWidth', data.viewItem.getNormalizedStyle( 'border-width' ), modelElement );\n\t} ) );\n}\n\n/**\n * Conversion helper for downcasting an attribute to a style.\n *\n * @param {module:engine/conversion/conversion~Conversion} conversion\n * @param {String} modelElement\n * @param {String} modelAttribute\n * @param {String} styleName\n */\nexport function downcastAttributeToStyle( conversion, modelElement, modelAttribute, styleName ) {\n\tconversion.for( 'downcast' ).attributeToAttribute( {\n\t\tmodel: {\n\t\t\tname: modelElement,\n\t\t\tkey: modelAttribute\n\t\t},\n\t\tview: modelAttributeValue => ( {\n\t\t\tkey: 'style',\n\t\t\tvalue: {\n\t\t\t\t[ styleName ]: modelAttributeValue\n\t\t\t}\n\t\t} )\n\t} );\n}\n\n/**\n * Conversion helper for downcasting attributes from the model table to a view table (not to `
`).\n *\n * @param {module:engine/conversion/conversion~Conversion} conversion\n * @param {String} modelAttribute\n * @param {String} styleName\n */\nexport function downcastTableAttribute( conversion, modelAttribute, styleName ) {\n\tconversion.for( 'downcast' ).add( dispatcher => dispatcher.on( `attribute:${ modelAttribute }:table`, ( evt, data, conversionApi ) => {\n\t\tconst { item, attributeNewValue } = data;\n\t\tconst { mapper, writer } = conversionApi;\n\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst table = [ ...mapper.toViewElement( item ).getChildren() ].find( child => child.is( 'element', 'table' ) );\n\n\t\tif ( attributeNewValue ) {\n\t\t\twriter.setStyle( styleName, attributeNewValue, table );\n\t\t} else {\n\t\t\twriter.removeStyle( styleName, table );\n\t\t}\n\t} ) );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/splitcellcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport { getSelectionAffectedTableCells } from '../utils/selection';\n\n/**\n * The split cell command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'splitTableCellVertically'`\n * and `'splitTableCellHorizontally'` editor commands.\n *\n * You can split any cell vertically or horizontally by executing this command. For example, to split the selected table cell vertically:\n *\n *\t\teditor.execute( 'splitTableCellVertically' );\n *\n * @extends module:core/command~Command\n */\nexport default class SplitCellCommand extends Command {\n\t/**\n\t * Creates a new `SplitCellCommand` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor on which this command will be used.\n\t * @param {Object} options\n\t * @param {String} options.direction Indicates whether the command should split cells `'horizontally'` or `'vertically'`.\n\t */\n\tconstructor( editor, options = {} ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The direction that indicates which cell will be split.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} #direction\n\t\t */\n\t\tthis.direction = options.direction || 'horizontally';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selectedCells = getSelectionAffectedTableCells( this.editor.model.document.selection );\n\n\t\tthis.isEnabled = selectedCells.length === 1;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst tableCell = getSelectionAffectedTableCells( this.editor.model.document.selection )[ 0 ];\n\t\tconst isHorizontal = this.direction === 'horizontally';\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\n\t\tif ( isHorizontal ) {\n\t\t\ttableUtils.splitCellHorizontally( tableCell, 2 );\n\t\t} else {\n\t\t\ttableUtils.splitCellVertically( tableCell, 2 );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/selectrowcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\n\nimport { getRowIndexes, getSelectionAffectedTableCells } from '../utils/selection';\n\n/**\n * The select row command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'selectTableRow'` editor command.\n *\n * To select the rows containing the selected cells, execute the command:\n *\n *\t\teditor.execute( 'selectTableRow' );\n *\n * @extends module:core/command~Command\n */\nexport default class SelectRowCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selectedCells = getSelectionAffectedTableCells( this.editor.model.document.selection );\n\n\t\tthis.isEnabled = selectedCells.length > 0;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst referenceCells = getSelectionAffectedTableCells( model.document.selection );\n\t\tconst rowIndexes = getRowIndexes( referenceCells );\n\n\t\tconst table = referenceCells[ 0 ].findAncestor( 'table' );\n\t\tconst rangesToSelect = [];\n\n\t\tfor ( let rowIndex = rowIndexes.first; rowIndex <= rowIndexes.last; rowIndex++ ) {\n\t\t\tfor ( const cell of table.getChild( rowIndex ).getChildren() ) {\n\t\t\t\trangesToSelect.push( model.createRangeOn( cell ) );\n\t\t\t}\n\t\t}\n\n\t\tmodel.change( writer => {\n\t\t\twriter.setSelection( rangesToSelect );\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/converters/table-cell-refresh-post-fixer\n */\n\nimport { isSingleParagraphWithoutAttributes } from './downcast';\n\n/**\n * Injects a table cell post-fixer into the model which marks the table cell in the differ to have it re-rendered.\n *\n * Model `paragraph` inside a table cell can be rendered as `` or `

`. It is rendered as `` if this is the only block\n * element in that table cell and it does not have any attributes. It is rendered as `

` otherwise.\n *\n * When table cell content changes, for example a second `paragraph` element is added, we need to ensure that the first `paragraph` is\n * re-rendered so it changes from `` to `

`. The easiest way to do it is to re-render the entire table cell.\n *\n * @param {module:engine/model/model~Model} model\n * @param {module:engine/conversion/mapper~Mapper} mapper\n */\nexport default function injectTableCellRefreshPostFixer( model, mapper ) {\n\tmodel.document.registerPostFixer( () => tableCellRefreshPostFixer( model.document.differ, mapper ) );\n}\n\nfunction tableCellRefreshPostFixer( differ, mapper ) {\n\t// Stores cells to be refreshed, so the table cell will be refreshed once for multiple changes.\n\n\t// 1. Gather all changes inside table cell.\n\tconst cellsToCheck = new Set();\n\n\tfor ( const change of differ.getChanges() ) {\n\t\tconst parent = change.type == 'attribute' ? change.range.start.parent : change.position.parent;\n\n\t\tif ( parent.is( 'element', 'tableCell' ) ) {\n\t\t\tcellsToCheck.add( parent );\n\t\t}\n\t}\n\n\t// @if CK_DEBUG_TABLE // console.log( `Post-fixing table: Checking table cell to refresh (${ cellsToCheck.size }).` );\n\t// @if CK_DEBUG_TABLE // let paragraphsRefreshed = 0;\n\n\tfor ( const tableCell of cellsToCheck.values() ) {\n\t\tfor ( const paragraph of [ ...tableCell.getChildren() ].filter( child => shouldRefresh( child, mapper ) ) ) {\n\t\t\t// @if CK_DEBUG_TABLE // console.log( `Post-fixing table: refreshing paragraph in table cell (${++paragraphsRefreshed}).` );\n\t\t\tdiffer.refreshItem( paragraph );\n\t\t}\n\t}\n\n\t// Always return false to prevent the refresh post-fixer from re-running on the same set of changes and going into an infinite loop.\n\t// This \"post-fixer\" does not change the model structure so there shouldn't be need to run other post-fixers again.\n\t// See https://github.com/ckeditor/ckeditor5/issues/1936 & https://github.com/ckeditor/ckeditor5/issues/8200.\n\treturn false;\n}\n\n// Check if given model element needs refreshing.\n//\n// @param {module:engine/model/element~Element} modelElement\n// @param {module:engine/conversion/mapper~Mapper} mapper\n// @returns {Boolean}\nfunction shouldRefresh( child, mapper ) {\n\tif ( !child.is( 'element', 'paragraph' ) ) {\n\t\treturn false;\n\t}\n\n\tconst viewElement = mapper.toViewElement( child );\n\n\tif ( !viewElement ) {\n\t\treturn false;\n\t}\n\n\treturn isSingleParagraphWithoutAttributes( child ) !== viewElement.is( 'element', 'span' );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/removecolumncommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\n\nimport TableWalker from '../tablewalker';\nimport { getColumnIndexes, getSelectionAffectedTableCells } from '../utils/selection';\n\n/**\n * The remove column command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'removeTableColumn'` editor command.\n *\n * To remove the column containing the selected cell, execute the command:\n *\n *\t\teditor.execute( 'removeTableColumn' );\n *\n * @extends module:core/command~Command\n */\nexport default class RemoveColumnCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selectedCells = getSelectionAffectedTableCells( this.editor.model.document.selection );\n\t\tconst firstCell = selectedCells[ 0 ];\n\n\t\tif ( firstCell ) {\n\t\t\tconst table = firstCell.findAncestor( 'table' );\n\t\t\tconst tableColumnCount = this.editor.plugins.get( 'TableUtils' ).getColumns( table );\n\n\t\t\tconst { first, last } = getColumnIndexes( selectedCells );\n\n\t\t\tthis.isEnabled = last - first < ( tableColumnCount - 1 );\n\t\t} else {\n\t\t\tthis.isEnabled = false;\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst [ firstCell, lastCell ] = getBoundaryCells( this.editor.model.document.selection );\n\t\tconst table = firstCell.parent.parent;\n\n\t\t// Cache the table before removing or updating colspans.\n\t\tconst tableMap = [ ...new TableWalker( table ) ];\n\n\t\t// Store column indexes of removed columns.\n\t\tconst removedColumnIndexes = {\n\t\t\tfirst: tableMap.find( value => value.cell === firstCell ).column,\n\t\t\tlast: tableMap.find( value => value.cell === lastCell ).column\n\t\t};\n\n\t\tconst cellToFocus = getCellToFocus( tableMap, firstCell, lastCell, removedColumnIndexes );\n\n\t\tthis.editor.model.change( writer => {\n\t\t\tconst columnsToRemove = removedColumnIndexes.last - removedColumnIndexes.first + 1;\n\n\t\t\tthis.editor.plugins.get( 'TableUtils' ).removeColumns( table, {\n\t\t\t\tat: removedColumnIndexes.first,\n\t\t\t\tcolumns: columnsToRemove\n\t\t\t} );\n\n\t\t\twriter.setSelection( writer.createPositionAt( cellToFocus, 0 ) );\n\t\t} );\n\t}\n}\n\n// Returns a proper table cell to focus after removing a column.\n// - selection is on last table cell it will return previous cell.\nfunction getCellToFocus( tableMap, firstCell, lastCell, removedColumnIndexes ) {\n\tconst colspan = parseInt( lastCell.getAttribute( 'colspan' ) || 1 );\n\n\t// If the table cell is spanned over 2+ columns - it will be truncated so the selection should\n\t// stay in that cell.\n\tif ( colspan > 1 ) {\n\t\treturn lastCell;\n\t}\n\t// Normally, look for the cell in the same row that precedes the first cell to put selection there (\"column on the left\").\n\t// If the deleted column is the first column of the table, there will be no predecessor: use the cell\n\t// from the column that follows then (also in the same row).\n\telse if ( firstCell.previousSibling || lastCell.nextSibling ) {\n\t\treturn lastCell.nextSibling || firstCell.previousSibling;\n\t}\n\t// It can happen that table cells have no siblings in a row, for instance, when there are row spans\n\t// in the table (in the previous row). Then just look for the closest cell that is in a column\n\t// that will not be removed to put the selection there.\n\telse {\n\t\t// Look for any cell in a column that precedes the first removed column.\n\t\tif ( removedColumnIndexes.first ) {\n\t\t\treturn tableMap.reverse().find( ( { column } ) => {\n\t\t\t\treturn column < removedColumnIndexes.first;\n\t\t\t} ).cell;\n\t\t}\n\t\t// If the first removed column is the first column of the table, then\n\t\t// look for any cell that is in a column that follows the last removed column.\n\t\telse {\n\t\t\treturn tableMap.reverse().find( ( { column } ) => {\n\t\t\t\treturn column > removedColumnIndexes.last;\n\t\t\t} ).cell;\n\t\t}\n\t}\n}\n\n// Returns helper object returning the first and the last cell contained in given selection, based on DOM order.\nfunction getBoundaryCells( selection ) {\n\tconst referenceCells = getSelectionAffectedTableCells( selection );\n\tconst firstCell = referenceCells[ 0 ];\n\tconst lastCell = referenceCells.pop();\n\n\tconst returnValue = [ firstCell, lastCell ];\n\n\treturn firstCell.isBefore( lastCell ) ? returnValue : returnValue.reverse();\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/insertrowcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport { getRowIndexes, getSelectionAffectedTableCells } from '../utils/selection';\n\n/**\n * The insert row command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'insertTableRowBelow'` and\n * `'insertTableRowAbove'` editor commands.\n *\n * To insert a row below the selected cell, execute the following command:\n *\n *\t\teditor.execute( 'insertTableRowBelow' );\n *\n * To insert a row above the selected cell, execute the following command:\n *\n *\t\teditor.execute( 'insertTableRowAbove' );\n *\n * @extends module:core/command~Command\n */\nexport default class InsertRowCommand extends Command {\n\t/**\n\t * Creates a new `InsertRowCommand` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor on which this command will be used.\n\t * @param {Object} options\n\t * @param {String} [options.order=\"below\"] The order of insertion relative to the row in which the caret is located.\n\t * Possible values: `\"above\"` and `\"below\"`.\n\t */\n\tconstructor( editor, options = {} ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The order of insertion relative to the row in which the caret is located.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} module:table/commands/insertrowcommand~InsertRowCommand#order\n\t\t */\n\t\tthis.order = options.order || 'below';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selection = this.editor.model.document.selection;\n\n\t\tconst tableParent = selection.getFirstPosition().findAncestor( 'table' );\n\n\t\tthis.isEnabled = !!tableParent;\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * Depending on the command's {@link #order} value, it inserts a row `'below'` or `'above'` the row in which selection is set.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\t\tconst tableUtils = editor.plugins.get( 'TableUtils' );\n\t\tconst insertAbove = this.order === 'above';\n\n\t\tconst affectedTableCells = getSelectionAffectedTableCells( selection );\n\t\tconst rowIndexes = getRowIndexes( affectedTableCells );\n\n\t\tconst row = insertAbove ? rowIndexes.first : rowIndexes.last;\n\t\tconst table = affectedTableCells[ 0 ].findAncestor( 'table' );\n\n\t\ttableUtils.insertRows( table, { at: insertAbove ? row : row + 1, copyStructureFromAbove: !insertAbove } );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/commands/setheaderrowcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\n\nimport { updateNumericAttribute } from '../utils/common';\nimport { getRowIndexes, getSelectionAffectedTableCells } from '../utils/selection';\nimport { getVerticallyOverlappingCells, splitHorizontally } from '../utils/structure';\n\n/**\n * The header row command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as the `'setTableColumnHeader'` editor command.\n *\n * You can make the row containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element) by executing:\n *\n *\t\teditor.execute( 'setTableRowHeader' );\n *\n * **Note:** All preceding rows will also become headers. If the current row is already a header, executing this command\n * will make it a regular row back again (including the following rows).\n *\n * @extends module:core/command~Command\n */\nexport default class SetHeaderRowCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst selectedCells = getSelectionAffectedTableCells( model.document.selection );\n\t\tconst isInTable = selectedCells.length > 0;\n\n\t\tthis.isEnabled = isInTable;\n\n\t\t/**\n\t\t * Flag indicating whether the command is active. The command is active when the\n\t\t * {@link module:engine/model/selection~Selection} is in a header row.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #value\n\t\t */\n\t\tthis.value = isInTable && selectedCells.every( cell => this._isInHeading( cell, cell.parent.parent ) );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * When the selection is in a non-header row, the command will set the `headingRows` table attribute to cover that row.\n\t *\n\t * When the selection is already in a header row, it will set `headingRows` so the heading section will end before that row.\n\t *\n\t * @fires execute\n\t * @param {Object} options\n\t * @param {Boolean} [options.forceValue] If set, the command will set (`true`) or unset (`false`) the header rows according to\n\t * the `forceValue` parameter instead of the current model state.\n\t */\n\texecute( options = {} ) {\n\t\tif ( options.forceValue === this.value ) {\n\t\t\treturn;\n\t\t}\n\t\tconst model = this.editor.model;\n\t\tconst selectedCells = getSelectionAffectedTableCells( model.document.selection );\n\t\tconst table = selectedCells[ 0 ].findAncestor( 'table' );\n\n\t\tconst { first, last } = getRowIndexes( selectedCells );\n\t\tconst headingRowsToSet = this.value ? first : last + 1;\n\t\tconst currentHeadingRows = table.getAttribute( 'headingRows' ) || 0;\n\n\t\tmodel.change( writer => {\n\t\t\tif ( headingRowsToSet ) {\n\t\t\t\t// Changing heading rows requires to check if any of a heading cell is overlapping vertically the table head.\n\t\t\t\t// Any table cell that has a rowspan attribute > 1 will not exceed the table head so we need to fix it in rows below.\n\t\t\t\tconst startRow = headingRowsToSet > currentHeadingRows ? currentHeadingRows : 0;\n\t\t\t\tconst overlappingCells = getVerticallyOverlappingCells( table, headingRowsToSet, startRow );\n\n\t\t\t\tfor ( const { cell } of overlappingCells ) {\n\t\t\t\t\tsplitHorizontally( cell, headingRowsToSet, writer );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tupdateNumericAttribute( 'headingRows', headingRowsToSet, table, writer, 0 );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks if a table cell is in the heading section.\n\t *\n\t * @param {module:engine/model/element~Element} tableCell\n\t * @param {module:engine/model/element~Element} table\n\t * @returns {Boolean}\n\t * @private\n\t */\n\t_isInHeading( tableCell, table ) {\n\t\tconst headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );\n\n\t\treturn !!headingRows && tableCell.parent.index < headingRows;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module table/converters/table-cell-paragraph-post-fixer\n */\n\n/**\n * Injects a table cell post-fixer into the model which inserts a `paragraph` element into empty table cells.\n *\n * A table cell must contain at least one block element as a child. An empty table cell will have an empty `paragraph` as a child.\n *\n *\t\t

\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
\n *\n * Will be fixed to:\n *\n *\t\t\n *\t\t\t\n *\t\t\t\t\n *\t\t\t\n *\t\t
\n *\n * @param {module:engine/model/model~Model} model\n */\nexport default function injectTableCellParagraphPostFixer( model ) {\n\tmodel.document.registerPostFixer( writer => tableCellContentsPostFixer( writer, model ) );\n}\n\n// The table cell contents post-fixer.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/model~Model} model\nfunction tableCellContentsPostFixer( writer, model ) {\n\tconst changes = model.document.differ.getChanges();\n\n\tlet wasFixed = false;\n\n\tfor ( const entry of changes ) {\n\t\tif ( entry.type == 'insert' && entry.name == 'table' ) {\n\t\t\twasFixed = fixTable( entry.position.nodeAfter, writer ) || wasFixed;\n\t\t}\n\n\t\tif ( entry.type == 'insert' && entry.name == 'tableRow' ) {\n\t\t\twasFixed = fixTableRow( entry.position.nodeAfter, writer ) || wasFixed;\n\t\t}\n\n\t\tif ( entry.type == 'insert' && entry.name == 'tableCell' ) {\n\t\t\twasFixed = fixTableCellContent( entry.position.nodeAfter, writer ) || wasFixed;\n\t\t}\n\n\t\tif ( checkTableCellChange( entry ) ) {\n\t\t\twasFixed = fixTableCellContent( entry.position.parent, writer ) || wasFixed;\n\t\t}\n\t}\n\n\treturn wasFixed;\n}\n\n// Fixes all table cells in a table.\n//\n// @param {module:engine/model/element~Element} table\n// @param {module:engine/model/writer~Writer} writer\nfunction fixTable( table, writer ) {\n\tlet wasFixed = false;\n\n\tfor ( const row of table.getChildren() ) {\n\t\twasFixed = fixTableRow( row, writer ) || wasFixed;\n\t}\n\n\treturn wasFixed;\n}\n\n// Fixes all table cells in a table row.\n//\n// @param {module:engine/model/element~Element} tableRow\n// @param {module:engine/model/writer~Writer} writer\nfunction fixTableRow( tableRow, writer ) {\n\tlet wasFixed = false;\n\n\tfor ( const tableCell of tableRow.getChildren() ) {\n\t\twasFixed = fixTableCellContent( tableCell, writer ) || wasFixed;\n\t}\n\n\treturn wasFixed;\n}\n\n// Fixes all table cell content by:\n// - Adding a paragraph to a table cell without any child.\n// - Wrapping direct $text in a ``.\n//\n// @param {module:engine/model/element~Element} table\n// @param {module:engine/model/writer~Writer} writer\n// @returns {Boolean}\nfunction fixTableCellContent( tableCell, writer ) {\n\t// Insert paragraph to an empty table cell.\n\tif ( tableCell.childCount == 0 ) {\n\t\t// @if CK_DEBUG_TABLE // console.log( 'Post-fixing table: insert paragraph in empty cell.' );\n\n\t\twriter.insertElement( 'paragraph', tableCell );\n\n\t\treturn true;\n\t}\n\n\t// Check table cell children for directly placed text nodes.\n\t// Temporary solution. See https://github.com/ckeditor/ckeditor5/issues/1464.\n\tconst textNodes = Array.from( tableCell.getChildren() ).filter( child => child.is( '$text' ) );\n\n\t// @if CK_DEBUG_TABLE // textNodes.length && console.log( 'Post-fixing table: wrap cell content with paragraph.' );\n\n\tfor ( const child of textNodes ) {\n\t\twriter.wrap( writer.createRangeOn( child ), 'paragraph' );\n\t}\n\n\t// Return true when there were text nodes to fix.\n\treturn !!textNodes.length;\n}\n\n// Checks if a differ change should fix the table cell. This happens on:\n// - Removing content from the table cell (i.e. `tableCell` can be left empty).\n// - Adding a text node directly into a table cell.\n//\n// @param {Object} differ change entry\n// @returns {Boolean}\nfunction checkTableCellChange( entry ) {\n\tif ( !entry.position || !entry.position.parent.is( 'element', 'tableCell' ) ) {\n\t\treturn false;\n\t}\n\n\treturn entry.type == 'insert' && entry.name == '$text' || entry.type == 'remove';\n}\n","module.exports = \"\""],"sourceRoot":""}