autumnnote 1.0.7 → 1.0.8

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.
@@ -566,8 +566,24 @@ function underline() {
566
566
  }
567
567
  /**
568
568
  * Strikethrough / removes strikethrough.
569
+ * Falls back to manual DOM manipulation inside nested formats where
570
+ * execCommand's state detection is unreliable (mirrors underline() logic).
569
571
  */
570
- var strikethrough = () => execCommand("strikeThrough");
572
+ function strikethrough() {
573
+ const sel = window.getSelection();
574
+ if (!sel || !sel.rangeCount) return;
575
+ let sc = sel.getRangeAt(0).startContainer;
576
+ if (sc.nodeType === 3) sc = sc.parentElement;
577
+ const sEl = sc && sc.closest && (sc.closest("s") || sc.closest("strike"));
578
+ const nativeState = document.queryCommandState("strikeThrough");
579
+ if (sEl && !nativeState) {
580
+ const parent = sEl.parentNode;
581
+ while (sEl.firstChild) parent.insertBefore(sEl.firstChild, sEl);
582
+ parent.removeChild(sEl);
583
+ return;
584
+ }
585
+ execCommand("strikeThrough");
586
+ }
571
587
  /**
572
588
  * Superscript toggle.
573
589
  */
@@ -600,6 +616,22 @@ var fontName = (name) => execCommand("fontName", name);
600
616
  function fontSize(size, editable = document) {
601
617
  const sel = window.getSelection();
602
618
  const wasCollapsed = !sel || !sel.rangeCount || sel.getRangeAt(0).collapsed;
619
+ if (wasCollapsed && sel && sel.rangeCount > 0) {
620
+ try {
621
+ const range = sel.getRangeAt(0);
622
+ const span = document.createElement("span");
623
+ span.style.fontSize = size;
624
+ const zwsNode = document.createTextNode("​");
625
+ span.appendChild(zwsNode);
626
+ range.insertNode(span);
627
+ const nr = document.createRange();
628
+ nr.setStart(zwsNode, zwsNode.textContent.length);
629
+ nr.collapse(true);
630
+ sel.removeAllRanges();
631
+ sel.addRange(nr);
632
+ } catch (_) {}
633
+ return;
634
+ }
603
635
  execCommand("fontSize", "7");
604
636
  const scope = editable instanceof HTMLElement ? editable : document;
605
637
  const newSpans = [];
@@ -611,27 +643,17 @@ function fontSize(size, editable = document) {
611
643
  el.parentNode.removeChild(el);
612
644
  newSpans.push(span);
613
645
  });
614
- if (sel && newSpans.length > 0) {
646
+ if (!wasCollapsed && sel && newSpans.length > 0) {
615
647
  const first = newSpans[0];
616
648
  const last = newSpans[newSpans.length - 1];
617
649
  try {
618
- if (wasCollapsed) {
619
- if (!first.firstChild) first.appendChild(document.createTextNode("​"));
620
- const nr = document.createRange();
621
- const anchor = first.firstChild;
622
- nr.setStart(anchor, anchor.textContent.length);
623
- nr.collapse(true);
624
- sel.removeAllRanges();
625
- sel.addRange(nr);
626
- } else {
627
- const nr = document.createRange();
628
- const startNode = first.firstChild || first;
629
- const endNode = last.lastChild || last;
630
- nr.setStart(startNode, 0);
631
- nr.setEnd(endNode, endNode.nodeType === Node.TEXT_NODE ? endNode.textContent.length : endNode.childNodes.length);
632
- sel.removeAllRanges();
633
- sel.addRange(nr);
634
- }
650
+ const nr = document.createRange();
651
+ const startNode = first.firstChild || first;
652
+ const endNode = last.lastChild || last;
653
+ nr.setStart(startNode, 0);
654
+ nr.setEnd(endNode, endNode.nodeType === Node.TEXT_NODE ? endNode.textContent.length : endNode.childNodes.length);
655
+ sel.removeAllRanges();
656
+ sel.addRange(nr);
635
657
  } catch (_) {}
636
658
  }
637
659
  }
@@ -662,8 +684,57 @@ var justifyFull = () => execCommand("justifyFull");
662
684
  var indent = () => execCommand("indent");
663
685
  /**
664
686
  * Outdents the list or block.
687
+ * G.5: When cursor is inside a checklist item, "outdent" means converting
688
+ * that item back to a regular <p> element rather than calling execCommand
689
+ * (which would destroy the ul > li checklist structure).
665
690
  */
666
- var outdent = () => execCommand("outdent");
691
+ function outdent() {
692
+ const sel = window.getSelection();
693
+ if (sel && sel.rangeCount) {
694
+ let container = sel.getRangeAt(0).commonAncestorContainer;
695
+ if (container.nodeType === 3) container = container.parentElement;
696
+ const checkLi = container && container.closest && container.closest(".an-checklist li");
697
+ if (checkLi) {
698
+ _checklistItemToP(checkLi);
699
+ return;
700
+ }
701
+ }
702
+ execCommand("outdent");
703
+ }
704
+ /**
705
+ * G.5 helper: splits a checklist at checkLi, converts it to a <p>,
706
+ * and keeps items before/after as separate checklists.
707
+ * @param {HTMLElement} checkLi
708
+ */
709
+ function _checklistItemToP(checkLi) {
710
+ const checkUl = checkLi.closest(".an-checklist");
711
+ if (!checkUl) return;
712
+ const allLis = Array.from(checkUl.children);
713
+ const liIndex = allLis.indexOf(checkLi);
714
+ const afterLis = allLis.slice(liIndex + 1);
715
+ const p = document.createElement("p");
716
+ p.textContent = Array.from(checkLi.childNodes).filter((n) => !(n.nodeType === 1 && n.tagName === "INPUT")).map((n) => n.textContent).join("").replace(/\u200B/g, "").trim() || "\xA0";
717
+ if (afterLis.length > 0) {
718
+ const newUl = document.createElement("ul");
719
+ newUl.className = "an-checklist";
720
+ afterLis.forEach((li) => newUl.appendChild(li));
721
+ checkUl.parentNode.insertBefore(newUl, checkUl.nextSibling);
722
+ }
723
+ checkUl.parentNode.insertBefore(p, checkUl.nextSibling);
724
+ checkUl.removeChild(checkLi);
725
+ if (checkUl.children.length === 0) checkUl.parentNode.removeChild(checkUl);
726
+ try {
727
+ const nr = document.createRange();
728
+ const firstChild = p.firstChild;
729
+ nr.setStart(firstChild && firstChild.nodeType === 3 ? firstChild : p, 0);
730
+ nr.collapse(true);
731
+ const s = window.getSelection();
732
+ if (s) {
733
+ s.removeAllRanges();
734
+ s.addRange(nr);
735
+ }
736
+ } catch {}
737
+ }
667
738
  /**
668
739
  * Inserts an unordered list or converts selection.
669
740
  */
@@ -867,10 +938,60 @@ function toggleChecklist() {
867
938
  sel.addRange(nr);
868
939
  return;
869
940
  }
870
- const lines = sel.toString().split(/\r?\n/).filter((l) => l.trim().length > 0);
871
- if (lines.length === 0) return;
872
- const items = lines.map((l) => `<li><input type="checkbox" contenteditable="false">${l || "​"}</li>`).join("");
873
- document.execCommand("insertHTML", false, `<ul class="an-checklist">${items}</ul>`);
941
+ if (!sel.toString().replace(/[\u00a0\u200B]/g, " ").trim()) return;
942
+ const BLOCK_TAGS_MULTI = new Set([
943
+ "P",
944
+ "DIV",
945
+ "H1",
946
+ "H2",
947
+ "H3",
948
+ "H4",
949
+ "H5",
950
+ "H6",
951
+ "BLOCKQUOTE",
952
+ "PRE",
953
+ "LI"
954
+ ]);
955
+ const blocks = [];
956
+ const seenBlocks = /* @__PURE__ */ new Set();
957
+ const commonAncestor = range.commonAncestorContainer;
958
+ const iter = document.createNodeIterator(commonAncestor.nodeType === Node.TEXT_NODE ? commonAncestor.parentNode : commonAncestor, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT, null);
959
+ let node;
960
+ while (node = iter.nextNode()) {
961
+ if (!range.intersectsNode(node)) continue;
962
+ let block = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
963
+ while (block && !BLOCK_TAGS_MULTI.has(block.tagName)) block = block.parentElement;
964
+ if (block && !seenBlocks.has(block)) {
965
+ seenBlocks.add(block);
966
+ blocks.push(block);
967
+ }
968
+ }
969
+ if (blocks.length === 0) return;
970
+ const newUl = document.createElement("ul");
971
+ newUl.className = "an-checklist";
972
+ let lastTextNode = null;
973
+ blocks.forEach((block) => {
974
+ const li = document.createElement("li");
975
+ const cb = document.createElement("input");
976
+ cb.type = "checkbox";
977
+ cb.setAttribute("contenteditable", "false");
978
+ li.appendChild(cb);
979
+ const blockText = Array.from(block.childNodes).map((n) => n.textContent).join("").replace(/[\u00a0\u200B]/g, " ").trim();
980
+ const tn = document.createTextNode(blockText || "​");
981
+ li.appendChild(tn);
982
+ newUl.appendChild(li);
983
+ lastTextNode = tn;
984
+ });
985
+ const firstBlock = blocks[0];
986
+ firstBlock.parentNode.insertBefore(newUl, firstBlock);
987
+ blocks.forEach((block) => block.parentNode && block.parentNode.removeChild(block));
988
+ if (lastTextNode) {
989
+ const nr = document.createRange();
990
+ nr.setStart(lastTextNode, lastTextNode.textContent.length);
991
+ nr.collapse(true);
992
+ sel.removeAllRanges();
993
+ sel.addRange(nr);
994
+ }
874
995
  }
875
996
  /**
876
997
  * Returns true when the cursor is inside a checklist item.
@@ -1958,7 +2079,7 @@ function handleKeydown(event, editable, options = {}) {
1958
2079
  const para = closestPara(range.sc, editable);
1959
2080
  if (para && isLi(para)) {
1960
2081
  event.preventDefault();
1961
- if (event.shiftKey) execCommand("outdent");
2082
+ if (event.shiftKey) outdent();
1962
2083
  else execCommand("indent");
1963
2084
  return true;
1964
2085
  }
@@ -2379,7 +2500,12 @@ var Editor = class {
2379
2500
  };
2380
2501
  const isReadOnly = () => this.context.layoutInfo.container.classList.contains("an-disabled");
2381
2502
  this._disposers.push(on(editable, "keydown", onKeydown), on(editable, "beforeinput", onBeforeInput), on(editable, "input", onInput), on(document, "selectionchange", onSelChange), on(editable, "click", onCheckboxClick), on(editable, "mouseup", fixChecklistCursor), on(editable, "keyup", fixChecklistCursor), on(editable, "dragstart", (e) => {
2382
- if (isReadOnly()) e.preventDefault();
2503
+ if (isReadOnly()) {
2504
+ e.preventDefault();
2505
+ return;
2506
+ }
2507
+ const target = e.target;
2508
+ if (target && (target.nodeName === "IFRAME" || target.closest && target.closest(".an-video-wrapper"))) e.preventDefault();
2383
2509
  }), on(editable, "drop", (e) => {
2384
2510
  if (isReadOnly()) e.preventDefault();
2385
2511
  }));
@@ -2536,7 +2662,7 @@ var Editor = class {
2536
2662
  * @param {string} html - HTML string (will be sanitised)
2537
2663
  */
2538
2664
  setHTML(html) {
2539
- this.context.layoutInfo.editable.innerHTML = sanitiseHTML(html);
2665
+ this.context.layoutInfo.editable.innerHTML = sanitiseHTML(html, { allowIframes: true });
2540
2666
  if (this._history) this._history.reset();
2541
2667
  this.afterCommand();
2542
2668
  }
@@ -3911,7 +4037,7 @@ var Placeholder = class {
3911
4037
  _update() {
3912
4038
  const editable = this.context.layoutInfo.editable;
3913
4039
  const isFocused = document.activeElement === editable;
3914
- const isEmpty = !editable.textContent.trim() && !editable.querySelector("img, table, hr, .an-video-wrapper");
4040
+ const isEmpty = !(editable.textContent.replace(/\u200B/g, "").trim().length > 0) && !editable.querySelector("img, table, hr, .an-video-wrapper");
3915
4041
  editable.classList.toggle("an-placeholder", isEmpty && !isFocused);
3916
4042
  }
3917
4043
  };
@@ -4346,7 +4472,7 @@ var ImageDialog = class {
4346
4472
  const fileInput = createElement("input", {
4347
4473
  type: "file",
4348
4474
  class: "an-input",
4349
- accept: "image/*"
4475
+ accept: "image/jpeg,image/png,image/gif,image/webp,image/svg+xml,image/avif"
4350
4476
  });
4351
4477
  this._fileInput = fileInput;
4352
4478
  const fileHint = createElement("p", { class: "an-dialog-hint" });
@@ -4393,14 +4519,15 @@ var ImageDialog = class {
4393
4519
  _onFileChange() {
4394
4520
  const file = this._fileInput && this._fileInput.files && this._fileInput.files[0];
4395
4521
  if (!file || !file.type.startsWith("image/")) return;
4396
- if ([
4397
- "image/tiff",
4398
- "image/x-tiff",
4399
- "image/bmp",
4400
- "image/x-bmp",
4401
- "image/x-ms-bmp"
4402
- ].includes(file.type)) {
4403
- const message = `Format "${file.type}" is not supported for display in web browsers. Please convert to PNG, JPEG, or WebP first.`;
4522
+ if (!new Set([
4523
+ "image/jpeg",
4524
+ "image/png",
4525
+ "image/gif",
4526
+ "image/webp",
4527
+ "image/svg+xml",
4528
+ "image/avif"
4529
+ ]).has(file.type)) {
4530
+ const message = `Format "${file.type}" is not supported for display in web browsers. Please convert to JPEG, PNG, or WebP first.`;
4404
4531
  if (this._fileHint) this._fileHint.textContent = message;
4405
4532
  this.context.triggerEvent("imageError", {
4406
4533
  file,
@@ -5854,6 +5981,47 @@ function getCellAfterVisualCol(row, visualIdx) {
5854
5981
  }
5855
5982
  return null;
5856
5983
  }
5984
+ /**
5985
+ * Build a 2D grid map of the table, accounting for both rowspan and colspan.
5986
+ *
5987
+ * gridMap[r][c] = the DOM cell occupying visual grid position (r, c).
5988
+ * cellPos = WeakMap: cell → { r, c, rs, cs } (top-left grid origin + span).
5989
+ *
5990
+ * Uses HTMLTableElement.rows which is scoped to the table itself and never
5991
+ * includes rows from nested tables.
5992
+ *
5993
+ * @param {HTMLTableElement} table
5994
+ * @returns {{ gridMap: Object, cellPos: WeakMap }}
5995
+ */
5996
+ function buildGridMap(table) {
5997
+ const rows = Array.from(table.rows);
5998
+ const gridMap = {};
5999
+ const cellPos = /* @__PURE__ */ new WeakMap();
6000
+ rows.forEach((row, r) => {
6001
+ if (!gridMap[r]) gridMap[r] = {};
6002
+ let c = 0;
6003
+ for (const cell of row.cells) {
6004
+ while (gridMap[r][c]) c++;
6005
+ const rs = cell.rowSpan || 1;
6006
+ const cs = cell.colSpan || 1;
6007
+ cellPos.set(cell, {
6008
+ r,
6009
+ c,
6010
+ rs,
6011
+ cs
6012
+ });
6013
+ for (let dr = 0; dr < rs; dr++) {
6014
+ if (!gridMap[r + dr]) gridMap[r + dr] = {};
6015
+ for (let dc = 0; dc < cs; dc++) gridMap[r + dr][c + dc] = cell;
6016
+ }
6017
+ c += cs;
6018
+ }
6019
+ });
6020
+ return {
6021
+ gridMap,
6022
+ cellPos
6023
+ };
6024
+ }
5857
6025
  var ICONS$2 = {
5858
6026
  rowAbove: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="3" y1="12" x2="21" y2="12"/><path d="M12 3v7"/><path d="M9 7l3-4 3 4"/></svg>`,
5859
6027
  rowBelow: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="3" y1="12" x2="21" y2="12"/><path d="M12 12v7"/><path d="M9 17l3 4 3-4"/></svg>`,
@@ -5862,10 +6030,12 @@ var ICONS$2 = {
5862
6030
  colRight: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="12" y1="3" x2="12" y2="21"/><path d="M12 12h9"/><path d="M17 8l4 4-4 4"/></svg>`,
5863
6031
  deleteCol: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="12" y1="3" x2="12" y2="21"/><line x1="15" y1="6" x2="21" y2="12"/><line x1="21" y1="6" x2="15" y2="12"/></svg>`,
5864
6032
  mergeCells: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="8" height="10" rx="1"/><rect x="14" y="7" width="8" height="10" rx="1"/><path d="M10 12h4"/><path d="M12 10l2 2-2 2"/></svg>`,
6033
+ unmergeCells: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="5" width="20" height="14" rx="1"/><line x1="12" y1="5" x2="12" y2="19" stroke-dasharray="2.5 2"/><line x1="2" y1="12" x2="22" y2="12" stroke-dasharray="2.5 2"/><path d="M9 9 L6 12 L9 15"/><path d="M15 9 L18 12 L15 15"/></svg>`,
5865
6034
  colWidth: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="4" x2="7" y2="20"/><line x1="17" y1="4" x2="17" y2="20"/><line x1="7" y1="12" x2="17" y2="12"/><path d="M10 9l-3 3 3 3"/><path d="M14 9l3 3-3 3"/></svg>`,
5866
6035
  rowHeight: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="7" x2="20" y2="7"/><line x1="4" y1="17" x2="20" y2="17"/><line x1="12" y1="7" x2="12" y2="17"/><path d="M9 10l3-3 3 3"/><path d="M9 14l3 3 3-3"/></svg>`,
5867
6036
  tableBorder: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6" stroke-width="1"/><line x1="3" y1="13" x2="21" y2="13" stroke-width="2"/><line x1="3" y1="20" x2="21" y2="20" stroke-width="3"/></svg>`,
5868
- deleteTable: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/><line x1="16" y1="16" x2="22" y2="22" stroke="#ef4444"/><line x1="22" y1="16" x2="16" y2="22" stroke="#ef4444"/></svg>`
6037
+ deleteTable: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/><line x1="16" y1="16" x2="22" y2="22" stroke="#ef4444"/><line x1="22" y1="16" x2="16" y2="22" stroke="#ef4444"/></svg>`,
6038
+ selectCells: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4 L4 20 L9 15 L12 21 L14 20 L11 14 L17 14 Z" fill="currentColor" opacity="0.15"/><path d="M4 4 L4 20 L9 15 L12 21 L14 20 L11 14 L17 14 Z"/></svg>`
5869
6039
  };
5870
6040
  var TableTooltip = class {
5871
6041
  /** @param {import('../Context.js').Context} context */
@@ -5881,6 +6051,12 @@ var TableTooltip = class {
5881
6051
  this._sizeApply = null;
5882
6052
  this._sizeTitleEl = null;
5883
6053
  this._sizeInputEl = null;
6054
+ this._selectMode = false;
6055
+ this._selectedCells = [];
6056
+ this._selectStart = null;
6057
+ this._selectDragging = false;
6058
+ this._selectBtn = null;
6059
+ this._editable = null;
5884
6060
  }
5885
6061
  initialize() {
5886
6062
  this._el = this._buildTooltip();
@@ -5888,6 +6064,29 @@ var TableTooltip = class {
5888
6064
  this._sizePopover = this._buildSizePopover();
5889
6065
  document.body.appendChild(this._sizePopover);
5890
6066
  const editable = this.context.layoutInfo.editable;
6067
+ this._editable = editable;
6068
+ const onSelMousedown = (e) => {
6069
+ if (!this._selectMode) return;
6070
+ const cell = e.target.closest("td, th");
6071
+ if (!cell || !editable.contains(cell)) return;
6072
+ if (cell.style.cursor === "col-resize" || cell.style.cursor === "row-resize") return;
6073
+ e.preventDefault();
6074
+ this._activeTable = cell.closest("table");
6075
+ this._selectStart = cell;
6076
+ this._selectDragging = true;
6077
+ this._setSelection([cell]);
6078
+ };
6079
+ const onSelMousemove = (e) => {
6080
+ if (!this._selectMode || !this._selectDragging || !this._selectStart) return;
6081
+ const cell = e.target.closest("td, th");
6082
+ if (!cell || !editable.contains(cell)) return;
6083
+ if (cell.closest("table") !== this._activeTable) return;
6084
+ this._setSelection(this._getRectCells(this._selectStart, cell));
6085
+ };
6086
+ const onSelMouseup = () => {
6087
+ this._selectDragging = false;
6088
+ };
6089
+ this._disposers.push(on(editable, "mousedown", onSelMousedown), on(editable, "mousemove", onSelMousemove), on(document, "mouseup", onSelMouseup));
5891
6090
  this._disposers.push(on(editable, "mouseover", (e) => {
5892
6091
  if (this.context.layoutInfo.container.classList.contains("an-disabled")) return;
5893
6092
  const table = e.target.closest("table");
@@ -5897,9 +6096,11 @@ var TableTooltip = class {
5897
6096
  this._scheduleShow(table);
5898
6097
  }
5899
6098
  }, { passive: true }), on(editable, "mouseout", (e) => {
6099
+ if (this._selectMode) return;
5900
6100
  const to = e.relatedTarget;
5901
6101
  if (!to || !editable.contains(to) && !this._el.contains(to) && !(this._sizePopover && this._sizePopover.contains(to))) this._scheduleHide();
5902
6102
  }, { passive: true }), on(document, "click", (e) => {
6103
+ if (this._selectMode && this._activeTable && this._activeTable.contains(e.target)) return;
5903
6104
  if (this._activeTable && !this._activeTable.contains(e.target) && !this._el.contains(e.target) && !(this._sizePopover && this._sizePopover.contains(e.target))) this._hide();
5904
6105
  }));
5905
6106
  this._initResize();
@@ -5972,7 +6173,7 @@ var TableTooltip = class {
5972
6173
  if (_edge === "col") {
5973
6174
  _startW = _nearCell.offsetWidth;
5974
6175
  _colIdx = getVisualColIndex(_nearCell);
5975
- _colCells = _colIdx >= 0 ? Array.from(_table.querySelectorAll("tr")).map((r) => getCellAtVisualCol(r, _colIdx)).filter(Boolean) : [];
6176
+ _colCells = _colIdx >= 0 ? Array.from(_table.querySelectorAll("tr")).map((r) => getCellAtVisualCol(r, _colIdx)).filter(Boolean).filter((c) => (c.colSpan || 1) === 1) : [];
5976
6177
  document.body.style.cursor = "col-resize";
5977
6178
  } else {
5978
6179
  _row = _nearCell.closest("tr");
@@ -6043,6 +6244,9 @@ var TableTooltip = class {
6043
6244
  this._label.textContent = "Table";
6044
6245
  el.appendChild(this._label);
6045
6246
  el.appendChild(this._sep());
6247
+ this._selectBtn = this._makeBtn(ICONS$2.selectCells, "Select Cells", () => this._toggleSelectMode());
6248
+ el.appendChild(this._selectBtn);
6249
+ el.appendChild(this._sep());
6046
6250
  el.appendChild(this._makeBtn(ICONS$2.rowAbove, "Add Row Above", () => this._addRow("above")));
6047
6251
  el.appendChild(this._makeBtn(ICONS$2.rowBelow, "Add Row Below", () => this._addRow("below")));
6048
6252
  el.appendChild(this._makeBtn(ICONS$2.deleteRow, "Delete Row", () => this._deleteRow()));
@@ -6052,6 +6256,7 @@ var TableTooltip = class {
6052
6256
  el.appendChild(this._makeBtn(ICONS$2.deleteCol, "Delete Column", () => this._deleteColumn()));
6053
6257
  el.appendChild(this._sep());
6054
6258
  el.appendChild(this._makeBtn(ICONS$2.mergeCells, "Merge Cells", () => this._mergeCells()));
6259
+ el.appendChild(this._makeBtn(ICONS$2.unmergeCells, "Unmerge Cells", () => this._unmergeCells()));
6055
6260
  el.appendChild(this._sep());
6056
6261
  el.appendChild(this._makeBtn(ICONS$2.colWidth, "Column Width", () => this._openSizePopover("col")));
6057
6262
  el.appendChild(this._makeBtn(ICONS$2.rowHeight, "Row Height", () => this._openSizePopover("row")));
@@ -6059,6 +6264,7 @@ var TableTooltip = class {
6059
6264
  el.appendChild(this._sep());
6060
6265
  el.appendChild(this._makeBtn(ICONS$2.deleteTable, "Delete Table", () => this._deleteTable(), true));
6061
6266
  this._disposers.push(on(el, "mouseenter", () => this._clearTimers()), on(el, "mouseleave", () => {
6267
+ if (this._selectMode) return;
6062
6268
  if (this._sizePopover && this._sizePopover.style.display !== "none") return;
6063
6269
  this._scheduleHide();
6064
6270
  }));
@@ -6114,6 +6320,12 @@ var TableTooltip = class {
6114
6320
  this._el.style.display = "none";
6115
6321
  this._activeTable = null;
6116
6322
  this._activeCell = null;
6323
+ if (this._selectMode) {
6324
+ this._selectMode = false;
6325
+ if (this._selectBtn) this._selectBtn.classList.remove("an-link-tooltip-btn--active");
6326
+ if (this._editable) this._editable.classList.remove("an-table-select-mode");
6327
+ }
6328
+ this._clearSelection();
6117
6329
  this._clearTimers();
6118
6330
  this._hideSizePopover();
6119
6331
  }
@@ -6147,14 +6359,111 @@ var TableTooltip = class {
6147
6359
  }
6148
6360
  return this._activeCell || this._activeTable && this._activeTable.querySelector("td, th");
6149
6361
  }
6362
+ _toggleSelectMode() {
6363
+ this._selectMode = !this._selectMode;
6364
+ if (this._selectBtn) this._selectBtn.classList.toggle("an-link-tooltip-btn--active", this._selectMode);
6365
+ if (this._editable) this._editable.classList.toggle("an-table-select-mode", this._selectMode);
6366
+ if (!this._selectMode) this._clearSelection();
6367
+ }
6368
+ _clearSelection() {
6369
+ this._selectedCells.forEach((c) => c.classList.remove("an-cell-selected"));
6370
+ this._selectedCells = [];
6371
+ this._selectStart = null;
6372
+ }
6373
+ _setSelection(cells) {
6374
+ this._selectedCells.forEach((c) => {
6375
+ if (!cells.includes(c)) c.classList.remove("an-cell-selected");
6376
+ });
6377
+ this._selectedCells = cells;
6378
+ cells.forEach((c) => c.classList.add("an-cell-selected"));
6379
+ }
6380
+ /**
6381
+ * Returns all cells in the rectangular area between startCell and endCell,
6382
+ * correctly handling rowspan/colspan by using the grid map.
6383
+ * The rect is expanded iteratively until it is stable — this ensures any
6384
+ * merged cell that starts outside the initial rect but spans into it is
6385
+ * fully included.
6386
+ */
6387
+ _getRectCells(startCell, endCell) {
6388
+ if (!startCell) return [];
6389
+ if (!endCell || startCell === endCell) return [startCell];
6390
+ const table = startCell.closest("table");
6391
+ if (!table || !table.contains(endCell)) return [startCell];
6392
+ const { gridMap, cellPos } = buildGridMap(table);
6393
+ const sp = cellPos.get(startCell);
6394
+ const ep = cellPos.get(endCell);
6395
+ if (!sp || !ep) return [startCell];
6396
+ let minR = Math.min(sp.r, ep.r);
6397
+ let maxR = Math.max(sp.r + sp.rs - 1, ep.r + ep.rs - 1);
6398
+ let minC = Math.min(sp.c, ep.c);
6399
+ let maxC = Math.max(sp.c + sp.cs - 1, ep.c + ep.cs - 1);
6400
+ let changed = true;
6401
+ while (changed) {
6402
+ changed = false;
6403
+ for (let r = minR; r <= maxR; r++) {
6404
+ const rowMap = gridMap[r];
6405
+ if (!rowMap) continue;
6406
+ for (let c = minC; c <= maxC; c++) {
6407
+ const cell = rowMap[c];
6408
+ if (!cell) continue;
6409
+ const pos = cellPos.get(cell);
6410
+ if (!pos) continue;
6411
+ if (pos.r < minR) {
6412
+ minR = pos.r;
6413
+ changed = true;
6414
+ }
6415
+ if (pos.r + pos.rs - 1 > maxR) {
6416
+ maxR = pos.r + pos.rs - 1;
6417
+ changed = true;
6418
+ }
6419
+ if (pos.c < minC) {
6420
+ minC = pos.c;
6421
+ changed = true;
6422
+ }
6423
+ if (pos.c + pos.cs - 1 > maxC) {
6424
+ maxC = pos.c + pos.cs - 1;
6425
+ changed = true;
6426
+ }
6427
+ }
6428
+ }
6429
+ }
6430
+ const seen = /* @__PURE__ */ new Set();
6431
+ const result = [];
6432
+ for (let r = minR; r <= maxR; r++) {
6433
+ const rowMap = gridMap[r];
6434
+ if (!rowMap) continue;
6435
+ for (let c = minC; c <= maxC; c++) {
6436
+ const cell = rowMap[c];
6437
+ if (cell && !seen.has(cell)) {
6438
+ seen.add(cell);
6439
+ result.push(cell);
6440
+ }
6441
+ }
6442
+ }
6443
+ return result.length > 0 ? result : [startCell];
6444
+ }
6445
+ /**
6446
+ * Returns the active cell set: user-selected cells when available,
6447
+ * otherwise the single active/cursor cell.
6448
+ * @returns {HTMLTableCellElement[]}
6449
+ */
6450
+ _getSelectedCells() {
6451
+ return this._selectedCells.length > 0 ? this._selectedCells : [this._getCell()].filter(Boolean);
6452
+ }
6150
6453
  _addRow(position) {
6151
- const cell = this._getCell();
6152
- if (!cell) return;
6153
- const row = cell.closest("tr");
6154
- if (!row) return;
6155
- const colCount = Array.from(row.cells).reduce((sum, c) => sum + (c.colSpan || 1), 0);
6454
+ const cells = this._getSelectedCells();
6455
+ if (!cells.length) return;
6456
+ const table = cells[0].closest("table");
6457
+ if (!table) return;
6458
+ const allRows = Array.from(table.querySelectorAll("tr"));
6459
+ const refRow = [...new Set(cells.map((c) => c.closest("tr")).filter(Boolean))].reduce((best, r) => {
6460
+ const bi = allRows.indexOf(best);
6461
+ const ri = allRows.indexOf(r);
6462
+ return position === "above" ? ri < bi ? r : best : ri > bi ? r : best;
6463
+ });
6464
+ const colCount = Array.from(refRow.cells).reduce((sum, c) => sum + (c.colSpan || 1), 0);
6156
6465
  const newRow = document.createElement("tr");
6157
- const refCells = Array.from(row.cells);
6466
+ const refCells = Array.from(refRow.cells);
6158
6467
  for (let i = 0; i < colCount; i++) {
6159
6468
  const td = createElement("td", {}, ["\xA0"]);
6160
6469
  const ref = refCells[i];
@@ -6162,19 +6471,20 @@ var TableTooltip = class {
6162
6471
  if (ref && ref.style.minWidth) td.style.minWidth = ref.style.minWidth;
6163
6472
  newRow.appendChild(td);
6164
6473
  }
6165
- if (position === "above") row.parentElement?.insertBefore(newRow, row);
6166
- else row.insertAdjacentElement("afterend", newRow);
6474
+ if (position === "above") refRow.parentElement?.insertBefore(newRow, refRow);
6475
+ else refRow.insertAdjacentElement("afterend", newRow);
6167
6476
  requestAnimationFrame(() => this._positionNear(this._activeTable));
6168
6477
  this.context.invoke("editor.afterCommand");
6169
6478
  }
6170
6479
  _addColumn(position) {
6171
- const cell = this._getCell();
6172
- if (!cell) return;
6173
- const table = cell.closest("table");
6480
+ const cells = this._getSelectedCells();
6481
+ if (!cells.length) return;
6482
+ const table = cells[0].closest("table");
6174
6483
  if (!table) return;
6175
- const visualColIdx = getVisualColIndex(cell);
6484
+ const colIndices = cells.map((c) => getVisualColIndex(c));
6485
+ const targetColIdx = position === "left" ? Math.min(...colIndices) : Math.max(...colIndices);
6176
6486
  const rows = Array.from(table.querySelectorAll("tr"));
6177
- const refs = rows.map((r) => position === "left" ? getCellAtVisualCol(r, visualColIdx) : getCellAfterVisualCol(r, visualColIdx));
6487
+ const refs = rows.map((r) => position === "left" ? getCellAtVisualCol(r, targetColIdx) : getCellAfterVisualCol(r, targetColIdx));
6178
6488
  const isHeaders = rows.map((r) => r.closest("thead") !== null);
6179
6489
  rows.forEach((r, i) => {
6180
6490
  r.insertBefore(createElement(isHeaders[i] ? "th" : "td", {}, ["\xA0"]), refs[i]);
@@ -6183,68 +6493,93 @@ var TableTooltip = class {
6183
6493
  this.context.invoke("editor.afterCommand");
6184
6494
  }
6185
6495
  _deleteRow() {
6186
- const cell = this._getCell();
6187
- if (!cell) return;
6188
- const row = cell.closest("tr");
6189
- const table = cell.closest("table");
6190
- if (!row || !table) return;
6496
+ const cells = this._getSelectedCells();
6497
+ if (!cells.length) return;
6498
+ const table = cells[0].closest("table");
6499
+ if (!table) return;
6191
6500
  const tbody = table.querySelector("tbody");
6192
- if ((tbody ? tbody.querySelectorAll("tr").length : table.querySelectorAll("tr").length) <= 1 && row.closest("tbody")) return;
6501
+ const totalBodyRows = tbody ? tbody.querySelectorAll("tr").length : table.querySelectorAll("tr").length;
6502
+ const selectedRows = [...new Set(cells.map((c) => c.closest("tr")).filter(Boolean))];
6503
+ if (selectedRows.filter((r) => r.closest("tbody")).length >= totalBodyRows) return;
6193
6504
  this._activeCell = null;
6194
- row.parentElement?.removeChild(row);
6505
+ this._clearSelection();
6506
+ selectedRows.forEach((r) => r.parentElement?.removeChild(r));
6195
6507
  requestAnimationFrame(() => this._positionNear(this._activeTable));
6196
6508
  this.context.invoke("editor.afterCommand");
6197
6509
  }
6198
6510
  _deleteColumn() {
6199
- const cell = this._getCell();
6200
- if (!cell) return;
6201
- const table = cell.closest("table");
6511
+ const cells = this._getSelectedCells();
6512
+ if (!cells.length) return;
6513
+ const table = cells[0].closest("table");
6202
6514
  if (!table) return;
6203
- const row = cell.closest("tr");
6204
- if (row && row.cells.length <= 1) return;
6205
- const visualColIdx = getVisualColIndex(cell);
6206
- this._activeCell = null;
6207
- const rows = Array.from(table.querySelectorAll("tr"));
6208
- rows.map((r) => getCellAtVisualCol(r, visualColIdx)).forEach((c, i) => {
6209
- if (c) rows[i].removeChild(c);
6515
+ const tableRows = Array.from(table.querySelectorAll("tr"));
6516
+ if (tableRows[0] && tableRows[0].cells.length <= 1) return;
6517
+ const colIndices = [...new Set(cells.map((c) => getVisualColIndex(c)))];
6518
+ if (colIndices.length >= (tableRows[0]?.cells.length ?? 1)) return;
6519
+ const cellsToDelete = [];
6520
+ colIndices.forEach((colIdx) => {
6521
+ tableRows.forEach((r) => {
6522
+ const c = getCellAtVisualCol(r, colIdx);
6523
+ if (c) cellsToDelete.push(c);
6524
+ });
6210
6525
  });
6526
+ this._activeCell = null;
6527
+ this._clearSelection();
6528
+ cellsToDelete.forEach((c) => c.parentElement?.removeChild(c));
6211
6529
  requestAnimationFrame(() => this._positionNear(this._activeTable));
6212
6530
  this.context.invoke("editor.afterCommand");
6213
6531
  }
6214
6532
  _mergeCells() {
6215
6533
  const cell = this._getCell();
6216
6534
  if (!cell) return;
6217
- const sel = window.getSelection();
6218
- if (!sel || sel.rangeCount === 0) return;
6219
- const range = sel.getRangeAt(0);
6220
6535
  const table = cell.closest("table");
6221
6536
  if (!table) return;
6222
- const selected = Array.from(table.querySelectorAll("td, th")).filter((c) => {
6223
- try {
6224
- return range.intersectsNode(c);
6225
- } catch {
6226
- return false;
6227
- }
6228
- });
6229
- if (selected.length < 2) return;
6230
- const rows = [...new Set(selected.map((c) => c.closest("tr")))];
6231
- if (rows.length === 1) {
6232
- const row = rows[0];
6233
- const rowSelected = Array.from(row.cells).filter((c) => selected.includes(c));
6234
- if (rowSelected.length < 2) return;
6235
- const first = rowSelected[0];
6236
- first.colSpan = rowSelected.reduce((sum, c) => sum + (c.colSpan || 1), 0);
6237
- first.innerHTML = rowSelected.map((c) => c.innerHTML).join("");
6238
- rowSelected.slice(1).forEach((c) => row.removeChild(c));
6239
- } else {
6240
- if ([...new Set(selected.map((c) => getVisualColIndex(c)))].length !== 1) return;
6241
- const first = selected[0];
6242
- first.rowSpan = selected.reduce((sum, c) => sum + (c.rowSpan || 1), 0);
6243
- first.innerHTML = selected.map((c) => c.innerHTML).join("");
6244
- selected.slice(1).forEach((c) => {
6245
- if (c.closest("tr")) c.closest("tr").removeChild(c);
6537
+ let selected = this._getSelectedCells().filter((c) => table.contains(c));
6538
+ if (selected.length < 2) {
6539
+ const sel = window.getSelection();
6540
+ if (!sel || sel.rangeCount === 0) return;
6541
+ const range = sel.getRangeAt(0);
6542
+ selected = Array.from(table.querySelectorAll("td, th")).filter((c) => {
6543
+ try {
6544
+ return range.intersectsNode(c);
6545
+ } catch {
6546
+ return false;
6547
+ }
6246
6548
  });
6549
+ if (selected.length < 2) return;
6550
+ }
6551
+ const { gridMap, cellPos } = buildGridMap(table);
6552
+ let minR = Infinity, maxR = -Infinity, minC = Infinity, maxC = -Infinity;
6553
+ selected.forEach((c) => {
6554
+ const pos = cellPos.get(c);
6555
+ if (!pos) return;
6556
+ if (pos.r < minR) minR = pos.r;
6557
+ if (pos.r + pos.rs - 1 > maxR) maxR = pos.r + pos.rs - 1;
6558
+ if (pos.c < minC) minC = pos.c;
6559
+ if (pos.c + pos.cs - 1 > maxC) maxC = pos.c + pos.cs - 1;
6560
+ });
6561
+ if (minR === Infinity) return;
6562
+ const seen = /* @__PURE__ */ new Set();
6563
+ const rectCells = [];
6564
+ for (let r = minR; r <= maxR; r++) {
6565
+ const rowMap = gridMap[r];
6566
+ if (!rowMap) continue;
6567
+ for (let c = minC; c <= maxC; c++) {
6568
+ const tc = rowMap[c];
6569
+ if (tc && !seen.has(tc)) {
6570
+ seen.add(tc);
6571
+ rectCells.push(tc);
6572
+ }
6573
+ }
6247
6574
  }
6575
+ if (rectCells.length < 2) return;
6576
+ const first = rectCells[0];
6577
+ first.colSpan = maxC - minC + 1;
6578
+ first.rowSpan = maxR - minR + 1;
6579
+ first.style.verticalAlign = "middle";
6580
+ first.innerHTML = rectCells.map((c) => c.innerHTML).join("");
6581
+ rectCells.slice(1).forEach((c) => c.parentElement?.removeChild(c));
6582
+ this._clearSelection();
6248
6583
  this.context.invoke("editor.afterCommand");
6249
6584
  }
6250
6585
  _deleteTable() {
@@ -6254,6 +6589,57 @@ var TableTooltip = class {
6254
6589
  if (table.parentNode) table.parentNode.removeChild(table);
6255
6590
  this.context.invoke("editor.afterCommand");
6256
6591
  }
6592
+ _unmergeCells() {
6593
+ const cells = this._getSelectedCells();
6594
+ if (!cells.length) return;
6595
+ const table = cells[0].closest("table");
6596
+ if (!table) return;
6597
+ const mergedCells = cells.filter((c) => table.contains(c) && ((c.colSpan || 1) > 1 || (c.rowSpan || 1) > 1));
6598
+ if (!mergedCells.length) return;
6599
+ mergedCells.forEach((cell) => {
6600
+ if (table.contains(cell)) this._unmergeOne(cell, table);
6601
+ });
6602
+ this._clearSelection();
6603
+ requestAnimationFrame(() => this._positionNear(this._activeTable));
6604
+ this.context.invoke("editor.afterCommand");
6605
+ }
6606
+ /**
6607
+ * Split a single merged cell (colspan/rowspan > 1) back into individual cells.
6608
+ * New cells are empty (&nbsp;); the original cell retains its content.
6609
+ * @param {HTMLTableCellElement} cell
6610
+ * @param {HTMLTableElement} table
6611
+ */
6612
+ _unmergeOne(cell, table) {
6613
+ const cs = cell.colSpan || 1;
6614
+ const rs = cell.rowSpan || 1;
6615
+ if (cs === 1 && rs === 1) return;
6616
+ const { cellPos } = buildGridMap(table);
6617
+ const pos = cellPos.get(cell);
6618
+ if (!pos) return;
6619
+ const { r, c } = pos;
6620
+ const tableRows = Array.from(table.rows);
6621
+ const tag = cell.tagName.toLowerCase();
6622
+ cell.rowSpan = 1;
6623
+ cell.colSpan = 1;
6624
+ cell.style.verticalAlign = "";
6625
+ if (cs > 1) {
6626
+ const insertRef = cell.nextElementSibling;
6627
+ for (let dc = 1; dc < cs; dc++) tableRows[r].insertBefore(createElement(tag, {}, ["\xA0"]), insertRef);
6628
+ }
6629
+ for (let dr = 1; dr < rs; dr++) {
6630
+ const targetRow = tableRows[r + dr];
6631
+ if (!targetRow) continue;
6632
+ let ref = null;
6633
+ for (const tc of targetRow.cells) {
6634
+ const tp = cellPos.get(tc);
6635
+ if (tp && tp.c > c) {
6636
+ ref = tc;
6637
+ break;
6638
+ }
6639
+ }
6640
+ for (let dc = 0; dc < cs; dc++) targetRow.insertBefore(createElement(tag, {}, ["\xA0"]), ref);
6641
+ }
6642
+ }
6257
6643
  _buildSizePopover() {
6258
6644
  const popover = createElement("div", { class: "an-size-popover" });
6259
6645
  popover.style.display = "none";
@@ -6335,27 +6721,35 @@ var TableTooltip = class {
6335
6721
  };
6336
6722
  } else {
6337
6723
  const isCol = type === "col";
6724
+ const activeCells = this._getSelectedCells().filter((c) => {
6725
+ const t = c.closest("table");
6726
+ return t && t === cell.closest("table");
6727
+ });
6338
6728
  this._sizeTitleEl.textContent = isCol ? "Column Width (px)" : "Row Height (px)";
6339
6729
  this._sizeInputEl.min = "1";
6340
6730
  this._sizeInputEl.max = "2000";
6341
6731
  this._sizeInputEl.value = isCol ? cell.offsetWidth || 120 : cell.closest("tr") ? cell.closest("tr").offsetHeight || 40 : 40;
6342
6732
  this._sizeApply = (val) => {
6733
+ const table = cell.closest("table");
6734
+ if (!table) return;
6343
6735
  if (isCol) {
6344
- const table = cell.closest("table");
6345
- const visualColIdx = getVisualColIndex(cell);
6346
- Array.from(table.querySelectorAll("tr")).map((r) => getCellAtVisualCol(r, visualColIdx)).forEach((c) => {
6347
- if (c) {
6348
- c.style.width = `${val}px`;
6349
- c.style.minWidth = `${val}px`;
6350
- }
6736
+ const colIndices = [...new Set(activeCells.map((c) => getVisualColIndex(c)))];
6737
+ const tableRows = Array.from(table.querySelectorAll("tr"));
6738
+ colIndices.forEach((colIdx) => {
6739
+ tableRows.forEach((r) => {
6740
+ const c = getCellAtVisualCol(r, colIdx);
6741
+ if (c && (c.colSpan || 1) === 1) {
6742
+ c.style.width = `${val}px`;
6743
+ c.style.minWidth = `${val}px`;
6744
+ }
6745
+ });
6351
6746
  });
6352
- } else {
6353
- const row = cell.closest("tr");
6354
- if (row) for (const c of row.cells) {
6747
+ } else [...new Set(activeCells.map((c) => c.closest("tr")).filter(Boolean))].forEach((row) => {
6748
+ for (const c of row.cells) {
6355
6749
  c.style.height = `${val}px`;
6356
6750
  c.style.minHeight = `${val}px`;
6357
6751
  }
6358
- }
6752
+ });
6359
6753
  this.context.invoke("editor.afterCommand");
6360
6754
  };
6361
6755
  }
@@ -9210,7 +9604,13 @@ var EmojiDialog = class {
9210
9604
  range.selectNodeContents(editable);
9211
9605
  range.collapse(false);
9212
9606
  }
9607
+ const _sc = range.startContainer;
9608
+ const _tdAnchor = (_sc.nodeType === 1 ? _sc : _sc.parentElement)?.closest?.("td, th");
9213
9609
  range.deleteContents();
9610
+ if (_tdAnchor && _tdAnchor.isConnected && !_tdAnchor.contains(range.startContainer)) {
9611
+ range.setStart(_tdAnchor, 0);
9612
+ range.collapse(true);
9613
+ }
9214
9614
  const textNode = document.createTextNode(char);
9215
9615
  range.insertNode(textNode);
9216
9616
  range.setStartAfter(textNode);
@@ -9779,7 +10179,13 @@ var IconDialog = class {
9779
10179
  range.selectNodeContents(editable);
9780
10180
  range.collapse(false);
9781
10181
  }
10182
+ const _sc = range.startContainer;
10183
+ const _tdAnchor = (_sc.nodeType === 1 ? _sc : _sc.parentElement)?.closest?.("td, th");
9782
10184
  range.deleteContents();
10185
+ if (_tdAnchor && _tdAnchor.isConnected && !_tdAnchor.contains(range.startContainer)) {
10186
+ range.setStart(_tdAnchor, 0);
10187
+ range.collapse(true);
10188
+ }
9783
10189
  range.insertNode(iconEl);
9784
10190
  let caretTextNode = iconEl.nextSibling;
9785
10191
  if (!caretTextNode || caretTextNode.nodeType !== Node.TEXT_NODE) {