{"version":3,"sources":["../src/lib/get-text-around-cursor.ts"],"sourcesContent":["import { Editor, Node, Path, Range, Text, Element, BasePoint, BaseRange, Point } from \"slate\";\nimport { EditorAutocompleteState } from \"../types/base/editor-autocomplete-state\";\n\nexport interface EditorTextState {\n  selection: BaseRange;\n\n  textBeforeCursor: string;\n  selectedText: string;\n  textAfterCursor: string;\n}\n\nexport function getTextAroundCollapsedCursor(editor: Editor): EditorAutocompleteState | null {\n  const { selection } = editor;\n  if (!selection || !Range.isCollapsed(selection)) {\n    return null;\n  }\n\n  const cursorPoint = selection.anchor;\n\n  // Create two ranges: one before the anchor and one after\n  const beforeRange: Range = {\n    anchor: Editor.start(editor, []),\n    focus: cursorPoint,\n  };\n  const afterRange: Range = {\n    anchor: cursorPoint,\n    focus: Editor.end(editor, []),\n  };\n\n  // Extract text for these ranges\n  const before = extractTextWithNewlines(editor, beforeRange);\n  const after = extractTextWithNewlines(editor, afterRange);\n\n  return {\n    cursorPoint: cursorPoint,\n    textBeforeCursor: before,\n    textAfterCursor: after,\n  };\n}\n\nexport function getTextAroundSelection(editor: Editor): EditorTextState | null {\n  const { selection } = editor;\n  if (!selection) {\n    return null;\n  }\n\n  const wellOrderedSelection = wellOrderedRange(selection);\n\n  // Create two ranges: one before the anchor and one after\n  const beforeRange: Range = {\n    anchor: Editor.start(editor, []),\n    focus: wellOrderedSelection.anchor,\n  };\n  const afterRange: Range = {\n    anchor: wellOrderedSelection.focus,\n    focus: Editor.end(editor, []),\n  };\n\n  // Extract text for these ranges\n  const before = extractTextWithNewlines(editor, beforeRange);\n  const after = extractTextWithNewlines(editor, afterRange);\n  const selectedText = extractTextWithNewlines(editor, wellOrderedSelection);\n\n  return {\n    selection: wellOrderedSelection,\n    textBeforeCursor: before,\n    selectedText,\n    textAfterCursor: after,\n  };\n}\n\nexport function getFullEditorTextWithNewlines(editor: Editor): string {\n  const fullDocumentRange: Range = {\n    anchor: Editor.start(editor, []),\n    focus: Editor.end(editor, []),\n  };\n  return extractTextWithNewlines(editor, fullDocumentRange);\n}\n\n// Helper function to extract text with newlines\nexport function extractTextWithNewlines(editor: Editor, range: Range): string {\n  const voids = false;\n  const [start, end] = Range.edges(range);\n  let text = \"\";\n  let lastBlock: Node | null = null;\n\n  for (const [node, path] of Editor.nodes(editor, {\n    at: range,\n    match: Text.isText,\n    voids,\n  })) {\n    let t = node.text;\n\n    // Determine the parent block of the current text node\n    const [block] = Editor.above(editor, {\n      at: path,\n      match: (n) => Element.isElement(n) && n.type === \"paragraph\",\n    }) || [null];\n\n    // If we encounter a new block, prepend a newline\n    if (lastBlock !== block && block) {\n      // check that lastBlock is not null to avoid adding a newline at the beginning\n      if (lastBlock) {\n        text += \"\\n\";\n      }\n      lastBlock = block;\n    }\n\n    if (Path.equals(path, end.path)) {\n      t = t.slice(0, end.offset);\n    }\n\n    if (Path.equals(path, start.path)) {\n      t = t.slice(start.offset);\n    }\n\n    text += t;\n  }\n\n  return text;\n}\n\nfunction wellOrderedRange(range: BaseRange): BaseRange {\n  const { anchor, focus } = range;\n  // if anchor is before focus, return range as is\n  if (Point.isBefore(anchor, focus)) {\n    return range;\n  }\n\n  // if focus is before anchor, return range with anchor and focus swapped\n  return {\n    anchor: focus,\n    focus: anchor,\n  };\n}\n"],"mappings":";AAAA,SAAS,QAAc,MAAM,OAAO,MAAM,SAA+B,aAAa;AAW/E,SAAS,6BAA6B,QAAgD;AAC3F,QAAM,EAAE,UAAU,IAAI;AACtB,MAAI,CAAC,aAAa,CAAC,MAAM,YAAY,SAAS,GAAG;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,UAAU;AAG9B,QAAM,cAAqB;AAAA,IACzB,QAAQ,OAAO,MAAM,QAAQ,CAAC,CAAC;AAAA,IAC/B,OAAO;AAAA,EACT;AACA,QAAM,aAAoB;AAAA,IACxB,QAAQ;AAAA,IACR,OAAO,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,EAC9B;AAGA,QAAM,SAAS,wBAAwB,QAAQ,WAAW;AAC1D,QAAM,QAAQ,wBAAwB,QAAQ,UAAU;AAExD,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,EACnB;AACF;AAEO,SAAS,uBAAuB,QAAwC;AAC7E,QAAM,EAAE,UAAU,IAAI;AACtB,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,QAAM,uBAAuB,iBAAiB,SAAS;AAGvD,QAAM,cAAqB;AAAA,IACzB,QAAQ,OAAO,MAAM,QAAQ,CAAC,CAAC;AAAA,IAC/B,OAAO,qBAAqB;AAAA,EAC9B;AACA,QAAM,aAAoB;AAAA,IACxB,QAAQ,qBAAqB;AAAA,IAC7B,OAAO,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,EAC9B;AAGA,QAAM,SAAS,wBAAwB,QAAQ,WAAW;AAC1D,QAAM,QAAQ,wBAAwB,QAAQ,UAAU;AACxD,QAAM,eAAe,wBAAwB,QAAQ,oBAAoB;AAEzE,SAAO;AAAA,IACL,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB;AAAA,IACA,iBAAiB;AAAA,EACnB;AACF;AAEO,SAAS,8BAA8B,QAAwB;AACpE,QAAM,oBAA2B;AAAA,IAC/B,QAAQ,OAAO,MAAM,QAAQ,CAAC,CAAC;AAAA,IAC/B,OAAO,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,EAC9B;AACA,SAAO,wBAAwB,QAAQ,iBAAiB;AAC1D;AAGO,SAAS,wBAAwB,QAAgB,OAAsB;AAC5E,QAAM,QAAQ;AACd,QAAM,CAAC,OAAO,GAAG,IAAI,MAAM,MAAM,KAAK;AACtC,MAAI,OAAO;AACX,MAAI,YAAyB;AAE7B,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,MAAM,QAAQ;AAAA,IAC9C,IAAI;AAAA,IACJ,OAAO,KAAK;AAAA,IACZ;AAAA,EACF,CAAC,GAAG;AACF,QAAI,IAAI,KAAK;AAGb,UAAM,CAAC,KAAK,IAAI,OAAO,MAAM,QAAQ;AAAA,MACnC,IAAI;AAAA,MACJ,OAAO,CAAC,MAAM,QAAQ,UAAU,CAAC,KAAK,EAAE,SAAS;AAAA,IACnD,CAAC,KAAK,CAAC,IAAI;AAGX,QAAI,cAAc,SAAS,OAAO;AAEhC,UAAI,WAAW;AACb,gBAAQ;AAAA,MACV;AACA,kBAAY;AAAA,IACd;AAEA,QAAI,KAAK,OAAO,MAAM,IAAI,IAAI,GAAG;AAC/B,UAAI,EAAE,MAAM,GAAG,IAAI,MAAM;AAAA,IAC3B;AAEA,QAAI,KAAK,OAAO,MAAM,MAAM,IAAI,GAAG;AACjC,UAAI,EAAE,MAAM,MAAM,MAAM;AAAA,IAC1B;AAEA,YAAQ;AAAA,EACV;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAA6B;AACrD,QAAM,EAAE,QAAQ,MAAM,IAAI;AAE1B,MAAI,MAAM,SAAS,QAAQ,KAAK,GAAG;AACjC,WAAO;AAAA,EACT;AAGA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AACF;","names":[]}