@harbour-enterprises/superdoc 0.14.5-next.1 → 0.14.5-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/chunks/{super-editor.es-CbdU9k19.cjs → super-editor.es-CFpGpOoc.cjs} +492 -351
  2. package/dist/chunks/{super-editor.es-C6n5_0Ab.es.js → super-editor.es-CiA4uq6O.es.js} +492 -351
  3. package/dist/style.css +169 -169
  4. package/dist/super-editor/ai-writer.es.js +2 -2
  5. package/dist/super-editor/chunks/{converter-B7H3Sf5_.js → converter-CqN1dLza.js} +31 -25
  6. package/dist/super-editor/chunks/{docx-zipper-CRnln7Lc.js → docx-zipper-BFOjwdTS.js} +1 -1
  7. package/dist/super-editor/chunks/{editor-qdpgLEYR.js → editor-BgFDYm6H.js} +17 -16
  8. package/dist/super-editor/chunks/{toolbar-D_-x5OZN.js → toolbar-DVtiKzYb.js} +2 -2
  9. package/dist/super-editor/components/slash-menu/menuItems.d.ts.map +1 -1
  10. package/dist/super-editor/components/toolbar/defaultItems.d.ts.map +1 -1
  11. package/dist/super-editor/components/toolbar/super-toolbar.d.ts.map +1 -1
  12. package/dist/super-editor/converter.es.js +1 -1
  13. package/dist/super-editor/core/InputRule.d.ts +26 -0
  14. package/dist/super-editor/core/InputRule.d.ts.map +1 -1
  15. package/dist/super-editor/core/inputRules/docx-paste/docx-paste.d.ts +1 -1
  16. package/dist/super-editor/core/inputRules/docx-paste/docx-paste.d.ts.map +1 -1
  17. package/dist/super-editor/docx-zipper.es.js +2 -2
  18. package/dist/super-editor/editor.es.js +3 -3
  19. package/dist/super-editor/extensions/link/link.d.ts.map +1 -1
  20. package/dist/super-editor/file-zipper.es.js +1 -1
  21. package/dist/super-editor/style.css +169 -169
  22. package/dist/super-editor/super-editor.es.js +411 -275
  23. package/dist/super-editor/toolbar.es.js +2 -2
  24. package/dist/super-editor.cjs +1 -1
  25. package/dist/super-editor.es.js +1 -1
  26. package/dist/superdoc.cjs +2 -2
  27. package/dist/superdoc.es.js +3 -3
  28. package/dist/superdoc.umd.js +493 -352
  29. package/dist/superdoc.umd.js.map +1 -1
  30. package/package.json +1 -1
@@ -15039,7 +15039,7 @@ class Selection {
15039
15039
  found.
15040
15040
  */
15041
15041
  static findFrom($pos, dir, textOnly = false) {
15042
- let inner = $pos.parent.inlineContent ? new TextSelection($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
15042
+ let inner = $pos.parent.inlineContent ? new TextSelection$1($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
15043
15043
  if (inner)
15044
15044
  return inner;
15045
15045
  for (let depth = $pos.depth - 1; depth >= 0; depth--) {
@@ -15108,7 +15108,7 @@ class Selection {
15108
15108
  returns the bookmark for that.
15109
15109
  */
15110
15110
  getBookmark() {
15111
- return TextSelection.between(this.$anchor, this.$head).getBookmark();
15111
+ return TextSelection$1.between(this.$anchor, this.$head).getBookmark();
15112
15112
  }
15113
15113
  }
15114
15114
  Selection.prototype.visible = true;
@@ -15128,7 +15128,7 @@ function checkTextSelection($pos) {
15128
15128
  console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
15129
15129
  }
15130
15130
  }
15131
- class TextSelection extends Selection {
15131
+ let TextSelection$1 = class TextSelection2 extends Selection {
15132
15132
  /**
15133
15133
  Construct a text selection between the given points.
15134
15134
  */
@@ -15149,7 +15149,7 @@ class TextSelection extends Selection {
15149
15149
  if (!$head.parent.inlineContent)
15150
15150
  return Selection.near($head);
15151
15151
  let $anchor = doc2.resolve(mapping.map(this.anchor));
15152
- return new TextSelection($anchor.parent.inlineContent ? $anchor : $head, $head);
15152
+ return new TextSelection2($anchor.parent.inlineContent ? $anchor : $head, $head);
15153
15153
  }
15154
15154
  replace(tr, content = Slice.empty) {
15155
15155
  super.replace(tr, content);
@@ -15160,7 +15160,7 @@ class TextSelection extends Selection {
15160
15160
  }
15161
15161
  }
15162
15162
  eq(other) {
15163
- return other instanceof TextSelection && other.anchor == this.anchor && other.head == this.head;
15163
+ return other instanceof TextSelection2 && other.anchor == this.anchor && other.head == this.head;
15164
15164
  }
15165
15165
  getBookmark() {
15166
15166
  return new TextBookmark(this.anchor, this.head);
@@ -15174,7 +15174,7 @@ class TextSelection extends Selection {
15174
15174
  static fromJSON(doc2, json) {
15175
15175
  if (typeof json.anchor != "number" || typeof json.head != "number")
15176
15176
  throw new RangeError("Invalid input for TextSelection.fromJSON");
15177
- return new TextSelection(doc2.resolve(json.anchor), doc2.resolve(json.head));
15177
+ return new TextSelection2(doc2.resolve(json.anchor), doc2.resolve(json.head));
15178
15178
  }
15179
15179
  /**
15180
15180
  Create a text selection from non-resolved positions.
@@ -15211,10 +15211,10 @@ class TextSelection extends Selection {
15211
15211
  $anchor = $head;
15212
15212
  }
15213
15213
  }
15214
- return new TextSelection($anchor, $head);
15214
+ return new TextSelection2($anchor, $head);
15215
15215
  }
15216
- }
15217
- Selection.jsonID("text", TextSelection);
15216
+ };
15217
+ Selection.jsonID("text", TextSelection$1);
15218
15218
  class TextBookmark {
15219
15219
  constructor(anchor, head) {
15220
15220
  this.anchor = anchor;
@@ -15224,7 +15224,7 @@ class TextBookmark {
15224
15224
  return new TextBookmark(mapping.map(this.anchor), mapping.map(this.head));
15225
15225
  }
15226
15226
  resolve(doc2) {
15227
- return TextSelection.between(doc2.resolve(this.anchor), doc2.resolve(this.head));
15227
+ return TextSelection$1.between(doc2.resolve(this.anchor), doc2.resolve(this.head));
15228
15228
  }
15229
15229
  }
15230
15230
  class NodeSelection extends Selection {
@@ -15343,7 +15343,7 @@ const AllBookmark = {
15343
15343
  };
15344
15344
  function findSelectionIn(doc2, node2, pos, index2, dir, text = false) {
15345
15345
  if (node2.inlineContent)
15346
- return TextSelection.create(doc2, pos);
15346
+ return TextSelection$1.create(doc2, pos);
15347
15347
  for (let i = index2 - (dir > 0 ? 0 : 1); dir > 0 ? i < node2.childCount : i >= 0; i += dir) {
15348
15348
  let child = node2.child(i);
15349
15349
  if (!child.isAtom) {
@@ -19061,7 +19061,7 @@ const getTextContentFromNodes = ($from, maxMatch = 500) => {
19061
19061
  };
19062
19062
  const handleDocxPaste = (html, editor, view, plugin2) => {
19063
19063
  const { converter } = editor;
19064
- if (!converter || !converter.convertedXml) return handleHtmlPaste(html, editor, view, plugin2);
19064
+ if (!converter || !converter.convertedXml) return handleHtmlPaste(html, editor);
19065
19065
  let cleanedHtml = convertEmToPt(html);
19066
19066
  cleanedHtml = cleanHtmlUnnecessaryTags(cleanedHtml);
19067
19067
  const tempDiv = document.createElement("div");
@@ -19381,29 +19381,13 @@ const inputRulesPlugin = ({ editor, rules }) => {
19381
19381
  const clipboard = event.clipboardData;
19382
19382
  const html = clipboard.getData("text/html");
19383
19383
  clipboard.getData("text/plain");
19384
- const fieldAnnotationContent = slice2.content.content.filter((item) => item.type.name === "fieldAnnotation");
19384
+ const fieldAnnotationContent = slice2.content.content.filter(
19385
+ (item) => item.type.name === "fieldAnnotation"
19386
+ );
19385
19387
  if (fieldAnnotationContent.length) {
19386
19388
  return false;
19387
19389
  }
19388
- let source;
19389
- if (!html) {
19390
- source = "plain-text";
19391
- } else if (isWordHtml(html)) {
19392
- source = "word-html";
19393
- } else {
19394
- source = "browser-html";
19395
- }
19396
- switch (source) {
19397
- case "plain-text":
19398
- break;
19399
- case "word-html":
19400
- if (editor.options.mode === "docx") {
19401
- return handleDocxPaste(html, editor, view, plugin2);
19402
- }
19403
- case "browser-html":
19404
- return handleHtmlPaste$1(html, editor);
19405
- }
19406
- return false;
19390
+ return handleClipboardPaste({ editor, view }, html);
19407
19391
  }
19408
19392
  },
19409
19393
  isInputRules: true
@@ -19413,7 +19397,7 @@ const inputRulesPlugin = ({ editor, rules }) => {
19413
19397
  function isWordHtml(html) {
19414
19398
  return /class=["']?Mso|xmlns:o=["']?urn:schemas-microsoft-com|<!--\[if gte mso|<meta[^>]+name=["']?Generator["']?[^>]+Word/i.test(html);
19415
19399
  }
19416
- const handleHtmlPaste$1 = (html, editor) => {
19400
+ function handleHtmlPaste(html, editor) {
19417
19401
  const htmlWithPtSizing = convertEmToPt(html);
19418
19402
  const cleanedHtml = sanitizeHtml(htmlWithPtSizing);
19419
19403
  const doc2 = DOMParser$1.fromSchema(editor.schema).parse(cleanedHtml);
@@ -19430,7 +19414,7 @@ const handleHtmlPaste$1 = (html, editor) => {
19430
19414
  dispatch(state2.tr.replaceSelectionWith(doc2, true));
19431
19415
  }
19432
19416
  return true;
19433
- };
19417
+ }
19434
19418
  const convertEmToPt = (html) => {
19435
19419
  return html.replace(
19436
19420
  /font-size\s*:\s*([\d.]+)em/gi,
@@ -19462,6 +19446,27 @@ function sanitizeHtml(html, forbiddenTags = ["meta", "svg", "script", "style", "
19462
19446
  walkAndClean(container);
19463
19447
  return container;
19464
19448
  }
19449
+ function handleClipboardPaste({ editor, view }, html, text) {
19450
+ let source;
19451
+ if (!html) {
19452
+ source = "plain-text";
19453
+ } else if (isWordHtml(html)) {
19454
+ source = "word-html";
19455
+ } else {
19456
+ source = "browser-html";
19457
+ }
19458
+ switch (source) {
19459
+ case "plain-text":
19460
+ return false;
19461
+ case "word-html":
19462
+ if (editor.options.mode === "docx") {
19463
+ return handleDocxPaste(html, editor, view);
19464
+ }
19465
+ case "browser-html":
19466
+ return handleHtmlPaste(html, editor);
19467
+ }
19468
+ return false;
19469
+ }
19465
19470
  function exportSchemaToJson(params2) {
19466
19471
  const { type: type2 } = params2.node || {};
19467
19472
  const router = {
@@ -24343,7 +24348,7 @@ const _SuperConverter = class _SuperConverter2 {
24343
24348
  return;
24344
24349
  }
24345
24350
  }
24346
- static updateDocumentVersion(docx = this.convertedXml, version2 = "0.14.5-next.1") {
24351
+ static updateDocumentVersion(docx = this.convertedXml, version2 = "0.14.5-next.3") {
24347
24352
  const customLocation = "docProps/custom.xml";
24348
24353
  if (!docx[customLocation]) {
24349
24354
  docx[customLocation] = generateCustomXml();
@@ -24819,7 +24824,7 @@ function storeSuperdocVersion(docx) {
24819
24824
  function generateCustomXml() {
24820
24825
  return DEFAULT_CUSTOM_XML;
24821
24826
  }
24822
- function generateSuperdocVersion(pid = 2, version2 = "0.14.5-next.1") {
24827
+ function generateSuperdocVersion(pid = 2, version2 = "0.14.5-next.3") {
24823
24828
  return {
24824
24829
  type: "element",
24825
24830
  name: "property",
@@ -28557,7 +28562,7 @@ const insertTabCharacter = ({ tr, state: state2, dispatch }) => {
28557
28562
  const { from: from2 } = tr.selection;
28558
28563
  const tabText = state2.schema.text(" ");
28559
28564
  tr = tr.replaceSelectionWith(tabText);
28560
- tr = tr.setSelection(TextSelection.create(tr.doc, from2 + 1));
28565
+ tr = tr.setSelection(TextSelection$1.create(tr.doc, from2 + 1));
28561
28566
  if (dispatch) dispatch(tr);
28562
28567
  return true;
28563
28568
  };
@@ -28794,7 +28799,7 @@ const createParagraphNear$1 = (state2, dispatch) => {
28794
28799
  if (dispatch) {
28795
28800
  let side = (!$from.parentOffset && $to.index() < $to.parent.childCount ? $from : $to).pos;
28796
28801
  let tr = state2.tr.insert(side, type2.createAndFill());
28797
- tr.setSelection(TextSelection.create(tr.doc, side + 1));
28802
+ tr.setSelection(TextSelection$1.create(tr.doc, side + 1));
28798
28803
  dispatch(tr.scrollIntoView());
28799
28804
  }
28800
28805
  return true;
@@ -28848,7 +28853,7 @@ function splitBlockAs(splitNode) {
28848
28853
  }
28849
28854
  }
28850
28855
  let tr = state2.tr;
28851
- if (state2.selection instanceof TextSelection || state2.selection instanceof AllSelection)
28856
+ if (state2.selection instanceof TextSelection$1 || state2.selection instanceof AllSelection)
28852
28857
  tr.deleteSelection();
28853
28858
  let splitPos = tr.mapping.map($from.pos);
28854
28859
  let can = canSplit(tr.doc, splitPos, types2.length, types2);
@@ -28953,7 +28958,7 @@ function selectTextblockSide(side) {
28953
28958
  if (!$pos.node(depth).isTextblock)
28954
28959
  return false;
28955
28960
  if (dispatch)
28956
- dispatch(state2.tr.setSelection(TextSelection.create(state2.doc, side < 0 ? $pos.start(depth) : $pos.end(depth))));
28961
+ dispatch(state2.tr.setSelection(TextSelection$1.create(state2.doc, side < 0 ? $pos.start(depth) : $pos.end(depth))));
28957
28962
  return true;
28958
28963
  };
28959
28964
  }
@@ -29035,7 +29040,7 @@ const splitBlock = ({ keepMarks = true } = {}) => (props) => {
29035
29040
  if (!$from.parent.isBlock) return false;
29036
29041
  if (dispatch) {
29037
29042
  const atEnd = $to.parentOffset === $to.parent.content.size;
29038
- if (selection instanceof TextSelection) tr.deleteSelection();
29043
+ if (selection instanceof TextSelection$1) tr.deleteSelection();
29039
29044
  const deflt = $from.depth === 0 ? null : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
29040
29045
  let types2 = atEnd && deflt ? [{ type: deflt, attrs: newAttrs }] : void 0;
29041
29046
  let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types2);
@@ -29386,7 +29391,7 @@ const handleBackspaceNextToList = () => ({ state: state2, dispatch }) => {
29386
29391
  tr.delete(oldParaPos, oldParaPos + $from.parent.nodeSize);
29387
29392
  const insertPos = paraStartPos + 1 + targetPara.content.size;
29388
29393
  tr.insert(insertPos, inlineContent);
29389
- tr.setSelection(TextSelection.near(tr.doc.resolve(insertPos), 1));
29394
+ tr.setSelection(TextSelection$1.near(tr.doc.resolve(insertPos), 1));
29390
29395
  dispatch(tr);
29391
29396
  return true;
29392
29397
  };
@@ -29430,7 +29435,7 @@ const handleDeleteNextToList = () => ({ state: state2, dispatch }) => {
29430
29435
  tr.delete(nextListStartPos, nextListStartPos + nextNode.nodeSize);
29431
29436
  const insertPos = tr.mapping.map($from.pos);
29432
29437
  tr.insert(insertPos, targetInlineContent);
29433
- tr.setSelection(TextSelection.near(tr.doc.resolve(insertPos), 1));
29438
+ tr.setSelection(TextSelection$1.near(tr.doc.resolve(insertPos), 1));
29434
29439
  dispatch(tr);
29435
29440
  return true;
29436
29441
  } else {
@@ -29453,7 +29458,7 @@ const handleDeleteNextToList = () => ({ state: state2, dispatch }) => {
29453
29458
  tr.delete(listStartPos, listStartPos + afterNode.nodeSize);
29454
29459
  const insertPos = tr.mapping.map($from.pos);
29455
29460
  tr.insert(insertPos, targetInlineContent);
29456
- tr.setSelection(TextSelection.near(tr.doc.resolve(insertPos), 1));
29461
+ tr.setSelection(TextSelection$1.near(tr.doc.resolve(insertPos), 1));
29457
29462
  dispatch(tr);
29458
29463
  return true;
29459
29464
  }
@@ -31396,10 +31401,10 @@ const getParentOrderedList = (state2) => {
31396
31401
  const setSelectionInsideNewList = (tr, basePos) => {
31397
31402
  try {
31398
31403
  const $pos = tr.doc.resolve(basePos + 3);
31399
- tr.setSelection(TextSelection.near($pos));
31404
+ tr.setSelection(TextSelection$1.near($pos));
31400
31405
  } catch {
31401
31406
  const $fallback = tr.doc.resolve(basePos + 1);
31402
- tr.setSelection(TextSelection.near($fallback));
31407
+ tr.setSelection(TextSelection$1.near($fallback));
31403
31408
  }
31404
31409
  };
31405
31410
  const replaceListWithNode = ({ tr, from: from2, to, newNode }) => {
@@ -31416,7 +31421,7 @@ const convertListItemToParagraph = ({ state: state2, tr, currentNode, replaceFro
31416
31421
  replaceListWithNode({ tr, from: replaceFrom, to: replaceTo, newNode: paragraphNode });
31417
31422
  const newPos = replaceFrom + 1;
31418
31423
  const $pos = tr.doc.resolve(newPos);
31419
- tr.setSelection(TextSelection.near($pos));
31424
+ tr.setSelection(TextSelection$1.near($pos));
31420
31425
  return true;
31421
31426
  };
31422
31427
  const insertNewList = (tr, replaceFrom, replaceTo, listNode, marks = []) => {
@@ -31427,7 +31432,7 @@ const insertNewList = (tr, replaceFrom, replaceTo, listNode, marks = []) => {
31427
31432
  const paragraphNode = $paragraphStart.parent;
31428
31433
  const endPos = $paragraphStart.pos + paragraphNode.content.size;
31429
31434
  const $endPos = tr.doc.resolve(endPos);
31430
- tr.setSelection(TextSelection.near($endPos));
31435
+ tr.setSelection(TextSelection$1.near($endPos));
31431
31436
  return true;
31432
31437
  };
31433
31438
  const getListItemStyleDefinitions = ({ styleId, node: node2, numId, level, editor, tries }) => {
@@ -31625,7 +31630,7 @@ const splitListItem = () => (props) => {
31625
31630
  const insertPosition = listStart + firstList.nodeSize;
31626
31631
  tr.insert(insertPosition, secondList);
31627
31632
  const secondListStart = insertPosition + 2;
31628
- tr.setSelection(TextSelection.near(tr.doc.resolve(secondListStart)));
31633
+ tr.setSelection(TextSelection$1.near(tr.doc.resolve(secondListStart)));
31629
31634
  tr.scrollIntoView();
31630
31635
  const marks = state2.storedMarks || $from.marks() || [];
31631
31636
  if (marks?.length) {
@@ -31660,7 +31665,7 @@ const handleSplitInEmptyBlock = (props, currentListItem) => {
31660
31665
  const insertPos = parentList.pos + parentList.node.nodeSize;
31661
31666
  tr.insert(insertPos, newList);
31662
31667
  const newPos = insertPos + 2;
31663
- tr.setSelection(TextSelection.near(tr.doc.resolve(newPos)));
31668
+ tr.setSelection(TextSelection$1.near(tr.doc.resolve(newPos)));
31664
31669
  tr.scrollIntoView();
31665
31670
  return true;
31666
31671
  } catch (error) {
@@ -31709,7 +31714,7 @@ const handleSplitInEmptyBlock = (props, currentListItem) => {
31709
31714
  const listEnd = parentList.pos + parentList.node.nodeSize;
31710
31715
  tr.replaceWith(listStart, listEnd, newParagraph);
31711
31716
  const newPos = listStart + 1;
31712
- tr.setSelection(TextSelection.near(tr.doc.resolve(newPos)));
31717
+ tr.setSelection(TextSelection$1.near(tr.doc.resolve(newPos)));
31713
31718
  tr.scrollIntoView();
31714
31719
  return true;
31715
31720
  } catch (error) {
@@ -31744,7 +31749,7 @@ const deleteListItem = () => (props) => {
31744
31749
  tr.delete(pos, pos + size2);
31745
31750
  });
31746
31751
  const $new = tr.doc.resolve(from2);
31747
- tr.setSelection(TextSelection.near($new));
31752
+ tr.setSelection(TextSelection$1.near($new));
31748
31753
  return true;
31749
31754
  }
31750
31755
  return false;
@@ -31772,7 +31777,7 @@ const deleteListItem = () => (props) => {
31772
31777
  });
31773
31778
  tr.replaceWith(listFrom, listTo, nodes);
31774
31779
  const $pos = tr.doc.resolve(listFrom + 1);
31775
- tr.setSelection(TextSelection.near($pos));
31780
+ tr.setSelection(TextSelection$1.near($pos));
31776
31781
  return true;
31777
31782
  };
31778
31783
  const increaseListIndent = () => ({ editor, tr }) => {
@@ -33209,7 +33214,7 @@ class NodeViewDesc extends ViewDesc {
33209
33214
  }
33210
33215
  localCompositionInfo(view, pos) {
33211
33216
  let { from: from2, to } = view.state.selection;
33212
- if (!(view.state.selection instanceof TextSelection) || from2 < pos || to > pos + this.node.content.size)
33217
+ if (!(view.state.selection instanceof TextSelection$1) || from2 < pos || to > pos + this.node.content.size)
33213
33218
  return null;
33214
33219
  let textNode = view.input.compositionNode;
33215
33220
  if (!textNode || !this.dom.contains(textNode.parentNode))
@@ -33975,7 +33980,7 @@ function selectionToDOM(view, force = false) {
33975
33980
  selectCursorWrapper(view);
33976
33981
  } else {
33977
33982
  let { anchor, head } = sel, resetEditableFrom, resetEditableTo;
33978
- if (brokenSelectBetweenUneditable && !(sel instanceof TextSelection)) {
33983
+ if (brokenSelectBetweenUneditable && !(sel instanceof TextSelection$1)) {
33979
33984
  if (!sel.$from.parent.inlineContent)
33980
33985
  resetEditableFrom = temporarilyEditableNear(view, sel.from);
33981
33986
  if (!sel.empty && !sel.$from.parent.inlineContent)
@@ -34081,7 +34086,7 @@ function clearNodeSelection(view) {
34081
34086
  }
34082
34087
  }
34083
34088
  function selectionBetween(view, $anchor, $head, bias) {
34084
- return view.someProp("createSelectionBetween", (f) => f(view, $anchor, $head)) || TextSelection.between($anchor, $head, bias);
34089
+ return view.someProp("createSelectionBetween", (f) => f(view, $anchor, $head)) || TextSelection$1.between($anchor, $head, bias);
34085
34090
  }
34086
34091
  function hasFocusAndSelection(view) {
34087
34092
  if (view.editable && !view.hasFocus())
@@ -34115,13 +34120,13 @@ function apply$1(view, sel) {
34115
34120
  }
34116
34121
  function selectHorizontally(view, dir, mods) {
34117
34122
  let sel = view.state.selection;
34118
- if (sel instanceof TextSelection) {
34123
+ if (sel instanceof TextSelection$1) {
34119
34124
  if (mods.indexOf("s") > -1) {
34120
34125
  let { $head } = sel, node2 = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter;
34121
34126
  if (!node2 || node2.isText || !node2.isLeaf)
34122
34127
  return false;
34123
34128
  let $newHead = view.state.doc.resolve($head.pos + node2.nodeSize * (dir < 0 ? -1 : 1));
34124
- return apply$1(view, new TextSelection(sel.$anchor, $newHead));
34129
+ return apply$1(view, new TextSelection$1(sel.$anchor, $newHead));
34125
34130
  } else if (!sel.empty) {
34126
34131
  return false;
34127
34132
  } else if (view.endOfTextblock(dir > 0 ? "forward" : "backward")) {
@@ -34139,13 +34144,13 @@ function selectHorizontally(view, dir, mods) {
34139
34144
  if (NodeSelection.isSelectable(node2)) {
34140
34145
  return apply$1(view, new NodeSelection(dir < 0 ? view.state.doc.resolve($head.pos - node2.nodeSize) : $head));
34141
34146
  } else if (webkit) {
34142
- return apply$1(view, new TextSelection(view.state.doc.resolve(dir < 0 ? nodePos : nodePos + node2.nodeSize)));
34147
+ return apply$1(view, new TextSelection$1(view.state.doc.resolve(dir < 0 ? nodePos : nodePos + node2.nodeSize)));
34143
34148
  } else {
34144
34149
  return false;
34145
34150
  }
34146
34151
  }
34147
34152
  } else if (sel instanceof NodeSelection && sel.node.isInline) {
34148
- return apply$1(view, new TextSelection(dir > 0 ? sel.$to : sel.$from));
34153
+ return apply$1(view, new TextSelection$1(dir > 0 ? sel.$to : sel.$from));
34149
34154
  } else {
34150
34155
  let next = moveSelectionBlock(view.state, dir);
34151
34156
  if (next)
@@ -34338,7 +34343,7 @@ function findDirection(view, pos) {
34338
34343
  }
34339
34344
  function selectVertically(view, dir, mods) {
34340
34345
  let sel = view.state.selection;
34341
- if (sel instanceof TextSelection && !sel.empty || mods.indexOf("s") > -1)
34346
+ if (sel instanceof TextSelection$1 && !sel.empty || mods.indexOf("s") > -1)
34342
34347
  return false;
34343
34348
  if (mac$2 && mods.indexOf("m") > -1)
34344
34349
  return false;
@@ -34356,7 +34361,7 @@ function selectVertically(view, dir, mods) {
34356
34361
  return false;
34357
34362
  }
34358
34363
  function stopNativeHorizontalDelete(view, dir) {
34359
- if (!(view.state.selection instanceof TextSelection))
34364
+ if (!(view.state.selection instanceof TextSelection$1))
34360
34365
  return true;
34361
34366
  let { $head, $anchor, empty: empty2 } = view.state.selection;
34362
34367
  if (!$head.sameParent($anchor))
@@ -34786,7 +34791,7 @@ editHandlers.keypress = (view, _event) => {
34786
34791
  return;
34787
34792
  }
34788
34793
  let sel = view.state.selection;
34789
- if (!(sel instanceof TextSelection) || !sel.$from.sameParent(sel.$to)) {
34794
+ if (!(sel instanceof TextSelection$1) || !sel.$from.sameParent(sel.$to)) {
34790
34795
  let text = String.fromCharCode(event.charCode);
34791
34796
  let deflt = () => view.state.tr.insertText(text).scrollIntoView();
34792
34797
  if (!/[\r\n]/.test(text) && !view.someProp("handleTextInput", (f) => f(view, sel.$from.pos, sel.$to.pos, text, deflt)))
@@ -34869,7 +34874,7 @@ function defaultTripleClick(view, inside, event) {
34869
34874
  let doc2 = view.state.doc;
34870
34875
  if (inside == -1) {
34871
34876
  if (doc2.inlineContent) {
34872
- updateSelection(view, TextSelection.create(doc2, 0, doc2.content.size));
34877
+ updateSelection(view, TextSelection$1.create(doc2, 0, doc2.content.size));
34873
34878
  return true;
34874
34879
  }
34875
34880
  return false;
@@ -34879,7 +34884,7 @@ function defaultTripleClick(view, inside, event) {
34879
34884
  let node2 = i > $pos.depth ? $pos.nodeAfter : $pos.node(i);
34880
34885
  let nodePos = $pos.before(i);
34881
34886
  if (node2.inlineContent)
34882
- updateSelection(view, TextSelection.create(doc2, nodePos + 1, nodePos + 1 + node2.content.size));
34887
+ updateSelection(view, TextSelection$1.create(doc2, nodePos + 1, nodePos + 1 + node2.content.size));
34883
34888
  else if (NodeSelection.isSelectable(node2))
34884
34889
  updateSelection(view, NodeSelection.create(doc2, nodePos));
34885
34890
  else
@@ -35039,7 +35044,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
35039
35044
  if (!view.composing) {
35040
35045
  view.domObserver.flush();
35041
35046
  let { state: state2 } = view, $pos = state2.selection.$to;
35042
- if (state2.selection instanceof TextSelection && (state2.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m) => m.type.spec.inclusive === false))) {
35047
+ if (state2.selection instanceof TextSelection$1 && (state2.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m) => m.type.spec.inclusive === false))) {
35043
35048
  view.markCursor = view.state.storedMarks || $pos.marks();
35044
35049
  endComposition(view, true);
35045
35050
  view.markCursor = null;
@@ -36397,7 +36402,7 @@ function readDOMChange(view, from2, to, typeOver, addedNodes) {
36397
36402
  return;
36398
36403
  }
36399
36404
  if (!change) {
36400
- if (typeOver && sel instanceof TextSelection && !sel.empty && sel.$head.sameParent(sel.$anchor) && !view.composing && !(parse2.sel && parse2.sel.anchor != parse2.sel.head)) {
36405
+ if (typeOver && sel instanceof TextSelection$1 && !sel.empty && sel.$head.sameParent(sel.$anchor) && !view.composing && !(parse2.sel && parse2.sel.anchor != parse2.sel.head)) {
36401
36406
  change = { start: sel.from, endA: sel.to, endB: sel.to };
36402
36407
  } else {
36403
36408
  if (parse2.sel) {
@@ -36412,7 +36417,7 @@ function readDOMChange(view, from2, to, typeOver, addedNodes) {
36412
36417
  return;
36413
36418
  }
36414
36419
  }
36415
- if (view.state.selection.from < view.state.selection.to && change.start == change.endB && view.state.selection instanceof TextSelection) {
36420
+ if (view.state.selection.from < view.state.selection.to && change.start == change.endB && view.state.selection instanceof TextSelection$1) {
36416
36421
  if (change.start > view.state.selection.from && change.start <= view.state.selection.from + 2 && view.state.selection.from >= parse2.from) {
36417
36422
  change.start = view.state.selection.from;
36418
36423
  } else if (change.endA < view.state.selection.to && change.endA >= view.state.selection.to - 2 && view.state.selection.to <= parse2.to) {
@@ -37840,7 +37845,7 @@ const restoreRelativeSelection = (tr, relSel, binding) => {
37840
37845
  binding.mapping
37841
37846
  );
37842
37847
  if (anchor !== null && head !== null) {
37843
- const sel = TextSelection.between(tr.doc.resolve(anchor), tr.doc.resolve(head));
37848
+ const sel = TextSelection$1.between(tr.doc.resolve(anchor), tr.doc.resolve(head));
37844
37849
  tr.setSelection(sel);
37845
37850
  }
37846
37851
  }
@@ -37975,7 +37980,7 @@ class ProsemirrorBinding {
37975
37980
  if (sel) {
37976
37981
  const clampedAnchor = min$2(max$2(sel.anchor, 0), tr.doc.content.size);
37977
37982
  const clampedHead = min$2(max$2(sel.head, 0), tr.doc.content.size);
37978
- tr.setSelection(TextSelection.create(tr.doc, clampedAnchor, clampedHead));
37983
+ tr.setSelection(TextSelection$1.create(tr.doc, clampedAnchor, clampedHead));
37979
37984
  }
37980
37985
  this.prosemirrorView.dispatch(
37981
37986
  tr.setMeta(ySyncPluginKey, { isChangeOrigin: true, binding: this })
@@ -40936,18 +40941,18 @@ const trackedTransaction = ({ tr, state: state2, user }) => {
40936
40941
  if (tr.selectionSet) {
40937
40942
  const deletionMarkSchema = state2.schema.marks[TrackDeleteMarkName];
40938
40943
  const deletionMark = findMark(state2, deletionMarkSchema, false);
40939
- if (tr.selection instanceof TextSelection && (tr.selection.from < state2.selection.from || tr.getMeta("inputType") === "deleteContentBackward")) {
40944
+ if (tr.selection instanceof TextSelection$1 && (tr.selection.from < state2.selection.from || tr.getMeta("inputType") === "deleteContentBackward")) {
40940
40945
  const caretPos = map22.map(tr.selection.from, -1);
40941
- newTr.setSelection(new TextSelection(newTr.doc.resolve(caretPos)));
40946
+ newTr.setSelection(new TextSelection$1(newTr.doc.resolve(caretPos)));
40942
40947
  } else if (tr.selection.from > state2.selection.from && deletionMark) {
40943
40948
  const caretPos = map22.map(deletionMark.to + 1, 1);
40944
- newTr.setSelection(new TextSelection(newTr.doc.resolve(caretPos)));
40949
+ newTr.setSelection(new TextSelection$1(newTr.doc.resolve(caretPos)));
40945
40950
  } else {
40946
40951
  newTr.setSelection(tr.selection.map(newTr.doc, map22));
40947
40952
  }
40948
40953
  } else if (state2.selection.from - tr.selection.from > 1 && tr.selection.$head.depth > 1) {
40949
40954
  const caretPos = map22.map(tr.selection.from - 2, -1);
40950
- newTr.setSelection(new TextSelection(newTr.doc.resolve(caretPos)));
40955
+ newTr.setSelection(new TextSelection$1(newTr.doc.resolve(caretPos)));
40951
40956
  } else ;
40952
40957
  if (tr.storedMarksSet) {
40953
40958
  newTr.setStoredMarks(tr.storedMarks);
@@ -41524,7 +41529,7 @@ const findWordBounds = (doc2, pos) => {
41524
41529
  const setWordSelection = (view, pos) => {
41525
41530
  const { state: state2, dispatch } = view;
41526
41531
  const word = findWordBounds(state2.doc, pos);
41527
- const tr = state2.tr.setSelection(TextSelection.create(state2.doc, word.from, word.to));
41532
+ const tr = state2.tr.setSelection(TextSelection$1.create(state2.doc, word.from, word.to));
41528
41533
  dispatch(tr);
41529
41534
  };
41530
41535
  const setImageNodeSelection = (view, pos) => {
@@ -42413,7 +42418,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
42413
42418
  * @returns {Object | void} Migration results
42414
42419
  */
42415
42420
  processCollaborationMigrations() {
42416
- console.debug("[checkVersionMigrations] Current editor version", "0.14.5-next.1");
42421
+ console.debug("[checkVersionMigrations] Current editor version", "0.14.5-next.3");
42417
42422
  if (!this.options.ydoc) return;
42418
42423
  const metaMap = this.options.ydoc.getMap("meta");
42419
42424
  let docVersion = metaMap.get("version");
@@ -43611,7 +43616,7 @@ function arrow$3(axis, dir) {
43611
43616
  return function(state2, dispatch, view) {
43612
43617
  let sel = state2.selection;
43613
43618
  let $start = dir > 0 ? sel.$to : sel.$from, mustMove = sel.empty;
43614
- if (sel instanceof TextSelection) {
43619
+ if (sel instanceof TextSelection$1) {
43615
43620
  if (!view.endOfTextblock(dirStr) || $start.depth == 0)
43616
43621
  return false;
43617
43622
  mustMove = false;
@@ -43648,7 +43653,7 @@ function beforeinput(view, event) {
43648
43653
  for (let i = insert.length - 1; i >= 0; i--)
43649
43654
  frag = Fragment.from(insert[i].createAndFill(null, frag));
43650
43655
  let tr = view.state.tr.replace($from.pos, $from.pos, new Slice(frag, 0, 0));
43651
- tr.setSelection(TextSelection.near(tr.doc.resolve($from.pos + 1)));
43656
+ tr.setSelection(TextSelection$1.near(tr.doc.resolve($from.pos + 1)));
43652
43657
  view.dispatch(tr);
43653
43658
  return false;
43654
43659
  }
@@ -46125,7 +46130,7 @@ var CellSelection = class _CellSelection extends Selection {
46125
46130
  return _CellSelection.colSelection($anchorCell, $headCell);
46126
46131
  else return new _CellSelection($anchorCell, $headCell);
46127
46132
  }
46128
- return TextSelection.between($anchorCell, $headCell);
46133
+ return TextSelection$1.between($anchorCell, $headCell);
46129
46134
  }
46130
46135
  // Returns a rectangular slice of table rows containing the selected
46131
46136
  // cells.
@@ -46397,10 +46402,10 @@ function normalizeSelection(state2, tr, allowTableNodeSelection) {
46397
46402
  const lastCell = start2 + map22.map[map22.width * map22.height - 1];
46398
46403
  normalize22 = CellSelection.create(doc2, start2 + 1, lastCell);
46399
46404
  }
46400
- } else if (sel instanceof TextSelection && isCellBoundarySelection(sel)) {
46401
- normalize22 = TextSelection.create(doc2, sel.from);
46402
- } else if (sel instanceof TextSelection && isTextSelectionAcrossCells(sel)) {
46403
- normalize22 = TextSelection.create(doc2, sel.$from.start(), sel.$from.end());
46405
+ } else if (sel instanceof TextSelection$1 && isCellBoundarySelection(sel)) {
46406
+ normalize22 = TextSelection$1.create(doc2, sel.from);
46407
+ } else if (sel instanceof TextSelection$1 && isTextSelectionAcrossCells(sel)) {
46408
+ normalize22 = TextSelection$1.create(doc2, sel.$from.start(), sel.$from.end());
46404
46409
  }
46405
46410
  if (normalize22) (tr || (tr = state2.tr)).setSelection(normalize22);
46406
46411
  return tr;
@@ -46996,7 +47001,7 @@ function goToNextCell(direction) {
46996
47001
  if (dispatch) {
46997
47002
  const $cell = state2.doc.resolve(cell);
46998
47003
  dispatch(
46999
- state2.tr.setSelection(TextSelection.between($cell, moveCellForward($cell))).scrollIntoView()
47004
+ state2.tr.setSelection(TextSelection$1.between($cell, moveCellForward($cell))).scrollIntoView()
47000
47005
  );
47001
47006
  }
47002
47007
  return true;
@@ -47449,7 +47454,7 @@ function handleMouseDown(view, startEvent) {
47449
47454
  view.root.addEventListener("mousemove", move2);
47450
47455
  }
47451
47456
  function atEndOfCell(view, axis, dir) {
47452
- if (!(view.state.selection instanceof TextSelection)) return null;
47457
+ if (!(view.state.selection instanceof TextSelection$1)) return null;
47453
47458
  const { $head } = view.state.selection;
47454
47459
  for (let d = $head.depth - 1; d >= 0; d--) {
47455
47460
  const parent = $head.node(d), index2 = dir < 0 ? $head.index(d) : $head.indexAfter(d);
@@ -48016,7 +48021,7 @@ const Table = Node$1.create({
48016
48021
  const node2 = createTable(editor.schema, rows, cols, withHeaderRow);
48017
48022
  if (dispatch) {
48018
48023
  const offset2 = tr.selection.from + 1;
48019
- tr.replaceSelectionWith(node2).scrollIntoView().setSelection(TextSelection.near(tr.doc.resolve(offset2)));
48024
+ tr.replaceSelectionWith(node2).scrollIntoView().setSelection(TextSelection$1.near(tr.doc.resolve(offset2)));
48020
48025
  }
48021
48026
  return true;
48022
48027
  },
@@ -51342,7 +51347,7 @@ const Link = Mark2.create({
51342
51347
  return chain().setMark("underline").setMark(this.name, { href }).run();
51343
51348
  },
51344
51349
  unsetLink: () => ({ chain }) => {
51345
- return chain().unsetMark("underline").unsetColor().unsetMark(this.name, { extendEmptyMarkRange: true }).run();
51350
+ return chain().unsetMark("underline", { extendEmptyMarkRange: true }).unsetColor().unsetMark("link", { extendEmptyMarkRange: true }).run();
51346
51351
  },
51347
51352
  toggleLink: ({ href }) => ({ commands: commands2 }) => {
51348
51353
  if (!href) return commands2.unsetLink();
@@ -56808,7 +56813,7 @@ const Search = Extension.create({
56808
56813
  goToSearchResult: (match) => ({ state: state2, dispatch, editor }) => {
56809
56814
  const { from: from2, to } = match;
56810
56815
  editor.view.focus();
56811
- const tr = state2.tr.setSelection(TextSelection.create(state2.doc, from2, to)).scrollIntoView();
56816
+ const tr = state2.tr.setSelection(TextSelection$1.create(state2.doc, from2, to)).scrollIntoView();
56812
56817
  dispatch(tr);
56813
56818
  const { node: node2 } = editor.view.domAtPos(from2);
56814
56819
  if (node2?.scrollIntoView) {
@@ -67629,7 +67634,7 @@ const _sfc_main$f = {
67629
67634
  const { state: state2 } = props.editor;
67630
67635
  const { from: from2, to } = selectionState.value;
67631
67636
  const tr = state2.tr.setSelection(
67632
- TextSelection.create(state2.doc, from2, to)
67637
+ TextSelection$1.create(state2.doc, from2, to)
67633
67638
  );
67634
67639
  props.editor.view.dispatch(tr);
67635
67640
  } else {
@@ -67861,7 +67866,7 @@ var eventemitter3 = { exports: {} };
67861
67866
  var evt = prefix2 ? prefix2 + event : event, handlers2 = this._events[evt];
67862
67867
  if (!handlers2) return [];
67863
67868
  if (handlers2.fn) return [handlers2.fn];
67864
- for (var i = 0, l2 = handlers2.length, ee = new Array(l2); i < l2; i++) {
67869
+ for (var i = 0, l = handlers2.length, ee = new Array(l); i < l; i++) {
67865
67870
  ee[i] = handlers2[i].fn;
67866
67871
  }
67867
67872
  return ee;
@@ -68362,11 +68367,238 @@ const _sfc_main$c = {
68362
68367
  }
68363
68368
  };
68364
68369
  const LinkedStyle = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["__scopeId", "data-v-2cf079a2"]]);
68365
- const _hoisted_1$9 = ["aria-label", "onClick", "onKeydown"];
68366
- const _hoisted_2$7 = ["innerHTML"];
68367
- const _hoisted_3$6 = ["innerHTML"];
68368
- const ROW_SIZE$1 = 7;
68370
+ const _hoisted_1$9 = {
68371
+ key: 0,
68372
+ class: "link-title"
68373
+ };
68374
+ const _hoisted_2$7 = {
68375
+ key: 1,
68376
+ class: "link-title"
68377
+ };
68378
+ const _hoisted_3$6 = {
68379
+ key: 2,
68380
+ class: "link-title"
68381
+ };
68382
+ const _hoisted_4$2 = { key: 3 };
68383
+ const _hoisted_5$1 = { class: "input-row" };
68384
+ const _hoisted_6 = ["innerHTML"];
68385
+ const _hoisted_7 = ["onKeydown"];
68386
+ const _hoisted_8 = ["innerHTML"];
68387
+ const _hoisted_9 = { class: "input-row link-buttons" };
68388
+ const _hoisted_10 = ["innerHTML"];
68389
+ const _hoisted_11 = {
68390
+ key: 4,
68391
+ class: "input-row go-to-anchor clickable"
68392
+ };
68369
68393
  const _sfc_main$b = {
68394
+ __name: "LinkInput",
68395
+ props: {
68396
+ showInput: {
68397
+ type: Boolean,
68398
+ default: true
68399
+ },
68400
+ showLink: {
68401
+ type: Boolean,
68402
+ default: true
68403
+ },
68404
+ goToAnchor: {
68405
+ type: Function,
68406
+ default: () => {
68407
+ }
68408
+ },
68409
+ editor: {
68410
+ type: Object,
68411
+ required: true
68412
+ },
68413
+ closePopover: {
68414
+ type: Function,
68415
+ default: () => {
68416
+ }
68417
+ }
68418
+ },
68419
+ setup(__props) {
68420
+ const props = __props;
68421
+ const { isHighContrastMode: isHighContrastMode2 } = useHighContrastMode();
68422
+ const urlError = vue.ref(false);
68423
+ const getSelectedText = () => {
68424
+ if (!props.editor || !props.editor.state) return "";
68425
+ const { state: state2 } = props.editor;
68426
+ const { from: from2, to } = state2.selection;
68427
+ return state2.doc.textBetween(from2, to, " ");
68428
+ };
68429
+ const getLinkHrefAtSelection = () => {
68430
+ if (!props.editor || !props.editor.state) return "";
68431
+ const { state: state2 } = props.editor;
68432
+ const { schema, selection } = state2;
68433
+ const linkMark = schema.marks.link;
68434
+ if (!linkMark) return "";
68435
+ let href = "";
68436
+ const { $from, empty: empty2 } = selection;
68437
+ if (empty2) {
68438
+ const marks = state2.storedMarks || $from.marks();
68439
+ const link = marks.find((mark) => mark.type === linkMark);
68440
+ if (link) href = link.attrs.href;
68441
+ } else {
68442
+ state2.doc.nodesBetween(selection.from, selection.to, (node2) => {
68443
+ if (node2.marks) {
68444
+ const link = node2.marks.find((mark) => mark.type === linkMark);
68445
+ if (link) href = link.attrs.href;
68446
+ }
68447
+ });
68448
+ }
68449
+ return href || "";
68450
+ };
68451
+ const text = vue.ref("");
68452
+ const rawUrl = vue.ref("");
68453
+ const isAnchor = vue.ref(false);
68454
+ const url = vue.computed(() => {
68455
+ if (!rawUrl.value?.startsWith("http")) return "http://" + rawUrl.value;
68456
+ return rawUrl.value;
68457
+ });
68458
+ const validUrl = vue.computed(() => {
68459
+ const urlSplit = url.value.split(".").filter(Boolean);
68460
+ return url.value.includes(".") && urlSplit.length > 1;
68461
+ });
68462
+ const isEditing = vue.computed(() => !isAnchor.value && !!getLinkHrefAtSelection());
68463
+ const getApplyText = vue.computed(() => showApply.value ? "Apply" : "Remove");
68464
+ const isDisabled2 = vue.computed(() => !validUrl.value);
68465
+ const showApply = vue.computed(() => !showRemove.value);
68466
+ const showRemove = vue.computed(() => rawUrl.value === "" && getLinkHrefAtSelection());
68467
+ const openLink = () => {
68468
+ window.open(url.value, "_blank");
68469
+ };
68470
+ const updateFromEditor = () => {
68471
+ text.value = getSelectedText();
68472
+ rawUrl.value = getLinkHrefAtSelection();
68473
+ };
68474
+ vue.watch(
68475
+ () => props.editor?.state?.selection,
68476
+ () => {
68477
+ updateFromEditor();
68478
+ },
68479
+ { immediate: true }
68480
+ );
68481
+ const focusInput = () => {
68482
+ const input = document.querySelector(".link-input-ctn input");
68483
+ if (!input) return;
68484
+ input.focus();
68485
+ };
68486
+ vue.onMounted(() => {
68487
+ updateFromEditor();
68488
+ isAnchor.value = rawUrl.value.startsWith("#");
68489
+ if (props.showInput) focusInput();
68490
+ });
68491
+ const handleSubmit = () => {
68492
+ if (rawUrl.value && validUrl.value) {
68493
+ if (props.editor && props.editor.commands) {
68494
+ if (isEditing.value) {
68495
+ const { state: state2, view: view2 } = props.editor;
68496
+ const linkMark = state2.schema.marks.link;
68497
+ let { from: from2, to } = state2.selection;
68498
+ if (state2.selection.empty) {
68499
+ const range2 = getMarkRange(state2.selection.$from, linkMark);
68500
+ if (range2) {
68501
+ from2 = range2.from;
68502
+ to = range2.to;
68503
+ }
68504
+ }
68505
+ const tr2 = state2.tr.removeMark(from2, to, linkMark).addMark(from2, to, linkMark.create({ href: url.value }));
68506
+ view2.dispatch(tr2);
68507
+ } else if (props.editor.commands.toggleLink) {
68508
+ props.editor.commands.toggleLink({ href: url.value, text: text.value });
68509
+ }
68510
+ const { view } = props.editor;
68511
+ let { selection } = view.state;
68512
+ const endPos = selection.$to.pos;
68513
+ const tr = view.state.tr.setSelection(new TextSelection$1(view.state.doc.resolve(endPos)));
68514
+ view.dispatch(tr);
68515
+ setTimeout(() => {
68516
+ view.focus();
68517
+ }, 100);
68518
+ }
68519
+ props.closePopover();
68520
+ return;
68521
+ } else if (!rawUrl.value) {
68522
+ if (props.editor && props.editor.commands && props.editor.commands.unsetLink) {
68523
+ props.editor.commands.unsetLink();
68524
+ }
68525
+ props.closePopover();
68526
+ return;
68527
+ }
68528
+ urlError.value = true;
68529
+ };
68530
+ const handleRemove = () => {
68531
+ if (props.editor && props.editor.commands && props.editor.commands.unsetLink) {
68532
+ props.editor.commands.unsetLink();
68533
+ props.closePopover();
68534
+ }
68535
+ };
68536
+ return (_ctx, _cache) => {
68537
+ return vue.openBlock(), vue.createElementBlock("div", {
68538
+ class: vue.normalizeClass(["link-input-ctn", { "high-contrast": vue.unref(isHighContrastMode2) }])
68539
+ }, [
68540
+ isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$9, "Page anchor")) : isEditing.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$7, "Edit link")) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$6, "Add link")),
68541
+ __props.showInput && !isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$2, [
68542
+ vue.createBaseVNode("div", _hoisted_5$1, [
68543
+ vue.createBaseVNode("div", {
68544
+ class: "input-icon",
68545
+ innerHTML: vue.unref(toolbarIcons).linkInput
68546
+ }, null, 8, _hoisted_6),
68547
+ vue.withDirectives(vue.createBaseVNode("input", {
68548
+ type: "text",
68549
+ name: "link",
68550
+ placeholder: "Type or paste a link",
68551
+ class: vue.normalizeClass({ error: urlError.value }),
68552
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => rawUrl.value = $event),
68553
+ onKeydown: [
68554
+ vue.withKeys(vue.withModifiers(handleSubmit, ["stop", "prevent"]), ["enter"]),
68555
+ _cache[1] || (_cache[1] = ($event) => urlError.value = false)
68556
+ ]
68557
+ }, null, 42, _hoisted_7), [
68558
+ [vue.vModelText, rawUrl.value]
68559
+ ]),
68560
+ vue.createBaseVNode("div", {
68561
+ class: vue.normalizeClass(["open-link-icon", { disabled: !validUrl.value }]),
68562
+ innerHTML: vue.unref(toolbarIcons).openLink,
68563
+ onClick: openLink,
68564
+ "data-item": "btn-link-open"
68565
+ }, null, 10, _hoisted_8)
68566
+ ]),
68567
+ vue.createBaseVNode("div", _hoisted_9, [
68568
+ rawUrl.value ? (vue.openBlock(), vue.createElementBlock("button", {
68569
+ key: 0,
68570
+ class: "remove-btn",
68571
+ onClick: handleRemove,
68572
+ "data-item": "btn-link-remove"
68573
+ }, [
68574
+ vue.createBaseVNode("div", {
68575
+ class: "remove-btn__icon",
68576
+ innerHTML: vue.unref(toolbarIcons).removeLink
68577
+ }, null, 8, _hoisted_10),
68578
+ _cache[3] || (_cache[3] = vue.createTextVNode(" Remove "))
68579
+ ])) : vue.createCommentVNode("", true),
68580
+ showApply.value ? (vue.openBlock(), vue.createElementBlock("button", {
68581
+ key: 1,
68582
+ class: vue.normalizeClass(["submit-btn", { "disable-btn": isDisabled2.value }]),
68583
+ onClick: handleSubmit,
68584
+ "data-item": "btn-link-apply"
68585
+ }, vue.toDisplayString(getApplyText.value), 3)) : vue.createCommentVNode("", true)
68586
+ ])
68587
+ ])) : isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_11, [
68588
+ vue.createBaseVNode("a", {
68589
+ onClick: _cache[2] || (_cache[2] = vue.withModifiers((...args) => __props.goToAnchor && __props.goToAnchor(...args), ["stop", "prevent"]))
68590
+ }, "Go to " + vue.toDisplayString(rawUrl.value.startsWith("#_") ? rawUrl.value.substring(2) : rawUrl.value), 1)
68591
+ ])) : vue.createCommentVNode("", true)
68592
+ ], 2);
68593
+ };
68594
+ }
68595
+ };
68596
+ const LinkInput = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-0c411ee5"]]);
68597
+ const _hoisted_1$8 = ["aria-label", "onClick", "onKeydown"];
68598
+ const _hoisted_2$6 = ["innerHTML"];
68599
+ const _hoisted_3$5 = ["innerHTML"];
68600
+ const ROW_SIZE$1 = 7;
68601
+ const _sfc_main$a = {
68370
68602
  __name: "IconGridRow",
68371
68603
  props: {
68372
68604
  icons: {
@@ -68485,26 +68717,26 @@ const _sfc_main$b = {
68485
68717
  class: "option__icon",
68486
68718
  innerHTML: option.icon,
68487
68719
  style: vue.normalizeStyle(option.style)
68488
- }, null, 12, _hoisted_2$7),
68720
+ }, null, 12, _hoisted_2$6),
68489
68721
  isActive2.value(option) ? (vue.openBlock(), vue.createElementBlock("div", {
68490
68722
  key: 0,
68491
68723
  class: "option__check",
68492
68724
  innerHTML: vue.unref(toolbarIcons).colorOptionCheck,
68493
68725
  style: vue.normalizeStyle(getCheckStyle(option.value, optionIndex))
68494
- }, null, 12, _hoisted_3$6)) : vue.createCommentVNode("", true)
68495
- ], 40, _hoisted_1$9);
68726
+ }, null, 12, _hoisted_3$5)) : vue.createCommentVNode("", true)
68727
+ ], 40, _hoisted_1$8);
68496
68728
  }), 128))
68497
68729
  ]);
68498
68730
  }), 128);
68499
68731
  };
68500
68732
  }
68501
68733
  };
68502
- const IconGridRow = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-e89b7f5f"]]);
68734
+ const IconGridRow = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-e89b7f5f"]]);
68503
68735
  const DropIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M320 512c53.2 0 101.4-21.6 136.1-56.6l-298.3-235C140 257.1 128 292.3 128 320c0 106 86 192 192 192zM505.2 370.7c4.4-16.2 6.8-33.1 6.8-50.7c0-91.2-130.2-262.3-166.6-308.3C339.4 4.2 330.5 0 320.9 0l-1.8 0c-9.6 0-18.5 4.2-24.5 11.7C277.8 33 240.7 81.3 205.8 136L38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L505.2 370.7zM224 336c0 44.2 35.8 80 80 80c8.8 0 16 7.2 16 16s-7.2 16-16 16c-61.9 0-112-50.1-112-112c0-8.8 7.2-16 16-16s16 7.2 16 16z"/></svg>\n';
68504
- const _hoisted_1$8 = { class: "options-grid-wrap" };
68505
- const _hoisted_2$6 = ["innerHTML"];
68506
- const _hoisted_3$5 = { class: "option-grid-ctn" };
68507
- const _sfc_main$a = {
68736
+ const _hoisted_1$7 = { class: "options-grid-wrap" };
68737
+ const _hoisted_2$5 = ["innerHTML"];
68738
+ const _hoisted_3$4 = { class: "option-grid-ctn" };
68739
+ const _sfc_main$9 = {
68508
68740
  __name: "IconGrid",
68509
68741
  props: {
68510
68742
  icons: {
@@ -68531,7 +68763,7 @@ const _sfc_main$a = {
68531
68763
  emit("select", option);
68532
68764
  };
68533
68765
  return (_ctx, _cache) => {
68534
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$8, [
68766
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$7, [
68535
68767
  __props.hasNoneIcon ? (vue.openBlock(), vue.createElementBlock("div", {
68536
68768
  key: 0,
68537
68769
  class: "none-option",
@@ -68542,10 +68774,10 @@ const _sfc_main$a = {
68542
68774
  vue.createBaseVNode("span", {
68543
68775
  innerHTML: vue.unref(DropIcon),
68544
68776
  class: "none-icon"
68545
- }, null, 8, _hoisted_2$6),
68777
+ }, null, 8, _hoisted_2$5),
68546
68778
  _cache[1] || (_cache[1] = vue.createTextVNode(" None "))
68547
68779
  ])) : vue.createCommentVNode("", true),
68548
- vue.createBaseVNode("div", _hoisted_3$5, [
68780
+ vue.createBaseVNode("div", _hoisted_3$4, [
68549
68781
  vue.createVNode(IconGridRow, {
68550
68782
  icons: __props.icons,
68551
68783
  "active-color": __props.activeColor,
@@ -68564,7 +68796,7 @@ const _sfc_main$a = {
68564
68796
  };
68565
68797
  }
68566
68798
  };
68567
- const IconGrid = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-a00a9a3e"]]);
68799
+ const IconGrid = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-a00a9a3e"]]);
68568
68800
  const closeDropdown$1 = (dropdown) => {
68569
68801
  dropdown.expand.value = false;
68570
68802
  };
@@ -68673,10 +68905,10 @@ const icons = [
68673
68905
  const getAvailableColorOptions = () => {
68674
68906
  return icons.flat().map((item) => item.value);
68675
68907
  };
68676
- const _hoisted_1$7 = ["data-cols", "data-rows", "onKeydown", "onClick"];
68677
- const _hoisted_2$5 = ["aria-valuetext"];
68908
+ const _hoisted_1$6 = ["data-cols", "data-rows", "onKeydown", "onClick"];
68909
+ const _hoisted_2$4 = ["aria-valuetext"];
68678
68910
  const ROW_SIZE = 5;
68679
- const _sfc_main$9 = {
68911
+ const _sfc_main$8 = {
68680
68912
  __name: "TableGrid",
68681
68913
  emits: ["select", "clickoutside"],
68682
68914
  setup(__props, { emit: __emit }) {
@@ -68792,7 +69024,7 @@ const _sfc_main$9 = {
68792
69024
  ref: tableGridItems,
68793
69025
  onKeydown: vue.withModifiers((event) => handleKeyDown2(event, n2, i), ["prevent"]),
68794
69026
  onClick: vue.withModifiers(($event) => handleClick2({ cols: n2, rows: i }), ["stop", "prevent"])
68795
- }, null, 40, _hoisted_1$7);
69027
+ }, null, 40, _hoisted_1$6);
68796
69028
  }), 64))
68797
69029
  ], 64);
68798
69030
  }), 64))
@@ -68800,17 +69032,39 @@ const _sfc_main$9 = {
68800
69032
  vue.createBaseVNode("div", {
68801
69033
  class: "toolbar-table-grid-value",
68802
69034
  "aria-valuetext": `${selectedRows.value} x ${selectedCols.value}`
68803
- }, vue.toDisplayString(selectedRows.value) + " x " + vue.toDisplayString(selectedCols.value), 9, _hoisted_2$5)
69035
+ }, vue.toDisplayString(selectedRows.value) + " x " + vue.toDisplayString(selectedCols.value), 9, _hoisted_2$4)
68804
69036
  ], 2);
68805
69037
  };
68806
69038
  }
68807
69039
  };
68808
- const TableGrid = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-3e1154b8"]]);
69040
+ const TableGrid = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-3e1154b8"]]);
69041
+ function getScrollableParent(element) {
69042
+ let currentElement2 = element;
69043
+ while (currentElement2) {
69044
+ const overflowY = window.getComputedStyle(currentElement2).overflowY;
69045
+ if (/(auto|scroll)/.test(overflowY) && currentElement2.scrollHeight > currentElement2.clientHeight) {
69046
+ return currentElement2;
69047
+ }
69048
+ currentElement2 = currentElement2.parentElement;
69049
+ }
69050
+ return document.scrollingElement || document.documentElement;
69051
+ }
69052
+ function scrollToElement(targetElement, options2 = { behavior: "smooth", block: "start" }) {
69053
+ if (!targetElement) return;
69054
+ const container = getScrollableParent(targetElement);
69055
+ const containerRect = container.getBoundingClientRect();
69056
+ const targetRect = targetElement.getBoundingClientRect();
69057
+ const offsetTop = targetRect.top - containerRect.top + container.scrollTop;
69058
+ container.scrollTo({
69059
+ top: options2.block === "start" ? offsetTop : offsetTop - container.clientHeight + targetElement.offsetHeight,
69060
+ behavior: options2.behavior
69061
+ });
69062
+ }
68809
69063
  const checkIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>\n';
68810
- const _hoisted_1$6 = { class: "search-input-ctn" };
68811
- const _hoisted_2$4 = { class: "row" };
68812
- const _hoisted_3$4 = ["onKeydown"];
68813
- const _sfc_main$8 = {
69064
+ const _hoisted_1$5 = { class: "search-input-ctn" };
69065
+ const _hoisted_2$3 = { class: "row" };
69066
+ const _hoisted_3$3 = ["onKeydown"];
69067
+ const _sfc_main$7 = {
68814
69068
  __name: "SearchInput",
68815
69069
  props: {
68816
69070
  searchRef: {
@@ -68825,8 +69079,8 @@ const _sfc_main$8 = {
68825
69079
  emit("submit", { value: searchValue.value });
68826
69080
  };
68827
69081
  return (_ctx, _cache) => {
68828
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, [
68829
- vue.createBaseVNode("div", _hoisted_2$4, [
69082
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$5, [
69083
+ vue.createBaseVNode("div", _hoisted_2$3, [
68830
69084
  vue.withDirectives(vue.createBaseVNode("input", {
68831
69085
  ref: __props.searchRef,
68832
69086
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchValue.value = $event),
@@ -68835,7 +69089,7 @@ const _sfc_main$8 = {
68835
69089
  name: "search",
68836
69090
  placeholder: "Type search string",
68837
69091
  onKeydown: vue.withKeys(vue.withModifiers(handleSubmit, ["stop", "prevent"]), ["enter"])
68838
- }, null, 40, _hoisted_3$4), [
69092
+ }, null, 40, _hoisted_3$3), [
68839
69093
  [vue.vModelText, searchValue.value]
68840
69094
  ])
68841
69095
  ]),
@@ -68849,7 +69103,7 @@ const _sfc_main$8 = {
68849
69103
  };
68850
69104
  }
68851
69105
  };
68852
- const SearchInput = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-af870fbd"]]);
69106
+ const SearchInput = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-af870fbd"]]);
68853
69107
  const TOOLBAR_FONTS = [
68854
69108
  {
68855
69109
  label: "Georgia",
@@ -69131,6 +69385,54 @@ const makeDefaultItems = ({
69131
69385
  })
69132
69386
  ]);
69133
69387
  };
69388
+ const link = useToolbarItem({
69389
+ type: "dropdown",
69390
+ name: "link",
69391
+ markName: "link",
69392
+ icon: toolbarIcons2.link,
69393
+ tooltip: toolbarTexts2.link,
69394
+ attributes: {
69395
+ ariaLabel: "Link dropdown"
69396
+ },
69397
+ options: [
69398
+ {
69399
+ type: "render",
69400
+ key: "linkDropdown",
69401
+ render: () => renderLinkDropdown(link)
69402
+ }
69403
+ ],
69404
+ onActivate: ({ href }) => {
69405
+ if (href) link.attributes.value = { href };
69406
+ else link.attributes.value = {};
69407
+ },
69408
+ onDeactivate: () => {
69409
+ link.attributes.value = {};
69410
+ link.expand.value = false;
69411
+ }
69412
+ });
69413
+ function renderLinkDropdown(link2) {
69414
+ return vue.h("div", {}, [
69415
+ vue.h(LinkInput, {
69416
+ editor: superToolbar.activeEditor,
69417
+ closePopover: () => closeDropdown(link2),
69418
+ goToAnchor: () => {
69419
+ closeDropdown(link2);
69420
+ if (!superToolbar.activeEditor || !link2.attributes.value?.href) return;
69421
+ const anchorName = link2.attributes.value?.href?.slice(1);
69422
+ const container = superToolbar.activeEditor.element;
69423
+ const anchor = container.querySelector(`a[name='${anchorName}']`);
69424
+ if (anchor) scrollToElement(anchor);
69425
+ }
69426
+ })
69427
+ ]);
69428
+ }
69429
+ const linkInput = useToolbarItem({
69430
+ type: "options",
69431
+ name: "linkInput",
69432
+ command: "toggleLink"
69433
+ });
69434
+ link.childItem = linkInput;
69435
+ linkInput.parentItem = link;
69134
69436
  const image = useToolbarItem({
69135
69437
  type: "button",
69136
69438
  name: "image",
@@ -69628,6 +69930,7 @@ const makeDefaultItems = ({
69628
69930
  colorButton,
69629
69931
  highlight,
69630
69932
  separator,
69933
+ link,
69631
69934
  image,
69632
69935
  tableItem,
69633
69936
  separator,
@@ -69964,6 +70267,35 @@ class SuperToolbar extends EventEmitter2 {
69964
70267
  }
69965
70268
  this.updateToolbarState();
69966
70269
  },
70270
+ /**
70271
+ * Toggles link formatting and updates cursor position
70272
+ * @param {Object} params - Command parameters
70273
+ * @param {CommandItem} params.item - The command item
70274
+ * @param {*} params.argument - Command arguments
70275
+ * @returns {void}
70276
+ */
70277
+ toggleLink: ({ item, argument }) => {
70278
+ let command2 = item.command;
70279
+ if (command2 in this.activeEditor.commands) {
70280
+ this.activeEditor.commands[command2](argument);
70281
+ const { view } = this.activeEditor;
70282
+ let { selection } = view.state;
70283
+ if (this.activeEditor.options.isHeaderOrFooter) {
70284
+ selection = this.activeEditor.options.lastSelection;
70285
+ }
70286
+ const endPos = selection.$to.pos;
70287
+ const newSelection = new TextSelection(view.state.doc.resolve(endPos));
70288
+ const tr = view.state.tr.setSelection(newSelection);
70289
+ const state2 = view.state.apply(tr);
70290
+ view.updateState(state2);
70291
+ if (!this.activeEditor.options.isHeaderOrFooter) {
70292
+ setTimeout(() => {
70293
+ view.focus();
70294
+ }, 100);
70295
+ }
70296
+ }
70297
+ this.updateToolbarState();
70298
+ },
69967
70299
  /**
69968
70300
  * Inserts a table into the document
69969
70301
  * @param {Object} params - Command parameters
@@ -70530,219 +70862,6 @@ async function getEditorContext(editor, event) {
70530
70862
  clipboardContent
70531
70863
  };
70532
70864
  }
70533
- const _hoisted_1$5 = {
70534
- key: 0,
70535
- class: "link-title"
70536
- };
70537
- const _hoisted_2$3 = {
70538
- key: 1,
70539
- class: "link-title"
70540
- };
70541
- const _hoisted_3$3 = {
70542
- key: 2,
70543
- class: "link-title"
70544
- };
70545
- const _hoisted_4$2 = { key: 3 };
70546
- const _hoisted_5$1 = { class: "input-row" };
70547
- const _hoisted_6 = ["innerHTML"];
70548
- const _hoisted_7 = ["onKeydown"];
70549
- const _hoisted_8 = ["innerHTML"];
70550
- const _hoisted_9 = { class: "input-row link-buttons" };
70551
- const _hoisted_10 = ["innerHTML"];
70552
- const _hoisted_11 = {
70553
- key: 4,
70554
- class: "input-row go-to-anchor clickable"
70555
- };
70556
- const _sfc_main$7 = {
70557
- __name: "LinkInput",
70558
- props: {
70559
- showInput: {
70560
- type: Boolean,
70561
- default: true
70562
- },
70563
- showLink: {
70564
- type: Boolean,
70565
- default: true
70566
- },
70567
- goToAnchor: {
70568
- type: Function,
70569
- default: () => {
70570
- }
70571
- },
70572
- editor: {
70573
- type: Object,
70574
- required: true
70575
- },
70576
- closePopover: {
70577
- type: Function,
70578
- default: () => {
70579
- }
70580
- }
70581
- },
70582
- setup(__props) {
70583
- const props = __props;
70584
- const { isHighContrastMode: isHighContrastMode2 } = useHighContrastMode();
70585
- const urlError = vue.ref(false);
70586
- const getSelectedText = () => {
70587
- if (!props.editor || !props.editor.state) return "";
70588
- const { state: state2 } = props.editor;
70589
- const { from: from2, to } = state2.selection;
70590
- return state2.doc.textBetween(from2, to, " ");
70591
- };
70592
- const getLinkHrefAtSelection = () => {
70593
- if (!props.editor || !props.editor.state) return "";
70594
- const { state: state2 } = props.editor;
70595
- const { schema, selection } = state2;
70596
- const linkMark = schema.marks.link;
70597
- if (!linkMark) return "";
70598
- let href = "";
70599
- const { $from, empty: empty2 } = selection;
70600
- if (empty2) {
70601
- const marks = state2.storedMarks || $from.marks();
70602
- const link = marks.find((mark) => mark.type === linkMark);
70603
- if (link) href = link.attrs.href;
70604
- } else {
70605
- state2.doc.nodesBetween(selection.from, selection.to, (node2) => {
70606
- if (node2.marks) {
70607
- const link = node2.marks.find((mark) => mark.type === linkMark);
70608
- if (link) href = link.attrs.href;
70609
- }
70610
- });
70611
- }
70612
- return href || "";
70613
- };
70614
- const text = vue.ref("");
70615
- const rawUrl = vue.ref("");
70616
- const isAnchor = vue.ref(false);
70617
- const url = vue.computed(() => {
70618
- if (!rawUrl.value?.startsWith("http")) return "http://" + rawUrl.value;
70619
- return rawUrl.value;
70620
- });
70621
- const validUrl = vue.computed(() => {
70622
- const urlSplit = url.value.split(".").filter(Boolean);
70623
- return url.value.includes(".") && urlSplit.length > 1;
70624
- });
70625
- const isEditing = vue.computed(() => !isAnchor.value && !!getLinkHrefAtSelection());
70626
- const getApplyText = vue.computed(() => showApply.value ? "Apply" : "Remove");
70627
- const isDisabled2 = vue.computed(() => !validUrl.value);
70628
- const showApply = vue.computed(() => !showRemove.value);
70629
- const showRemove = vue.computed(() => rawUrl.value === "" && getLinkHrefAtSelection());
70630
- const openLink = () => {
70631
- window.open(url.value, "_blank");
70632
- };
70633
- const updateFromEditor = () => {
70634
- text.value = getSelectedText();
70635
- rawUrl.value = getLinkHrefAtSelection();
70636
- };
70637
- vue.watch(
70638
- () => props.editor?.state?.selection,
70639
- () => {
70640
- updateFromEditor();
70641
- },
70642
- { immediate: true }
70643
- );
70644
- const focusInput = () => {
70645
- const input = document.querySelector(".link-input-ctn input");
70646
- if (!input) return;
70647
- input.focus();
70648
- };
70649
- vue.onMounted(() => {
70650
- updateFromEditor();
70651
- isAnchor.value = rawUrl.value.startsWith("#");
70652
- if (props.showInput) focusInput();
70653
- });
70654
- const handleSubmit = () => {
70655
- if (rawUrl.value && validUrl.value) {
70656
- if (props.editor && props.editor.commands && props.editor.commands.toggleLink) {
70657
- props.editor.commands.toggleLink({ href: url.value, text: text.value });
70658
- const { view } = props.editor;
70659
- let { selection } = view.state;
70660
- const endPos = selection.$to.pos;
70661
- const tr = view.state.tr.setSelection(new TextSelection(view.state.doc.resolve(endPos)));
70662
- const state2 = view.state.apply(tr);
70663
- view.updateState(state2);
70664
- setTimeout(() => {
70665
- view.focus();
70666
- }, 100);
70667
- }
70668
- props.closePopover();
70669
- return;
70670
- } else if (!rawUrl.value) {
70671
- if (props.editor && props.editor.commands && props.editor.commands.unsetLink) {
70672
- props.editor.commands.unsetLink();
70673
- }
70674
- props.closePopover();
70675
- return;
70676
- }
70677
- urlError.value = true;
70678
- };
70679
- const handleRemove = () => {
70680
- if (props.editor && props.editor.commands && props.editor.commands.unsetLink) {
70681
- props.editor.commands.unsetLink();
70682
- props.closePopover();
70683
- }
70684
- };
70685
- return (_ctx, _cache) => {
70686
- return vue.openBlock(), vue.createElementBlock("div", {
70687
- class: vue.normalizeClass(["link-input-ctn", { "high-contrast": vue.unref(isHighContrastMode2) }])
70688
- }, [
70689
- isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$5, "Page anchor")) : isEditing.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$3, "Edit link")) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$3, "Add link")),
70690
- __props.showInput && !isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$2, [
70691
- vue.createBaseVNode("div", _hoisted_5$1, [
70692
- vue.createBaseVNode("div", {
70693
- class: "input-icon",
70694
- innerHTML: vue.unref(toolbarIcons).linkInput
70695
- }, null, 8, _hoisted_6),
70696
- vue.withDirectives(vue.createBaseVNode("input", {
70697
- type: "text",
70698
- name: "link",
70699
- placeholder: "Type or paste a link",
70700
- class: vue.normalizeClass({ error: urlError.value }),
70701
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => rawUrl.value = $event),
70702
- onKeydown: [
70703
- vue.withKeys(vue.withModifiers(handleSubmit, ["stop", "prevent"]), ["enter"]),
70704
- _cache[1] || (_cache[1] = ($event) => urlError.value = false)
70705
- ]
70706
- }, null, 42, _hoisted_7), [
70707
- [vue.vModelText, rawUrl.value]
70708
- ]),
70709
- vue.createBaseVNode("div", {
70710
- class: vue.normalizeClass(["open-link-icon", { disabled: !validUrl.value }]),
70711
- innerHTML: vue.unref(toolbarIcons).openLink,
70712
- onClick: openLink,
70713
- "data-item": "btn-link-open"
70714
- }, null, 10, _hoisted_8)
70715
- ]),
70716
- vue.createBaseVNode("div", _hoisted_9, [
70717
- rawUrl.value ? (vue.openBlock(), vue.createElementBlock("button", {
70718
- key: 0,
70719
- class: "remove-btn",
70720
- onClick: handleRemove,
70721
- "data-item": "btn-link-remove"
70722
- }, [
70723
- vue.createBaseVNode("div", {
70724
- class: "remove-btn__icon",
70725
- innerHTML: vue.unref(toolbarIcons).removeLink
70726
- }, null, 8, _hoisted_10),
70727
- _cache[3] || (_cache[3] = vue.createTextVNode(" Remove "))
70728
- ])) : vue.createCommentVNode("", true),
70729
- showApply.value ? (vue.openBlock(), vue.createElementBlock("button", {
70730
- key: 1,
70731
- class: vue.normalizeClass(["submit-btn", { "disable-btn": isDisabled2.value }]),
70732
- onClick: handleSubmit,
70733
- "data-item": "btn-link-apply"
70734
- }, vue.toDisplayString(getApplyText.value), 3)) : vue.createCommentVNode("", true)
70735
- ])
70736
- ])) : isAnchor.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_11, [
70737
- vue.createBaseVNode("a", {
70738
- onClick: _cache[2] || (_cache[2] = vue.withModifiers((...args) => __props.goToAnchor && __props.goToAnchor(...args), ["stop", "prevent"]))
70739
- }, "Go to " + vue.toDisplayString(rawUrl.value.startsWith("#_") ? rawUrl.value.substring(2) : rawUrl.value), 1)
70740
- ])) : vue.createCommentVNode("", true)
70741
- ], 2);
70742
- };
70743
- }
70744
- };
70745
- const LinkInput = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-2632571a"]]);
70746
70865
  const onMarginClickCursorChange = (event, editor) => {
70747
70866
  const y = event.clientY;
70748
70867
  const x = event.clientX;
@@ -70771,7 +70890,7 @@ const onMarginClickCursorChange = (event, editor) => {
70771
70890
  cursorPos = node2?.isText && charAtPos !== " " ? pos - 1 : pos;
70772
70891
  }
70773
70892
  const transaction = view.state.tr.setSelection(
70774
- TextSelection.create(view.state.doc, cursorPos)
70893
+ TextSelection$1.create(view.state.doc, cursorPos)
70775
70894
  );
70776
70895
  view.dispatch(transaction);
70777
70896
  view.focus();
@@ -70850,7 +70969,7 @@ function moveCursorToMouseEvent(event, editor) {
70850
70969
  const pos = view.posAtCoords(coords)?.pos;
70851
70970
  if (typeof pos === "number") {
70852
70971
  const tr = view.state.tr.setSelection(
70853
- TextSelection.create(view.state.doc, pos)
70972
+ TextSelection$1.create(view.state.doc, pos)
70854
70973
  );
70855
70974
  view.dispatch(tr);
70856
70975
  view.focus();
@@ -70990,19 +71109,29 @@ function getItems(context) {
70990
71109
  icon: ICONS.paste,
70991
71110
  action: async (editor2) => {
70992
71111
  try {
70993
- const clipboardData = await navigator.clipboard.read();
70994
- const event = new ClipboardEvent("paste", {
70995
- clipboardData: new DataTransfer(),
70996
- bubbles: true,
70997
- cancelable: true
70998
- });
70999
- for (const item of clipboardData) {
71000
- for (const type2 of item.types) {
71001
- const blob = await item.getType(type2);
71002
- event.clipboardData.setData(type2, await blob.text());
71112
+ const clipboardItems = await navigator.clipboard.read();
71113
+ let html = "";
71114
+ let text = "";
71115
+ for (const item of clipboardItems) {
71116
+ if (!html && item.types.includes("text/html")) {
71117
+ html = await (await item.getType("text/html")).text();
71003
71118
  }
71119
+ if (!text && item.types.includes("text/plain")) {
71120
+ text = await (await item.getType("text/plain")).text();
71121
+ }
71122
+ }
71123
+ const handled = handleClipboardPaste({ editor: editor2, view: editor2.view }, html, text);
71124
+ if (!handled) {
71125
+ const dataTransfer = new DataTransfer();
71126
+ if (html) dataTransfer.setData("text/html", html);
71127
+ if (text) dataTransfer.setData("text/plain", text);
71128
+ const event = new ClipboardEvent("paste", {
71129
+ clipboardData: dataTransfer,
71130
+ bubbles: true,
71131
+ cancelable: true
71132
+ });
71133
+ editor2.view.dom.dispatchEvent(event);
71004
71134
  }
71005
- editor2.view.dom.dispatchEvent(event);
71006
71135
  } catch (error) {
71007
71136
  console.warn("Failed to paste:", error);
71008
71137
  }
@@ -71062,6 +71191,11 @@ const _sfc_main$5 = {
71062
71191
  const menuRef = vue.ref(null);
71063
71192
  const sections = vue.ref([]);
71064
71193
  const selectedId = vue.ref(null);
71194
+ const handleEditorUpdate = () => {
71195
+ if (!props.editor?.isEditable && isOpen.value) {
71196
+ closeMenu({ restoreCursor: false });
71197
+ }
71198
+ };
71065
71199
  const flattenedItems = vue.computed(() => {
71066
71200
  const items = [];
71067
71201
  sections.value.forEach((section) => {
@@ -71146,7 +71280,9 @@ const _sfc_main$5 = {
71146
71280
  }
71147
71281
  };
71148
71282
  const handleRightClick = async (event) => {
71149
- if (event.ctrlKey) {
71283
+ const readOnly = !props.editor?.isEditable;
71284
+ const isHoldingCtrl = event.ctrlKey;
71285
+ if (readOnly || isHoldingCtrl) {
71150
71286
  return;
71151
71287
  }
71152
71288
  event.preventDefault();
@@ -71204,7 +71340,10 @@ const _sfc_main$5 = {
71204
71340
  if (!props.editor) return;
71205
71341
  document.addEventListener("keydown", handleGlobalKeyDown);
71206
71342
  document.addEventListener("mousedown", handleGlobalOutsideClick);
71343
+ props.editor.on("update", handleEditorUpdate);
71207
71344
  props.editor.on("slashMenu:open", async (event) => {
71345
+ const readOnly = !props.editor?.isEditable;
71346
+ if (readOnly) return;
71208
71347
  isOpen.value = true;
71209
71348
  menuPosition.value = event.menuPosition;
71210
71349
  searchQuery.value = "";
@@ -71225,6 +71364,7 @@ const _sfc_main$5 = {
71225
71364
  try {
71226
71365
  props.editor.off("slashMenu:open");
71227
71366
  props.editor.off("slashMenu:close");
71367
+ props.editor.off("update", handleEditorUpdate);
71228
71368
  props.editor.view.dom.removeEventListener("contextmenu", handleRightClick);
71229
71369
  } catch (error) {
71230
71370
  }
@@ -71827,8 +71967,9 @@ const _sfc_main$2 = {
71827
71967
  style: { "width": "70%" }
71828
71968
  })
71829
71969
  ])) : vue.createCommentVNode("", true),
71830
- vue.createVNode(GenericPopover, {
71831
- editor: editor.value ?? {},
71970
+ editor.value ? (vue.openBlock(), vue.createBlock(GenericPopover, {
71971
+ key: 2,
71972
+ editor: editor.value,
71832
71973
  visible: popoverControls.visible,
71833
71974
  position: popoverControls.position,
71834
71975
  onClose: closePopover
@@ -71837,12 +71978,12 @@ const _sfc_main$2 = {
71837
71978
  (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(popoverControls.component), vue.normalizeProps(vue.guardReactiveProps({ ...popoverControls.props, editor: editor.value, closePopover })), null, 16))
71838
71979
  ]),
71839
71980
  _: 1
71840
- }, 8, ["editor", "visible", "position"])
71981
+ }, 8, ["editor", "visible", "position"])) : vue.createCommentVNode("", true)
71841
71982
  ]);
71842
71983
  };
71843
71984
  }
71844
71985
  };
71845
- const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-b71313e5"]]);
71986
+ const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-d4ce5f62"]]);
71846
71987
  const _sfc_main$1 = {
71847
71988
  __name: "BasicUpload",
71848
71989
  emits: ["file-change"],