@atlaskit/adf-schema
Version:
Shared package that contains the ADF-schema (json) and ProseMirror node/mark specs
192 lines (185 loc) • 7.65 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
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) { _defineProperty(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; }
import { addColSpan, removeColSpan } from '@atlaskit/editor-tables/utils';
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
*/
export 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 ? removeColSpan(cellNode.attrs, columns) : 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
*/
export 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 = _slicedToArray(_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
*/
export 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
*/
export 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;
}