@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
146 lines (142 loc) • 4.11 kB
JavaScript
/**
* Returns an array of column widths (0 if column width is undefined) of a given table node by scanning the **entire table**.
*
* Warning: the entire table is scanned and should only be used if where the table can be in a broken state such that rows have different number of cells (e.g. in **renderer**).
* @param node - Table node
* @example
* ```ts
* const columnWidths = getColumnWidths(tableNode);
* console.log(columnWidths);
* // Output: [100, 200, 300]
* ```
* @returns Array<number>
*/
export function getColumnWidths(node) {
let tableColumnWidths = [];
node.forEach(row => {
const currentTableWidth = [];
row.forEach(cell => {
const {
colspan,
colwidth
} = cell.attrs;
// column has been resized, colWidth will be an array, can safely take values even if cell is merged
if (Array.isArray(colwidth)) {
currentTableWidth.push(...colwidth);
// table has merged cells but no colWidth, so columns haven't been resized, default to 0
} else if (colspan !== undefined && colspan > 1) {
currentTableWidth.push(...Array(colspan).fill(0));
// no merged cells, no column resized, default to 0
} else {
currentTableWidth.push(0);
}
});
if (currentTableWidth.length > tableColumnWidths.length) {
tableColumnWidths = currentTableWidth;
}
});
return tableColumnWidths;
}
/**
* Returns an array of column widths (0 if column width is undefined) of a given table node by scanning the **first row**.
*
* Warning: is preferred and should be used if the table is not in a broken state (e.g. in **editor**).
* @param node - Table node
* @example
* ```ts
* const columnWidths = calcTableColumnWidths(tableNode);
* console.log(columnWidths);
* // Output: [100, 200, 300]
* ```
* @returns Array<number>
*/
export function calcTableColumnWidths(node) {
const firstRow = node.firstChild;
const tableColumnWidths = [];
if (firstRow) {
firstRow.forEach(cell => {
const {
colspan,
colwidth
} = cell.attrs;
// column has been resized, colWidth will be an array, can safely take values even if cell is merged
if (Array.isArray(colwidth)) {
tableColumnWidths.push(...colwidth);
// table has merged cells but no colWidth, so columns haven't been resized, default to 0
} else if (colspan > 1) {
tableColumnWidths.push(...Array(colspan).fill(0));
// no merged cells, no column resized, default to 0
} else {
tableColumnWidths.push(0);
}
});
}
return tableColumnWidths;
}
/**
*
* @param tableNode
* @example
*/
export function hasMergedCell(tableNode) {
let hasSpan = false;
tableNode.descendants(node => {
if (node.type.name === 'tableRow') {
return true;
}
const {
colspan,
rowspan
} = node.attrs;
if (colspan > 1 || rowspan > 1) {
hasSpan = true;
}
return false;
});
return hasSpan;
}
/**
*
* @param tableNode
* @example
*/
export function convertProsemirrorTableNodeToArrayOfRows(tableNode) {
const result = [];
tableNode.forEach(rowNode => {
if (rowNode.type.name === 'tableRow') {
const row = [];
rowNode.forEach(n => row.push(n));
result.push(row);
}
});
return result;
}
/*
isPositionNearTableRow()
Returns true when a sibling node, or any of the parent's sibling
nodes are a tableRow
*/
/**
*
* @param pos
* @param schema
* @param direction
* @example
*/
export function isPositionNearTableRow(pos, schema, direction) {
if (!schema.nodes.tableRow) {
return false;
}
const doc = pos.doc;
let resolved = pos;
const sibling = direction === 'before' ? 'nodeBefore' : 'nodeAfter';
while (resolved.depth > 0) {
var _resolved$sibling;
const siblingType = (_resolved$sibling = resolved[sibling]) === null || _resolved$sibling === void 0 ? void 0 : _resolved$sibling.type;
if (siblingType === schema.nodes.tableRow) {
return true;
}
resolved = doc.resolve(resolved[direction]());
}
return false;
}