UNPKG

@atlaskit/adf-utils

Version:

Set of utilities to traverse, modify and create ADF documents.

158 lines (157 loc) 6.05 kB
import { traverse } from '../traverse/traverse'; import { tableRow, tableCell, paragraph, listItem } from '../builders'; import { isEmpty } from './helpers'; const getMaxColumnsCountForTable = tableNode => { var _tableNode$content; let colsInRow = 1; (_tableNode$content = tableNode.content) === null || _tableNode$content === void 0 ? void 0 : _tableNode$content.forEach(childNode => { var _childNode$content; if ((childNode === null || childNode === void 0 ? void 0 : childNode.type) === 'tableRow' && typeof ((_childNode$content = childNode.content) === null || _childNode$content === void 0 ? void 0 : _childNode$content.length) === 'number' && childNode.content.length > colsInRow) { colsInRow = childNode.content.length; } }); return colsInRow; }; const createValidEmptyContent = node => { switch (node.type) { case 'tableCell': return [paragraph()]; default: return []; } }; const fixIfTableCellInvalidEmpty = reportTransform => node => { if (isEmpty(node)) { reportTransform(); return { ...node, content: createValidEmptyContent(node) }; } return; }; const hasNonListItemChildren = node => { var _node$content; return (_node$content = node.content) === null || _node$content === void 0 ? void 0 : _node$content.some(node => (node === null || node === void 0 ? void 0 : node.type) !== 'listItem'); }; const hasEmptyListItemChildren = node => { var _node$content2; return (_node$content2 = node.content) === null || _node$content2 === void 0 ? void 0 : _node$content2.some(childNode => { var _childNode$content2; return (childNode === null || childNode === void 0 ? void 0 : childNode.type) === 'listItem' && !((_childNode$content2 = childNode.content) !== null && _childNode$content2 !== void 0 && _childNode$content2.length); }); }; const tryCreateValidListItemWrappedChildren = parentListNode => { var _parentListNode$conte; return (_parentListNode$conte = parentListNode.content) === null || _parentListNode$conte === void 0 ? void 0 : _parentListNode$conte.map(childNode => { if (childNode) { switch (childNode.type) { case 'listItem': { if (isEmpty(childNode)) { const result = listItem([paragraph()]); return result; } return childNode; } case 'text': return listItem([paragraph(childNode)]); default: // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any return listItem([childNode]); } } return childNode; }); }; const fixIfListParentWithInvalidListItemChildren = reportTransform => node => { if (hasNonListItemChildren(node) || hasEmptyListItemChildren(node)) { reportTransform(); return { ...node, content: tryCreateValidListItemWrappedChildren(node) }; } return; }; const hasNonTableRowChildren = node => { var _node$content3; return (_node$content3 = node.content) === null || _node$content3 === void 0 ? void 0 : _node$content3.some(node => (node === null || node === void 0 ? void 0 : node.type) !== 'tableRow'); }; const tryCreateValidTableRowWrappedChildren = parentTableNode => { var _parentTableNode$cont; const maxColsCount = getMaxColumnsCountForTable(parentTableNode); return (_parentTableNode$cont = parentTableNode.content) === null || _parentTableNode$cont === void 0 ? void 0 : _parentTableNode$cont.map(childNode => { if (childNode) { switch (childNode.type) { case 'text': { return tableRow([tableCell({})(paragraph(childNode)), ...new Array(maxColsCount - 1).fill(tableCell({})(paragraph()))]); } case 'tableCell': { return tableRow([childNode]); } case 'tableRow': { if (isEmpty(childNode)) { return tableRow([...new Array(maxColsCount).fill(tableCell({})(paragraph()))]); } return childNode; } default: return childNode; } } return childNode; }); }; const hasEmptyTableRowChildren = node => { var _node$content4; return (node === null || node === void 0 ? void 0 : (_node$content4 = node.content) === null || _node$content4 === void 0 ? void 0 : _node$content4.some(node => { var _node$content5; return (node === null || node === void 0 ? void 0 : node.type) === 'tableRow' && (node === null || node === void 0 ? void 0 : (_node$content5 = node.content) === null || _node$content5 === void 0 ? void 0 : _node$content5.length) === 0; })) || undefined; }; const fixIfTableParentWithInvalidTableRowChildren = reportTransform => node => { if (hasEmptyTableRowChildren(node) || hasNonTableRowChildren(node)) { reportTransform(); return { ...node, content: tryCreateValidTableRowWrappedChildren(node) }; } return; }; const removeMediaSingleWithNoContent = reportTransform => node => { if (isEmpty(node)) { reportTransform(); return false; } return; }; export const transformNodesMissingContent = adf => { let isTransformed = false; const reportTransform = () => { isTransformed = true; }; let transformedAdf = traverse(adf, { tableCell: fixIfTableCellInvalidEmpty(reportTransform) }); // Empty mediaSingle nodes get stripped from the document and so this transform // will create an empty listItem if the media node is in a list. Empty listItems // are invalid adf, so we need to transform the mediaSingle nodes first. transformedAdf = traverse(transformedAdf || adf, { mediaSingle: removeMediaSingleWithNoContent(reportTransform) }); transformedAdf = traverse(transformedAdf || adf, { bulletList: fixIfListParentWithInvalidListItemChildren(reportTransform), orderedList: fixIfListParentWithInvalidListItemChildren(reportTransform), table: fixIfTableParentWithInvalidTableRowChildren(reportTransform) }); return { transformedAdf, isTransformed }; };