UNPKG

@atlaskit/adf-schema

Version:

Shared package that contains the ADF-schema (json) and ProseMirror node/mark specs

202 lines (194 loc) 8.05 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.applyCellStep = applyCellStep; exports.createCellStep = createCellStep; exports.getMapFromCellStep = getMapFromCellStep; exports.invertCellStep = invertCellStep; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _utils = require("@atlaskit/editor-tables/utils"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } var EmptyCellNodeSize = 4; function calculateRowsToSkip(attrs) { if (attrs && attrs.rowspan) { return attrs.rowspan - 1; } return 0; } /** * Given a cell step, this function has to do the specific transformation to executed that step. * It returns the applied cellStep and rows that needs to skip (because it was already handled). * @param tr * @param tableRect * @param cell * @param cellStep * @param isDelete * @param column */ function applyCellStep(tr, tableRect, cell, cellStep, isDelete, column) { // Apply the merge actions, if (cellStep.mergeWith !== undefined) { var cellNode = tr.doc.nodeAt(tr.mapping.map(cellStep.mergeWith)); var columns = column - tableRect.map.colCount(cellStep.mergeWith - tableRect.tableStart); var cellAttrs = isDelete ? (0, _utils.removeColSpan)(cellNode.attrs, columns) : (0, _utils.addColSpan)(cellNode.attrs, columns); if (cellAttrs.colspan > 0) { // When colspan is 0 should remove the cell tr.setNodeMarkup(tr.mapping.map(cellStep.mergeWith), undefined, cellAttrs); return { tr: tr, skipRows: calculateRowsToSkip(cellAttrs), cellStep: cellStep }; } // When the new colspan is 0, I need to change the operation to a delete operation // Update cellStep with the proper data cellStep.from = cellStep.mergeWith; cellStep.to = cellStep.from + cellNode.nodeSize; cellStep.mergeWith = undefined; } var skipRows = 0; // Modify temporary document if (isDelete) { var _cellNode = tr.doc.nodeAt(tr.mapping.map(cellStep.from)); skipRows = calculateRowsToSkip(_cellNode.attrs); tr.delete(tr.mapping.map(cellStep.from), tr.mapping.map(cellStep.to)); } else { if (cellStep.newCell) { tr.insert(tr.mapping.map(cellStep.from), cellStep.newCell); skipRows = calculateRowsToSkip(cellStep.newCell.attrs); } else { tr.insert(tr.mapping.map(cellStep.from), cell.type.createAndFill()); } } return { tr: tr, skipRows: skipRows, cellStep: cellStep }; } /** * Given a cell step, this functions return un StepMap representing this action. * [position, oldSize, newSize] * @param cellStep * @param isDelete */ function getMapFromCellStep(cellStep, isDelete) { if (cellStep.mergeWith !== undefined) { return [cellStep.mergeWith, 1, 1]; } if (isDelete) { return [cellStep.from, cellStep.to - cellStep.from, 0]; } else { if (cellStep.newCell) { return [cellStep.from, 0, cellStep.newCell.nodeSize]; } return [cellStep.from, 0, EmptyCellNodeSize]; } } /** * Helper to calculate the offset of the inverted cells. * When you delete consecutive rows in a single step, the position in the generated document * are skipped by the all the changes except your own. (StepMap.map is not valid) * @param map * @param cellStep * @param isDelete */ function getOffset(map, cellStep, isDelete) { if (isDelete) { return map.map(cellStep.from) - cellStep.from; } var _getMapFromCellStep = getMapFromCellStep(cellStep, isDelete), _getMapFromCellStep2 = (0, _slicedToArray2.default)(_getMapFromCellStep, 3), oldSize = _getMapFromCellStep2[1], newSize = _getMapFromCellStep2[2]; return map.map(cellStep.from) - cellStep.from - (newSize - oldSize); } /** * Given a cell step, this function invert that step. * @param doc * @param getTableRectAndColumn * @param cellStep * @param isDelete * @param stepMap */ function invertCellStep(doc, getTableRectAndColumn, cellStep, isDelete, stepMap) { /** * We need a correct map when a cell is added * We need the normal map position minus the size of the cell you added it. Why? * Having a table 3x3 and we add a new column at 2 creates this ranges * [ * 10, 0, 4, * 20, 0, 4, * 30, 0, 4, * ] * Where: * * [10, 20, 30] are the original cell positions where we add the cells * * [0, 0, 0] are the old size. We are adding new cells, so it's always zero * * [4, 4, 4] are the new size. In this case, we are adding empty cell and has size 4, this will be different for prefill cells. * In the document generated the cells that I want to delete (if I invert this step) are [10, 24, 38] * this is calculated in the given way * * Map the position using this step mapping function, this will return the cell in the next column * * Remove the diff (4 - 0 in this case) of the current position. * For a delete action this not happen, it will always return the right value */ var offset = getOffset(stepMap, cellStep, isDelete); var newCellStepInfo = _objectSpread(_objectSpread({}, cellStep), {}, { // Map the position to position of the generated document from: cellStep.from + offset, to: cellStep.to + offset }); if (cellStep.mergeWith !== undefined) { newCellStepInfo.mergeWith = cellStep.mergeWith + offset; } if (isDelete) { // Add the removed cell as the new cell of the inverted step var removedCell = doc.nodeAt(cellStep.from); newCellStepInfo.newCell = removedCell.copy(removedCell.content); // When we delete a column we can end in a position that doesnt represent the right column. // This only happens on merged cell that ends in the deleted column. // We need to remap this position to the "next" cell (AKA cellStep.to) var _getTableRectAndColum = getTableRectAndColumn(), column = _getTableRectAndColum.column, rect = _getTableRectAndColum.rect; if (column < rect.map.width) { var isAtTheEnd = rect.map.colCount(cellStep.from - rect.tableStart) + removedCell.attrs.colspan - 1 === column; if (cellStep.mergeWith !== undefined && isAtTheEnd) { newCellStepInfo.mergeWith = newCellStepInfo.from; newCellStepInfo.from = newCellStepInfo.to; } } } return newCellStepInfo; } /** * Create a cell step based on the current cell and operation (add/delete) * @param cell * @param column * @param isDelete * @param previousCellStep */ function createCellStep(cell, column, isDelete, previousCellStep) { var newCellStepInfo = { from: cell.from, to: cell.to }; if (cell.hasMergedCells) { // Check what column has to merge if (column !== cell.col || isDelete) { newCellStepInfo.mergeWith = cell.from; } } if (previousCellStep) { if (previousCellStep.mergeWith !== undefined) { newCellStepInfo.mergeWith = previousCellStep.mergeWith; } if (previousCellStep.newCell) { newCellStepInfo.newCell = previousCellStep.newCell; } } return newCellStepInfo; }