{"version":3,"sources":["jsdelivr-header.js","/npm/ramunarasinga-changesets-demo@2.1.7/dist/index.js"],"names":[],"mappings":"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","file":"/npm/ramunarasinga-changesets-demo@2.1.7/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/ramunarasinga-changesets-demo@2.1.7/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { isNodeEmpty as isNodeEmpty$1, Extension, Node as Node$1, mergeAttributes } from '@tiptap/core';\nimport { keymap } from '@tiptap/pm/keymap';\nimport { Selection, TextSelection, Plugin, PluginKey } from '@tiptap/pm/state';\nimport { DOMSerializer } from '@tiptap/pm/model';\n\n/**\n * @file /src/constants/paperSize.ts\n * @name PaperSize\n * @description Constants for the paper sizes\n */\nconst DEFAULT_PAPER_SIZE = \"A4\";\nconst aPaperSizes = {\n  A0: {\n    width: 841,\n    height: 1189\n  },\n  A1: {\n    width: 594,\n    height: 841\n  },\n  A2: {\n    width: 420,\n    height: 594\n  },\n  A3: {\n    width: 297,\n    height: 420\n  },\n  A4: {\n    width: 210,\n    height: 297\n  },\n  A5: {\n    width: 148,\n    height: 210\n  },\n  A6: {\n    width: 105,\n    height: 148\n  },\n  A7: {\n    width: 74,\n    height: 105\n  },\n  A8: {\n    width: 52,\n    height: 74\n  },\n  A9: {\n    width: 37,\n    height: 52\n  },\n  A10: {\n    width: 26,\n    height: 37\n  },\n  A11: {\n    width: 18,\n    height: 26\n  },\n  A12: {\n    width: 13,\n    height: 18\n  },\n  A13: {\n    width: 9,\n    height: 13\n  },\n  \"2A0\": {\n    width: 1189,\n    height: 1682\n  },\n  \"4A0\": {\n    width: 1682,\n    height: 2378\n  },\n  \"A0+\": {\n    width: 914,\n    height: 1292\n  },\n  \"A1+\": {\n    width: 609,\n    height: 914\n  },\n  \"A3+\": {\n    width: 329,\n    height: 483\n  }\n};\nconst bPaperSizes = {\n  B0: {\n    width: 1000,\n    height: 1414\n  },\n  B1: {\n    width: 707,\n    height: 1000\n  },\n  B2: {\n    width: 500,\n    height: 707\n  },\n  B3: {\n    width: 353,\n    height: 500\n  },\n  B4: {\n    width: 250,\n    height: 353\n  },\n  B5: {\n    width: 176,\n    height: 250\n  },\n  B6: {\n    width: 125,\n    height: 176\n  },\n  B7: {\n    width: 88,\n    height: 125\n  },\n  B8: {\n    width: 62,\n    height: 88\n  },\n  B9: {\n    width: 44,\n    height: 62\n  },\n  B10: {\n    width: 31,\n    height: 44\n  },\n  B11: {\n    width: 22,\n    height: 31\n  },\n  B12: {\n    width: 15,\n    height: 22\n  },\n  B13: {\n    width: 11,\n    height: 15\n  },\n  \"B0+\": {\n    width: 1118,\n    height: 1580\n  },\n  \"B1+\": {\n    width: 720,\n    height: 1020\n  },\n  \"B2+\": {\n    width: 520,\n    height: 720\n  }\n};\nconst cPaperSizes = {\n  C0: {\n    width: 917,\n    height: 1297\n  },\n  C1: {\n    width: 648,\n    height: 917\n  },\n  C2: {\n    width: 458,\n    height: 648\n  },\n  C3: {\n    width: 324,\n    height: 458\n  },\n  C4: {\n    width: 229,\n    height: 324\n  },\n  C5: {\n    width: 162,\n    height: 229\n  },\n  C6: {\n    width: 114,\n    height: 162\n  },\n  C7: {\n    width: 81,\n    height: 114\n  },\n  C8: {\n    width: 57,\n    height: 81\n  },\n  C9: {\n    width: 40,\n    height: 57\n  },\n  C10: {\n    width: 28,\n    height: 40\n  }\n};\nconst usPaperSizes = {\n  Letter: {\n    width: 216,\n    height: 279\n  },\n  Legal: {\n    width: 216,\n    height: 356\n  },\n  Tabloid: {\n    width: 279,\n    height: 432\n  },\n  Ledger: {\n    width: 432,\n    height: 279\n  },\n  \"Junior Legal\": {\n    width: 127,\n    height: 203\n  },\n  \"Half Letter\": {\n    width: 140,\n    height: 216\n  },\n  \"Government Letter\": {\n    width: 203,\n    height: 267\n  },\n  \"Government Legal\": {\n    width: 216,\n    height: 330\n  },\n  \"ANSI A\": {\n    width: 216,\n    height: 279\n  },\n  \"ANSI B\": {\n    width: 279,\n    height: 432\n  },\n  \"ANSI C\": {\n    width: 432,\n    height: 559\n  },\n  \"ANSI D\": {\n    width: 559,\n    height: 864\n  },\n  \"ANSI E\": {\n    width: 864,\n    height: 1118\n  },\n  \"Arch A\": {\n    width: 229,\n    height: 305\n  },\n  \"Arch B\": {\n    width: 305,\n    height: 457\n  },\n  \"Arch C\": {\n    width: 457,\n    height: 610\n  },\n  \"Arch D\": {\n    width: 610,\n    height: 914\n  },\n  \"Arch E\": {\n    width: 914,\n    height: 1219\n  },\n  \"Arch E1\": {\n    width: 762,\n    height: 1067\n  },\n  \"Arch E2\": {\n    width: 660,\n    height: 965\n  },\n  \"Arch E3\": {\n    width: 686,\n    height: 991\n  }\n};\nconst paperDimensions = {\n  ...aPaperSizes,\n  ...bPaperSizes,\n  ...cPaperSizes,\n  ...usPaperSizes\n};\nconst paperSizes = Object.keys(paperDimensions);\n\n/**\n * @file /src/constants/paperColours.ts\n * @name PaperColours\n * @description Constants for paper colours in the editor.\n */\nconst LIGHT_PAPER_COLOUR = \"#fff\";\nconst DARK_PAPER_COLOUR = \"#222\";\nconst DEFAULT_PAPER_COLOUR = LIGHT_PAPER_COLOUR;\n\n/**\n * @file /src/constants/pageMargins.ts\n * @name PageMargins\n * @description Constants for page margins in the editor.\n */\n/**\n * Common margin configurations for different margin sizes.\n */\nconst commonMarginConfigs = {\n  normal: {\n    top: 25.4,\n    right: 25.4,\n    bottom: 25.4,\n    left: 25.4\n  },\n  narrow: {\n    top: 12.7,\n    right: 12.7,\n    bottom: 12.7,\n    left: 12.7\n  },\n  moderate: {\n    top: 25.4,\n    right: 19.1,\n    bottom: 25.4,\n    left: 19.1\n  },\n  wide: {\n    top: 25.4,\n    right: 50.8,\n    bottom: 25.4,\n    left: 50.8\n  }\n};\n/**\n * The common margin name for the default margin configuration.\n */\nconst DEFAULT_PAGE_MARGIN_NAME = \"normal\";\n/**\n * Standard margins are 1 inch or 25.4mm on all sides.\n */\nconst DEFAULT_PAGE_MARGIN_CONFIG = commonMarginConfigs[DEFAULT_PAGE_MARGIN_NAME];\n/**\n * Default x margin configuration.\n */\nconst DEFAULT_X_MARGIN_CONFIG = {\n  left: DEFAULT_PAGE_MARGIN_CONFIG.left,\n  right: DEFAULT_PAGE_MARGIN_CONFIG.right\n};\n\n/**\n * @file /src/utils/string.ts\n * @name String\n * @description Utility functions for string manipulation.\n */\n/**\n * Converts a string to title case.\n *\n * @param str - The input string to convert.\n * @returns {string} The string in title case.\n */\nconst titleCase = str => {\n  return str.replace(/\\b\\w/g, char => char.toUpperCase());\n};\n\n/**\n * @file /src/constants/pageMargins.ts\n * @name PageMargins\n * @description Constants for page margins in the editor.\n */\nconst paperOrientations = [\"portrait\", \"landscape\"];\n/**\n * A mapped version of the paper orientations where the oreintation is the key\n * and the label is the title cased version of the orientation. E.g. can be used\n * in a select input.\n */\nconst paperOrientationsSelect = paperOrientations.map(orientation => ({\n  orientation,\n  label: titleCase(orientation)\n}));\nconst DEFAULT_PAPER_ORIENTATION = \"portrait\";\n\n/**\n * @file /src/constants/pageBorders.ts\n * @name PageBorders\n * @description Constants for page borders in the editor.\n */\nconst DEFAULT_PAGE_BORDER_CONFIG = {\n  top: 1,\n  right: 1,\n  bottom: 1,\n  left: 1\n};\n\n/**\n * @file /src/constants/page.ts\n * @name Page\n * @description Constants for page nodes in the editor.\n */\nconst PAGE_NODE_NAME = \"page\";\nconst PAGE_NODE_ATTR_KEYS = {\n  paperSize: \"paperSize\",\n  paperColour: \"paperColour\",\n  paperOrientation: \"paperOrientation\",\n  pageBorders: \"pageBorders\"\n};\nconst PAGE_ATTRIBUTES = {\n  paperSize: {\n    default: DEFAULT_PAPER_SIZE\n  },\n  paperColour: {\n    default: DEFAULT_PAPER_COLOUR\n  },\n  paperOrientation: {\n    default: DEFAULT_PAPER_ORIENTATION\n  },\n  pageBorders: {\n    default: DEFAULT_PAGE_BORDER_CONFIG\n  }\n};\n// ====== Page Gap ======\nconst DEFAULT_PAGE_GAP = 12;\n\n/**\n * @file /src/constants/pagination.ts\n * @name Pagination\n * @description Pagination constants.\n */\nconst PAGINATION_EXTENSION_NAME = \"pagination\";\nconst MIN_PARAGRAPH_HEIGHT = 40;\n\n/**\n * @file /src/constants/pageAmendment.ts\n * @name PageAmendment\n * @description Constants for page amendment in the editor.\n */\nconst DEFAULT_PAGE_AMENDMENT_CONFIG = {\n  enableFooter: true,\n  enableHeader: true\n};\n\n/**\n * @file /src/constants/body.ts\n * @name Body\n * @description Constants for body node in the editor.\n */\nconst BODY_NODE_NAME = \"body\";\n/**\n * Lookup keys for body node attributes.\n */\nconst BODY_NODE_ATTR_KEYS = {\n  pageMargins: \"pageMargins\"\n};\n/**\n * The default body node attributes.\n */\nconst BODY_DEFAULT_ATTRIBUTES = {\n  pageMargins: DEFAULT_PAGE_MARGIN_CONFIG\n};\n/**\n * The body node attributes.\n */\nconst BODY_ATTRIBUTES = {\n  pageMargins: {\n    default: DEFAULT_PAGE_MARGIN_CONFIG\n  }\n};\n\n/**\n * @file /src/utils/object.ts\n * @name Object\n * @description Utility functions for object manipulation.\n */\n/**\n * Determines if a string needs to be JSON parsed.\n *\n * @param value - The value to check.\n * @returns {boolean} True if the value needs to be parsed, false otherwise.\n */\nconst needsParsing = value => {\n  if (typeof value !== \"string\" || value.trim() === \"\") {\n    return false; // Exclude non-strings or empty strings\n  }\n  // Normalize to avoid trailing/leading spaces affecting checks\n  const normalized = value.trim();\n  // Check for JSON-like structures\n  return normalized.startsWith(\"{\") ||\n  // Object\n  normalized.startsWith(\"[\") ||\n  // Array\n  normalized.startsWith('\"') ||\n  // Quoted string\n  normalized.startsWith(\"'\") ||\n  // Single-quoted string\n  normalized.startsWith(\"`\") ||\n  // Template string\n  normalized === \"null\" ||\n  // Null value\n  normalized === \"true\" ||\n  // Boolean true\n  normalized === \"false\" ||\n  // Boolean false\n  !isNaN(normalized) // Numeric strings like \"123\" or \"0.5\"\n  ;\n};\n/**\n * Wrap JSON.parse. Checks if the value needs to be parsed before attempting to parse it.\n * Handles errors by returning the original value if it cannot be parsed.\n *\n * @param value - The value to parse.\n * @returns - The parsed value or the original value if it does not need to be parsed.\n */\nconst wrapJSONParse = value => {\n  if (!needsParsing(value)) {\n    return value;\n  }\n  try {\n    return JSON.parse(value);\n  } catch (e) {\n    return value;\n  }\n};\n\n/**\n * @file /src/utils/attributes/getAttributes.ts\n * @name GetAttributes\n * @description Utility functions for getting node attributes.\n */\n/**\n * Check if the node has the specified attribute.\n *\n * @param node - The node to check.\n * @param attr - The attribute to check for.\n * @returns {boolean} True if the node has the specified attribute, false otherwise.\n */\nconst nodeHasAttribute = (node, attr) => {\n  const {\n    attrs\n  } = node;\n  return attr in attrs && attrs[attr] !== undefined && attrs[attr] !== null;\n};\n/**\n * A function used to compute the attributes for the node or mark\n * created by this rule. Can also be used to describe further\n * conditions the DOM element or style must match.\n *\n * @param nodeTagAttribute - The attribute of the node tag.\n * @param preventNestedNodes - True if nested nodes should be prevented, false otherwise.\n * @returns {Attrs | false | null} When it returns `false`, the rule won't match.\n * When it returns null or undefined, that is interpreted as an empty/default set of\n * attributes.\n */\nconst parseHTMLNodeGetAttrs = (nodeTagAttribute, preventNestedNodes) => node => {\n  const parent = node.parentElement;\n  {\n    if (parent && parent.hasAttribute(nodeTagAttribute)) {\n      return false;\n    }\n  }\n  const attrs = Array.from(node.attributes);\n  return attrs.reduce((acc, attribute) => {\n    const {\n      name,\n      value\n    } = attribute;\n    if (name in acc) {\n      return acc;\n    }\n    return {\n      ...acc,\n      [name]: wrapJSONParse(value)\n    };\n  }, {});\n};\n\n/**\n * @file /src/utils/node.ts\n * @name Node\n * @description Utility functions for creating custom nodes in the editor.\n */\n/**\n * Get the type of the node at the specified position.\n *\n * @param $pos - The resolved position in the document.\n * @returns {ResolvedPos} The type of the node at the specified position.\n */\nconst getPositionNodeType = $pos => {\n  return $pos.parent.type.name;\n};\n/**\n * Retrieves the size of a ProseMirror node if it is defined, otherwise returns 0.\n *\n * @param node - The ProseMirror node which may be undefined.\n * @returns The size of the node if it is defined, otherwise 0.\n */\nconst getMaybeNodeSize = node => {\n  return node?.nodeSize ?? 0;\n};\n/**\n * Check if the node type matches the specified type.\n *\n * @param node - The node to check.\n * @param type - The type of the node to match. Can be string or an array of strings.\n * @returns {boolean} True if the node type matches, false otherwise.\n */\nconst doesNodeTypeMatch = (node, type) => {\n  if (!node) {\n    return false;\n  }\n  const nodeTypeName = node.type.name;\n  if (Array.isArray(type)) {\n    return type.includes(nodeTypeName);\n  }\n  return nodeTypeName === type;\n};\n/**\n * Get the parent node position of the specified type.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @param type - The type of the node to search for. Can be string or an array of strings.\n * @returns {ResolvedPos} The position of the parent node of the specified type.\n */\nconst getParentNodePosOfType = (doc, $pos, type) => {\n  // Base case: If the position is a number, resolve it\n  if (typeof $pos !== \"number\") {\n    const thisNode = doc.nodeAt($pos.pos);\n    if (thisNode) {\n      if (doesNodeTypeMatch(thisNode, type)) {\n        return $pos;\n      }\n    }\n    if ($pos.pos === 0) {\n      // We have not found the node of the specified type\n      console.error(`Could not find node of type ${type}`);\n      return $pos;\n    }\n    try {\n      return getParentNodePosOfType(doc, $pos.before(), type);\n    } catch (error) {\n      return getParentNodePosOfType(doc, doc.resolve($pos.pos - 1), type);\n    }\n  }\n  const thisPos = doc.resolve($pos);\n  // Base case: If the node at the position is of the specified type, return the position\n  if (doesNodeTypeMatch(doc.nodeAt($pos), type)) {\n    return thisPos;\n  }\n  if ($pos === 0) {\n    // We have not found the node of the specified type\n    console.error(`Could not find node of type ${type}`);\n    return thisPos;\n  }\n  // Recursive case: Move one level up and check again\n  const prevPos = thisPos.before();\n  return getParentNodePosOfType(doc, prevPos, type);\n};\n/**\n * Append the new node to the existing node and replace the existing node with the new node.\n *\n * @param tr - The current transaction.\n * @param pos - The position to replace the node at.\n * @param existingNode - The existing node to replace.\n * @param newNode - The new node to append and replace with.\n * @returns {void}\n */\nconst appendAndReplaceNode = (tr, pos, existingNode, newNode) => {\n  const newContent = existingNode.content.append(newNode.content);\n  tr.replaceWith(pos, pos + existingNode.nodeSize - 1, newContent);\n};\n/**\n * Delete the node at the specified position.\n *\n * @param tr - The current transaction.\n * @param pos - The position of the node to delete.\n * @param node - The node to delete.\n * @returns {void}\n */\nconst deleteNode = (tr, pos, node) => {\n  tr.delete(pos, pos + node.nodeSize);\n};\n/**\n * Check if the node is empty.\n *\n * @param node - The node to check.\n * @returns {boolean} True if the node is empty, false otherwise.\n */\nconst isNodeEmpty = node => {\n  return node.content.size === 0;\n};\n/**\n * A rule that matches a node based on the specified tag and attribute.\n *\n * @param baseElement - The base element to match.\n * @param nodeTagAttribute - The attribute of the node tag.\n * @param preventNestedNodes - True if nested nodes should be prevented, false otherwise.\n * @returns {TagParseRule} The rule that matches the node based on the specified tag and attribute.\n */\nconst parseHTMLNode = (baseElement, nodeTagAttribute, preventNestedNodes) => ({\n  tag: `${baseElement}[${nodeTagAttribute}]`,\n  getAttrs: parseHTMLNodeGetAttrs(nodeTagAttribute)\n});\n/**\n * Check if the given node is atomic.\n *\n * @param node - The node to check.\n * @returns {boolean} True if the node is a text node, false otherwise.\n */\nconst isAtomNode = (view, node) => {\n  const pos = view.posAtDOM(node, 0);\n  const pmNode = view.state.doc.nodeAt(pos);\n  return !!(pmNode && pmNode.type.spec.atom);\n};\n\n/**\n * @file /src/utils/math.ts\n * @name Math\n * @description Utility functions for mathematical operations.\n */\n/**\n * Checks if a value is within a specified range inclusive of the bounds.\n *\n * @param value - The value to check.\n * @param min - The minimum value of the range.\n * @param max - The maximum value of the range.\n * @returns True if the value is within the range, false otherwise.\n */\nconst inRange = (value, min, max) => {\n  return value >= min && value <= max;\n};\n/**\n * Calculates the hypotenuse of a right triangle given the lengths of the other two sides.\n *\n * @param a - The length of side A.\n * @param b - The length of side B.\n * @returns The length of the hypotenuse.\n */\nconst pythagoreanTheorem = (a, b) => {\n  return Math.sqrt(a ** 2 + b ** 2);\n};\n/**\n * Generic binary search function.\n *\n * @param arr - The sorted array to search.\n * @param target - The target value to search for.\n * @param compare - A comparison function that returns:\n *                  - A negative number if `target` < element at current index\n *                  - Zero if `target` === element at current index\n *                  - A positive number if `target` > element at current index\n * @returns {number} - The index of the target element, or null if not found.\n */\nconst binarySearch = (arr, target, compare) => {\n  let low = 0;\n  let high = arr.length - 1;\n  while (low <= high) {\n    const mid = Math.floor((low + high) / 2);\n    const comparison = compare(target, arr[mid]);\n    if (comparison === 0) {\n      return mid; // Found the target\n    }\n    if (comparison < 0) {\n      high = mid - 1; // Search in the left half\n    } else {\n      low = mid + 1; // Search in the right half\n    }\n  }\n  return high;\n};\n/**\n * Find the index of the closest element in an array to a target value.\n *\n * @param arr - The array to search.\n * @param target - The target value to find the closest element to.\n * @returns The index of the closest element in the array.\n */\nconst findClosestIndex = (arr, target) => {\n  let lo = 0,\n    hi = arr.length - 1;\n  let closestIndex = -1;\n  let closestDistance = Infinity;\n  while (lo <= hi) {\n    let mid = lo + Math.floor((hi - lo) / 2);\n    const currentDistance = Math.abs(arr[mid] - target);\n    // Update closestIndex if mid is closer to target\n    if (currentDistance < closestDistance) {\n      closestDistance = currentDistance;\n      closestIndex = mid;\n      // In case of a tie, prefer the larger value\n    } else if (currentDistance === closestDistance) {\n      closestIndex = Math.max(closestIndex, mid);\n    }\n    if (arr[mid] === target) {\n      return mid; // If we find an exact match\n    } else if (arr[mid] < target) {\n      lo = mid + 1;\n    } else {\n      hi = mid - 1;\n    }\n  }\n  return closestIndex;\n};\n\n/**\n * @file /src/components/TipTap/utils/selection.ts\n * @name Selection\n * @description Utility functions for working with selections in the editor.\n */\n/**\n * Check if the editor is currently highlighting text.\n *\n * @param state - The current editor state.\n * @returns True if text is currently highlighted, false otherwise.\n */\nconst isHighlighting = state => {\n  const {\n    from,\n    to\n  } = state.selection;\n  return from !== to;\n};\n/**\n * Get the resolved position in the document.\n *\n * @param state - The current editor state.\n * @returns The resolved position in the document.\n */\nconst getResolvedPosition = state => {\n  const {\n    from\n  } = state.selection;\n  const $pos = state.doc.resolve(from);\n  return $pos;\n};\n/**\n * Set the selection at the specified anchor and head positions. If head is not provided,\n * it will be set to the anchor position.\n *\n * @param tr - The current transaction.\n * @param anchor - The anchor position.\n * @param head - The head position.\n * @returns The updated transaction.\n */\nconst setSelectionAtPos = (tr, anchor, head) => {\n  const selection = TextSelection.create(tr.doc, anchor, anchor);\n  return setSelection(tr, selection);\n};\n/**\n * Set the selection to the specified selection object.\n *\n * @param tr - The current transaction.\n * @param selection - The selection object.\n * @returns The updated transaction.\n */\nconst setSelection = (tr, selection) => {\n  console.log(\"Setting selection to\", selection.$anchor.pos, \"-\", selection.$head.pos);\n  return tr.setSelection(selection);\n};\n/**\n * Set the selection at the end of the document.\n *\n * @param tr - The current transaction.\n * @returns The updated transaction.\n */\nconst setSelectionAtEndOfDocument = tr => {\n  return setSelectionAtPos(tr, tr.doc.content.size);\n};\n/**\n * Set the selection to the start of the paragraph.\n *\n * @param tr - The current transaction.\n * @param paragraphPos - The position of the paragraph in the document.\n * @param paragraphNode - The paragraph node.\n * @returns {void}\n */\nconst setSelectionToStartOfParagraph = (tr, paragraphPos, paragraphNode) => {\n  if (isNodeEmpty(paragraphNode)) {\n    const selection = moveToThisTextBlock(tr, paragraphPos, 1);\n    setSelection(tr, selection);\n  } else {\n    const paragraphStartPos = tr.doc.resolve(paragraphPos + 1);\n    moveToNearestTextSelection(tr, paragraphStartPos, 1);\n  }\n};\n/**\n * Set the selection to the paragraph with an optional offset.\n *\n * @param tr - The current transaction.\n * @param paragraphPos - The position of the paragraph in the document.\n * @param paragraphNode - The paragraph node.\n * @param offsetInNode - The offset in the paragraph node. Default is 0.\n * @returns {void}\n */\nconst setSelectionToParagraph = (tr, paragraphPos, paragraphNode, offsetInNode = 0) => {\n  if (isNodeEmpty(paragraphNode)) {\n    // Node will not have a text selection so move to the start of the paragraph\n    setSelectionToStartOfParagraph(tr, paragraphPos, paragraphNode);\n  } else {\n    if (!inRange(offsetInNode, 0, paragraphNode.nodeSize - 1)) {\n      console.warn(\"Cannot set selection: Invalid offset in node. Node is of size\", paragraphNode.nodeSize);\n      return;\n    }\n    const paragraphPosWithOffset = paragraphPos + offsetInNode;\n    const $pos = tr.doc.resolve(paragraphPosWithOffset);\n    moveToNearestTextSelection(tr, $pos, 1);\n  }\n};\n/**\n * Set the selection to the end of the paragraph.\n *\n * @param tr - The current transaction.\n * @param paragraphPos - The position of the paragraph in the document.\n * @param paragraphNode - The paragraph node.\n * @returns {void}\n */\nconst setSelectionToEndOfParagraph = (tr, paragraphPos, paragraphNode) => {\n  if (isNodeEmpty(paragraphNode)) {\n    // Node will not have a text selection so move to the start=end of the paragraph\n    setSelectionToStartOfParagraph(tr, paragraphPos, paragraphNode);\n  } else {\n    const paragraphEndPos = tr.doc.resolve(paragraphPos + paragraphNode.nodeSize - 1);\n    moveToNearestTextSelection(tr, paragraphEndPos, -1);\n  }\n};\n/**\n * Move the cursor to the previous text block.\n *\n * @param tr - The current transaction.\n * @param $pos - The resolved position in the document.\n * @returns {Selection} The new selection.\n */\nconst moveToPreviousTextBlock = (tr, $pos) => {\n  if (typeof $pos === \"number\") {\n    return moveToPreviousTextBlock(tr, tr.doc.resolve($pos));\n  }\n  const prevPos = $pos.pos - 1;\n  const prevResPos = tr.doc.resolve(prevPos);\n  const searchDirection = -1;\n  const selection = Selection.near(prevResPos, searchDirection);\n  return selection;\n};\n/**\n * Caps the offset in the node to the length of the node.\n *\n * @param tr - The current transaction.\n * @param $pos - The resolved position in the document.\n * @param offsetInNode - The offset in the node.\n * @returns {number} The capped offset in the node.\n */\nconst capOffsetInNode = (tr, $pos, offsetInNode) => {\n  const thisNode = tr.doc.nodeAt($pos.pos);\n  if (!thisNode) {\n    console.warn(`Unable to resolve node at position ${$pos.pos}. Capping offset to 0`);\n    return offsetInNode;\n  }\n  return Math.min(offsetInNode, thisNode.nodeSize - 1);\n};\n/**\n * Move the cursor to the current text block.\n *\n * @param tr - The current transaction.\n * @param $pos - The resolved position in the document.\n * @param bias - The search direction. Default is 1 (forward).\n * @param offsetInNode - The offset in the node. Default is 0. Will cap at the length of the node.\n * @returns {Selection} The new selection.\n */\nconst moveToThisTextBlock = (tr, $pos, bias = 1, offsetInNode = 0) => {\n  if (typeof $pos === \"number\") {\n    $pos = tr.doc.resolve($pos);\n  }\n  const adjustedOffset = capOffsetInNode(tr, $pos, offsetInNode);\n  const offsetPos = $pos.pos + adjustedOffset;\n  const $offsetPos = tr.doc.resolve(offsetPos);\n  const selection = Selection.near($offsetPos, bias);\n  return selection;\n};\n/**\n * Move the cursor to the next text block.\n *\n * @param tr - The current transaction.\n * @param $pos - The resolved position in the document.\n * @returns {Selection} The new selection.\n */\nconst moveToNextTextBlock = (tr, $pos) => {\n  if (typeof $pos === \"number\") {\n    return moveToNextTextBlock(tr, tr.doc.resolve($pos));\n  }\n  const nextPos = $pos.pos + 1;\n  const nextResPos = tr.doc.resolve(nextPos);\n  const searchDirection = 1;\n  const selection = Selection.near(nextResPos, searchDirection);\n  return selection;\n};\n/**\n * Move the cursor to the nearest text selection.\n *\n * @param tr - The current transaction.\n * @param $pos - The resolved position in the document.\n * @param bias - The search direction.\n * @returns {void} The new selection.\n */\nconst moveToNearestTextSelection = (tr, $pos, bias = 1) => {\n  const textSelection = getNearestTextSelection($pos, bias);\n  setSelection(tr, textSelection);\n};\n/**\n * Get the nearest text selection to the given position.\n *\n * @param $pos - The resolved position in the document.\n * @param bias - The search direction.\n * @returns {Selection} The nearest text selection.\n */\nconst getNearestTextSelection = ($pos, bias = 1) => {\n  return TextSelection.near($pos, bias);\n};\n/**\n * Move the cursor to the nearest valid cursor position.\n *\n * @param tr - The current transaction.\n * @param $pos - The resolved position in the document.\n * @returns {Selection} The new selection.\n */\nconst moveToNearestValidCursorPosition = $pos => {\n  const selection = Selection.findFrom($pos, 1, true) || Selection.findFrom($pos, -1, true);\n  return selection;\n};\n\n/**\n * @file /src/utils/nodes/document.ts\n * @name Document\n * @description Utility functions for the document node.\n */\n/**\n * Check if the given position is at the start of the document.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @param allowTextBlock - Whether to allow text blocks at the start of the document. Default is false.\n * @returns {boolean} True if the position is at the start of the document, false otherwise.\n */\nconst isPosAtStartOfDocument = (doc, $pos, allowTextBlock) => {\n  if (typeof $pos === \"number\") {\n    return isPosAtStartOfDocument(doc, doc.resolve($pos));\n  }\n  const maxPos = 1;\n  return $pos.pos <= maxPos;\n};\n/**\n * Check if the given position is at the end of the document.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the end of the document, false otherwise.\n */\nconst isPosAtEndOfDocument = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return isPosAtEndOfDocument(doc, doc.resolve($pos));\n  }\n  return $pos.pos >= doc.nodeSize - 2;\n};\n\n/**\n * @file /src/utils/pageRegion/body.ts\n * @name Body\n * @description Utility functions for body in the editor.\n */\n/**\n * Check if the given node is a body node.\n *\n * @param node - The node to check.\n * @returns {boolean} True if the node is a body node, false otherwise.\n */\nconst isBodyNode = node => {\n  if (!node) {\n    console.warn(\"No node provided\");\n    return false;\n  }\n  return node.type.name === BODY_NODE_NAME;\n};\n/**\n * Retrieves the body node attributes, filling in any missing attributes with the default values.\n * @param bodyNode - The body node to retrieve the attributes for.\n * @returns {BodyNodeAttributes} The attributes of the specified body.\n */\nconst getBodyNodeAttributes = bodyNode => {\n  const {\n    attrs\n  } = bodyNode;\n  return {\n    ...BODY_DEFAULT_ATTRIBUTES,\n    ...attrs\n  };\n};\n/**\n * Get the page margins from a body node.\n *\n * @param bodyNode - The body node to get the page margins from.\n * @returns {Nullable<MarginConfig>} The page margins of the specified page.\n */\nconst getBodyNodeMargins = bodyNode => {\n  const {\n    attrs\n  } = bodyNode;\n  return attrs[BODY_NODE_ATTR_KEYS.pageMargins];\n};\n\n/**\n * @file /src/constants/pageRegions.ts\n * @name PageRegions\n * @description Constants for page regions in the editor.\n */\nconst HEADER_FOOTER_NODE_NAME = \"header-footer\";\n/**\n * Key for the header footer node attributes.\n */\nconst HEADER_FOOTER_NODE_ATTR_KEYS = {\n  type: \"type\",\n  pageEndOffset: \"pageEndOffset\",\n  height: \"height\",\n  xMargins: \"xMargins\"\n};\n/**\n * Default attributes for header and footer nodes.\n */\nconst HEADER_FOOTER_DEFAULT_ATTRIBUTES = {\n  height: 10,\n  xMargins: {\n    left: 25.4,\n    right: 25.4\n  },\n  pageEndOffset: 10\n};\n/**\n * Default attributes for header nodes\n */\nconst HEADER_DEFAULT_ATTRIBUTES = {\n  type: \"header\",\n  ...HEADER_FOOTER_DEFAULT_ATTRIBUTES\n};\n/**\n * Default attributes for footer nodes\n */\nconst FOOTER_DEFAULT_ATTRIBUTES = {\n  type: \"footer\",\n  ...HEADER_FOOTER_DEFAULT_ATTRIBUTES\n};\n/**\n * The header/footer node attributes.\n */\nconst HEADER_FOOTER_ATTRIBUTES = Object.fromEntries(Object.entries(HEADER_DEFAULT_ATTRIBUTES).map(([key, value]) => [key, {\n  default: value\n}]));\n\n/**\n * @file /src/utils/page.ts\n * @name Page\n * @description Utility functions for page nodes in the editor.\n */\n/**\n * Check if the given node is a page node.\n *\n * @param node - The node to check.\n * @returns {boolean} True if the node is a page node, false otherwise.\n */\nconst isPageNode = node => {\n  if (!node) {\n    console.warn(\"No node provided\");\n    return false;\n  }\n  return node.type.name === PAGE_NODE_NAME;\n};\n/**\n * Check if the document has page nodes.\n *\n * @param state - The editor state.\n * @returns {boolean} True if the document has page nodes, false otherwise.\n */\nconst doesDocHavePageNodes = state => {\n  const {\n    schema\n  } = state;\n  const pageType = schema.nodes.page;\n  let hasPageNodes = false;\n  state.doc.forEach(node => {\n    if (node.type === pageType) {\n      hasPageNodes = true;\n      return false;\n    }\n  });\n  return hasPageNodes;\n};\n/**\n * Collect page nodes and their positions in the document.\n *\n * @param doc - The document node.\n * @returns {NodePosArray} A map of page positions to page nodes.\n */\nconst collectPageNodes = doc => {\n  const pageNodes = [];\n  doc.forEach((node, offset) => {\n    if (isPageNode(node)) {\n      pageNodes.push({\n        node,\n        pos: offset\n      });\n    }\n  });\n  return pageNodes;\n};\n/**\n * Given a position in the document, get the child node of the page node at that position.\n * I.e. that will be a header/footer node or a body node.\n * @param doc - The document node.\n * @param $pos - The resolved position in the document.\n * @returns {NullableNodePos} The child node position of the page node at the given position.\n */\nconst getPageChildNodePosFromPosition = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return getPageChildNodePosFromPosition(doc, doc.resolve($pos));\n  }\n  const pageChildPos = getParentNodePosOfType(doc, $pos, [BODY_NODE_NAME, HEADER_FOOTER_NODE_NAME]);\n  const pageChildNode = doc.nodeAt(pageChildPos.pos);\n  if (!pageChildNode) {\n    console.warn(\"No page child node found\");\n    return {\n      pos: -1,\n      node: pageChildNode\n    };\n  }\n  return {\n    pos: pageChildPos.pos,\n    node: pageChildNode\n  };\n};\n\n/**\n * @file /src/utils/nodes/page/pageRange.ts\n * @name PageRange\n * @description Utility functions for page ranges.\n */\n/**\n * Get the page number of the given node.\n *\n * @param node - The node to get the page number for.\n * @returns {Nullable<number>} The page number of the node or null if the node is not a page node.\n */\nconst getNumPagesInDoc = doc => {\n  return doc.childCount;\n};\n/**\n * Get the last page number in the document (0-indexed).\n * @param doc - The current document.\n * @returns {number} The last page number in the document (0-indexed).\n */\nconst getLastPageNum = doc => {\n  return getNumPagesInDoc(doc) - 1;\n};\n/**\n * Handles cases where the given page number is out of range.\n * Logs a warning and falls back to the last page number.\n *\n * @param state - The current editor state.\n * @param pageNum - The page number to validate.\n * @param fallbackFn - A function to determine the fallback value based on the last page number.\n * @returns {T} The result of the fallback function.\n */\nconst handleOutOfRangePageNum = (state, pageNum, fallbackFn) => {\n  console.warn(\"Page number:\", pageNum, \"is out of range for the document. Using last page.\");\n  const lastPageNum = getLastPageNum(state.doc);\n  return fallbackFn(state, lastPageNum);\n};\n/**\n * Check if the page number is in range for the document.\n *\n * @param doc - The current document.\n * @param pageNum - The page number to check (0-indexed).\n * @returns {boolean} True if the page number is in range, false otherwise.\n */\nconst isPageNumInRange = (doc, pageNum) => {\n  const lastPageNum = getLastPageNum(doc);\n  return inRange(pageNum, 0, lastPageNum);\n};\n\n/**\n * @file /src/utils/nodes/page/pagePosition.ts\n * @name PagePosition\n * @description Utility functions for page position nodes.\n */\n/**\n * Get the page node (parent of the current node) position.\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The position of the page node.\n */\nconst getThisPageNodePosition = (doc, pos) => {\n  return getParentNodePosOfType(doc, pos, PAGE_NODE_NAME).pos;\n};\n/**\n * Get the page node position and the page node itself.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {NullableNodePos} The position and the node of the page.\n */\nconst getPageNodeAndPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getPageNodeAndPosition(doc, doc.resolve(pos));\n  }\n  const pagePos = getThisPageNodePosition(doc, pos);\n  const pageNode = doc.nodeAt(pagePos);\n  if (!isPageNode(pageNode)) {\n    console.warn(\"No page node found\");\n    return {\n      pos: -1,\n      node: pageNode\n    };\n  }\n  return {\n    pos: pagePos,\n    node: pageNode\n  };\n};\n/**\n * Get the child of the page node at the specified position.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {DirectChild} The child of the page node at the specified position.\n */\nconst getPageChild = (doc, pos) => {\n  if (typeof pos !== \"number\") {\n    return getPageChild(doc, pos.pos);\n  }\n  return doc.childAfter(pos);\n};\n/**\n * Gets the page node of the page before the page at the specified position.\n *\n * @param doc - The document node.\n * @param pos - Any position in the current page.\n * @returns {NullableNodePos} The page node of the page before the current page.\n */\nconst getPageBeforePos = (doc, pos) => {\n  const thisPageChild = getPageChild(doc, pos);\n  const thisPageNode = thisPageChild.node;\n  if (!thisPageNode || !isPageNode(thisPageNode)) {\n    console.warn(\"No page node found\");\n    return {\n      node: null,\n      pos: -1\n    };\n  }\n  const pageNum = thisPageChild.index;\n  const prevPageNum = pageNum - 1;\n  if (!isPageNumInRange(doc, prevPageNum)) {\n    return {\n      node: null,\n      pos: -1\n    };\n  }\n  const prevPagePos = thisPageChild.offset - 1;\n  return getPageNodeAndPosition(doc, prevPagePos);\n};\n/**\n * Gets the page node of the page after the page at the specified position.\n *\n * @param doc - The document node.\n * @param pos - Any position in the current page.\n * @returns {NullableNodePos} The page node of the page after the current page.\n */\nconst getPageAfterPos = (doc, pos) => {\n  const thisPageChild = getPageChild(doc, pos);\n  const thisPageNode = thisPageChild.node;\n  if (!thisPageNode || !isPageNode(thisPageNode)) {\n    console.warn(\"No page node found\");\n    return {\n      node: null,\n      pos: -1\n    };\n  }\n  const pageNum = thisPageChild.index;\n  const nextPageNum = pageNum + 1;\n  if (!isPageNumInRange(doc, nextPageNum)) {\n    return {\n      node: null,\n      pos: -1\n    };\n  }\n  const nextPagePos = thisPageChild.offset + thisPageNode.nodeSize;\n  return getPageNodeAndPosition(doc, nextPagePos);\n};\n\n/**\n * @file /src/utils/pageRegion/pageRegion.ts\n * @name PageRegion\n * @description Utility functions for creating custom page regions in the editor.\n */\n/**\n * Determines if the given node is a header node.\n *\n * @param node - The node to check.\n * @returns {boolean} True if the node is a header node, false otherwise.\n */\nconst isHeaderFooterNode = node => {\n  return node.type.name === HEADER_FOOTER_NODE_NAME;\n};\n/**\n * Get the type of the header or footer node.\n *\n * @param headerFooterNode - The header or footer node to retrieve the type for.\n * @returns {Nullable<HeaderFooter>} The type of the specified header or footer node or null if not found.\n */\nconst getHeaderFooterNodeType = headerFooterNode => {\n  const {\n    attrs\n  } = headerFooterNode;\n  return attrs[HEADER_FOOTER_NODE_ATTR_KEYS.type];\n};\n/**\n * Get the x margins from a header or footer node.\n *\n * @param headerFooterNode - The header or footer node.\n * @returns {Nullable<XMarginConfig>} The x margins of the specified header or footer.\n */\nconst getHeaderFooterNodeXMargins = headerFooterNode => {\n  const {\n    attrs\n  } = headerFooterNode;\n  return attrs[HEADER_FOOTER_NODE_ATTR_KEYS.xMargins];\n};\n/**\n * Get the page end offset of the header or footer node.\n *\n * @param headerFooterNode - The header or footer node to retrieve the page end offset for.\n * @returns {Nullable<number>} The page end offset of the specified header or footer node or null if not found.\n */\nconst getHeaderFooterNodePageEndOffset = headerFooterNode => {\n  const {\n    attrs\n  } = headerFooterNode;\n  return attrs[HEADER_FOOTER_NODE_ATTR_KEYS.pageEndOffset];\n};\n/**\n * Get the height of the header or footer node.\n *\n * @param headerFooterNode - The header or footer node to retrieve the height for.\n * @returns {Nullable<number>} The height of the specified header or footer node or null if not found.\n */\nconst getHeaderFooterNodeHeight = headerFooterNode => {\n  const {\n    attrs\n  } = headerFooterNode;\n  return attrs[HEADER_FOOTER_NODE_ATTR_KEYS.height];\n};\n/**\n * Retrieves the header node attributes, filling in any missing attributes with the default values.\n * @param headerFooterNode - The header or footer node to retrieve the attributes for.\n * @returns {HeaderNodeAttributes} The attributes of the specified header.\n */\nconst getHeaderNodeAttributes = headerFooterNode => {\n  const {\n    attrs\n  } = headerFooterNode;\n  const mergedAttrs = {\n    ...HEADER_DEFAULT_ATTRIBUTES,\n    ...attrs\n  };\n  if (mergedAttrs.type !== \"header\") {\n    console.warn(\"Header node attributes are not of type 'header'\");\n  }\n  return mergedAttrs;\n};\n/**\n * Retrieves the footer node attributes, filling in any missing attributes with the default values.\n * @param headerFooterNode - The header or footer node to retrieve the attributes for.\n * @returns {FooterNodeAttributes} The attributes of the specified footer.\n */\nconst getFooterNodeAttributes = headerFooterNode => {\n  const {\n    attrs\n  } = headerFooterNode;\n  const mergedAttrs = {\n    ...FOOTER_DEFAULT_ATTRIBUTES,\n    ...attrs\n  };\n  if (mergedAttrs.type !== \"footer\") {\n    console.warn(\"Footer node attributes are not of type 'footer'\");\n  }\n  return mergedAttrs;\n};\n\n/**\n * @file /src/utils/nodes/page/pageNumber.ts\n * @name PageNumber\n * @description Utility functions for page numbers\n */\n/**\n * Get the page node by page number.\n *\n * @param doc - The current document.\n * @param pageNum - The page number to find the page node for (0-indexed).\n * @returns {Nullable<PMNode>} The page node of the specified page or null\n * if the page could not be found.\n */\nconst getPageNodeByPageNum = (doc, pageNum) => {\n  if (!isPageNumInRange(doc, pageNum)) {\n    console.warn(\"Page number:\", pageNum, \"is out of range for the document\");\n    return null;\n  }\n  const pageNode = doc.child(pageNum);\n  if (!isPageNode(pageNode)) {\n    console.error(\"Unexpected! Doc child num:\", pageNum, \"is not a page node!\");\n    return null;\n  }\n  return pageNode;\n};\n/**\n * Get the page node and position by page number.\n *\n * @param doc - The current document.\n * @param pageNum - The page number to find the page node for (0-indexed).\n * @returns {Nullable<NodePos>} The page node position of the specified page or null\n * if the page could not be found.\n */\nconst getPageNodePosByPageNum = (doc, pageNum) => {\n  if (!isPageNumInRange(doc, pageNum)) {\n    console.warn(\"Page number:\", pageNum, \"is out of range for the document\");\n    return null;\n  }\n  const pageNodes = collectPageNodes(doc);\n  return pageNodes[pageNum];\n};\n/**\n * Get the page number of the resolved position.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document.\n * @param zeroIndexed - Whether to return the page number as zero-indexed. Default is true.\n * @returns {number} The page number of the resolved position.\n */\nconst getPageNumber = (doc, $pos, zeroIndexed = true) => {\n  if (typeof $pos === \"number\") {\n    return getPageNumber(doc, doc.resolve($pos));\n  }\n  const {\n    pos: pagePos\n  } = getPageNodeAndPosition(doc, $pos);\n  if (pagePos < 0) {\n    console.log(\"Unable to find page node\");\n    return -1;\n  }\n  const pageNodes = collectPageNodes(doc);\n  const pageNode = pageNodes.findIndex(node => node.pos === pagePos);\n  return pageNode + (zeroIndexed ? 0 : 1);\n};\n/**\n * Retrieves a specific attribute of a given page number.\n * Falls back to defaults if the page number is invalid or the attribute is missing.\n *\n * @param state - The editor state.\n * @param pageNum - The page number to retrieve the attribute for.\n * @param defaultValue - The default value to return if the attribute is missing.\n * @param getNodeAttribute - A function to extract the attribute from the page node.\n * @returns {T} The attribute of the specified page or default.\n */\nconst getPageAttributeByPageNum = (state, pageNum, defaultValue, getNodeAttribute) => {\n  if (!doesDocHavePageNodes(state)) {\n    return defaultValue;\n  }\n  const {\n    doc\n  } = state;\n  if (!isPageNumInRange(doc, pageNum)) {\n    return handleOutOfRangePageNum(state, pageNum, (s, p) => getPageAttributeByPageNum(s, p, defaultValue, getNodeAttribute));\n  }\n  const pageNode = getPageNodeByPageNum(doc, pageNum);\n  if (!pageNode) {\n    return defaultValue;\n  }\n  return getNodeAttribute(pageNode) ?? defaultValue;\n};\n\n/**\n * @file /src/utils/pageRegion/getAttributes.ts\n * @name GetAttributes\n * @description Utility functions for getting page region attributes.\n */\n/**\n * Get the page region node of the current page by the page region type.\n *\n * @param pageNode - The page node to search for the neighbouring page region.\n * @param regionType - The type of the page region to search for.\n * @returns {Nullable<PMNode>} The neighbouring page region node or null if not found.\n */\nconst getPageRegionNode = (pageNode, regionType) => {\n  let pageRegionNode = null;\n  pageNode.forEach(node => {\n    if (isHeaderFooterNode(node)) {\n      if (getHeaderFooterNodeType(node) === regionType) {\n        pageRegionNode = node;\n      }\n    } else if (isBodyNode(node)) {\n      if (node.type.name === regionType) {\n        pageRegionNode = node;\n      }\n    }\n  });\n  return pageRegionNode;\n};\n/**\n * Get the page region node and position of the current page by the page region type.\n *\n * @param pagePos - The position of the page node to search for the neighbouring page region.\n * @param pageNode - The page node to search for the neighbouring page region.\n * @param regionType - The type of the page region to search for.\n * @returns {NullableNodePos} The neighbouring page region node and position or null if not found.\n */\nconst getPageRegionNodeAndPos = (pagePos, pageNode, regionType) => {\n  let pageRegionNode = null;\n  let pos = pagePos;\n  if (!pageNode) {\n    return {\n      node: null,\n      pos: -1\n    };\n  }\n  pageNode.forEach((node, offset) => {\n    if (!pageRegionNode) {\n      if (isHeaderFooterNode(node)) {\n        if (getHeaderFooterNodeType(node) === regionType) {\n          pageRegionNode = node;\n          pos += offset + 1;\n        }\n      } else if (isBodyNode(node)) {\n        if (node.type.name === regionType) {\n          pageRegionNode = node;\n          pos += offset + 1;\n        }\n      }\n    }\n  });\n  return {\n    node: pageRegionNode,\n    pos: pageRegionNode ? pos : -1\n  };\n};\n/**\n * Retrieves a specific attribute of a the body node of specified type of a given page number.\n * Falls back to the default value if the page number is invalid or the attribute is missing.\n *\n * @param state - The editor state.\n * @param pageNum - The page number to retrieve the attribute for.\n * @param regionType - The type of the region to retrieve the attribute for.\n * @param defaultValue - The default value to return if the attribute is missing.\n * @param getNodeAttribute - A function to retrieve the attribute from a body node.\n * @returns {T} The attribute of the specified body node or default.\n */\nconst getPageRegionAttributeByPageNum = (state, pageNum, regionType, defaultValue, getNodeAttribute) => {\n  if (!doesDocHavePageNodes(state)) {\n    return defaultValue;\n  }\n  const {\n    doc\n  } = state;\n  if (!isPageNumInRange(doc, pageNum)) {\n    return handleOutOfRangePageNum(state, pageNum, (s, p) => getPageRegionAttributeByPageNum(s, p, regionType, defaultValue, getNodeAttribute));\n  }\n  const pageNode = getPageNodeByPageNum(doc, pageNum);\n  if (!pageNode) {\n    return defaultValue;\n  }\n  const pageRegionNode = getPageRegionNode(pageNode, regionType);\n  if (!pageRegionNode) {\n    return defaultValue;\n  }\n  return getNodeAttribute(pageRegionNode) ?? defaultValue;\n};\n\n/**\n * @file /src/utils/nodes/body/bodyPosition.ts\n * @name BodyPosition\n * @description Utility functions for the body position node.\n */\n/**\n * Get the body node (parent of the current node) position.\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The position of the body node.\n */\nconst getThisBodyNodePosition = (doc, pos) => {\n  return getParentNodePosOfType(doc, pos, BODY_NODE_NAME).pos;\n};\n/**\n * Get the body node position and the body node itself.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {bodyPos: number, bodyNode: Node} The position and the node of the body.\n */\nconst getBodyNodeAndPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getBodyNodeAndPosition(doc, doc.resolve(pos));\n  }\n  const bodyPos = getThisBodyNodePosition(doc, pos);\n  const bodyNode = doc.nodeAt(bodyPos);\n  if (!isBodyNode(bodyNode)) {\n    console.warn(\"No body node found\");\n    return {\n      bodyPos: -1,\n      bodyNode\n    };\n  }\n  return {\n    bodyPos,\n    bodyNode\n  };\n};\n/**\n * Get the start of the body position.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The start position of the body.\n */\nconst getStartOfBodyPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getStartOfBodyPosition(doc, doc.resolve(pos));\n  }\n  const {\n    bodyPos\n  } = getBodyNodeAndPosition(doc, pos);\n  return bodyPos;\n};\n/**\n * Get the end of the body position.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The end position of the body.\n */\nconst getEndOfBodyPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getEndOfBodyPosition(doc, doc.resolve(pos));\n  }\n  const {\n    bodyPos,\n    bodyNode\n  } = getBodyNodeAndPosition(doc, pos);\n  if (!bodyNode) {\n    return bodyPos;\n  }\n  return bodyPos + bodyNode.content.size;\n};\n/**\n * Gets the previous page's body and positiom, if any, after the given position.\n * @param doc - The current document.\n * @param pos - Any position within the current page's body\n * @returns {NullableNodePos} The previous page's body and position, if any.\n */\nconst getBodyBeforePos = (doc, pos) => {\n  const previousPage = getPageBeforePos(doc, pos);\n  if (!previousPage.node) {\n    return previousPage;\n  }\n  const {\n    node: previousPageNode,\n    pos: previousPagePos\n  } = previousPage;\n  return getPageRegionNodeAndPos(previousPagePos, previousPageNode, BODY_NODE_NAME);\n};\n/**\n * Gets the next page's body and positiom, if any, after the given position.\n * @param doc - The current document.\n * @param pos - Any position within the current page's body\n * @returns {NullableNodePos} The next page's body and position, if any.\n */\nconst getBodyAfterPos = (doc, pos) => {\n  const nextPage = getPageAfterPos(doc, pos);\n  if (!nextPage.node) {\n    return nextPage;\n  }\n  const {\n    node: nextPageNode,\n    pos: nextPagePos\n  } = nextPage;\n  return getPageRegionNodeAndPos(nextPagePos, nextPageNode, BODY_NODE_NAME);\n};\n\n/**\n * @file /src/utils/nodes/text.ts\n * @name Text\n * @description Utility functions for text nodes.\n */\n/**\n * Check if the given node is a text node.\n *\n * @param node - The node to check.\n * @returns {boolean} True if the node is a text node, false otherwise.\n */\nconst isTextNode = node => {\n  if (!node) {\n    console.warn(\"No node provided\");\n    return false;\n  }\n  return node.type.name === \"text\";\n};\n/**\n * Check if the given position is at the start of the text node.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the start of the text node, false otherwise.\n */\nconst isAtStartOfTextNode = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return isAtStartOfTextNode(doc, doc.resolve($pos));\n  }\n  const {\n    pos: textPos,\n    node: textNode\n  } = getTextNodeAndPosition(doc, $pos);\n  if (!textNode) {\n    return false;\n  }\n  return $pos.pos === textPos;\n};\n/**\n * Check if the given position is at the end of the text node.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the end of the text node, false otherwise.\n */\nconst isAtEndOfTextNode = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return isAtEndOfTextNode(doc, doc.resolve($pos));\n  }\n  const {\n    pos: textPos,\n    node: textNode\n  } = getTextNodeAndPosition(doc, $pos);\n  if (!textNode) {\n    return false;\n  }\n  return $pos.pos + 1 === textPos + textNode.nodeSize;\n};\n/**\n * Get the position of the text node.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The position of the text node.\n */\nconst getThisTextNodePosition = (doc, pos) => {\n  return getParentNodePosOfType(doc, pos, \"text\").pos;\n};\n/**\n * Get the text node and the position of the text node.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {NullableNodePos} The text node and the position of the text node.\n */\nconst getTextNodeAndPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getTextNodeAndPosition(doc, doc.resolve(pos));\n  }\n  const textPos = getThisTextNodePosition(doc, pos);\n  const textNode = doc.nodeAt(textPos);\n  if (!isTextNode(textNode)) {\n    console.warn(\"No text node found\");\n    return {\n      pos: -1,\n      node: textNode\n    };\n  }\n  return {\n    pos: textPos,\n    node: textNode\n  };\n};\n/**\n * Measure the width and height of a text node.\n *\n * @param text - The text content of the node.\n * @param computedStyles - The computed styles of the node.\n * @returns {DOMRect} The bounding rectangle of the text node.\n */\nconst measureText = (text, computedStyles) => {\n  const span = document.createElement(\"span\");\n  span.textContent = text;\n  span.style.position = \"absolute\";\n  span.style.visibility = \"hidden\";\n  span.style.whiteSpace = \"nowrap\";\n  span.style.font = computedStyles.font;\n  span.style.letterSpacing = computedStyles.letterSpacing;\n  span.style.wordSpacing = computedStyles.wordSpacing;\n  span.style.lineHeight = computedStyles.lineHeight;\n  document.body.appendChild(span);\n  const clientBoundingRect = span.getBoundingClientRect();\n  document.body.removeChild(span);\n  return clientBoundingRect;\n};\n/**\n * Measure the cumulative width of each character in a text node.\n *\n * @param textContent - The text content of the node.\n * @param computedStyles - The computed styles of the node.\n * @returns {number[]} The cumulative width of each character in the text node.\n */\nconst measureCumulativeTextWidths = (textContent, computedStyles) => {\n  const cumulativeWidths = [];\n  let cumulativeWidth = 0;\n  for (let i = 0; i < textContent.length; i++) {\n    const char = textContent[i];\n    const {\n      width\n    } = measureText(char, computedStyles);\n    cumulativeWidth += width;\n    cumulativeWidths.push(cumulativeWidth);\n  }\n  return cumulativeWidths;\n};\n\n/**\n * @file /src/utils/nodes/hardBreak.ts\n * @name HardBreak\n * @description Utility functions for hard breaks.\n */\n/**\n * Check if the given node is a hard break node.\n *\n * @param node - The node to check.\n * @returns {boolean} True if the node is a hard break node, false otherwise.\n */\nconst isHardBreakNode = node => {\n  return node.type.name === \"hardBreak\";\n};\n/**\n * Check if the given position is at the start of the hard break node.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the start of the hard break node, false otherwise.\n */\nconst isAtHardBreak = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return isAtHardBreak(doc, doc.resolve($pos));\n  }\n  const node = doc.nodeAt($pos.pos);\n  if (!node) {\n    return false;\n  }\n  return isHardBreakNode(node);\n};\n\n/**\n * @file /src/utils/paragraph.ts\n * @name Paragraph\n * @description Utility functions for paragraphs.\n */\n/**\n * Check if the given node is a paragraph node.\n *\n * @param node - The node to check.\n * @returns {boolean} True if the node is a paragraph node, false otherwise.\n */\nconst isParagraphNode = node => {\n  if (!node) {\n    console.warn(\"No node provided\");\n    return false;\n  }\n  return node.type.name === \"paragraph\";\n};\n/**\n * Get the type of the node at the specified position.\n *\n * @param $pos - The resolved position in the document.\n * @returns The type of the node at the specified position.\n */\nconst isPositionWithinParagraph = $pos => {\n  return getPositionNodeType($pos) === \"paragraph\";\n};\n/**\n * Get the start of the paragraph position.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The start position of the paragraph.\n */\nconst getStartOfParagraphPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getStartOfParagraphPosition(doc, doc.resolve(pos));\n  }\n  const {\n    pos: paragraphPos\n  } = getParagraphNodeAndPosition(doc, pos);\n  return paragraphPos;\n};\n/**\n * Get the end of the paragraph position.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The end position of the paragraph.\n */\nconst getEndOfParagraphPosition = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return getEndOfParagraphPosition(doc, doc.resolve($pos));\n  }\n  const {\n    pos: paragraphPos,\n    node: paragraphNode\n  } = getParagraphNodeAndPosition(doc, $pos);\n  if (!paragraphNode) {\n    return paragraphPos;\n  }\n  return paragraphPos + paragraphNode.content.size;\n};\n/**\n * Get the previous paragraph node.\n *\n * @param doc - The document node.\n * @param pos - The position in the document.\n * @returns {NullableNodePos} The previous paragraph node or null if not found and position.\n */\nconst getPreviousParagraph = (doc, pos) => {\n  let prevParagraphPos = pos;\n  let prevParagraphNode = null;\n  while (prevParagraphNode === null && prevParagraphPos > 0) {\n    prevParagraphPos -= 1;\n    const node = doc.nodeAt(prevParagraphPos);\n    if (!node) {\n      continue;\n    }\n    if (isParagraphNode(node)) {\n      prevParagraphNode = node;\n      prevParagraphPos = prevParagraphPos;\n    }\n  }\n  if (!prevParagraphNode) {\n    prevParagraphPos = -1;\n  }\n  return {\n    pos: prevParagraphPos,\n    node: prevParagraphNode\n  };\n};\n/**\n * Get the next paragraph node.\n *\n * @param doc - The document node.\n * @param pos - The position in the document.\n * @returns {NullableNodePos} The next paragraph node or null if not found and position.\n */\nconst getNextParagraph = (doc, pos) => {\n  const documentLength = doc.content.size;\n  let nextParagraphPos = pos;\n  let nextParagraphNode = null;\n  while (nextParagraphNode === null && nextParagraphPos < documentLength) {\n    nextParagraphPos += 1;\n    const node = doc.nodeAt(nextParagraphPos);\n    if (!node) {\n      continue;\n    }\n    if (isParagraphNode(node)) {\n      nextParagraphNode = node;\n      nextParagraphPos = nextParagraphPos;\n    }\n  }\n  if (!nextParagraphNode) {\n    nextParagraphPos = -1;\n  }\n  return {\n    pos: nextParagraphPos,\n    node: nextParagraphNode\n  };\n};\n/**\n * Determine if the resolved position is at the start of a paragraph node.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document.\n * @returns {boolean} True if the position is at the start of a paragraph node, false otherwise.\n */\nconst isAtStartOfParagraph = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return isAtStartOfParagraph(doc, doc.resolve($pos));\n  }\n  const {\n    pos: paragraphPos,\n    node: paragraphNode\n  } = getParagraphNodeAndPosition(doc, $pos);\n  if (!paragraphNode) {\n    return false;\n  }\n  // We allow for the cursor to be at the start of the paragraph node or the start of the first text child node.\n  return inRange($pos.pos, paragraphPos, paragraphPos + 1);\n};\n/**\n * Determine if the resolved position is at the end of a paragraph node.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document.\n * @returns {boolean} True if the position is at the end of a paragraph node, false otherwise.\n */\nconst isAtEndOfParagraph = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return isAtEndOfParagraph(doc, doc.resolve($pos));\n  }\n  const {\n    pos: paragraphPos,\n    node: paragraphNode\n  } = getParagraphNodeAndPosition(doc, $pos);\n  if (!paragraphNode) {\n    return false;\n  }\n  return $pos.pos + 1 === paragraphPos + paragraphNode.nodeSize;\n};\n/**\n * Determine if the resolved position is at the start or end of a paragraph node.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document.\n * @returns {boolean} True if the position is at the start or end of a paragraph node, false otherwise.\n */\nconst isAtStartOrEndOfParagraph = (doc, $pos) => {\n  return isAtStartOfParagraph(doc, $pos) || isAtEndOfParagraph(doc, $pos);\n};\n/**\n * Get the paragraph node position.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The position of the paragraph node.\n */\nconst getThisParagraphNodePosition = (doc, pos) => {\n  return getParentNodePosOfType(doc, pos, \"paragraph\").pos;\n};\n/**\n * Get the paragraph node position and the paragraph node itself.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {NullableNodePos} The position and the node or null if not found of the paragraph.\n */\nconst getParagraphNodeAndPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getParagraphNodeAndPosition(doc, doc.resolve(pos));\n  }\n  if (isPosAtStartOfDocument(doc, pos)) {\n    return getNextParagraph(doc, pos.pos);\n  } else if (isPosAtEndOfDocument(doc, pos)) {\n    return getPreviousParagraph(doc, pos.pos);\n  }\n  const paragraphPos = getThisParagraphNodePosition(doc, pos);\n  const paragraphNode = doc.nodeAt(paragraphPos);\n  if (!isParagraphNode(paragraphNode)) {\n    console.warn(\"No paragraph node found\");\n    return {\n      pos: -1,\n      node: paragraphNode\n    };\n  }\n  return {\n    pos: paragraphPos,\n    node: paragraphNode\n  };\n};\n/**\n * Gets the previous page's past body paragraph and position, if any, before the given position.\n * @param doc - The current document.\n * @param pos - Any position within the current page's body\n * @returns {NullableNodePos} The previous page body's last paragraph and position, if any.\n */\nconst getLastParagraphInPreviousPageBodyBeforePos = (doc, pos) => {\n  const previousPageBody = getBodyBeforePos(doc, pos);\n  if (!previousPageBody.node) {\n    return previousPageBody;\n  }\n  const endOfPrevPgBodyPos = getEndOfBodyPosition(doc, previousPageBody.pos);\n  return getPreviousParagraph(doc, endOfPrevPgBodyPos);\n};\n/**\n * Gets the next page's first body paragraph and positiom, if any, after the given position.\n * @param doc - The current document.\n * @param pos - Any position within the current page's body\n * @returns {NullableNodePos} The next page body's first paragraph and position, if any.\n */\nconst getFirstParagraphInNextPageBodyAfterPos = (doc, pos) => {\n  const nextPageBody = getBodyAfterPos(doc, pos);\n  if (!nextPageBody.node) {\n    return nextPageBody;\n  }\n  return getNextParagraph(doc, nextPageBody.pos);\n};\n/**\n * Get the paragraph DOM node.\n *\n * @param view - The editor view.\n * @param paragraphPos - The position of the paragraph in the document.\n * @returns {Node} The paragraph DOM node.\n */\nconst getParagraphDOMNode = (view, paragraphPos) => {\n  // DOM nodes are offsetted by 1 for some reason.\n  const paragraphTextPos = paragraphPos + 1;\n  return view.domAtPos(paragraphTextPos).node ?? null;\n};\n/**\n * Measure the widths of each character in a paragraph.\n *\n * @param pDOMNode - The paragraph DOM node.\n * @returns {number[]} An array of character widths.\n */\nconst measureTextWidths = pDOMNode => {\n  const charWidths = [];\n  const textContent = pDOMNode.textContent || \"\";\n  const computedStyles = getComputedStyle(pDOMNode);\n  for (let i = 0; i < textContent.length; i++) {\n    const char = textContent[i];\n    const {\n      width\n    } = measureText(char, computedStyles);\n    charWidths.push(width);\n  }\n  return charWidths;\n};\n/**\n * Measure the width of the text up to a given offset in a paragraph.\n *\n * @param pDOMNode - The paragraph DOM node.\n * @param offset - The offset within the paragraph.\n * @param lineNumber - The line number within the paragraph.\n * @param lineBreakOffsets - The offsets where line breaks occur.\n * @returns {number} The width of the text up to the offset.\n */\nconst getTextWidthUpToOffsetInLine = (pDOMNode, offset, lineNumber, lineBreakOffsets) => {\n  const textUpToOffset = pDOMNode.textContent?.slice(lineBreakOffsets[lineNumber], offset) || \"\";\n  const computedStyles = getComputedStyle(pDOMNode);\n  const {\n    width\n  } = measureText(textUpToOffset, computedStyles);\n  return width;\n};\n/**\n * Get the offset within a line given the offset in the paragraph and line number.\n *\n * @param offset - The offset within the paragraph.\n * @param lineNumber - The line number within the paragraph.\n * @param lineBreakOffsets - The offsets where line breaks occur.\n * @returns {number} The offset within the line.\n */\nconst getOffsetInLine = (offset, lineNumber, lineBreakOffsets) => {\n  if (lineNumber === 0) {\n    return offset;\n  }\n  return offset - lineBreakOffsets[lineNumber];\n};\nconst getOffsetForDistanceInLine = (view, pos, lineNumber, targetDistance) => {\n  const pDOMNode = getPDOMNodeFromPos(view, pos);\n  if (!pDOMNode) return 0;\n  const lineBreakOffsets = getParagraphLineBreakOffsets(view, pDOMNode);\n  const thisLineOffset = lineBreakOffsets[lineNumber];\n  const nextLineOffset = lineBreakOffsets[lineNumber + 1];\n  const textContent = pDOMNode.textContent?.slice(thisLineOffset, nextLineOffset) || \"\";\n  const computedStyles = getComputedStyle(pDOMNode);\n  const charWidths = measureCumulativeTextWidths(textContent, computedStyles);\n  const closestIndex = findClosestIndex(charWidths, targetDistance);\n  return thisLineOffset + closestIndex + 1;\n};\n/**\n * Measure the widths of each line in a paragraph.\n *\n * @param pDOMNode - The paragraph DOM node.\n * @returns {number[]} An array of line widths.\n */\nconst measureParagraphLineWidths = pDOMNode => {\n  const range = document.createRange();\n  range.selectNodeContents(pDOMNode);\n  const rects = range.getClientRects();\n  const lines = [];\n  let currentLineWidths = [];\n  let cumulativeLineLeft = rects[0]?.left || 0;\n  let cumulativeLineTop = rects[0]?.top || 0;\n  let prevLineRight = 0;\n  const addNewLine = width => {\n    lines.push(currentLineWidths.reduce((acc, width) => acc + width, 0));\n    if (width) {\n      currentLineWidths = [width];\n    }\n  };\n  Array.from(rects).forEach((rect, index) => {\n    if (index === 0) {\n      // First line\n      currentLineWidths.push(rect.width);\n    } else {\n      if (rect.left === prevLineRight) {\n        // Next element in line\n        currentLineWidths.push(rect.width);\n      } else if (rect.left === cumulativeLineLeft && rect.top > cumulativeLineTop) {\n        // New Line\n        addNewLine(rect.width);\n      } else if (rect.left >= cumulativeLineLeft) ; else {\n        // New Line\n        addNewLine(rect.width);\n      }\n    }\n    cumulativeLineLeft = rect.left;\n    cumulativeLineTop = rect.top;\n    prevLineRight = rect.right;\n  });\n  if (currentLineWidths.length > 0) {\n    // Add the last line\n    addNewLine();\n  }\n  return lines;\n};\n/**\n * Get offsets where explicit and soft line breaks occur in a paragraph.\n *\n * @param pDOMNode - The paragraph DOM node.\n * @returns {number[]} An array of offsets where line breaks occur.\n */\nconst getParagraphLineBreakOffsets = (view, pDOMNode) => {\n  const charWidths = measureTextWidths(pDOMNode);\n  const lineWidths = measureParagraphLineWidths(pDOMNode);\n  let offsets = [0];\n  let cumulativeWidth = 0;\n  let rectIndex = 0;\n  let charIndex = 0;\n  const sumTextNodes = node => {\n    const isBr = node.nodeType === Node.ELEMENT_NODE && node.tagName === \"BR\";\n    if (isBr && offsets[offsets.length - 1] !== charIndex) {\n      offsets.push(charIndex);\n      rectIndex++;\n      cumulativeWidth = 0;\n    } else if (isAtomNode(view, node)) {\n      // Atom nodes are treated as a single character\n      charIndex += 1;\n    } else if (node.nodeType === Node.TEXT_NODE) {\n      const nodeTextContent = node.textContent || \"\";\n      for (let i = 0; i < nodeTextContent.length; i++) {\n        charIndex += 1;\n        cumulativeWidth += charWidths[charIndex] || 0;\n        if (cumulativeWidth > lineWidths[rectIndex]) {\n          offsets.push(charIndex);\n          rectIndex++;\n          cumulativeWidth = 0;\n        }\n      }\n    } else {\n      // Recursively call for nested elements\n      const nestedChildren = node.childNodes;\n      Array.from(nestedChildren).forEach(childNode => {\n        sumTextNodes(childNode);\n      });\n    }\n  };\n  sumTextNodes(pDOMNode);\n  return offsets;\n};\n/**\n * Get the line number for a given position within a paragraph using binary search.\n *\n * @param lineBreakOffsets - The offsets where line breaks occur.\n * @param offset - The position within the paragraph.\n * @returns {number} The line number of the position (0-indexed).\n */\nconst getLineNumberForPosition = (lineBreakOffsets, offset) => {\n  const compareOffsets = (a, b) => a - b;\n  return binarySearch(lineBreakOffsets, offset, compareOffsets);\n};\nconst getPDOMNodeFromPos = (view, pos) => {\n  if (typeof pos !== \"number\") {\n    pos = pos.pos;\n  }\n  const paragraphPos = getThisParagraphNodePosition(view.state.doc, pos);\n  return getParagraphDOMNode(view, paragraphPos);\n};\n/**\n * Helper function to calculate the total length of text content in an element.\n * It will recursively sum the lengths of all text nodes within the element.\n *\n * @param elementNode - The DOM element node (e.g., <code>, <span>).\n * @returns {number} - The total length of text content inside the element.\n */\nconst getTextLengthFromElement = (view, elementNode, end) => {\n  let totalLength = 0;\n  // Traverse all child nodes and sum the lengths of text nodes\n  Array.from(elementNode.childNodes).slice(0, end).forEach(childNode => {\n    if (childNode.nodeType === Node.TEXT_NODE) {\n      totalLength += childNode.length;\n    } else if (childNode.nodeType === Node.ELEMENT_NODE) {\n      if (isAtomNode(view, childNode)) {\n        // Atom nodes are treated as a single character\n        totalLength += 1;\n      } else {\n        // Recursively call for nested elements\n        totalLength += getTextLengthFromElement(view, childNode);\n      }\n    }\n  });\n  return totalLength;\n};\n/**\n * Calculate the paragraph end offset based on the position. Used to correct\n * getting the right DOM node when the position is at the start or end of a paragraph / text node.\n * @param view - The editor view.\n * @param pos - The [resolved] position in the document.\n * @returns {number} The paragraph end offset.\n */\nconst calculateParagraphEndOffset = (view, pos) => {\n  const {\n    doc\n  } = view.state;\n  if (isAtStartOfParagraph(doc, pos) || isAtStartOfTextNode(doc, pos)) {\n    return 1;\n  } else if (isAtEndOfParagraph(doc, pos) || isAtEndOfTextNode(doc, pos) || isAtHardBreak(doc, pos)) {\n    return -1;\n  } else {\n    return 0;\n  }\n};\n/**\n * Given a paragraph position and position within said paragraph, return the number of\n * lines in the paragraph and the line number of the position.\n *\n * @param view - The editor view.\n * @param pos - The [resolved] position in the document.\n * @returns {ParagraphLineInfo} The number of lines in the paragraph and the\n * line number of the position (0-indexed).\n */\nconst getParagraphLineInfo = (view, pos) => {\n  if (typeof pos !== \"number\") {\n    pos = pos.pos;\n  }\n  const returnDefaultLineInfo = () => ({\n    lineCount: 0,\n    lineBreakOffsets: [0],\n    lineNumber: 0,\n    offsetInLine: 0,\n    offsetDistance: 0\n  });\n  const pDOMNode = getPDOMNodeFromPos(view, pos);\n  if (!pDOMNode) return returnDefaultLineInfo();\n  const lineBreakOffsets = getParagraphLineBreakOffsets(view, pDOMNode);\n  const lineCount = lineBreakOffsets.length;\n  const paragraphEndOffset = calculateParagraphEndOffset(view, pos);\n  let {\n    offset\n  } = view.domAtPos(pos + paragraphEndOffset);\n  const {\n    node: paragraphNode,\n    offset: paragraphOffset\n  } = view.domAtPos(pos - offset + paragraphEndOffset);\n  const previousOffset = getTextLengthFromElement(view, paragraphNode, paragraphOffset);\n  offset += previousOffset;\n  const lineNumber = getLineNumberForPosition(lineBreakOffsets, offset);\n  offset -= paragraphEndOffset;\n  const offsetInLine = getOffsetInLine(offset, lineNumber, lineBreakOffsets);\n  const offsetDistance = getTextWidthUpToOffsetInLine(pDOMNode, offset, lineNumber, lineBreakOffsets);\n  return {\n    lineCount,\n    lineBreakOffsets,\n    lineNumber,\n    offsetInLine,\n    offsetDistance\n  };\n};\n/**\n * Checks if the position is at the first line of the paragraph.\n *\n * @param view - The editor view.\n * @param $pos - The [resolved] position in the document.\n * @returns {boolean} True if the position is at the first line of the paragraph, false otherwise.\n */\nconst isPosAtFirstLineOfParagraph = (view, $pos) => {\n  const {\n    lineNumber,\n    ...otherLineInfo\n  } = getParagraphLineInfo(view, $pos);\n  const isAtFirstLine = lineNumber === 0;\n  return {\n    isAtFirstLine,\n    lineNumber,\n    ...otherLineInfo\n  };\n};\n/**\n * Checks if the position is at the last line of the paragraph.\n *\n * @param view - The editor view.\n * @param $pos - The [resolved] position in the document.\n * @returns {boolean} True if the position is at the last line of the paragraph, false otherwise.\n */\nconst isPosAtLastLineOfParagraph = (view, $pos) => {\n  const {\n    lineCount,\n    lineNumber,\n    ...otherLineInfo\n  } = getParagraphLineInfo(view, $pos);\n  const isAtLastLine = lineNumber + 1 === lineCount;\n  return {\n    isAtLastLine,\n    lineCount,\n    lineNumber,\n    ...otherLineInfo\n  };\n};\n\n/**\n * @file /src/utils/nodes/headerFooter/headerFooterPosition.ts\n * @name HeaderFooterPosition\n * @description Utility functions for header and footer positions.\n */\n/**\n * Get the header or footer node (parent of the current node) position.\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The position of the header or footer node.\n */\nconst getThisPageAmendmentNodePosition = (doc, pos) => {\n  return getParentNodePosOfType(doc, pos, HEADER_FOOTER_NODE_NAME).pos;\n};\n/**\n * Get the header or footer node position and the header or footer node itself.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {pageAmendmentPos: number, pageAmendmentNode: Node} The position and the node of the header or footer.\n */\nconst getPageAmendmentNodeAndPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getPageAmendmentNodeAndPosition(doc, doc.resolve(pos));\n  }\n  const pageAmendmentPos = getThisPageAmendmentNodePosition(doc, pos);\n  const pageAmendmentNode = doc.nodeAt(pageAmendmentPos);\n  return {\n    pageAmendmentPos,\n    pageAmendmentNode\n  };\n};\n/**\n * Get the start of the header or footer position.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The start position of the header or footer.\n */\nconst getStartOfPageAmendmentPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getStartOfPageAmendmentPosition(doc, doc.resolve(pos));\n  }\n  const {\n    pageAmendmentPos\n  } = getPageAmendmentNodeAndPosition(doc, pos);\n  return pageAmendmentPos;\n};\n/**\n * Get the end of the header or footer position.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {number} The end position of the header or footer.\n */\nconst getEndOfPageAmendmentPosition = (doc, pos) => {\n  if (typeof pos === \"number\") {\n    return getEndOfPageAmendmentPosition(doc, doc.resolve(pos));\n  }\n  const {\n    pageAmendmentPos,\n    pageAmendmentNode\n  } = getPageAmendmentNodeAndPosition(doc, pos);\n  if (!pageAmendmentNode) {\n    return pageAmendmentPos;\n  }\n  return pageAmendmentPos + pageAmendmentNode.content.size;\n};\n\n/**\n * @file /src/utils/pagination.ts\n * @name Pagination\n * @description Utility functions for paginating the editor content.\n */\n/**\n * Get the start of the page amendment and paragraph positions.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {startOfPageAmendmentPos: number, startOfParagraphPos: number} The start positions of the\n * page amendment and paragraph.\n */\nconst getStartOfPageAmendmentAndParagraphPosition = (doc, pos) => {\n  const startOfParagraphPos = getStartOfParagraphPosition(doc, pos);\n  const startOfPageAmendmentPos = getStartOfPageAmendmentPosition(doc, pos);\n  return {\n    startOfPageAmendmentPos,\n    startOfParagraphPos\n  };\n};\n/**\n * Get the end of the page amendment and paragraph positions.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {endOfPageAmendmentPos: number, endOfParagraphPos: number} The end positions of the\n * page amendment and paragraph.\n */\nconst getEndOfPageAmendmentAndParagraphPosition = (doc, $pos) => {\n  const endOfParagraphPos = getEndOfParagraphPosition(doc, $pos);\n  const endOfPageAmendmentPos = getEndOfPageAmendmentPosition(doc, $pos);\n  return {\n    endOfPageAmendmentPos,\n    endOfParagraphPos\n  };\n};\n/**\n * Get the start of the body and paragraph positions.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {startOfBodyPos: number, startOfParagraphPos: number} The start positions of the body and paragraph.\n */\nconst getStartOfBodyAndParagraphPosition = (doc, pos) => {\n  const startOfParagraphPos = getStartOfParagraphPosition(doc, pos);\n  const startOfBodyPos = getStartOfBodyPosition(doc, pos);\n  return {\n    startOfBodyPos,\n    startOfParagraphPos\n  };\n};\n/**\n * Get the end of the body and paragraph positions.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {endOfBodyPos: number, endOfParagraphPos: number} The end positions of the body and paragraph.\n */\nconst getEndOfBodyAndParagraphPosition = (doc, $pos) => {\n  const endOfParagraphPos = getEndOfParagraphPosition(doc, $pos);\n  const endOfBodyPos = getEndOfBodyPosition(doc, $pos);\n  return {\n    endOfBodyPos,\n    endOfParagraphPos\n  };\n};\n/**\n * Collect the node types for pagination.\n *\n * @param schema - The schema of the editor.\n * @returns {PaginationNodeTypes} The node types for pagination.\n * @throws {Error} Throws an error if the page, body, or header/footer node types are not found in the schema.\n */\nconst getPaginationNodeTypes = schema => {\n  const {\n    nodes\n  } = schema;\n  const pageNodeType = nodes[PAGE_NODE_NAME];\n  const headerFooterNodeType = nodes[HEADER_FOOTER_NODE_NAME];\n  const bodyNodeType = nodes[BODY_NODE_NAME];\n  const paragraphNodeType = nodes.paragraph;\n  if (!pageNodeType || !bodyNodeType) {\n    throw new Error(\"Page or body node type not found in schema\");\n  }\n  return {\n    pageNodeType,\n    headerFooterNodeType,\n    bodyNodeType,\n    paragraphNodeType\n  };\n};\n\n/**\n * @file /src/utils/positionCondition.ts\n * @name PositionCondition\n * @description Utility functions for position conditions.\n */\nconst isAtStartOfNode = ($pos, startOfNodePos, startOfParagraphPos, checkExactStart) => {\n  // Determine the condition to check\n  // First position of paragraph will always be 1 more than the body position\n  const isFirstParagraph = startOfNodePos + 1 === startOfParagraphPos;\n  if (!isFirstParagraph) return false;\n  if (checkExactStart) {\n    // Check if position is exactly at the start of the body\n    // First position of text will always be 1 more than the first paragraph position\n    const isPosAtStartOfParagraph = startOfParagraphPos + 1 === $pos.pos;\n    return isPosAtStartOfParagraph;\n  }\n  return true;\n};\n/**\n * Check if the given position is exactly at the end of the node.\n *\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @param endOfNodePos - The position of the end of the node.\n * @param endOfParagraphPos - The position of the end of the paragraph.\n * @param checkExactEnd - Whether the position must be at the exact end of the node.\n * @returns {boolean} True if the condition is met, false otherwise.\n */\nconst isAtEndOfNode = ($pos, endOfNodePos, endOfParagraphPos, checkExactEnd) => {\n  const isLastParagraph = endOfParagraphPos + 1 === endOfNodePos;\n  if (!isLastParagraph) return false;\n  if (checkExactEnd) {\n    // Check if position is exactly at the end of the node\n    // Last position of text will always be 1 less than the end of the last paragraph position\n    const isPosAtEndOfParagraph = endOfParagraphPos + 1 === $pos.pos;\n    return isPosAtEndOfParagraph;\n  }\n  return true;\n};\n\n/**\n * @file /src/utils/nodes/body/bodyCondition.ts\n * @name BodyCondition\n * @description Utility functions for body conditions.\n */\n/**\n * Check if the given position is within the body.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is within the body, false otherwise.\n */\nconst isPosInBody = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    return isPosInBody(doc, doc.resolve($pos));\n  }\n  const {\n    node: pageChildNode\n  } = getPageChildNodePosFromPosition(doc, $pos);\n  if (!pageChildNode) return false;\n  return isBodyNode(pageChildNode);\n};\n/**\n * Check if the given position is exactly at the start of the first child of the body.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the condition is met, false otherwise.\n */\nconst isPosAtStartOfBody = (doc, $pos) => {\n  return isPosMatchingStartOfBodyCondition(doc, $pos, true);\n};\n/**\n * Check if the given position is within the first paragraph child of the body.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the start of the body, false otherwise.\n */\nconst isPosAtFirstChildOfBody = (doc, $pos) => {\n  return isPosMatchingStartOfBodyCondition(doc, $pos, false);\n};\n/**\n * Check if the given position is exactly at the end of the body.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the end of the body, false otherwise.\n */\nconst isPosAtEndOfBody = (doc, $pos) => {\n  return isPosMatchingEndOfBodyCondition(doc, $pos, true);\n};\n/**\n * Check if the given position is at the end of the last paragraph child of the body.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the end of the body, false otherwise.\n */\nconst isPosAtLastChildOfBody = (doc, $pos) => {\n  return isPosMatchingEndOfBodyCondition(doc, $pos, false);\n};\n/**\n * Checks if the given position is at the start of the first page's body.\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @param checkExactStart - Whether the position must be at the exact start of the body.\n * @returns {boolean} True if the position is at the start of the first page's body, false otherwise.\n */\nconst isPosAtStartOfDocumentBody = (doc, $pos, checkExactStart) => {\n  if (typeof $pos === \"number\") {\n    return isPosAtStartOfDocumentBody(doc, doc.resolve($pos), checkExactStart);\n  }\n  const pageNumber = getPageNumber(doc, $pos);\n  if (!isPosMatchingStartOfBodyCondition(doc, $pos, checkExactStart)) return false;\n  return pageNumber === 0;\n};\n/**\n * Check if the given position is at the start of the document.\n *\n * @param doc - The document node.\n * @param pos - The resolved position in the document or the absolute position of the node.\n * @param checkExactStart - Whether the position must be at the exact start of the body.\n * @returns {boolean} True if the position is at the start of the document, false otherwise.\n */\nconst isPosMatchingStartOfBodyCondition = (doc, $pos, checkExactStart) => {\n  // Resolve position if given as a number\n  if (typeof $pos === \"number\") {\n    return isPosMatchingStartOfBodyCondition(doc, doc.resolve($pos), checkExactStart);\n  }\n  if (!isPosInBody(doc, $pos)) {\n    return false;\n  }\n  // Check if we are at the start of the document\n  if (isPosAtStartOfDocument(doc, $pos)) {\n    return true;\n  }\n  // Ensure that the position is within a valid block (paragraph)\n  if (!isPositionWithinParagraph($pos)) {\n    return false;\n  }\n  // Get positions for paragraph and body\n  const {\n    startOfBodyPos,\n    startOfParagraphPos\n  } = getStartOfBodyAndParagraphPosition(doc, $pos);\n  if (startOfBodyPos < 0) {\n    console.warn(\"Invalid body position\");\n    return false;\n  }\n  if (startOfParagraphPos < 0) {\n    console.warn(\"Invalid paragraph position\");\n    return false;\n  }\n  return isAtStartOfNode($pos, startOfBodyPos, startOfParagraphPos, checkExactStart);\n};\n/**\n * Check if the given position is at the end of the body or the last child of the body.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @param checkExactEnd - Whether to check for the exact end of the body (true) or the last child of the body (false).\n * @returns {boolean} True if the condition is met, false otherwise.\n */\nconst isPosMatchingEndOfBodyCondition = (doc, $pos, checkExactEnd) => {\n  // Resolve position if given as a number\n  if (typeof $pos === \"number\") {\n    return isPosMatchingEndOfBodyCondition(doc, doc.resolve($pos), checkExactEnd);\n  }\n  if (!isPosInBody(doc, $pos)) {\n    return false;\n  }\n  // Check if we are at the end of the document\n  if (isPosAtEndOfDocument(doc, $pos)) {\n    return true;\n  }\n  // Ensure that the position is within a valid block (paragraph)\n  if (!isPositionWithinParagraph($pos)) {\n    return false;\n  }\n  // Get positions for paragraph and body\n  const {\n    endOfParagraphPos,\n    endOfBodyPos\n  } = getEndOfBodyAndParagraphPosition(doc, $pos);\n  if (endOfParagraphPos < 0) {\n    console.warn(\"Invalid end of paragraph position\");\n    return false;\n  }\n  if (endOfBodyPos < 0) {\n    console.warn(\"Invalid end of body position\");\n    return false;\n  }\n  return isAtEndOfNode($pos, endOfBodyPos, endOfParagraphPos, checkExactEnd);\n};\n\n/**\n * @file /src/utils/nodes/headerFooter/headerFooterCondition.ts\n * @name HeaderFooterCondition\n * @description Utility functions for header and footer conditions.\n */\n/**\n * Check if the given position is within a header or footer.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n */\nconst isPosInPageAmendment = (doc, $pos) => {\n  if (typeof $pos === \"number\") {\n    $pos = doc.resolve($pos);\n  }\n  const {\n    node: pageChildNode\n  } = getPageChildNodePosFromPosition(doc, $pos);\n  if (!pageChildNode) return false;\n  return isHeaderFooterNode(pageChildNode);\n};\n/**\n * Check if the given position is at the start of a header or footer.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the start of a header or footer, false otherwise.\n */\nconst isPosAtStartOfPageAmendment = (doc, $pos) => {\n  return isPosMatchingStartOfPageAmendmentCondition(doc, $pos, true);\n};\n/**\n * Check if the given position is at the first child of a header or footer.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the first child of the header or footer, false otherwise.\n */\nconst isPosAtFirstChildOfPageAmendment = (doc, $pos) => {\n  return isPosMatchingStartOfPageAmendmentCondition(doc, $pos, false);\n};\n/**\n * Check if the given position is at the end of a header or footer.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the end of a header or footer, false otherwise.\n */\nconst isPosAtEndOfPageAmendment = (doc, $pos) => {\n  return isPosMatchingEndOfPageAmendmentCondition(doc, $pos, true);\n};\n/**\n * Check if the given position is at the last child of a header or footer.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @returns {boolean} True if the position is at the last child of the header or footer, false otherwise.\n */\nconst isPosAtLastChildOfPageAmendment = (doc, $pos) => {\n  return isPosMatchingEndOfPageAmendmentCondition(doc, $pos, false);\n};\n/**\n * Check if the given position is at the start of the first page's header or footer.\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @param checkExactStart - Whether the position must be at the exact start of the header or footer.\n * @returns {boolean} True if the position is at the start of the first page's header or footer, false otherwise.\n */\nconst isPosMatchingStartOfPageAmendmentCondition = (doc, $pos, checkExactStart) => {\n  if (typeof $pos === \"number\") {\n    $pos = doc.resolve($pos);\n  }\n  if (!isPosInPageAmendment(doc, $pos)) {\n    return false;\n  }\n  // Ensure that the position is within a valid block (paragraph)\n  if (!isPositionWithinParagraph($pos)) {\n    return false;\n  }\n  const {\n    startOfPageAmendmentPos,\n    startOfParagraphPos\n  } = getStartOfPageAmendmentAndParagraphPosition(doc, $pos);\n  if (startOfPageAmendmentPos < 0) {\n    console.warn(\"Invalid page amendment position\");\n    return false;\n  }\n  if (startOfParagraphPos < 0) {\n    console.warn(\"Invalid paragraph position\");\n    return false;\n  }\n  return isAtStartOfNode($pos, startOfPageAmendmentPos, startOfParagraphPos, checkExactStart);\n};\n/**\n * Check if the given position is at the end of the last page's header or footer.\n * @param doc - The document node.\n * @param $pos - The resolved position in the document or the absolute position of the node.\n * @param checkExactEnd - Whether the position must be at the exact end of the header or footer.\n * @returns {boolean} True if the position is at the end of the last page's header or footer, false otherwise.\n */\nconst isPosMatchingEndOfPageAmendmentCondition = (doc, $pos, checkExactEnd) => {\n  if (typeof $pos === \"number\") {\n    $pos = doc.resolve($pos);\n  }\n  if (!isPosInPageAmendment(doc, $pos)) {\n    return false;\n  }\n  // Ensure that the position is within a valid block (paragraph)\n  if (!isPositionWithinParagraph($pos)) {\n    return false;\n  }\n  const {\n    endOfPageAmendmentPos,\n    endOfParagraphPos\n  } = getEndOfPageAmendmentAndParagraphPosition(doc, $pos);\n  if (endOfPageAmendmentPos < 0) {\n    console.warn(\"Invalid page amendment position\");\n    return false;\n  }\n  if (endOfParagraphPos < 0) {\n    console.warn(\"Invalid paragraph position\");\n    return false;\n  }\n  return isAtEndOfNode($pos, endOfPageAmendmentPos, endOfParagraphPos, checkExactEnd);\n};\n\n/**\n * @file /src/Plugins/Keymap.ts\n * @name Keymap\n * @description Custom plugin for handling keymaps for page navigation.\n */\nconst KeymapPlugin = keymap({\n  ArrowLeft: (state, dispatch) => {\n    if (!dispatch) {\n      console.warn(\"No dispatch function provided\");\n      return false;\n    }\n    if (isHighlighting(state)) {\n      return false;\n    }\n    const {\n      doc,\n      tr\n    } = state;\n    const $pos = getResolvedPosition(state);\n    if (isPosAtStartOfPageAmendment(doc, $pos)) {\n      // Handle to prevent cursor moving out of the page amendment\n      return true;\n    }\n    if (!isPosAtStartOfBody(doc, $pos)) {\n      return false;\n    }\n    // console.log(\"At start of page body\");\n    const thisPos = $pos.pos;\n    const expectedTextNodePos = thisPos - 1;\n    const thisTextNode = doc.nodeAt(expectedTextNodePos);\n    if (!thisTextNode) {\n      console.warn(\"No node found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: paragraphPos,\n      node: paragraphNode\n    } = getParagraphNodeAndPosition(doc, $pos);\n    if (!paragraphNode) {\n      console.warn(\"No current paragraph node found\");\n      return false;\n    }\n    if (!isParagraphNode(thisTextNode) && !isTextNode(thisTextNode)) {\n      console.warn(\"Unexpected node type found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: previousParagraphPos,\n      node: previousParagraphNode\n    } = getLastParagraphInPreviousPageBodyBeforePos(doc, paragraphPos);\n    if (!previousParagraphNode) {\n      // Handle to prevent cursor moving to header\n      return true;\n    }\n    setSelectionToEndOfParagraph(tr, previousParagraphPos, previousParagraphNode);\n    dispatch(tr);\n    return true;\n  },\n  ArrowRight: (state, dispatch) => {\n    if (!dispatch) {\n      console.warn(\"No dispatch function provided\");\n      return false;\n    }\n    if (isHighlighting(state)) {\n      return false;\n    }\n    const {\n      doc,\n      tr\n    } = state;\n    const $pos = getResolvedPosition(state);\n    if (isPosAtEndOfPageAmendment(doc, $pos)) {\n      // Handle to prevent cursor moving out of the page amendment\n      return true;\n    }\n    if (!isPosAtEndOfBody(doc, $pos)) {\n      return false;\n    }\n    // console.log(\"At end of page body\");\n    const thisPos = $pos.pos;\n    const expectedTextNodePos = thisPos - 1;\n    const thisTextNode = doc.nodeAt(expectedTextNodePos);\n    if (!thisTextNode) {\n      console.warn(\"No node found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: paragraphPos,\n      node: paragraphNode\n    } = getParagraphNodeAndPosition(doc, $pos);\n    if (!paragraphNode) {\n      console.warn(\"No current paragraph node found\");\n      return false;\n    }\n    if (!isParagraphNode(thisTextNode) && !isTextNode(thisTextNode)) {\n      console.warn(\"Unexpected node type found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: nextParagraphPos,\n      node: nextParagraphNode\n    } = getFirstParagraphInNextPageBodyAfterPos(doc, paragraphPos);\n    if (!nextParagraphNode) {\n      // Handle to prevent cursor moving to footer\n      return true;\n    }\n    const newSelection = moveToThisTextBlock(tr, nextParagraphPos);\n    setSelection(tr, newSelection);\n    dispatch(tr);\n    return true;\n  },\n  ArrowUp: (state, dispatch, view) => {\n    if (!dispatch) {\n      console.warn(\"No dispatch function provided\");\n      return false;\n    }\n    if (!view) {\n      console.warn(\"No view provided\");\n      return false;\n    }\n    if (isHighlighting(state)) {\n      return false;\n    }\n    const {\n      doc,\n      tr\n    } = state;\n    const $pos = getResolvedPosition(state);\n    if (isPosAtFirstChildOfPageAmendment(doc, $pos)) {\n      // Handle to prevent cursor moving out of the page amendment\n      return true;\n    }\n    if (!isPosAtFirstChildOfBody(doc, $pos)) {\n      return false;\n    }\n    // console.log(\"In first child of page body\");\n    const thisPos = $pos.pos;\n    const {\n      isAtFirstLine,\n      offsetDistance\n    } = isPosAtFirstLineOfParagraph(view, $pos);\n    if (!isAtFirstLine) {\n      return false;\n    }\n    const expectedTextNodePos = thisPos - 1;\n    const thisTextNode = doc.nodeAt(expectedTextNodePos);\n    if (!thisTextNode) {\n      console.warn(\"No node found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: paragraphPos,\n      node: paragraphNode\n    } = getParagraphNodeAndPosition(doc, $pos);\n    if (!paragraphNode) {\n      console.warn(\"No current paragraph node found\");\n      return false;\n    }\n    if (!isParagraphNode(thisTextNode) && !isTextNode(thisTextNode)) {\n      console.warn(\"Unexpected node type found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: previousParagraphPos,\n      node: previousParagraphNode\n    } = getLastParagraphInPreviousPageBodyBeforePos(doc, paragraphPos);\n    if (!previousParagraphNode) {\n      if (!isPosAtStartOfBody(doc, $pos)) {\n        // Move to the start of the current paragraph\n        setSelectionToStartOfParagraph(tr, paragraphPos, paragraphNode);\n        dispatch(tr);\n      }\n      return true;\n    }\n    const {\n      lineCount: prevParLineCount\n    } = getParagraphLineInfo(view, previousParagraphPos);\n    const prevParagraphLastLineNum = prevParLineCount - 1;\n    const cursorOffset = getOffsetForDistanceInLine(view, previousParagraphPos, prevParagraphLastLineNum, offsetDistance) + 1;\n    setSelectionToParagraph(tr, previousParagraphPos, previousParagraphNode, cursorOffset);\n    dispatch(tr);\n    return true;\n  },\n  ArrowDown: (state, dispatch, view) => {\n    if (!dispatch) {\n      console.warn(\"No dispatch function provided\");\n      return false;\n    }\n    if (!view) {\n      console.warn(\"No view provided\");\n      return false;\n    }\n    if (isHighlighting(state)) {\n      return false;\n    }\n    const {\n      doc,\n      tr\n    } = state;\n    const $pos = getResolvedPosition(state);\n    if (isPosAtLastChildOfPageAmendment(doc, $pos)) {\n      // Handle to prevent cursor moving out of the page amendment\n      return true;\n    }\n    if (!isPosAtLastChildOfBody(doc, $pos)) {\n      return false;\n    }\n    console.log(\"In last child of page body\");\n    const thisPos = $pos.pos;\n    const {\n      isAtLastLine,\n      offsetDistance\n    } = isPosAtLastLineOfParagraph(view, $pos);\n    if (!isAtLastLine) {\n      return false;\n    }\n    const expectedTextNodePos = thisPos - 1;\n    const thisTextNode = doc.nodeAt(expectedTextNodePos);\n    if (!thisTextNode) {\n      console.warn(\"No node found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: paragraphPos,\n      node: paragraphNode\n    } = getParagraphNodeAndPosition(doc, $pos);\n    if (!paragraphNode) {\n      console.warn(\"No current paragraph node found\");\n      return false;\n    }\n    if (!isParagraphNode(thisTextNode) && !isTextNode(thisTextNode)) {\n      console.warn(\"Unexpected node type found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: nextParagraphPos,\n      node: nextParagraphNode\n    } = getFirstParagraphInNextPageBodyAfterPos(doc, paragraphPos);\n    if (!nextParagraphNode) {\n      if (!isPosAtEndOfBody(doc, $pos)) {\n        // Move to the end of the current paragraph\n        setSelectionToEndOfParagraph(tr, paragraphPos, paragraphNode);\n        dispatch(tr);\n      }\n      return true;\n    }\n    const cursorOffset = getOffsetForDistanceInLine(view, nextParagraphPos, 0, offsetDistance) + 1;\n    const newSelection = moveToThisTextBlock(tr, nextParagraphPos, undefined, cursorOffset);\n    setSelection(tr, newSelection);\n    dispatch(tr);\n    return true;\n  },\n  Enter: (state, dispatch) => {\n    if (!dispatch) {\n      console.warn(\"No dispatch function provided\");\n      return false;\n    }\n    if (isHighlighting(state)) {\n      return false;\n    }\n    const {\n      doc,\n      tr,\n      schema,\n      selection\n    } = state;\n    const {\n      from\n    } = selection;\n    const $pos = getResolvedPosition(state);\n    // Ensure that the position is within a valid block (paragraph)\n    if (!isPositionWithinParagraph($pos)) {\n      console.warn(\"Not inside a paragraph node\");\n      return false;\n    }\n    const {\n      node: paragraphNode\n    } = getParagraphNodeAndPosition(doc, $pos);\n    if (!paragraphNode) {\n      console.warn(\"No current paragraph node found\");\n      return false;\n    }\n    // Create a new empty paragraph node\n    const newParagraph = schema.nodes.paragraph.create();\n    console.log(\"Inserting new paragraph at position\", from);\n    if (isNodeEmpty$1(paragraphNode)) {\n      tr.insert(from, newParagraph);\n    } else {\n      if (isAtStartOrEndOfParagraph(doc, $pos)) {\n        tr.replaceSelectionWith(newParagraph);\n      } else {\n        const remainingContent = paragraphNode.content.cut($pos.parentOffset);\n        const newContentParagraph = schema.nodes.paragraph.create({}, remainingContent);\n        tr.replaceWith($pos.pos, $pos.pos + remainingContent.size, newContentParagraph);\n      }\n    }\n    const newSelection = moveToNextTextBlock(tr, from);\n    setSelection(tr, newSelection);\n    dispatch(tr);\n    return true;\n  },\n  Backspace: (state, dispatch) => {\n    if (!dispatch) {\n      console.warn(\"No dispatch function provided\");\n      return false;\n    }\n    if (isHighlighting(state)) {\n      return false;\n    }\n    const {\n      doc,\n      tr,\n      schema\n    } = state;\n    const $pos = getResolvedPosition(state);\n    if (isPosAtStartOfPageAmendment(doc, $pos)) {\n      // Handle to prevent cursor moving out of the page amendment\n      return true;\n    }\n    // Ensure that the position is within a valid block (paragraph)\n    if (!isPositionWithinParagraph($pos)) {\n      return false;\n    }\n    const thisPos = $pos.pos;\n    if (isPosAtEndOfBody(doc, $pos)) {\n      const {\n        pos: paragraphPos,\n        node: paragraphNode\n      } = getParagraphNodeAndPosition(doc, $pos);\n      if (!paragraphNode) {\n        console.warn(\"No current paragraph node found\");\n        return false;\n      }\n      if (isNodeEmpty$1(paragraphNode)) {\n        deleteNode(tr, paragraphPos, paragraphNode);\n        const selection = moveToPreviousTextBlock(tr, paragraphPos);\n        setSelection(tr, selection);\n      } else {\n        // Remove the last character from the current paragraph\n        const newContent = paragraphNode.content.cut(0, paragraphNode.content.size - 1);\n        const newParagraph = schema.nodes.paragraph.create({}, newContent);\n        tr.replaceWith(paragraphPos, paragraphPos + paragraphNode.nodeSize, newParagraph);\n        setSelectionAtPos(tr, thisPos - 1);\n      }\n    } else if (isPosAtStartOfDocumentBody(doc, $pos, true)) {\n      // Prevent deleting the first page node\n      return true;\n    } else if (!isPosAtStartOfBody(doc, $pos)) {\n      return false;\n    } else {\n      const {\n        node: thisPageNode,\n        pos: thisPagePos\n      } = getPageNodeAndPosition(doc, $pos);\n      if (!thisPageNode) {\n        console.warn(\"No current page node found\");\n        return false;\n      }\n      if (!isPosAtStartOfBody(doc, thisPos)) {\n        return false;\n      }\n      const prevPageChild = doc.childBefore(thisPagePos);\n      const prevPageNode = prevPageChild.node;\n      // Confirm that the previous node is a page node\n      if (!prevPageNode) {\n        // Start of document\n        console.log(\"No previous page node found\");\n        return false;\n      }\n      if (!isPageNode(prevPageNode)) {\n        console.warn(\"Previous node is not a page node\");\n        return false;\n      }\n      // Append the content of the current paragraph to the end of the previous paragraph\n      const {\n        pos: paragraphPos,\n        node: paragraphNode\n      } = getParagraphNodeAndPosition(doc, $pos);\n      if (!paragraphNode) {\n        console.warn(\"No current paragraph node found\");\n        return false;\n      }\n      const {\n        pos: previousParagraphPos,\n        node: previousParagraphNode\n      } = getLastParagraphInPreviousPageBodyBeforePos(doc, paragraphPos);\n      if (!previousParagraphNode) {\n        // Handle to prevent cursor moving to header\n        return true;\n      }\n      if (!isNodeEmpty$1(previousParagraphNode) || !isNodeEmpty$1(paragraphNode)) {\n        deleteNode(tr, paragraphPos, paragraphNode);\n      }\n      appendAndReplaceNode(tr, previousParagraphPos, previousParagraphNode, paragraphNode);\n      // Set the selection to the end of the previous paragraph\n      setSelectionToEndOfParagraph(tr, previousParagraphPos, previousParagraphNode);\n    }\n    dispatch(tr);\n    return true;\n  },\n  Delete: (state, dispatch) => {\n    if (!dispatch) {\n      console.warn(\"No dispatch function provided\");\n      return false;\n    }\n    if (isHighlighting(state)) {\n      return false;\n    }\n    const {\n      doc,\n      tr\n    } = state;\n    const $pos = getResolvedPosition(state);\n    if (isPosAtEndOfPageAmendment(doc, $pos)) {\n      // Handle to prevent cursor moving out of the page amendment\n      return true;\n    }\n    // Ensure that the position is within a valid block (paragraph)\n    if (!isPositionWithinParagraph($pos)) {\n      console.warn(\"Not inside a paragraph node\");\n      return false;\n    }\n    if (!isPosAtEndOfBody(doc, $pos)) {\n      return false;\n    }\n    // We need to remove the current paragraph node and prepend any\n    // content to the next paragraph node (which will now be at the\n    // end of the current page)\n    const thisPos = $pos.pos;\n    const expectedTextNodePos = thisPos - 1;\n    const thisTextNode = doc.nodeAt(expectedTextNodePos);\n    if (!thisTextNode) {\n      console.warn(\"No node found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: paragraphPos,\n      node: paragraphNode\n    } = getParagraphNodeAndPosition(doc, $pos);\n    if (!paragraphNode) {\n      console.warn(\"No current paragraph node found\");\n      return false;\n    }\n    if (!isParagraphNode(thisTextNode) && !isTextNode(thisTextNode)) {\n      console.warn(\"Unexpected node type found at position\", expectedTextNodePos);\n      return false;\n    }\n    const {\n      pos: nextParagraphPos,\n      node: nextParagraphNode\n    } = getFirstParagraphInNextPageBodyAfterPos(doc, paragraphPos);\n    if (!nextParagraphNode) {\n      // Handle to prevent cursor moving to footer\n      return true;\n    }\n    const thisNodeEmpty = isNodeEmpty$1(paragraphNode);\n    const nextNodeEmpty = isNodeEmpty$1(nextParagraphNode);\n    if (!nextNodeEmpty) {\n      deleteNode(tr, nextParagraphPos, nextParagraphNode);\n    }\n    appendAndReplaceNode(tr, paragraphPos, paragraphNode, nextParagraphNode);\n    if (thisNodeEmpty) {\n      const $newPos = tr.doc.resolve(thisPos);\n      if (nextNodeEmpty) {\n        moveToNextTextBlock(tr, $newPos);\n      } else {\n        moveToNearestTextSelection(tr, $newPos);\n      }\n    } else {\n      setSelectionAtPos(tr, thisPos);\n    }\n    dispatch(tr);\n    return true;\n  }\n});\n\n/**\n * @file /src/constants/sizing.ts\n * @name Sizing\n * @description Constants for sizing and measurements.\n */\nconst MM_PER_INCH = 25.4;\nconst STANDARD_PIXELS_PER_INCH = 96;\n\n/**\n * @file /src/utils/window.ts\n * @name Window\n * @description Utility functions for interacting with the window object.\n */\n/**\n * Calculates the DPI of the window.\n * @returns The DPI of the window.\n */\nconst calculateWindowDPI = () => {\n  const ratio = pythagoreanTheorem(window.screen.width, window.screen.height) / pythagoreanTheorem(window.screen.availWidth, window.screen.availHeight);\n  const dpi = ratio * STANDARD_PIXELS_PER_INCH;\n  return dpi;\n};\n/**\n * Converts millimeters to pixels.\n *\n * @param mm - The length in millimeters.\n * @returns The length in pixels.\n */\nconst mmToPixels = mm => {\n  const dpi = calculateWindowDPI();\n  const inches = mm / MM_PER_INCH;\n  return inches * dpi;\n};\n\n/**\n * Set a node attribute to the given value.\n *\n * @param tr - The transaction to apply the change to.\n * @param pos - The position of the node to set the attribute for.\n * @param node - The node to set the attribute for.\n * @param attr - The attribute to set.\n * @param value - The value to set the attribute to.\n * @returns {boolean} True if the attribute was changed, false otherwise.\n */\nconst setNodeAttribute = (tr, pos, node, attr, value) => {\n  const nodeAttr = node.attrs[attr];\n  const isDifferent = nodeAttr !== value;\n  if (isDifferent) {\n    tr.setNodeAttribute(pos, attr, value);\n  }\n  return isDifferent;\n};\n/**\n * Set a node attribute to the given value for the nodes of the type handled by the setNodeTypeAttribute callback.\n *\n * @param tr - The transaction to apply the change to.\n * @param attr - The attribute to set.\n * @param value - The value to set the attribute to.\n * @param setNodesTypeAttribute - The callback to set the attribute for a node of the type handled by the callback.\n * @returns {boolean} True if any attribute was changed, false otherwise.\n */\nconst setNodesTypeAttribute = (tr, attr, value, setNodesTypeAttribute) => {\n  const {\n    doc\n  } = tr;\n  const transactions = [];\n  doc.forEach((node, pos) => {\n    transactions.push(setNodesTypeAttribute(tr, pos, node, attr, value));\n  });\n  return transactions.some(changed => changed);\n};\n\n/**\n * @file /src/utils/setPageAttributes.ts\n * @name SetPageAttributes\n * @description Utility functions for setting page attributes.\n */\n/**\n * Set a page node attribute to the given value for all page nodes in the document.\n *\n * @param tr - The transaction to apply the change to.\n * @param attr - The attribute to set.\n * @param value - The value to set the attribute to.\n * @returns {boolean} True if any attribute was changed, false otherwise.\n */\nconst setPageNodesAttribute = (tr, attr, value) => {\n  return setNodesTypeAttribute(tr, attr, value, setPageNodeAttribute);\n};\n/**\n * Set a page node attribute to the given value.\n *\n * @param tr - The transaction to apply the change to.\n * @param pos - The position of the node to set the attribute for.\n * @param node - The node to set the attribute for.\n * @param attr - The attribute to set.\n * @param value - The value to set the attribute to.\n * @returns {boolean} True if the attribute was changed, false otherwise.\n */\nconst setPageNodeAttribute = (tr, pos, node, attr, value) => {\n  if (!isPageNode(node)) {\n    return false;\n  }\n  return setNodeAttribute(tr, pos, node, attr, value);\n};\n/**\n * Set a body node attribute to the given value for all body nodes in the document.\n *\n * @param tr - The transaction to apply the change to.\n * @param attr - The attribute to set.\n * @param value - The value to set the attribute to.\n * @returns {boolean} True if any attribute was changed, false otherwise.\n */\nconst setBodyNodesAttribute = (tr, attr, value) => {\n  return setNodesTypeAttribute(tr, attr, value, setBodyNodeAttribute);\n};\n/**\n * Set a body node attribute to the given value.\n *\n * @param tr - The transaction to apply the change to.\n * @param pagePos - The position of the node to set the attribute for.\n * @param pageNode - The page node (parent of the body nody).\n * @param attr - The attribute to set.\n * @param value - The value to set the attribute to.\n * @returns {boolean} True if the attribute was changed, false otherwise.\n */\nconst setBodyNodeAttribute = (tr, pagePos, pageNode, attr, value) => {\n  if (!isPageNode(pageNode)) {\n    return false;\n  }\n  const {\n    node: bodyNode,\n    pos: bodyPos\n  } = getPageRegionNodeAndPos(pagePos, pageNode, \"body\");\n  if (!bodyNode || !isBodyNode(bodyNode)) {\n    return false;\n  }\n  return setNodeAttribute(tr, bodyPos, bodyNode, attr, value);\n};\n\n/**\n * @file /src/utils/extension.ts\n * @name Extension\n * @description Utility functions for extensions\n */\n/**\n * Finds an extension by its name in the editor's extension manager.\n *\n * @param editor - The editor instance containing the extension manager.\n * @param extensionName - The name of the extension to find.\n * @returns The extension if found, otherwise undefined.\n */\nconst findExtension = (editor, extensionName) => editor.extensionManager.extensions.find(ext => ext.name === extensionName);\n\n/**\n * @file /src/utils/options.ts\n * @name Options\n * @description Utility functions for retrieving extension options.\n */\n/**\n * Retrieves the options for a specified extension in the editor.\n *\n * @param editor - The editor instance containing the extensions.\n * @param extensionName - The name of the extension whose options are to be retrieved.\n * @returns The options of the specified extension, or undefined if the extension is not found.\n */\nconst getExtensionOptions = (editor, extensionName) => {\n  const extension = findExtension(editor, extensionName);\n  return extension?.options;\n};\n/**\n * Retrieves the options for the pagination extension in the editor.\n *\n * @param editor - The editor instance containing the extensions.\n * @returns The options of the pagination extension, or undefined if the extension is not found.\n * @throws An error if the pagination extension is not found in the editor.\n */\nconst getPaginationExtensionOptions = editor => {\n  const options = getExtensionOptions(editor, PAGINATION_EXTENSION_NAME);\n  if (!options) {\n    throw new Error(\"Pagination extension not found in the editor.\");\n  }\n  return options;\n};\n\n/**\n * @file /src/utils/paperOrientation.ts\n * @name PaperOrientation\n * @description Utility functions for paper orientations.\n */\n/**\n * Get the paper orientation of a particular page node in the document.\n *\n * @param pageNode - The page node to find the paper orientation for\n * @returns {Nullable<PaperOrientation>} The paper orientation of the specified page or null\n * if the paper orientation is not set.\n */\nconst getPageNodePaperOrientation = pageNode => {\n  const {\n    attrs\n  } = pageNode;\n  return attrs[PAGE_NODE_ATTR_KEYS.paperOrientation];\n};\n/**\n * Retrieves the paper orientation of a specific page using the editor instance.\n * Falls back to the default paper orientation if the page number is invalid.\n *\n * @param editor - The current editor instance.\n * @param pageNum - The page number to retrieve the paper orientation for.\n * @returns {PaperOrientation} The paper orientation of the specified page or default.\n */\nconst getPageNumPaperOrientation = (editor, pageNum) => getPageAttributeByPageNum(editor.state, pageNum, getPaginationExtensionOptions(editor).defaultPaperOrientation, getPageNodePaperOrientation);\n/**\n * Set the paper orientation of a page node to the given value.\n *\n * @param tr - The transaction to apply the change to.\n * @param dispatch - The dispatch function to apply the transaction.\n * @param pagePos - The position of the page node to set the paper colour for.\n * @param pageNode - The page node to set the paper colour for.\n * @param paperOrientation - The paper orientation to set.\n * @returns {boolean} True if the paper colour was set, false otherwise.\n */\nconst setPageNodePosPaperOrientation = (tr, dispatch, pagePos, pageNode, paperOrientation) => {\n  if (!dispatch) return false;\n  if (!isPageNode(pageNode)) {\n    console.error(\"Unexpected! Node at pos:\", pagePos, \"is not a page node!\");\n    return false;\n  }\n  if (getPageNodePaperOrientation(pageNode) === paperOrientation) {\n    // Paper colour is already set\n    return false;\n  }\n  setPageNodeAttribute(tr, pagePos, pageNode, PAGE_NODE_ATTR_KEYS.paperOrientation, paperOrientation);\n  dispatch(tr);\n  return true;\n};\n\n/**\n * @file /src/utils/paperSize.ts\n * @name PaperSize\n * @description Utility functions for paper sizes.\n */\n/**\n * Check if the given paper size is valid.\n *\n * @param paperSize - The paper size to check.\n * @returns {boolean} True if the paper size is valid, false otherwise.\n */\nconst isValidPaperSize = paperSize => {\n  return paperSize in paperDimensions;\n};\n/**\n * Given a paper size, return the dimensions of the paper in millimeters.\n *\n * @param paperSize - The paper size\n * @param orientation - The orientation of the paper\n * @returns {PaperDimensions} - The dimensions of the paper\n */\nconst getPaperDimensions = (paperSize, orientation) => {\n  if (!isValidPaperSize(paperSize)) {\n    paperSize = DEFAULT_PAPER_SIZE;\n  }\n  const dimensions = paperDimensions[paperSize];\n  if (orientation === \"landscape\") {\n    return flipDimensions(dimensions);\n  } else {\n    return dimensions;\n  }\n};\n/**\n * Gets the paper dimensions of a page node.\n *\n * @param pageNode - The page node to get the paper dimensions from\n * @returns {PaperDimensions} - The dimensions of the paper\n */\nconst getPaperDimensionsFromPageNode = pageNode => {\n  const paperSize = getPageNodePaperSize(pageNode) ?? DEFAULT_PAPER_SIZE;\n  const paperOrientation = getPageNodePaperOrientation(pageNode) ?? DEFAULT_PAPER_ORIENTATION;\n  return getPaperDimensions(paperSize, paperOrientation);\n};\n/**\n * Flips the width and height of a given set of dimensions.\n *\n * @param dimensions - The dimensions to flip.\n * @returns {PaperDimensions} The flipped dimensions.\n */\nconst flipDimensions = dimensions => {\n  return {\n    width: dimensions.height,\n    height: dimensions.width\n  };\n};\n/**\n * Calculates the pixel width and height of a given paper size.\n *\n * @param pageNodeAttributes - The attributes of the page node.\n * @param bodyNodeAttributes - The attributes of the body node.\n * @returns {PageContentPixelDimensions} The height and width of the page in pixels.\n */\nconst calculatePageContentPixelDimensions = (pageNodeAttributes, bodyNodeAttributes) => {\n  const {\n    paperSize,\n    paperOrientation,\n    pageBorders\n  } = pageNodeAttributes;\n  const {\n    width: paperWidth,\n    height: paperHeight\n  } = getPaperDimensions(paperSize, paperOrientation);\n  const {\n    top: marginTop,\n    left: marginLeft,\n    right: marginRight,\n    bottom: marginBottom\n  } = bodyNodeAttributes.pageMargins;\n  const verticalMargins = marginTop + marginBottom;\n  const horizontalMargins = marginLeft + marginRight;\n  const {\n    top: borderTop,\n    right: borderRight,\n    bottom: borderBottom,\n    left: borderLeft\n  } = pageBorders;\n  const verticalBorders = borderTop + borderBottom;\n  const horizontalBorders = borderLeft + borderRight;\n  const bodyHeight = mmToPixels(paperHeight - verticalMargins) - verticalBorders;\n  const bodyWidth = mmToPixels(paperWidth - horizontalMargins) - horizontalBorders;\n  return {\n    bodyHeight,\n    bodyWidth\n  };\n};\n/**\n * Check if a page node has a paper size attribute.\n *\n * @param pageNode - The page node to check.\n * @returns {boolean} True if the page node has a paper size attribute, false otherwise.\n */\nconst pageNodeHasPageSize = pageNode => {\n  return nodeHasAttribute(pageNode, PAGE_NODE_ATTR_KEYS.paperSize);\n};\n/**\n * Get the paper size of a particular page node in the document.\n *\n * @param pageNode - The page node to find the paper size for\n * @returns {Nullable<PaperSize>} The paper size of the specified page or null\n * if the paper size is not set.\n */\nconst getPageNodePaperSize = pageNode => {\n  const {\n    attrs\n  } = pageNode;\n  return attrs[PAGE_NODE_ATTR_KEYS.paperSize];\n};\n/**\n * Retrieves the paper size of a specific page using the editor instance.\n * Falls back to the default paper size if the page number is invalid.\n *\n * @param editor - The current editor instance.\n * @param pageNum - The page number to retrieve the paper size for.\n * @returns {PaperSize} The paper size of the specified page or default.\n */\nconst getPageNumPaperSize = (editor, pageNum) => getPageAttributeByPageNum(editor.state, pageNum, getPaginationExtensionOptions(editor).defaultPaperSize, getPageNodePaperSize);\n/**\n * Set the paper size for a page node at the specified position.\n *\n * @param tr - The transaction to apply the change to.\n * @param dispatch - The dispatch function to apply the transaction.\n * @param pagePos - The position of the page node to set the paper size for.\n * @param paperSize - The paper size to set.\n * @returns {boolean} True if the paper size was set, false otherwise.\n */\nconst setPagePaperSize = (tr, dispatch, pagePos, paperSize) => {\n  const pageNode = tr.doc.nodeAt(pagePos);\n  if (!pageNode) {\n    console.error(\"No node found at pos:\", pagePos);\n    return false;\n  }\n  return setPageNodePosPaperSize(tr, dispatch, pagePos, pageNode, paperSize);\n};\n/**\n * Helper to set the paper size for a page node at the specified position.\n *\n * @param tr - The transaction to apply the change to.\n * @param dispatch - The dispatch function to apply the transaction.\n * @param pagePos - The position of the page node to set the paper size for.\n * @param pageNode - The page node to set the paper size for.\n * @param paperSize - The paper size to set.\n * @returns {boolean} True if the paper size was set, false otherwise.\n */\nconst setPageNodePosPaperSize = (tr, dispatch, pagePos, pageNode, paperSize) => {\n  if (!dispatch) return false;\n  if (!isValidPaperSize(paperSize)) {\n    console.warn(`Invalid paper size: ${paperSize}`);\n    return false;\n  }\n  if (!isPageNode(pageNode)) {\n    console.error(\"Unexpected! Node at pos:\", pagePos, \"is not a page node!\");\n    return false;\n  }\n  if (getPageNodePaperSize(pageNode) === paperSize) {\n    // Paper size is already set\n    return false;\n  }\n  setPageNodeAttribute(tr, pagePos, pageNode, PAGE_NODE_ATTR_KEYS.paperSize, paperSize);\n  dispatch(tr);\n  return true;\n};\n\n/**\n * @file /src/constants/theme.ts\n * @name Theme\n * @description Constants related to the theme\n */\nconst DARK_THEME = \"Dark\";\nconst LIGHT_THEME = \"Light\";\n\n/**\n * @file /src/utils/colour.ts\n * @name Colour\n * @description Utility functions for working with colours.\n */\n/**\n * Checks if the given paper colour is a valid colour format.\n *\n * This function validates the paper colour by checking if it is in\n * hexadecimal, RGB, or RGBA format.\n *\n * @param paperColour - The colour string to validate.\n * @returns `true` if the colour is valid, otherwise `false`.\n */\nconst isValidColour = paperColour => {\n  return isHex(paperColour) || isRGB(paperColour) || isRGBA(paperColour);\n};\n/**\n * Checks if a given string is a valid hexadecimal color code.\n *\n * A valid hexadecimal color code starts with a '#' followed by either\n * 3 or 6 hexadecimal characters (0-9, A-F, a-f).\n *\n * @param colour - The string to be checked.\n * @returns `true` if the string is a valid hexadecimal color code, otherwise `false`.\n */\nconst isHex = colour => {\n  const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;\n  return hexRegex.test(colour);\n};\n/**\n * Checks if a given string is in the RGB color format.\n *\n * The RGB color format is defined as `rgb(r, g, b)` where `r`, `g`, and `b` are integers\n * between 0 and 255 inclusive.\n *\n * @param colour - The string to check.\n * @returns `true` if the string is in the RGB color format, otherwise `false`.\n */\nconst isRGB = colour => {\n  const rgbRegex = /^rgb\\((\\d{1,3}), (\\d{1,3}), (\\d{1,3})\\)$/;\n  return rgbRegex.test(colour);\n};\n/**\n * Checks if the given colour string is in the RGBA format.\n *\n * The RGBA format is expected to be in the form: `rgba(r, g, b, a)`\n * where `r`, `g`, and `b` are integers between 0 and 255, and `a` is a float between 0 and 1.\n *\n * @param colour - The colour string to check.\n * @returns `true` if the colour string is in the RGBA format, otherwise `false`.\n */\nconst isRGBA = colour => {\n  const rgbaRegex = /^rgba\\((\\d{1,3}), (\\d{1,3}), (\\d{1,3}), (0|1|0?\\.\\d+)\\)$/;\n  return rgbaRegex.test(colour);\n};\n\n/**\n * @file /src/utils/theme.ts\n * @name Theme\n * @description Utility functions for handling the theme of the application\n */\n/**\n * Returns the preferred device theme based on the user's system settings.\n * @returns The preferred device theme (either DARK_THEME or LIGHT_THEME).\n */\nconst getDeviceTheme = () => {\n  return window.matchMedia(`(prefers-color-scheme: ${DARK_THEME.toLowerCase()})`).matches ? DARK_THEME : LIGHT_THEME;\n};\n\n/**\n * @file /src/utils/paperColour.ts\n * @name PaperColour\n * @description Utility functions for paper colours.\n */\n/**\n * Get the paper colour based on the device theme.\n *\n * @returns {string} The paper colour based on the device theme.\n */\nconst getDeviceThemePaperColour = () => {\n  return getDeviceTheme() === DARK_THEME ? DARK_PAPER_COLOUR : LIGHT_PAPER_COLOUR;\n};\n/**\n * Retrieves the default paper colour based on the provided editor options.\n * If the `useDeviceThemeForPaperColour` option is enabled, it returns the device theme paper colour.\n * Otherwise, it returns the `defaultPaperColour` specified in the options.\n *\n * @param editor - The editor instance.\n * @returns The default paper colour as a string.\n */\nconst getDefaultPaperColour = editor => {\n  const paginationOptions = getPaginationExtensionOptions(editor);\n  if (paginationOptions.useDeviceThemeForPaperColour) {\n    return getDeviceThemePaperColour();\n  } else {\n    return paginationOptions.defaultPaperColour;\n  }\n};\n/**\n * Get the paper colour of a particular page node in the document.\n *\n * @param pageNode - The page node to find the paper colour for\n * @returns {Nullable<string>} The paper colour of the specified page or null\n * if the paper colour is not set.\n */\nconst getPageNodePaperColour = pageNode => {\n  const {\n    attrs\n  } = pageNode;\n  return attrs[PAGE_NODE_ATTR_KEYS.paperColour];\n};\n/**\n * Retrieves the paper color of a specific page using the editor instance.\n * Falls back to the default paper color if the page number is invalid.\n *\n * @param editor - The current editor instance.\n * @param pageNum - The page number to retrieve the paper color for.\n * @returns {string} The paper color of the specified page or default.\n */\nconst getPageNumPaperColour = (editor, pageNum) => {\n  const defaultPaperColour = getDefaultPaperColour(editor);\n  return getPageAttributeByPageNum(editor.state, pageNum, defaultPaperColour, getPageNodePaperColour);\n};\n/**\n * Set the paper colour for a page node at the specified position.\n *\n * @param tr - The transaction to apply the change to.\n * @param dispatch - The dispatch function to apply the transaction.\n * @param pagePos - The position of the page node to set the paper colour for.\n * @param pageNode - The page node to set the paper colour for.\n * @param paperColour - The paper colour to set.\n * @returns {boolean} True if the paper colour was set, false otherwise.\n */\nconst setPageNodePosPaperColour = (tr, dispatch, pagePos, pageNode, paperColour) => {\n  if (!dispatch) return false;\n  if (!isValidColour(paperColour)) {\n    console.warn(\"Invalid paper colour:\", paperColour);\n    return false;\n  }\n  if (!isPageNode(pageNode)) {\n    console.error(\"Unexpected! Node at pos:\", pagePos, \"is not a page node!\");\n    return false;\n  }\n  if (getPageNodePaperColour(pageNode) === paperColour) {\n    // Paper colour is already set\n    return false;\n  }\n  setPageNodeAttribute(tr, pagePos, pageNode, PAGE_NODE_ATTR_KEYS.paperColour, paperColour);\n  dispatch(tr);\n  return true;\n};\n\n/**\n * @file /src/utils/units.ts\n * @name Units\n * @description Utility functions for handling units of measurement.\n */\n/**\n * Format a value as a millimetre string.\n *\n * @param value - The value to format.\n * @returns {string} The value formatted as a millimetre string.\n * @example mm(10) // \"10mm\"\n */\nconst mm = value => {\n  return `${value}mm`;\n};\n/**\n * Format a value as a pixel string.\n *\n * @param value - The value to format.\n * @returns {string} The value formatted as a pixel string.\n * @example px(10) // \"10px\"\n */\nconst px = value => {\n  return `${value}px`;\n};\n\n/**\n * @file /src/constants/pageSides.ts\n * @name PageSides\n * @description Constants for page sides in the editor.\n */\nconst pageSides = [\"top\", \"right\", \"bottom\", \"left\"];\n\n/**\n * @file /src/utils/setSideConfig.ts\n * @name SetSideConfig\n * @description Utility functions for setting side configuration (e.g. margins, borders) for page nodes.\n */\n/**\n * Generic helper to set the side configuration of a document.\n *\n * @param attrKey - The key of the attribute to update.\n * @param isValidConfig - A function to validate the side configuration.\n * @param setNodesAttribute - A function to set the attribute nodes.\n * @returns\n */\nconst setDocumentSideConfig = (attrKey, isValidConfig, setNodesAttribute) => sideConfig => ({\n  tr,\n  dispatch\n}) => {\n  if (!dispatch) return false;\n  if (!isValidConfig(sideConfig)) {\n    console.warn(\"Invalid side config\", sideConfig);\n    return false;\n  }\n  setNodesAttribute(tr, attrKey, sideConfig);\n  dispatch(tr);\n  return true;\n};\n/**\n * Sets the side configuration of a node.\n *\n * @param setNodePosByPageNum - A function to get the position of a node by page number.\n * @param setGenericPageNodePosSideConfig - A function to set the side configuration of a node.\n * @param pageNum - The page number to set the side configuration for.\n * @param sideConfig - The side configuration to set.\n * @returns {boolean} True if the side configuration was set, false otherwise.\n */\nconst setPageSideConfig = (setNodePosByPageNum, setGenericPageNodePosSideConfig) => (pageNum, sideConfig) => ({\n  tr,\n  dispatch\n}) => {\n  const {\n    doc\n  } = tr;\n  const pageNodePos = setNodePosByPageNum(doc, pageNum);\n  if (!pageNodePos) {\n    return false;\n  }\n  const {\n    pos: pagePos,\n    node: pageNode\n  } = pageNodePos;\n  return setGenericPageNodePosSideConfig(tr, dispatch, pagePos, pageNode, sideConfig);\n};\n/**\n * Set one side of the document side configuration.\n *\n * @param setDocumentSideConfig - A function to set the document side configuration.\n * @param isValueValid - A function to validate the value.\n * @param updateSideConfig - A function to update the side configuration of a page node.\n * @returns {boolean} True if the side value was set, false otherwise.\n */\nconst setDocumentSideValue = (setDocumentSideConfig, isValueValid, updateSideConfig) => (side, value) => ({\n  tr,\n  dispatch\n}) => {\n  if (!dispatch) return false;\n  if (side === \"all\") {\n    const sideConfig = {\n      top: value,\n      right: value,\n      bottom: value,\n      left: value\n    };\n    return setDocumentSideConfig(sideConfig);\n  }\n  if (!isValueValid(value)) {\n    console.warn(\"Invalid margin value\", value);\n    return false;\n  }\n  const {\n    doc\n  } = tr;\n  const transactions = [];\n  doc.forEach((node, pos) => {\n    transactions.push(updateSideConfig(tr, pos, node, side, value));\n  });\n  const success = transactions.some(changed => changed);\n  if (success) {\n    dispatch(tr);\n  }\n  return success;\n};\n/**\n * Set one side of the page side configuration.\n *\n * @param setPageSideConfig - A function to set the side configuration of a page node.\n * @param isValueValid - A function to validate the value.\n * @param updateSideConfig - A function to update the side configuration of a page node.\n * @param pageNum - The page number to set the side value for.\n * @param side - The side to set the value for.\n * @returns {boolean} True if the side value was set, false otherwise.\n */\nconst setPageSideValue = (setPageSideConfig, isValueValid, updateSideConfig) => (pageNum, side, value) => ({\n  tr,\n  dispatch\n}) => {\n  if (!dispatch) return false;\n  if (side === \"all\") {\n    const sideConfig = {\n      top: value,\n      right: value,\n      bottom: value,\n      left: value\n    };\n    return setPageSideConfig(pageNum, sideConfig);\n  }\n  if (!isValueValid(value)) {\n    console.warn(\"Invalid side value\", value);\n    return false;\n  }\n  const {\n    doc\n  } = tr;\n  const pageNodePos = getPageNodePosByPageNum(doc, pageNum);\n  if (!pageNodePos) {\n    return false;\n  }\n  const {\n    pos: pagePos,\n    node: pageNode\n  } = pageNodePos;\n  const success = updateSideConfig(tr, pagePos, pageNode, side, value);\n  if (success) {\n    dispatch(tr);\n  }\n  return success;\n};\n/**\n * Set the paper side configuration of a page node.\n *\n * @param tr - The transaction to apply the change to.\n * @param dispatch - The dispatch function to apply the transaction.\n * @param pagePos - The position of the page node to set the side config for.\n * @param pageNode - The page node to set the side config for.\n * @param configObj - The side config to set.\n * @param isValidConfig - A function to validate the side config.\n * @param getPageNodeSideConfig - A function to get the existing side config from the page node.\n * @param attrKey - The key of the attribute to update.\n * @returns {boolean} True if the side config were set, false otherwise.\n */\nconst setPageNodePosSideConfig = (tr, dispatch, pagePos, pageNode, configObj, isValidConfig, getPageNodeSideConfig, attrKey) => {\n  if (!dispatch) return false;\n  if (!isValidConfig(configObj)) {\n    console.warn(\"Invalid side config:\", configObj);\n    return false;\n  }\n  if (!isPageNode(pageNode)) {\n    console.error(\"Unexpected! Node at pos:\", pagePos, \"is not a page node!\");\n    return false;\n  }\n  if (getPageNodeSideConfig(pageNode) === configObj) {\n    return false;\n  }\n  const success = setPageNodeAttribute(tr, pagePos, pageNode, attrKey, configObj);\n  if (success) {\n    dispatch(tr);\n  }\n  return success;\n};\n/**\n * Updates a page side configuration attribute. Does not dispatch the transaction.\n *\n * @param tr - The transaction to apply the change to.\n * @param pagePos - The position of the page node to update the attribute for.\n * @param pageNode - The page node to update the attribute for.\n * @param configObj - The configuration object to update.\n * @param value - The new value of the configuration object.\n * @param getExistingConfig - A function to get the existing configuration object from\n * the node. Can return null if the configuration object is missing or invalid.\n *\n * @param isValidConfig - A function to validate the configuration object.\n * @param defaultConfig - The default configuration object.\n * @param attrKey - The key of the attribute to update.\n * @returns {boolean} True if the attribute was updated, false otherwise.\n */\nconst updatePageSideConfig = (tr, pagePos, pageNode, configObj, value, getExistingConfig, isValidConfig, defaultConfig, attrKey) => {\n  if (!isPageNode(pageNode)) {\n    return false;\n  }\n  const existingConfig = getExistingConfig(pageNode);\n  let updatedConfig = {\n    ...defaultConfig\n  };\n  if (existingConfig && isValidConfig(existingConfig)) {\n    updatedConfig = {\n      ...existingConfig\n    };\n  } else {\n    if (pageSides.includes(configObj)) {\n      updatedConfig[configObj] = value;\n    } else {\n      switch (configObj) {\n        case \"x\":\n          updatedConfig.left = value;\n          updatedConfig.right = value;\n          break;\n        case \"y\":\n          updatedConfig.top = value;\n          updatedConfig.bottom = value;\n          break;\n        default:\n          console.error(\"Unhanded margin side\", configObj);\n      }\n    }\n  }\n  return setPageNodeAttribute(tr, pagePos, pageNode, attrKey, updatedConfig);\n};\n\n/**\n * @file /src/utils/pageBorders.ts\n * @name PageBorders\n * @description Utility functions for handling page borders.\n */\n/**\n * Checks if a (single) border is valid.\n * Borders must be non-negative and finite to be considered valid.\n *\n * @param border - The border to check.\n * @returns {boolean} True if the border is valid, false otherwise.\n */\nconst isBorderValid = border => {\n  return border >= 0 && isFinite(border);\n};\n/**\n * Checks if the page borders are valid.\n * Borders must be non-negative and finite to be considered valid.\n *\n * @param pageBorder - The page borders to check.\n * @returns {boolean} True if the page borders are valid, false otherwise.\n */\nconst isValidPageBorders = pageBorder => {\n  return Object.values(pageBorder).every(isBorderValid);\n};\n/**\n * Get the page borders from a page node.\n *\n * @param pageNode - The page node to get the page borders from.\n * @returns {Nullable<BorderConfig>} The page borders of the specified page.\n */\nconst getPageNodePageBorders = pageNode => {\n  const {\n    attrs\n  } = pageNode;\n  return attrs[PAGE_NODE_ATTR_KEYS.pageBorders];\n};\n/**\n * Converts a border config to a CSS string using px as the unit.\n *\n * @param pageBorders - The page borders to convert to a CSS string.\n * @returns {string} The CSS string representation of the page borders. Remember MDN says\n * order is (top, right, bottom, left). See https://developer.mozilla.org/en-US/docs/Web/CSS/border.\n */\nconst calculateShorthandPageBorders = pageBorders => {\n  const {\n    top,\n    right,\n    bottom,\n    left\n  } = pageBorders;\n  const borders = [top, right, bottom, left].map(px).join(\" \");\n  return borders;\n};\n/**\n * Retrieves the page border config of a specific page using the editor instance.\n * Falls back to the default page border config if the page number is invalid.\n *\n * @param editor - The current editor instance.\n * @param pageNum - The page number to retrieve the page border config for.\n * @returns {BorderConfig} The page border config of the specified page or default.\n */\nconst getPageNumPageBorders = (editor, pageNum) => getPageAttributeByPageNum(editor.state, pageNum, getPaginationExtensionOptions(editor).defaultPageBorders, getPageNodePageBorders);\n/**\n * Set the page borders of a page node.\n *\n * @param tr - The transaction to apply the change to.\n * @param dispatch - The dispatch function to apply the transaction.\n * @param pagePos - The position of the page node to set the page borders for.\n * @param pageNode - The page node to set the page borders for.\n * @param pageBorders - The page borders to set.\n * @returns {boolean} True if the page borders were set, false otherwise.\n */\nconst setPageNodePosPageBorders = (tr, dispatch, pagePos, pageNode, pageBorders) => {\n  return setPageNodePosSideConfig(tr, dispatch, pagePos, pageNode, pageBorders, isValidPageBorders, getPageNodePageBorders, PAGE_NODE_ATTR_KEYS.pageBorders);\n};\n/**\n * Updates the border on the given page. Does not dispatch the transaction.\n *\n * @param tr - The transaction to apply the change to.\n * @param pagePos - The position of the page node to update the border for.\n * @param pageNode - The page node to update the border for.\n * @param border - The border to update.\n * @param value - The new value of the border.\n * @returns {boolean} True if the border was updated, false otherwise.\n */\nconst updatePageBorder = (tr, pagePos, pageNode, border, value) => {\n  return updatePageSideConfig(tr, pagePos, pageNode, border, value, getPageNodePageBorders, isValidPageBorders, DEFAULT_PAGE_BORDER_CONFIG, PAGE_NODE_ATTR_KEYS.pageBorders);\n};\n\n/**\n * @file /src/utils/getPageAttributes.ts\n * @name GetPageAttributes\n * @description Utility functions for getting page attributes.\n */\n/**\n * Retrieves page attributes from the editor state for a given page number.\n *\n * @param editor - The editor instance.\n * @param pageNum - The page number to retrieve the attributes for.\n * @returns {PageNodeAttributes} The attributes of the specified page.\n */\nconst getPageNodeAttributesByPageNum = (editor, pageNum) => {\n  const paperSize = getPageNumPaperSize(editor, pageNum);\n  const paperColour = getPageNumPaperColour(editor, pageNum);\n  const paperOrientation = getPageNumPaperOrientation(editor, pageNum);\n  const pageBorders = getPageNumPageBorders(editor, pageNum);\n  return {\n    paperSize,\n    paperColour,\n    paperOrientation,\n    pageBorders\n  };\n};\n/**\n * Retrieves the default page region node attributes.\n *\n * @returns {PageRegionNodeAttributesObject} The default attributes of the page regions.\n */\nconst getDefaultPageRegionNodeAttributes = () => {\n  return {\n    header: HEADER_DEFAULT_ATTRIBUTES,\n    body: BODY_DEFAULT_ATTRIBUTES,\n    footer: FOOTER_DEFAULT_ATTRIBUTES\n  };\n};\n/**\n * Retrieves body attributes from the editor state.\n *\n * @param state - The current editor state.\n * @param pageNum - The page number to retrieve the attributes for.\n * @returns {PageNodeAttributes} The attributes of the specified page.\n */\nconst getPageRegionNodeAttributes = (state, pageNum) => {\n  if (!doesDocHavePageNodes(state)) {\n    return getDefaultPageRegionNodeAttributes();\n  }\n  const pageNode = getPageNodeByPageNum(state.doc, pageNum);\n  if (!pageNode) {\n    return getDefaultPageRegionNodeAttributes();\n  }\n  const headerNode = getPageRegionNode(pageNode, \"header\");\n  const bodyNode = getPageRegionNode(pageNode, \"body\");\n  const footerNode = getPageRegionNode(pageNode, \"footer\");\n  const headerAttributes = headerNode ? getHeaderNodeAttributes(headerNode) : HEADER_DEFAULT_ATTRIBUTES;\n  const bodyAttributes = bodyNode ? getBodyNodeAttributes(bodyNode) : BODY_DEFAULT_ATTRIBUTES;\n  const footerAttributes = footerNode ? getFooterNodeAttributes(footerNode) : FOOTER_DEFAULT_ATTRIBUTES;\n  return {\n    body: bodyAttributes,\n    header: headerAttributes,\n    footer: footerAttributes\n  };\n};\n/**\n * Retrieves the page node attributes and calculates the pixel dimensions of the page.\n *\n * @param editor - The editor instance.\n * @param pageNum - The page number to retrieve the attributes for.\n * @returns {PaginationNodeAttributes} The attributes of the page node,\n * body node and the pixel dimensions of the page.\n */\nconst getPaginationNodeAttributes = (editor, pageNum) => {\n  const {\n    state\n  } = editor;\n  const pageNodeAttributes = getPageNodeAttributesByPageNum(editor, pageNum);\n  const pageRegionNodeAttributes = getPageRegionNodeAttributes(state, pageNum);\n  const bodyPixelDimensions = calculatePageContentPixelDimensions(pageNodeAttributes, pageRegionNodeAttributes.body);\n  return {\n    pageNodeAttributes,\n    pageRegionNodeAttributes,\n    bodyPixelDimensions\n  };\n};\n\n/**\n * @file /src/utils/buildPageView.ts\n * @name BuildPageView\n * @description Utility functions for building the page view.\n */\n/**\n * Builds a new document with paginated content.\n *\n * @param view - The editor view.\n * @param options - The pagination options.\n * @returns {void}\n */\nconst buildPageView = (editor, view, options) => {\n  const {\n    state,\n    dispatch\n  } = view;\n  const {\n    doc\n  } = state;\n  try {\n    const contentNodes = collectContentNodes(doc);\n    const nodeHeights = measureNodeHeights(view, contentNodes);\n    // Record the cursor's old position\n    const {\n      tr,\n      selection\n    } = state;\n    const oldCursorPos = selection.from;\n    const {\n      newDoc,\n      oldToNewPosMap\n    } = buildNewDocument(editor, options, contentNodes, nodeHeights);\n    // Compare the content of the documents\n    if (!newDoc.content.eq(doc.content)) {\n      tr.replaceWith(0, doc.content.size, newDoc.content);\n      tr.setMeta(\"pagination\", true);\n      const newDocContentSize = newDoc.content.size;\n      const newCursorPos = mapCursorPosition(contentNodes, oldCursorPos, oldToNewPosMap, newDocContentSize);\n      paginationUpdateCursorPosition(tr, newCursorPos);\n    }\n    dispatch(tr);\n  } catch (error) {\n    console.error(\"Error updating page view. Details:\", error);\n  }\n};\n/**\n * Collect content nodes and their existing positions.\n *\n * @param doc - The document node.\n * @returns {NodePosArray} The content nodes and their positions.\n */\nconst collectContentNodes = doc => {\n  const contentNodes = [];\n  doc.forEach((pageNode, pageOffset) => {\n    if (isPageNode(pageNode)) {\n      pageNode.forEach((pageRegionNode, pageRegionOffset) => {\n        // Offsets in forEach loop start from 0, however, the child nodes of any given node\n        // have a starting offset of 1 (for the first child)\n        const truePageRegionOffset = pageRegionOffset + 1;\n        if (isHeaderFooterNode(pageRegionNode)) ; else if (isBodyNode(pageRegionNode)) {\n          pageRegionNode.forEach((child, childOffset) => {\n            // First child of body node (e.g. paragraph) has an offset of 1 more\n            // than the body node itself.\n            const trueChildOffset = childOffset + 1;\n            contentNodes.push({\n              node: child,\n              pos: pageOffset + truePageRegionOffset + trueChildOffset\n            });\n          });\n        } else {\n          contentNodes.push({\n            node: pageRegionNode,\n            pos: pageOffset + truePageRegionOffset\n          });\n        }\n      });\n    } else {\n      contentNodes.push({\n        node: pageNode,\n        pos: pageOffset + 1\n      });\n    }\n  });\n  return contentNodes;\n};\n/**\n * Calculates the margins of the element.\n *\n * @param element - The element to calculate margins for.\n * @returns {MarginConfig} The margins of the element.\n */\nconst calculateElementMargins = element => {\n  const style = window.getComputedStyle(element);\n  return {\n    top: parseFloat(style.marginTop),\n    right: parseFloat(style.marginRight),\n    bottom: parseFloat(style.marginBottom),\n    left: parseFloat(style.marginLeft)\n  };\n};\n/**\n * Measure the heights of the content nodes.\n *\n * @param view - The editor view.\n * @param contentNodes - The content nodes and their positions.\n * @returns {number[]} The heights of the content nodes.\n */\nconst measureNodeHeights = (view, contentNodes) => {\n  const paragraphType = view.state.schema.nodes.paragraph;\n  const nodeHeights = contentNodes.map(({\n    pos,\n    node\n  }) => {\n    const domNode = view.nodeDOM(pos);\n    if (domNode instanceof HTMLElement) {\n      let {\n        height\n      } = domNode.getBoundingClientRect();\n      const {\n        top: marginTop\n      } = calculateElementMargins(domNode);\n      if (height === 0) {\n        if (node.type === paragraphType || node.isTextblock) {\n          // Assign a minimum height to empty paragraphs or textblocks\n          height = MIN_PARAGRAPH_HEIGHT;\n        }\n      }\n      // We use top margin only because there is overlap of margins between paragraphs\n      return height + marginTop;\n    }\n    return MIN_PARAGRAPH_HEIGHT; // Default to minimum height if DOM element is not found\n  });\n  return nodeHeights;\n};\n/**\n * Build the new document and keep track of new positions.\n *\n * @param editor - The editor instance.\n * @param options - The pagination options.\n * @param contentNodes - The content nodes and their positions.\n * @param nodeHeights - The heights of the content nodes.\n * @returns {newDoc: PMNode, oldToNewPosMap: CursorMap} The new document and the mapping from old positions to new positions.\n */\nconst buildNewDocument = (editor, options, contentNodes, nodeHeights) => {\n  const {\n    schema,\n    doc\n  } = editor.state;\n  const {\n    pageAmendmentOptions\n  } = options;\n  const {\n    pageNodeType: pageType,\n    headerFooterNodeType: headerFooterType,\n    bodyNodeType: bodyType,\n    paragraphNodeType: paragraphType\n  } = getPaginationNodeTypes(schema);\n  let pageNum = 0;\n  const pages = [];\n  let existingPageNode = doc.maybeChild(pageNum);\n  let {\n    pageNodeAttributes,\n    pageRegionNodeAttributes,\n    bodyPixelDimensions\n  } = getPaginationNodeAttributes(editor, pageNum);\n  const constructHeaderFooter = pageRegionType => headerFooterAttrs => {\n    if (!headerFooterType) return;\n    if (existingPageNode) {\n      const hfNode = getPageRegionNode(existingPageNode, pageRegionType);\n      if (hfNode) {\n        return hfNode;\n      }\n    }\n    const emptyParagraph = paragraphType.create();\n    return headerFooterType.create(headerFooterAttrs, [emptyParagraph]);\n  };\n  const constructHeader = headerFooterAttrs => {\n    if (!pageAmendmentOptions.enableHeader) return;\n    return constructHeaderFooter(\"header\")(headerFooterAttrs);\n  };\n  const constructFooter = headerFooterAttrs => {\n    if (!pageAmendmentOptions.enableFooter) return;\n    return constructHeaderFooter(\"footer\")(headerFooterAttrs);\n  };\n  const constructPageRegions = currentPageContent => {\n    const {\n      body: bodyAttrs,\n      footer: footerAttrs\n    } = pageRegionNodeAttributes;\n    const pageBody = bodyType.create(bodyAttrs, currentPageContent);\n    const pageFooter = constructFooter(footerAttrs);\n    const pageRegions = [currentPageHeader, pageBody, pageFooter];\n    return pageRegions.filter(region => !!region);\n  };\n  const addPage = currentPageContent => {\n    const pageNodeContents = constructPageRegions(currentPageContent);\n    const pageNode = pageType.create(pageNodeAttributes, pageNodeContents);\n    pages.push(pageNode);\n    return pageNode;\n  };\n  // Header is constructed prior to the body because we need to know its node size for the cursor mapping\n  let currentPageHeader = constructHeader(pageRegionNodeAttributes.header);\n  let currentPageContent = [];\n  let currentHeight = 0;\n  const oldToNewPosMap = new Map();\n  const pageOffset = 1,\n    bodyOffset = 1;\n  let cumulativeNewDocPos = pageOffset + getMaybeNodeSize(currentPageHeader) + bodyOffset;\n  for (let i = 0; i < contentNodes.length; i++) {\n    const {\n      node,\n      pos: oldPos\n    } = contentNodes[i];\n    const nodeHeight = nodeHeights[i];\n    const isPageFull = currentHeight + nodeHeight > bodyPixelDimensions.bodyHeight;\n    if (isPageFull && currentPageContent.length > 0) {\n      const pageNode = addPage(currentPageContent);\n      cumulativeNewDocPos += pageNode.nodeSize - getMaybeNodeSize(currentPageHeader);\n      currentPageContent = [];\n      currentHeight = 0;\n      existingPageNode = doc.maybeChild(++pageNum);\n      if (isPageNumInRange(doc, pageNum)) {\n        ({\n          pageNodeAttributes,\n          pageRegionNodeAttributes,\n          bodyPixelDimensions\n        } = getPaginationNodeAttributes(editor, pageNum));\n      }\n      // Next page header\n      currentPageHeader = constructHeader(pageRegionNodeAttributes.header);\n      cumulativeNewDocPos += getMaybeNodeSize(currentPageHeader);\n    }\n    // Record the mapping from old position to new position\n    const nodeStartPosInNewDoc = cumulativeNewDocPos + currentPageContent.reduce((sum, n) => sum + n.nodeSize, 0);\n    oldToNewPosMap.set(oldPos, nodeStartPosInNewDoc);\n    currentPageContent.push(node);\n    currentHeight += nodeHeight;\n  }\n  if (currentPageContent.length > 0) {\n    // Add final page (may not be full)\n    addPage(currentPageContent);\n  } else {\n    pageNum--;\n  }\n  const newDoc = schema.topNodeType.create(null, pages);\n  const docSize = newDoc.content.size;\n  limitMappedCursorPositions(oldToNewPosMap, docSize);\n  return {\n    newDoc,\n    oldToNewPosMap\n  };\n};\n/**\n * Limit mapped cursor positions to document size to prevent out of bounds errors\n * when setting the cursor position.\n *\n * @param oldToNewPosMap - The mapping from old positions to new positions.\n * @param docSize - The size of the new document.\n * @returns {void}\n */\nconst limitMappedCursorPositions = (oldToNewPosMap, docSize) => {\n  oldToNewPosMap.forEach((newPos, oldPos) => {\n    if (newPos > docSize) {\n      oldToNewPosMap.set(oldPos, docSize);\n    }\n  });\n};\n/**\n * Map the cursor position from the old document to the new document.\n *\n * @param contentNodes - The content nodes and their positions.\n * @param oldCursorPos - The old cursor position.\n * @param oldToNewPosMap - The mapping from old positions to new positions.\n * @param newDocContentSize - The size of the new document. Serves as maximum limit for cursor position.\n * @returns {number} The new cursor position.\n */\nconst mapCursorPosition = (contentNodes, oldCursorPos, oldToNewPosMap, newDocContentSize) => {\n  let newCursorPos = null;\n  for (let i = 0; i < contentNodes.length; i++) {\n    const {\n      node,\n      pos: oldNodePos\n    } = contentNodes[i];\n    const nodeSize = node.nodeSize;\n    if (inRange(oldCursorPos, oldNodePos, oldNodePos + nodeSize)) {\n      const offsetInNode = oldCursorPos - oldNodePos;\n      const newNodePos = oldToNewPosMap.get(oldNodePos);\n      if (newNodePos === undefined) {\n        console.error(\"Unable to determine new node position from cursor map!\");\n        newCursorPos = 0;\n      } else {\n        newCursorPos = Math.min(newNodePos + offsetInNode, newDocContentSize - 1);\n      }\n      break;\n    }\n  }\n  return newCursorPos;\n};\n/**\n * Check if the given position is at the start of a text block.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document.\n * @returns {boolean} True if the position is at the start of a text block, false otherwise.\n */\nconst isNodeBeforeAvailable = $pos => {\n  return !!$pos.nodeBefore && (isTextNode($pos.nodeBefore) || isParagraphNode($pos.nodeBefore));\n};\n/**\n * Check if the given position is at the end of a text block.\n *\n * @param doc - The document node.\n * @param $pos - The resolved position in the document.\n * @returns {boolean} True if the position is at the end of a text block, false otherwise.\n */\nconst isNodeAfterAvailable = $pos => {\n  return !!$pos.nodeAfter && (isTextNode($pos.nodeAfter) || isParagraphNode($pos.nodeAfter));\n};\n/**\n * Sets the cursor selection after creating the new document.\n *\n * @param tr - The current transaction.\n * @returns {void}\n */\nconst paginationUpdateCursorPosition = (tr, newCursorPos) => {\n  if (newCursorPos !== null) {\n    const $pos = tr.doc.resolve(newCursorPos);\n    let selection;\n    if ($pos.parent.isTextblock || isNodeBeforeAvailable($pos) || isNodeAfterAvailable($pos)) {\n      selection = moveToThisTextBlock(tr, $pos);\n    } else {\n      selection = moveToNearestValidCursorPosition($pos);\n    }\n    if (selection) {\n      setSelection(tr, selection);\n    } else {\n      // Fallback to a safe selection at the end of the document\n      setSelectionAtEndOfDocument(tr);\n    }\n  } else {\n    setSelectionAtEndOfDocument(tr);\n  }\n};\n\n/**\n * @file /src/Plugins/Pagination.ts\n * @name Pagination\n * @description Custom plugin for paginating the editor content.\n */\nconst PaginationPlugin = ({\n  editor,\n  options\n}) => {\n  return new Plugin({\n    key: new PluginKey(\"pagination\"),\n    view() {\n      let isPaginating = false;\n      return {\n        update(view, prevState) {\n          if (isPaginating) return;\n          const {\n            state\n          } = view;\n          const {\n            doc,\n            schema\n          } = state;\n          const pageType = schema.nodes.page;\n          if (!pageType) return;\n          const docChanged = !doc.eq(prevState.doc);\n          const initialLoad = isNodeEmpty(prevState.doc) && !isNodeEmpty(doc);\n          const hasPageNodes = doesDocHavePageNodes(state);\n          if (!docChanged && hasPageNodes && !initialLoad) return;\n          isPaginating = true;\n          buildPageView(editor, view, options);\n          // Reset paginating flag regardless of success or failure because we do not want to get\n          // stuck out of this loop.\n          isPaginating = false;\n        }\n      };\n    }\n  });\n};\n\n/**\n * @file /src/utils/pageRegion/pageMargins.ts\n * @name PageMargins\n * @description Utility functions for body margins\n */\n/**\n * Checks if a (single) margin is valid.\n * Margins must be non-negative and finite to be considered valid.\n *\n * @param margin - The margin to check.\n * @returns {boolean} True if the margin is valid, false otherwise.\n */\nconst isMarginValid = margin => {\n  return margin >= 0 && isFinite(margin);\n};\n/**\n * Checks if the page margins are valid.\n * Margins must be non-negative and finite to be considered valid.\n *\n * @param pageMargins - The page margins to check.\n * @returns {boolean} True if the page margins are valid, false otherwise.\n */\nconst isValidPageMargins = pageMargins => {\n  return Object.values(pageMargins).every(isMarginValid);\n};\n/**\n * Retrieves the page margin config of a specific body using the editor instance.\n * Falls back to the default page margin config if the page number is invalid.\n *\n * @param editor - The current editor instance.\n * @param pageNum - The page number to retrieve the page margin config for.\n * @returns {MarginConfig} The page margin config of the specified page or default.\n */\nconst getPageNumPageMargins = (editor, pageNum) => getPageRegionAttributeByPageNum(editor.state, pageNum, \"body\", getPaginationExtensionOptions(editor).defaultMarginConfig, getBodyNodeMargins);\n/**\n * Calculate the effective DOM margins of the body node. Takes into account\n * what the margins should be to ensure the header and footer nodes are\n * visible on the page.\n *\n * @param bodyNode - The body node to calculate the margins for.\n * @returns {MarginConfig} The effective margins of the body node.\n */\nconst calculateBodyMargins = bodyNode => {\n  // Copy the default margin config to avoid modifying the original.\n  const {\n    ...bodyMargins\n  } = getBodyNodeMargins(bodyNode) ?? DEFAULT_PAGE_MARGIN_CONFIG;\n  return bodyMargins;\n};\n/**\n * Converts a margin config to a CSS string using millimeters as the unit.\n *\n * @param pageMargins - The page margins to convert to a CSS string.\n * @returns {string} The CSS string representation of the page margins. As per MDN reference, the\n * order is (top, right, bottom, left). See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/padding}.\n */\nconst calculateShorthandMargins = pageMargins => {\n  const {\n    top,\n    right,\n    bottom,\n    left\n  } = pageMargins;\n  const padding = [top, right, bottom, left].map(mm).join(\" \");\n  return padding;\n};\n/**\n * Set the page margins of a body node.\n *\n * @param tr - The transaction to apply the change to.\n * @param dispatch - The dispatch function to apply the transaction.\n * @param pagePos - The position of the body node to set the page margins for.\n * @param bodyNode - The body node to set the page margins for.\n * @param pageMargins - The page margins to set.\n * @returns {boolean} True if the page margins were set, false otherwise.\n */\nconst setBodyNodePosPageMargins = (tr, dispatch, pagePos, bodyNode, pageMargins) => {\n  return setPageNodePosSideConfig(tr, dispatch, pagePos, bodyNode, pageMargins, isValidPageMargins, getBodyNodeMargins, BODY_NODE_ATTR_KEYS.pageMargins);\n};\n/**\n * Updates the margin on the given page. Does not dispatch the transaction.\n *\n * @param tr - The transaction to apply the change to.\n * @param pagePos - The position of the body node to update the margin for.\n * @param bodyNode - The body node to update the margin for.\n * @param margin - The margin to update.\n * @param value - The new value of the margin.\n * @returns {boolean} True if the margin was updated, false otherwise.\n */\nconst updateBodyMargin = (tr, pagePos, bodyNode, margin, value) => {\n  return updatePageSideConfig(tr, pagePos, bodyNode, margin, value, getBodyNodeMargins, isValidPageMargins, DEFAULT_PAGE_MARGIN_CONFIG, BODY_NODE_ATTR_KEYS.pageMargins);\n};\n\n/**\n * @file /src/PaginationExtension.ts\n * @name Pagination\n * @description Custom pagination extension for the Tiptap editor.\n */\nconst PaginationExtension = Extension.create({\n  name: PAGINATION_EXTENSION_NAME,\n  addOptions() {\n    return {\n      defaultPaperSize: DEFAULT_PAPER_SIZE,\n      defaultPaperColour: DEFAULT_PAPER_COLOUR,\n      useDeviceThemeForPaperColour: false,\n      defaultPaperOrientation: DEFAULT_PAPER_ORIENTATION,\n      defaultMarginConfig: DEFAULT_PAGE_MARGIN_CONFIG,\n      defaultPageBorders: DEFAULT_PAGE_BORDER_CONFIG,\n      pageAmendmentOptions: DEFAULT_PAGE_AMENDMENT_CONFIG\n    };\n  },\n  onCreate() {\n    this.editor.commands.checkPaperSizes();\n  },\n  addProseMirrorPlugins() {\n    const {\n      editor,\n      options\n    } = this;\n    return [KeymapPlugin, PaginationPlugin({\n      editor,\n      options\n    })];\n  },\n  addCommands() {\n    return {\n      setDocumentPaperSize: paperSize => ({\n        tr,\n        dispatch\n      }) => {\n        if (!dispatch) return false;\n        if (!isValidPaperSize(paperSize)) {\n          console.warn(`Invalid paper size: ${paperSize}`);\n          return false;\n        }\n        setPageNodesAttribute(tr, PAGE_NODE_ATTR_KEYS.paperSize, paperSize);\n        dispatch(tr);\n        return true;\n      },\n      setDocumentDefaultPaperSize: () => ({\n        commands\n      }) => commands.setDocumentPaperSize(this.options.defaultPaperSize),\n      setPagePaperSize: (pageNum, paperSize) => ({\n        tr,\n        dispatch\n      }) => {\n        const {\n          doc\n        } = tr;\n        const pageNodePos = getPageNodePosByPageNum(doc, pageNum);\n        if (!pageNodePos) {\n          return false;\n        }\n        const {\n          pos: pagePos,\n          node: pageNode\n        } = pageNodePos;\n        return setPageNodePosPaperSize(tr, dispatch, pagePos, pageNode, paperSize);\n      },\n      checkPaperSizes: () => ({\n        tr,\n        dispatch\n      }) => {\n        const {\n          doc\n        } = tr;\n        const paperSizeUpdates = [];\n        doc.forEach((node, pos) => {\n          if (isPageNode(node)) {\n            if (!pageNodeHasPageSize(node)) {\n              paperSizeUpdates.push(setPagePaperSize(tr, dispatch, pos, this.options.defaultPaperSize));\n            }\n          }\n        });\n        // If any page sizes were updated\n        return paperSizeUpdates.some(update => update);\n      },\n      setDocumentPaperColour: paperColour => ({\n        tr,\n        dispatch\n      }) => {\n        if (!dispatch) return false;\n        setPageNodesAttribute(tr, PAGE_NODE_ATTR_KEYS.paperColour, paperColour);\n        dispatch(tr);\n        return true;\n      },\n      setDocumentDefaultPaperColour: () => ({\n        editor,\n        commands\n      }) => {\n        const defaultPaperColour = getDefaultPaperColour(editor);\n        return commands.setDocumentPaperColour(defaultPaperColour);\n      },\n      setPagePaperColour: (pageNum, paperColour) => ({\n        tr,\n        dispatch\n      }) => {\n        const {\n          doc\n        } = tr;\n        const pageNodePos = getPageNodePosByPageNum(doc, pageNum);\n        if (!pageNodePos) {\n          return false;\n        }\n        const {\n          pos: pagePos,\n          node: pageNode\n        } = pageNodePos;\n        return setPageNodePosPaperColour(tr, dispatch, pagePos, pageNode, paperColour);\n      },\n      setDocumentPaperOrientation: paperOrientation => ({\n        tr,\n        dispatch\n      }) => {\n        if (!dispatch) return false;\n        setPageNodesAttribute(tr, PAGE_NODE_ATTR_KEYS.paperOrientation, paperOrientation);\n        dispatch(tr);\n        return true;\n      },\n      setDocumentDefaultPaperOrientation: () => ({\n        commands\n      }) => commands.setDocumentPaperOrientation(this.options.defaultPaperOrientation),\n      setPagePaperOrientation: (pageNum, paperOrientation) => ({\n        tr,\n        dispatch\n      }) => {\n        const {\n          doc\n        } = tr;\n        const pageNodePos = getPageNodePosByPageNum(doc, pageNum);\n        if (!pageNodePos) {\n          return false;\n        }\n        const {\n          pos: pagePos,\n          node: pageNode\n        } = pageNodePos;\n        return setPageNodePosPaperOrientation(tr, dispatch, pagePos, pageNode, paperOrientation);\n      },\n      setDocumentPageMargins: setDocumentSideConfig(BODY_NODE_ATTR_KEYS.pageMargins, isValidPageMargins, setBodyNodesAttribute),\n      setDocumentDefaultPageMargins: () => ({\n        commands\n      }) => commands.setDocumentPageMargins(this.options.defaultMarginConfig),\n      setPagePageMargins: setPageSideConfig(getPageNodePosByPageNum, setBodyNodePosPageMargins),\n      setDocumentPageMargin: (margin, value) => ({\n        tr,\n        dispatch,\n        commands\n      }) => setDocumentSideValue(commands.setDocumentPageMargins, isMarginValid, updateBodyMargin)(margin, value)({\n        tr,\n        dispatch\n      }),\n      setPagePageMargin: (pageNum, margin, value) => ({\n        tr,\n        dispatch,\n        commands\n      }) => setPageSideValue(commands.setPagePageMargins, isMarginValid, updateBodyMargin)(pageNum, margin, value)({\n        tr,\n        dispatch\n      }),\n      setDocumentPageBorders: setDocumentSideConfig(PAGE_NODE_ATTR_KEYS.pageBorders, isValidPageBorders, setPageNodesAttribute),\n      setDocumentDefaultPageBorders: () => ({\n        commands\n      }) => commands.setDocumentPageBorders(this.options.defaultPageBorders),\n      setPageBorders: setPageSideConfig(getPageNodePosByPageNum, setPageNodePosPageBorders),\n      setDocumentPageBorder: (border, value) => ({\n        tr,\n        dispatch,\n        commands\n      }) => setDocumentSideValue(commands.setDocumentPageBorders, isBorderValid, updatePageBorder)(border, value)({\n        tr,\n        dispatch\n      }),\n      setPagePageBorder: (pageNum, border, value) => ({\n        tr,\n        dispatch,\n        commands\n      }) => setPageSideValue(commands.setPageBorders, isBorderValid, updatePageBorder)(pageNum, border, value)({\n        tr,\n        dispatch\n      })\n    };\n  }\n});\n\n/**\n * @file /src/utils/clipboard.ts\n * @name Clipboard\n * @description Utility functions for clipboard operations.\n */\n/**\n * Constructs a clipboard serialiser that serialises only the children of the nodes of the specified schema.\n *\n * @param schema - The schema to use for serialisation.\n * @returns {DOMSerializer} The constructed clipboard serialiser.\n */\nconst constructChildOnlyClipboardSerialiser = (schema, isNode) => {\n  // Extend DOMSerializer to override serializeFragment\n  const clipboardSerialiser = Object.create(DOMSerializer.fromSchema(schema));\n  // Override serializeFragment\n  clipboardSerialiser.serializeFragment = (fragment, options = {}, target = document.createDocumentFragment()) => {\n    const serializer = DOMSerializer.fromSchema(schema);\n    fragment.forEach(node => {\n      if (isNode(node)) {\n        // Serialize only the children of the page node\n        serializer.serializeFragment(node.content, options, target);\n      } else {\n        // Serialize non-page nodes directly\n        serializer.serializeNode(node, options);\n      }\n    });\n    return target;\n  };\n  return clipboardSerialiser;\n};\n/**\n * Constructs a clipboard plugin with the specified key and serialiser.\n *\n * @param name - The plugin key.\n * @param serialiser - The serialiser to use for clipboard operations.\n * @returns {Plugin} The constructed clipboard plugin.\n */\nconst constructClipboardPlugin = (name, serialiser) => {\n  return new Plugin({\n    key: new PluginKey(name),\n    props: {\n      clipboardSerializer: serialiser\n    }\n  });\n};\n/**\n * Constructs a clipboard plugin that serialises only the children of the nodes of the specified schema.\n *\n * @param name - The plugin key.\n * @param schema - The schema to use for serialisation.\n * @param isNode - A function that returns true if the node is a page node.\n * @returns {Plugin} The constructed clipboard plugin.\n */\nconst constructChildOnlyClipboardPlugin = (name, schema, isNode) => {\n  const clipboardSerialiser = constructChildOnlyClipboardSerialiser(schema, isNode);\n  return constructClipboardPlugin(name, clipboardSerialiser);\n};\n\n/**\n * @file /src/utils/attributes/addAttributes.ts\n * @name AddAttributes\n * @description Utility functions for adding node attributes.\n */\n/**\n * Add the specified attributes to the node.\n *\n * @param attributes - The attributes to add to the node.\n * @returns {Attributes} The attributes to add to the node.\n */\nconst addNodeAttributes = attributes => {\n  return Object.entries(attributes).reduce((attributes, [key, config]) => ({\n    ...attributes,\n    [key]: {\n      default: config.default,\n      parseHTML: parseHTMLAttribute(key, config.default),\n      renderHTML: renderHTMLAttribute(key)\n    }\n  }), {});\n};\n/**\n * Parse the HTML attribute of the element.\n *\n * @param element - The element to parse the attribute from.\n * @param attr - The attribute to parse.\n * @param fallback - The fallback value if the attribute is not found.\n * @returns {T} The parsed attribute value or the fallback value.\n */\nconst parseHTMLAttribute = (attr, fallback) => element => {\n  const attrValue = element.getAttribute(attr);\n  if (!attrValue) return fallback;\n  try {\n    return JSON.parse(attrValue);\n  } catch (error) {\n    return fallback;\n  }\n};\n/**\n * Render the HTML attribute.\n *\n * @param attr - The attribute to render.\n * @param attributes - The attributes to render.\n * @returns {Object} The rendered attribute.\n */\nconst renderHTMLAttribute = attr => attributes => {\n  const value = attributes[attr];\n  return {\n    [attr]: JSON.stringify(value)\n  };\n};\n\n/**\n * @file /src/Nodes/Page.ts\n * @name Page\n * @description Custom node for creating a page in the editor.\n */\nconst baseElement$2 = \"div\";\nconst dataPageAttribute = \"data-page\";\nconst PageNode = Node$1.create({\n  name: PAGE_NODE_NAME,\n  group: \"block\",\n  content: `block{1,3}`,\n  // We must have a body section and can optionally have a header and footer\n  defining: true,\n  isolating: false,\n  addOptions() {\n    return {\n      pageGap: DEFAULT_PAGE_GAP\n    };\n  },\n  addAttributes() {\n    return addNodeAttributes(PAGE_ATTRIBUTES);\n  },\n  parseHTML() {\n    return [parseHTMLNode(baseElement$2, dataPageAttribute)];\n  },\n  renderHTML({\n    HTMLAttributes\n  }) {\n    return [baseElement$2, mergeAttributes(HTMLAttributes, {\n      [dataPageAttribute]: true,\n      class: \"page\"\n    }), 0];\n  },\n  addNodeView() {\n    return props => {\n      const {\n        node\n      } = props;\n      const dom = document.createElement(baseElement$2);\n      dom.setAttribute(dataPageAttribute, String(true));\n      dom.classList.add(PAGE_NODE_NAME);\n      const {\n        width,\n        height\n      } = getPaperDimensionsFromPageNode(node);\n      dom.style.width = mm(width);\n      dom.style.height = mm(height);\n      const pageBorders = getPageNodePageBorders(node) ?? DEFAULT_PAGE_BORDER_CONFIG;\n      dom.style.borderWidth = calculateShorthandPageBorders(pageBorders);\n      dom.style.borderStyle = \"solid\";\n      dom.style.borderColor = \"#ccc\";\n      const paperColour = getPageNodePaperColour(node) ?? DEFAULT_PAPER_COLOUR;\n      dom.style.background = paperColour;\n      dom.style.overflow = \"hidden\";\n      dom.style.position = \"relative\";\n      dom.style.marginTop = px(this.options.pageGap);\n      dom.style.marginLeft = \"auto\";\n      dom.style.marginRight = \"auto\";\n      dom.style.boxSizing = \"border-box\";\n      const contentDOM = document.createElement(baseElement$2);\n      dom.appendChild(contentDOM);\n      return {\n        dom,\n        contentDOM\n      };\n    };\n  },\n  addProseMirrorPlugins() {\n    return [constructChildOnlyClipboardPlugin(\"pageClipboardPlugin\", this.editor.schema, isPageNode)];\n  }\n});\n\n/**\n * @file /src/utils/pageRegion/Dimensions.ts\n * @name Dimensions\n * @description Utility functions for body dimensions.\n */\n/**\n * Calculates the dimensions in millimetres of a header or footer node based on its paper size.\n *\n * @param pageNode - The page node containing the header or footer node.\n * @param headerFooterNode - The header or footer node to calculate the dimensions for.\n * @returns {PaperDimensions} The dimensions of the header or footer node.\n */\nconst calculateHeaderFooterDimensions = (pageNode, headerFooterNode) => {\n  const {\n    width: pageWidth\n  } = getPaperDimensionsFromPageNode(pageNode);\n  const {\n    left,\n    right\n  } = getHeaderFooterNodeXMargins(headerFooterNode) ?? DEFAULT_X_MARGIN_CONFIG;\n  const width = pageWidth - (left + right);\n  const height = getHeaderFooterNodeHeight(headerFooterNode) ?? HEADER_FOOTER_DEFAULT_ATTRIBUTES.height;\n  return {\n    width,\n    height\n  };\n};\n/**\n * Calculates the dimensions in millimetres of a body node based on its paper size\n * and orientation.\n *\n * @param pageNode - The page node containing the body node.\n * @param bodyNode - The body node to calculate the dimensions for.\n * @returns {PaperDimensions} The dimensions of the body node.\n */\nconst calculateBodyDimensions = (pageNode, bodyNode) => {\n  const {\n    width: pageWidth,\n    height: pageHeight\n  } = getPaperDimensionsFromPageNode(pageNode);\n  const {\n    bottom,\n    left,\n    right,\n    top\n  } = getBodyNodeMargins(bodyNode) ?? DEFAULT_PAGE_MARGIN_CONFIG;\n  const width = pageWidth - (left + right);\n  const height = pageHeight - (top + bottom);\n  return {\n    width,\n    height\n  };\n};\n\n/**\n * @file /src/Nodes/HeaderFooter.ts\n * @name HeaderFooter\n * @description The Header/Footer node for the editor.\n */\nconst baseElement$1 = \"div\";\nconst headerFooterAttribute = \"data-page-header-footer\";\nconst HeaderFooterNode = Node$1.create({\n  name: HEADER_FOOTER_NODE_NAME,\n  group: \"block\",\n  content: \"block+\",\n  defining: true,\n  isolating: true,\n  addAttributes() {\n    return addNodeAttributes(HEADER_FOOTER_ATTRIBUTES);\n  },\n  parseHTML() {\n    return [parseHTMLNode(baseElement$1, headerFooterAttribute)];\n  },\n  renderHTML({\n    HTMLAttributes\n  }) {\n    return [baseElement$1, mergeAttributes(HTMLAttributes, {\n      [headerFooterAttribute]: true,\n      class: HEADER_FOOTER_NODE_NAME\n    }), 0];\n  },\n  addNodeView() {\n    return props => {\n      const {\n        editor,\n        node,\n        getPos\n      } = props;\n      const pos = getPos();\n      const {\n        node: pageNode\n      } = getPageNodeAndPosition(editor.state.doc, pos);\n      const pageRegionType = getHeaderFooterNodeType(node);\n      if (!pageNode) {\n        throw new Error(`Page node not found from ${pageRegionType ?? HEADER_FOOTER_NODE_NAME} node at position ${pos}`);\n      }\n      const dom = document.createElement(baseElement$1);\n      dom.setAttribute(headerFooterAttribute, String(true));\n      dom.classList.add(HEADER_FOOTER_NODE_NAME);\n      const {\n        width,\n        height\n      } = calculateHeaderFooterDimensions(pageNode, node);\n      const endOffset = getHeaderFooterNodePageEndOffset(node) ?? FOOTER_DEFAULT_ATTRIBUTES.pageEndOffset;\n      const xMargins = getHeaderFooterNodeXMargins(node) ?? FOOTER_DEFAULT_ATTRIBUTES.xMargins;\n      dom.style.height = mm(height);\n      dom.style.width = mm(width);\n      dom.style.left = mm(xMargins.left);\n      switch (pageRegionType) {\n        case \"header\":\n          dom.style.top = mm(endOffset);\n          break;\n        case \"footer\":\n          dom.style.bottom = mm(endOffset);\n          break;\n      }\n      dom.style.border = \"1px solid #ccc\";\n      dom.style.overflow = \"hidden\";\n      dom.style.position = \"absolute\";\n      dom.style.boxSizing = \"border-box\";\n      const contentDOM = document.createElement(baseElement$1);\n      dom.appendChild(contentDOM);\n      return {\n        dom,\n        contentDOM\n      };\n    };\n  },\n  addProseMirrorPlugins() {\n    return [constructChildOnlyClipboardPlugin(\"headerChildOnlyClipboardPlugin\", this.editor.schema, isHeaderFooterNode)];\n  }\n});\n\n/**\n * @file /src/Nodes/Body.ts\n * @name Body\n * @description The Body node situated within a page.\n */\nconst baseElement = \"div\";\nconst bodyAttribute = \"data-page-body\";\nconst BodyNode = Node$1.create({\n  name: BODY_NODE_NAME,\n  group: \"block\",\n  content: \"block*\",\n  defining: true,\n  isolating: false,\n  addAttributes() {\n    return addNodeAttributes(BODY_ATTRIBUTES);\n  },\n  parseHTML() {\n    return [parseHTMLNode(baseElement, bodyAttribute)];\n  },\n  renderHTML({\n    HTMLAttributes\n  }) {\n    return [baseElement, mergeAttributes(HTMLAttributes, {\n      [bodyAttribute]: true,\n      class: BODY_NODE_NAME\n    }), 0];\n  },\n  addNodeView() {\n    return props => {\n      const {\n        editor,\n        node,\n        getPos\n      } = props;\n      const pos = getPos();\n      const {\n        node: pageNode\n      } = getPageNodeAndPosition(editor.state.doc, pos);\n      if (!pageNode) {\n        throw new Error(`Page node not found from body node at position ${pos}`);\n      }\n      const dom = document.createElement(baseElement);\n      dom.setAttribute(bodyAttribute, String(true));\n      dom.classList.add(BODY_NODE_NAME);\n      const {\n        width,\n        height\n      } = calculateBodyDimensions(pageNode, node);\n      const calculatedMargins = calculateBodyMargins(node);\n      dom.style.height = mm(height);\n      dom.style.width = mm(width);\n      dom.style.margin = calculateShorthandMargins(calculatedMargins);\n      dom.style.border = \"1px solid #ccc\";\n      dom.style.overflow = \"hidden\";\n      dom.style.position = \"relative\";\n      const contentDOM = document.createElement(baseElement);\n      dom.appendChild(contentDOM);\n      return {\n        dom,\n        contentDOM\n      };\n    };\n  },\n  addProseMirrorPlugins() {\n    return [constructChildOnlyClipboardPlugin(\"bodyChildOnlyClipboardPlugin\", this.editor.schema, isBodyNode)];\n  }\n});\n\n/**\n * @file /src/index.ts\n * @name Index\n * @description Main entry point for the package\n */\n// === Extensions ===\n\nexport { BodyNode, DARK_PAPER_COLOUR, DEFAULT_PAGE_AMENDMENT_CONFIG, DEFAULT_PAGE_BORDER_CONFIG, DEFAULT_PAGE_MARGIN_CONFIG, DEFAULT_PAGE_MARGIN_NAME, DEFAULT_PAPER_COLOUR, DEFAULT_PAPER_ORIENTATION, DEFAULT_PAPER_SIZE, HeaderFooterNode, LIGHT_PAPER_COLOUR, PageNode, commonMarginConfigs, PaginationExtension as default, doesDocHavePageNodes, getBodyNodeMargins, getPageNodePageBorders, getPageNodePaperColour, getPageNodePaperOrientation, getPageNodePaperSize, getPageNumPageBorders, getPageNumPageMargins, getPageNumPaperColour, getPageNumPaperOrientation, getPageNumPaperSize, getPageNumber, getThisPageNodePosition, isPageNode, pageSides, paperDimensions, paperOrientationsSelect, paperSizes };\n\n"]}