UNPKG

@atlaskit/editor-plugin-batch-attribute-updates

Version:

Provider a runtime tool to merge an array of SetAttrsStep and/or AttrsSteps into an unique BatchAttrsStep

83 lines 2.87 kB
import { BatchAttrsStep, SetAttrsStep } from '@atlaskit/adf-schema/steps'; import { AttrStep } from '@atlaskit/editor-prosemirror/transform'; export const parseStepAttributeData = step => { if (step instanceof SetAttrsStep) { return { position: step.pos, attrs: step.attrs }; } return { position: step.pos, attrs: { [step.attr]: step.value } }; }; export const groupAttributesPerPosition = steps => { const mappedData = steps.reduce((acc, step) => { const parsedStep = parseStepAttributeData(step); const previousAttributes = acc.get(parsedStep.position) || {}; acc.set(parsedStep.position, { ...previousAttributes, ...parsedStep.attrs }); return acc; }, new Map()); return Array.from(mappedData, ([position, attrs]) => ({ position, attrs })); }; const isValidSteps = steps => { const hasInvalidSteps = steps.some(step => { const isSetAttrsStep = step instanceof SetAttrsStep; const isAttrStep = step instanceof AttrStep; const isValidStep = isSetAttrsStep || isAttrStep; return !isValidStep; }); return !hasInvalidSteps; }; /** * Batches a series of attribute steps into a single `BatchAttrsStep`. * * This function takes a document and an array of steps, which should be instances of either * `SetAttrsStep` or `AttrStep`. It groups these steps by their position within the document * and aggregates their attributes. It then creates a `BatchAttrsStep` that applies all these * attribute changes at once. * * @param {Object} props - The properties required to batch steps. * @param {PMNode} props.doc - The ProseMirror document node in which the steps will be applied. * @param {Array<AttrStep | SetAttrsStep> | Array<Step>} props.steps - An array of steps that modify attributes. * * @returns {BatchAttrsStep} - A `BatchAttrsStep` that encapsulates all the attribute changes. * * @throws {Error} - Throws an error if any step in the steps array is not an attribute-related step. * @throws {Error} - Throws an error if a node does not exist at a given step position. */ export const batchSteps = ({ doc, steps: maybeAttrSteps }) => { if (!isValidSteps(maybeAttrSteps)) { // This is important to avoid any bad usage to ending up with data loss throw new Error('BatchAttrsSteps error: Invalid BatchStep usage - non attribute step used'); } const positionsAndAttributesData = groupAttributesPerPosition(maybeAttrSteps); const data = positionsAndAttributesData.map(({ position, attrs }) => { const maybeNode = doc.nodeAt(position); if (!maybeNode) { throw new Error(`BatchAttrsSteps error: Node does not exist at the position ${position}.`); } const nodeType = maybeNode.type.name; return { position, attrs, nodeType }; }); return new BatchAttrsStep(data); };