ct-rich-text-editor 1.3.27 → 1.3.28

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.
@@ -24,15 +24,15 @@ import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
24
24
  import { TableNode, TableCellNode, TableRowNode, $createTableNodeWithDimensions, $isTableRowNode, $isTableCellNode, TableCellHeaderStates, $isTableNode, $isTableSelection, $getTableCellNodeFromLexicalNode, $getTableNodeFromLexicalNodeOrThrow, getTableElement, getTableObserverFromTableElement, $getTableRowIndexFromTableCellNode, $getNodeTriplet, $insertTableRow__EXPERIMENTAL, $getTableColumnIndexFromTableCellNode, $insertTableColumn__EXPERIMENTAL, $deleteTableRow__EXPERIMENTAL, $deleteTableColumn__EXPERIMENTAL, $unmergeCell, $computeTableMapSkipCellCheck, getDOMCellFromTarget, $getTableAndElementByKey } from "@lexical/table";
25
25
  import { mergeRegister, $wrapNodeInElement, $findMatchingParent, $getNearestNodeOfType, $getNearestBlockElementAncestorOrThrow, $insertNodeToNearestRoot, $isEditorIsNestedEditor, mediaFileReader, isMimeType, calculateZoomLevel, CAN_USE_DOM } from "@lexical/utils";
26
26
  import Stack from "@mui/material/Stack";
27
- import { createCommand, DecoratorNode, createEditor, $applyNodeReplacement, $getSelection, $isRangeSelection, ElementNode, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, $insertNodes, $getNearestNodeFromDOMNode, isHTMLElement as isHTMLElement$1, TextNode, $getRoot, $createTextNode, $getNodeByKey, $isParagraphNode, $isTextNode, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, KEY_DOWN_COMMAND, COMMAND_PRIORITY_CRITICAL, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, $isElementNode, SELECTION_CHANGE_COMMAND, UNDO_COMMAND, REDO_COMMAND, KEY_SPACE_COMMAND, $isLineBreakNode, $createRangeSelection, $setSelection, COMMAND_PRIORITY_HIGH, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, getDOMSelection, CLICK_COMMAND, PASTE_COMMAND, ParagraphNode, $createLineBreakNode, isDOMNode } from "lexical";
27
+ import { createCommand, DecoratorNode, createEditor, $applyNodeReplacement, $insertNodes, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, $getSelection, $isRangeSelection, $getNearestNodeFromDOMNode, isHTMLElement as isHTMLElement$1, TextNode, $getRoot, $createTextNode, $getNodeByKey, $isParagraphNode, $isTextNode, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, KEY_DOWN_COMMAND, COMMAND_PRIORITY_CRITICAL, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, $isElementNode, SELECTION_CHANGE_COMMAND, UNDO_COMMAND, REDO_COMMAND, KEY_SPACE_COMMAND, $isLineBreakNode, $createRangeSelection, $setSelection, COMMAND_PRIORITY_HIGH, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, getDOMSelection, CLICK_COMMAND, KEY_BACKSPACE_COMMAND, PASTE_COMMAND, ParagraphNode, $createLineBreakNode, isDOMNode } from "lexical";
28
28
  import * as ReactDOM from "react-dom";
29
29
  import ReactDOM__default, { createPortal } from "react-dom";
30
30
  import { $isCodeNode, CodeNode, normalizeCodeLang, getLanguageFriendlyName, CodeHighlightNode, CODE_LANGUAGE_MAP, $createCodeNode, registerCodeHighlighting, $isCodeHighlightNode } from "@lexical/code";
31
31
  import { LinkNode, $isLinkNode, TOGGLE_LINK_COMMAND, $isAutoLinkNode, $createLinkNode } from "@lexical/link";
32
- import { ListNode, ListItemNode, $isListNode, INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, $createListNode, $createListItemNode } from "@lexical/list";
32
+ import { ListNode, ListItemNode, $isListNode, INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, $isListItemNode, $createListNode, $createListItemNode } from "@lexical/list";
33
33
  import { HeadingNode, QuoteNode, $isHeadingNode, $createHeadingNode, $createQuoteNode, DRAG_DROP_PASTE } from "@lexical/rich-text";
34
34
  import { $isAtNodeEnd, $selectAll, $patchStyleText, $setBlocksType, $getSelectionStyleValueForProperty, $isParentElementRTL } from "@lexical/selection";
35
- import { HorizontalRuleNode } from "@lexical/react/LexicalHorizontalRuleNode";
35
+ import { HorizontalRuleNode, INSERT_HORIZONTAL_RULE_COMMAND } from "@lexical/react/LexicalHorizontalRuleNode";
36
36
  import DescriptionIcon from "@mui/icons-material/Description";
37
37
  import FolderZipIcon from "@mui/icons-material/FolderZip";
38
38
  import InsertChartIcon from "@mui/icons-material/InsertChart";
@@ -1481,7 +1481,7 @@ const AiTextTransform = async ({ content, apiKey }) => {
1481
1481
  const AI_ACTION_COMMAND = createCommand(
1482
1482
  "AI_ACTION_COMMAND"
1483
1483
  );
1484
- const ImageView = React__default.lazy(() => import("./index-aa2e3927.js"));
1484
+ const ImageView = React__default.lazy(() => import("./index-c26337f6.js"));
1485
1485
  function isGoogleDocCheckboxImg(img) {
1486
1486
  return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
1487
1487
  }
@@ -1493,14 +1493,14 @@ function $convertImageElement(domNode) {
1493
1493
  const { alt: altText, src, width, height } = img;
1494
1494
  const positionAttr = img.getAttribute("data-position");
1495
1495
  let position = "none";
1496
- if (positionAttr === "left" || positionAttr === "right" || positionAttr === "full") {
1496
+ if (positionAttr === "left" || positionAttr === "right" || positionAttr === "full" || positionAttr === "inline-left" || positionAttr === "inline-center" || positionAttr === "inline-right") {
1497
1497
  position = positionAttr;
1498
1498
  }
1499
1499
  const node = $createImageNode({ altText, height, src, width, position });
1500
1500
  return { node };
1501
1501
  }
1502
1502
  class ImageNode extends DecoratorNode {
1503
- constructor(src, altText, maxWidth, width, height, showCaption, caption, captionsEnabled, originalPrompt, position, key) {
1503
+ constructor(src, altText, maxWidth, width, height, showCaption, caption, captionsEnabled, originalPrompt, position, linkUrl, key) {
1504
1504
  super(key);
1505
1505
  __publicField(this, "__src");
1506
1506
  __publicField(this, "__altText");
@@ -1513,6 +1513,7 @@ class ImageNode extends DecoratorNode {
1513
1513
  __publicField(this, "__captionsEnabled");
1514
1514
  __publicField(this, "__originalPrompt");
1515
1515
  __publicField(this, "__position");
1516
+ __publicField(this, "__linkUrl");
1516
1517
  this.__src = src;
1517
1518
  this.__altText = altText;
1518
1519
  this.__maxWidth = maxWidth;
@@ -1525,6 +1526,7 @@ class ImageNode extends DecoratorNode {
1525
1526
  this.__captionsEnabled = captionsEnabled || captionsEnabled === void 0;
1526
1527
  this.__originalPrompt = originalPrompt || "";
1527
1528
  this.__position = position || "none";
1529
+ this.__linkUrl = linkUrl || "";
1528
1530
  }
1529
1531
  // to identify the image node and must unique too
1530
1532
  static getType() {
@@ -1543,12 +1545,13 @@ class ImageNode extends DecoratorNode {
1543
1545
  node.__captionsEnabled,
1544
1546
  node.__originalPrompt,
1545
1547
  node.__position,
1548
+ node.__linkUrl,
1546
1549
  node.__key
1547
1550
  );
1548
1551
  }
1549
1552
  // importing to json format
1550
1553
  static importJSON(serializedNode) {
1551
- const { altText, height, width, maxWidth, caption, src, showCaption, originalPrompt, position } = serializedNode;
1554
+ const { altText, height, width, maxWidth, caption, src, showCaption, originalPrompt, position, linkUrl } = serializedNode;
1552
1555
  const node = $createImageNode({
1553
1556
  altText,
1554
1557
  height,
@@ -1558,7 +1561,8 @@ class ImageNode extends DecoratorNode {
1558
1561
  width,
1559
1562
  originalPrompt: originalPrompt || "",
1560
1563
  // Default to empty string if undefined
1561
- position: position || "none"
1564
+ position: position || "none",
1565
+ linkUrl: linkUrl || ""
1562
1566
  });
1563
1567
  const nestedEditor = node.__caption;
1564
1568
  const editorState = nestedEditor.parseEditorState(caption.editorState);
@@ -1600,7 +1604,8 @@ class ImageNode extends DecoratorNode {
1600
1604
  version: 1,
1601
1605
  width: this.__width === "inherit" ? 0 : this.__width,
1602
1606
  originalPrompt: this.__originalPrompt,
1603
- position: this.__position
1607
+ position: this.__position,
1608
+ linkUrl: this.__linkUrl
1604
1609
  };
1605
1610
  }
1606
1611
  // setting width and height when resizing
@@ -1614,6 +1619,26 @@ class ImageNode extends DecoratorNode {
1614
1619
  const writable = this.getWritable();
1615
1620
  writable.__showCaption = showCaption;
1616
1621
  }
1622
+ // Helper to get position-based CSS styles
1623
+ getPositionStyles() {
1624
+ const cursorStyle = "cursor: pointer;";
1625
+ switch (this.__position) {
1626
+ case "left":
1627
+ return `float: left; margin-right: 1em; margin-bottom: 0.5em; max-width: 50%; display: block; ${cursorStyle}`;
1628
+ case "right":
1629
+ return `float: right; margin-left: 1em; margin-bottom: 0.5em; max-width: 50%; display: block; ${cursorStyle}`;
1630
+ case "full":
1631
+ return `display: block; width: 100%; margin: 1em 0; text-align: center; ${cursorStyle}`;
1632
+ case "inline-left":
1633
+ return `display: block; margin: 1em 0; text-align: left; ${cursorStyle}`;
1634
+ case "inline-center":
1635
+ return `display: block; margin: 1em 0; text-align: center; ${cursorStyle}`;
1636
+ case "inline-right":
1637
+ return `display: block; margin: 1em 0; text-align: right; ${cursorStyle}`;
1638
+ default:
1639
+ return "";
1640
+ }
1641
+ }
1617
1642
  // To create a dom representation of image view
1618
1643
  createDOM(config) {
1619
1644
  const span = document.createElement("span");
@@ -1622,24 +1647,18 @@ class ImageNode extends DecoratorNode {
1622
1647
  if (className !== void 0) {
1623
1648
  span.className = className;
1624
1649
  }
1625
- if (this.__position === "left") {
1626
- span.style.cssText = "float: left; margin-right: 1em; margin-bottom: 0.5em; max-width: 50%; display: block;";
1627
- } else if (this.__position === "right") {
1628
- span.style.cssText = "float: right; margin-left: 1em; margin-bottom: 0.5em; max-width: 50%; display: block;";
1629
- } else if (this.__position === "full") {
1630
- span.style.cssText = "display: block; width: 100%; margin: 1em 0;";
1650
+ const positionStyles = this.getPositionStyles();
1651
+ if (positionStyles) {
1652
+ span.style.cssText = positionStyles;
1631
1653
  }
1632
1654
  return span;
1633
1655
  }
1634
1656
  updateDOM(prevNode, dom) {
1635
1657
  if (prevNode.__position !== this.__position) {
1636
1658
  dom.style.cssText = "";
1637
- if (this.__position === "left") {
1638
- dom.style.cssText = "float: left; margin-right: 1em; margin-bottom: 0.5em; max-width: 50%; display: block;";
1639
- } else if (this.__position === "right") {
1640
- dom.style.cssText = "float: right; margin-left: 1em; margin-bottom: 0.5em; max-width: 50%; display: block;";
1641
- } else if (this.__position === "full") {
1642
- dom.style.cssText = "display: block; width: 100%; margin: 1em 0;";
1659
+ const positionStyles = this.getPositionStyles();
1660
+ if (positionStyles) {
1661
+ dom.style.cssText = positionStyles;
1643
1662
  }
1644
1663
  }
1645
1664
  return false;
@@ -1674,6 +1693,15 @@ class ImageNode extends DecoratorNode {
1674
1693
  const writable = this.getWritable();
1675
1694
  writable.__position = position;
1676
1695
  }
1696
+ // to get the link URL (if image was wrapped in a link)
1697
+ getLinkUrl() {
1698
+ return this.__linkUrl;
1699
+ }
1700
+ // to set the link URL
1701
+ setLinkUrl(linkUrl) {
1702
+ const writable = this.getWritable();
1703
+ writable.__linkUrl = linkUrl;
1704
+ }
1677
1705
  // to render the image tag
1678
1706
  decorate() {
1679
1707
  return /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
@@ -1690,7 +1718,8 @@ class ImageNode extends DecoratorNode {
1690
1718
  captionsEnabled: this.__captionsEnabled,
1691
1719
  resizable: true,
1692
1720
  originalPrompt: this.__originalPrompt,
1693
- position: this.__position
1721
+ position: this.__position,
1722
+ linkUrl: this.__linkUrl
1694
1723
  }
1695
1724
  ) });
1696
1725
  }
@@ -1706,7 +1735,8 @@ function $createImageNode({
1706
1735
  caption,
1707
1736
  key,
1708
1737
  originalPrompt,
1709
- position
1738
+ position,
1739
+ linkUrl
1710
1740
  }) {
1711
1741
  return $applyNodeReplacement(
1712
1742
  new ImageNode(
@@ -1720,6 +1750,7 @@ function $createImageNode({
1720
1750
  captionsEnabled,
1721
1751
  originalPrompt,
1722
1752
  position,
1753
+ linkUrl,
1723
1754
  key
1724
1755
  )
1725
1756
  );
@@ -1741,37 +1772,7 @@ const ImagePlugin = ({
1741
1772
  INSERT_IMAGE_COMMAND,
1742
1773
  (payload) => {
1743
1774
  const imageNode = $createImageNode(payload);
1744
- const selection = $getSelection();
1745
- if ($isRangeSelection(selection)) {
1746
- const anchorNode = selection.anchor.getNode();
1747
- const anchorParent = anchorNode.getParent();
1748
- if (anchorParent instanceof ElementNode && !$isRootOrShadowRoot(anchorParent)) {
1749
- const parentType = anchorParent.getType();
1750
- if (parentType === "paragraph" || parentType === "listitem") {
1751
- const hasContent = anchorParent.getTextContent().trim().length > 0;
1752
- const isAtEnd = selection.anchor.offset === anchorNode.getTextContentSize();
1753
- const isAtStart = selection.anchor.offset === 0;
1754
- if (hasContent) {
1755
- const imageParagraph = $createParagraphNode();
1756
- imageParagraph.append(imageNode);
1757
- if (isAtEnd) {
1758
- anchorParent.insertAfter(imageParagraph);
1759
- } else if (isAtStart) {
1760
- anchorParent.insertBefore(imageParagraph);
1761
- } else {
1762
- anchorParent.insertAfter(imageParagraph);
1763
- }
1764
- const emptyParagraph = $createParagraphNode();
1765
- imageParagraph.insertAfter(emptyParagraph);
1766
- emptyParagraph.selectEnd();
1767
- return true;
1768
- }
1769
- }
1770
- }
1771
- }
1772
- if ($isRangeSelection(selection)) {
1773
- selection.insertNodes([imageNode]);
1774
- }
1775
+ $insertNodes([imageNode]);
1775
1776
  if ($isRootOrShadowRoot(imageNode.getParentOrThrow())) {
1776
1777
  $wrapNodeInElement(imageNode, $createParagraphNode).selectEnd();
1777
1778
  }
@@ -7344,6 +7345,19 @@ const FileSearch = createLucideIcon("FileSearch", [
7344
7345
  ["circle", { cx: "5", cy: "14", r: "3", key: "ufru5t" }],
7345
7346
  ["path", { d: "m9 18-1.5-1.5", key: "1j6qii" }]
7346
7347
  ]);
7348
+ /**
7349
+ * @license lucide-react v0.344.0 - ISC
7350
+ *
7351
+ * This source code is licensed under the ISC license.
7352
+ * See the LICENSE file in the root directory of this source tree.
7353
+ */
7354
+ const FileText = createLucideIcon("FileText", [
7355
+ ["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
7356
+ ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
7357
+ ["path", { d: "M10 9H8", key: "b1mrlr" }],
7358
+ ["path", { d: "M16 13H8", key: "t4e002" }],
7359
+ ["path", { d: "M16 17H8", key: "z1uh3a" }]
7360
+ ]);
7347
7361
  /**
7348
7362
  * @license lucide-react v0.344.0 - ISC
7349
7363
  *
@@ -7355,6 +7369,18 @@ const Globe = createLucideIcon("Globe", [
7355
7369
  ["path", { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", key: "13o1zl" }],
7356
7370
  ["path", { d: "M2 12h20", key: "9i4pu4" }]
7357
7371
  ]);
7372
+ /**
7373
+ * @license lucide-react v0.344.0 - ISC
7374
+ *
7375
+ * This source code is licensed under the ISC license.
7376
+ * See the LICENSE file in the root directory of this source tree.
7377
+ */
7378
+ const Hash = createLucideIcon("Hash", [
7379
+ ["line", { x1: "4", x2: "20", y1: "9", y2: "9", key: "4lhtct" }],
7380
+ ["line", { x1: "4", x2: "20", y1: "15", y2: "15", key: "vyu0kd" }],
7381
+ ["line", { x1: "10", x2: "8", y1: "3", y2: "21", key: "1ggp8o" }],
7382
+ ["line", { x1: "16", x2: "14", y1: "3", y2: "21", key: "weycgp" }]
7383
+ ]);
7358
7384
  /**
7359
7385
  * @license lucide-react v0.344.0 - ISC
7360
7386
  *
@@ -15403,7 +15429,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
15403
15429
  }
15404
15430
  );
15405
15431
  };
15406
- const FileComponent = React$1.lazy(() => import("./index-4edbb171.js"));
15432
+ const FileComponent = React$1.lazy(() => import("./index-03cae849.js"));
15407
15433
  function convertFileElement(domNode) {
15408
15434
  if (domNode instanceof HTMLDivElement) {
15409
15435
  const dataUrl = domNode.getAttribute("data-lexical-file-src");
@@ -20560,10 +20586,10 @@ const PDF_CONFIG = {
20560
20586
  };
20561
20587
  const loadHtml2Pdf = async () => {
20562
20588
  try {
20563
- const mod = await import("./html2pdf.bundle.min-382f2ad4.js").then((n) => n.h);
20589
+ const mod = await import("./html2pdf.bundle.min-d2f5d9cb.js").then((n) => n.h);
20564
20590
  return (mod == null ? void 0 : mod.default) || mod;
20565
20591
  } catch {
20566
- const mod2 = await import("./html2pdf.bundle-08dfd2d4.js").then((n) => n.h);
20592
+ const mod2 = await import("./html2pdf.bundle-0e71462c.js").then((n) => n.h);
20567
20593
  return (mod2 == null ? void 0 : mod2.default) || mod2;
20568
20594
  }
20569
20595
  };
@@ -31834,6 +31860,554 @@ const LocalStoragePlugin = ({ namespace }) => {
31834
31860
  return null;
31835
31861
  };
31836
31862
  const LocalStoragePlugin$1 = LocalStoragePlugin;
31863
+ const HORIZONTAL_RULE_PATTERNS = /^(---|___|\*\*\*)$/;
31864
+ const HEADING_PATTERN = /^(#{1,6})\s$/;
31865
+ const BULLET_LIST_PATTERN = /^(\*|-|\+)\s$/;
31866
+ const NUMBERED_LIST_PATTERN = /^(\d+)[\.\)]\s$/;
31867
+ const CHECKLIST_PATTERN = /^\[(x|\s)?\]\s$/i;
31868
+ const QUOTE_PATTERN = /^>\s$/;
31869
+ const CODE_BLOCK_PATTERN = /^```$/;
31870
+ function getLineTextBeforeCursor(editor) {
31871
+ let text = null;
31872
+ editor.getEditorState().read(() => {
31873
+ const selection = $getSelection();
31874
+ if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
31875
+ return;
31876
+ }
31877
+ const anchor = selection.anchor;
31878
+ const anchorNode = anchor.getNode();
31879
+ if (!$isTextNode(anchorNode)) {
31880
+ return;
31881
+ }
31882
+ const textContent = anchorNode.getTextContent();
31883
+ const offset2 = anchor.offset;
31884
+ text = textContent.slice(0, offset2);
31885
+ });
31886
+ return text;
31887
+ }
31888
+ function isAtBlockStart(editor, triggerLength) {
31889
+ let result = false;
31890
+ editor.getEditorState().read(() => {
31891
+ const selection = $getSelection();
31892
+ if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
31893
+ return;
31894
+ }
31895
+ const anchor = selection.anchor;
31896
+ const anchorNode = anchor.getNode();
31897
+ const parent = anchorNode.getParent();
31898
+ if (!parent || parent.getType() !== "paragraph") {
31899
+ return;
31900
+ }
31901
+ const children = parent.getChildren();
31902
+ if (children.length === 1 && children[0] === anchorNode) {
31903
+ const textContent = anchorNode.getTextContent();
31904
+ if (textContent.length === triggerLength) {
31905
+ result = true;
31906
+ }
31907
+ }
31908
+ });
31909
+ return result;
31910
+ }
31911
+ function isInsideListItem(node) {
31912
+ let current = node.getParent();
31913
+ while (current !== null) {
31914
+ if ($isListItemNode(current)) {
31915
+ return true;
31916
+ }
31917
+ current = current.getParent();
31918
+ }
31919
+ return false;
31920
+ }
31921
+ function handleHorizontalRule(editor) {
31922
+ const text = getLineTextBeforeCursor(editor);
31923
+ if (!text || !HORIZONTAL_RULE_PATTERNS.test(text)) {
31924
+ return false;
31925
+ }
31926
+ if (!isAtBlockStart(editor, text.length)) {
31927
+ return false;
31928
+ }
31929
+ editor.update(() => {
31930
+ const selection = $getSelection();
31931
+ if (!$isRangeSelection(selection))
31932
+ return;
31933
+ const anchorNode = selection.anchor.getNode();
31934
+ const parent = anchorNode.getParent();
31935
+ if (parent && parent.getType() === "paragraph") {
31936
+ editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, void 0);
31937
+ parent.remove();
31938
+ }
31939
+ });
31940
+ return true;
31941
+ }
31942
+ function handleHeading(editor) {
31943
+ const text = getLineTextBeforeCursor(editor);
31944
+ if (!text)
31945
+ return false;
31946
+ const match = text.match(HEADING_PATTERN);
31947
+ if (!match)
31948
+ return false;
31949
+ let isValidContext = false;
31950
+ editor.getEditorState().read(() => {
31951
+ const selection = $getSelection();
31952
+ if (!$isRangeSelection(selection))
31953
+ return;
31954
+ const anchorNode = selection.anchor.getNode();
31955
+ if (!$isTextNode(anchorNode))
31956
+ return;
31957
+ const parent = anchorNode.getParent();
31958
+ if (!parent || parent.getType() !== "paragraph")
31959
+ return;
31960
+ if (isInsideListItem(parent))
31961
+ return;
31962
+ const children = parent.getChildren();
31963
+ if (children.length !== 1 || children[0] !== anchorNode)
31964
+ return;
31965
+ const fullText = anchorNode.getTextContent();
31966
+ const headingMatch = fullText.match(HEADING_PATTERN);
31967
+ if (headingMatch && headingMatch.index === 0) {
31968
+ isValidContext = true;
31969
+ }
31970
+ });
31971
+ if (!isValidContext) {
31972
+ return false;
31973
+ }
31974
+ const level = match[1].length;
31975
+ const tag = `h${level}`;
31976
+ editor.update(() => {
31977
+ const selection = $getSelection();
31978
+ if (!$isRangeSelection(selection))
31979
+ return;
31980
+ const anchorNode = selection.anchor.getNode();
31981
+ if (!$isTextNode(anchorNode))
31982
+ return;
31983
+ const parent = anchorNode.getParent();
31984
+ if (parent && parent.getType() === "paragraph") {
31985
+ const fullText = anchorNode.getTextContent();
31986
+ const remainingText = fullText.slice(match[0].length);
31987
+ const headingNode = $createHeadingNode(tag);
31988
+ if (remainingText) {
31989
+ headingNode.append($createTextNode(remainingText));
31990
+ }
31991
+ parent.replace(headingNode);
31992
+ headingNode.selectEnd();
31993
+ }
31994
+ });
31995
+ return true;
31996
+ }
31997
+ function handleBulletList(editor) {
31998
+ const text = getLineTextBeforeCursor(editor);
31999
+ if (!text || !BULLET_LIST_PATTERN.test(text)) {
32000
+ return false;
32001
+ }
32002
+ let isValidContext = false;
32003
+ editor.getEditorState().read(() => {
32004
+ const selection = $getSelection();
32005
+ if (!$isRangeSelection(selection))
32006
+ return;
32007
+ const anchorNode = selection.anchor.getNode();
32008
+ if (!$isTextNode(anchorNode))
32009
+ return;
32010
+ const parent = anchorNode.getParent();
32011
+ if (!parent || parent.getType() !== "paragraph")
32012
+ return;
32013
+ if (isInsideListItem(parent))
32014
+ return;
32015
+ const children = parent.getChildren();
32016
+ if (children.length !== 1 || children[0] !== anchorNode)
32017
+ return;
32018
+ const fullText = anchorNode.getTextContent();
32019
+ const match = fullText.match(BULLET_LIST_PATTERN);
32020
+ if (match && match.index === 0) {
32021
+ isValidContext = true;
32022
+ }
32023
+ });
32024
+ if (!isValidContext) {
32025
+ return false;
32026
+ }
32027
+ editor.update(() => {
32028
+ const selection = $getSelection();
32029
+ if (!$isRangeSelection(selection))
32030
+ return;
32031
+ const anchorNode = selection.anchor.getNode();
32032
+ if (!$isTextNode(anchorNode))
32033
+ return;
32034
+ const parent = anchorNode.getParent();
32035
+ if (parent && parent.getType() === "paragraph") {
32036
+ const fullText = anchorNode.getTextContent();
32037
+ const match = text.match(BULLET_LIST_PATTERN);
32038
+ const remainingText = match ? fullText.slice(match[0].length) : "";
32039
+ const listNode = $createListNode("bullet");
32040
+ const listItemNode = $createListItemNode();
32041
+ if (remainingText) {
32042
+ listItemNode.append($createTextNode(remainingText));
32043
+ }
32044
+ listNode.append(listItemNode);
32045
+ parent.replace(listNode);
32046
+ listItemNode.selectEnd();
32047
+ }
32048
+ });
32049
+ return true;
32050
+ }
32051
+ function handleNumberedList(editor) {
32052
+ const text = getLineTextBeforeCursor(editor);
32053
+ if (!text || !NUMBERED_LIST_PATTERN.test(text)) {
32054
+ return false;
32055
+ }
32056
+ let isValidContext = false;
32057
+ editor.getEditorState().read(() => {
32058
+ const selection = $getSelection();
32059
+ if (!$isRangeSelection(selection))
32060
+ return;
32061
+ const anchorNode = selection.anchor.getNode();
32062
+ if (!$isTextNode(anchorNode))
32063
+ return;
32064
+ const parent = anchorNode.getParent();
32065
+ if (!parent || parent.getType() !== "paragraph")
32066
+ return;
32067
+ if (isInsideListItem(parent))
32068
+ return;
32069
+ const children = parent.getChildren();
32070
+ if (children.length !== 1 || children[0] !== anchorNode)
32071
+ return;
32072
+ const fullText = anchorNode.getTextContent();
32073
+ const match = fullText.match(NUMBERED_LIST_PATTERN);
32074
+ if (match && match.index === 0) {
32075
+ isValidContext = true;
32076
+ }
32077
+ });
32078
+ if (!isValidContext) {
32079
+ return false;
32080
+ }
32081
+ editor.update(() => {
32082
+ const selection = $getSelection();
32083
+ if (!$isRangeSelection(selection))
32084
+ return;
32085
+ const anchorNode = selection.anchor.getNode();
32086
+ if (!$isTextNode(anchorNode))
32087
+ return;
32088
+ const parent = anchorNode.getParent();
32089
+ if (parent && parent.getType() === "paragraph") {
32090
+ const fullText = anchorNode.getTextContent();
32091
+ const match = text.match(NUMBERED_LIST_PATTERN);
32092
+ const remainingText = match ? fullText.slice(match[0].length) : "";
32093
+ const listNode = $createListNode("number");
32094
+ const listItemNode = $createListItemNode();
32095
+ if (remainingText) {
32096
+ listItemNode.append($createTextNode(remainingText));
32097
+ }
32098
+ listNode.append(listItemNode);
32099
+ parent.replace(listNode);
32100
+ listItemNode.selectEnd();
32101
+ }
32102
+ });
32103
+ return true;
32104
+ }
32105
+ function handleChecklist(editor) {
32106
+ const text = getLineTextBeforeCursor(editor);
32107
+ if (!text || !CHECKLIST_PATTERN.test(text)) {
32108
+ return false;
32109
+ }
32110
+ let isValidContext = false;
32111
+ editor.getEditorState().read(() => {
32112
+ const selection = $getSelection();
32113
+ if (!$isRangeSelection(selection))
32114
+ return;
32115
+ const anchorNode = selection.anchor.getNode();
32116
+ if (!$isTextNode(anchorNode))
32117
+ return;
32118
+ const parent = anchorNode.getParent();
32119
+ if (!parent || parent.getType() !== "paragraph")
32120
+ return;
32121
+ if (isInsideListItem(parent))
32122
+ return;
32123
+ const children = parent.getChildren();
32124
+ if (children.length !== 1 || children[0] !== anchorNode)
32125
+ return;
32126
+ const fullText = anchorNode.getTextContent();
32127
+ const match = fullText.match(CHECKLIST_PATTERN);
32128
+ if (match && match.index === 0) {
32129
+ isValidContext = true;
32130
+ }
32131
+ });
32132
+ if (!isValidContext) {
32133
+ return false;
32134
+ }
32135
+ editor.update(() => {
32136
+ const selection = $getSelection();
32137
+ if (!$isRangeSelection(selection))
32138
+ return;
32139
+ const anchorNode = selection.anchor.getNode();
32140
+ if (!$isTextNode(anchorNode))
32141
+ return;
32142
+ const parent = anchorNode.getParent();
32143
+ if (parent && parent.getType() === "paragraph") {
32144
+ const fullText = anchorNode.getTextContent();
32145
+ const match = text.match(CHECKLIST_PATTERN);
32146
+ const remainingText = match ? fullText.slice(match[0].length) : "";
32147
+ const listNode = $createListNode("check");
32148
+ const listItemNode = $createListItemNode();
32149
+ if (remainingText) {
32150
+ listItemNode.append($createTextNode(remainingText));
32151
+ }
32152
+ listNode.append(listItemNode);
32153
+ parent.replace(listNode);
32154
+ listItemNode.selectEnd();
32155
+ }
32156
+ });
32157
+ return true;
32158
+ }
32159
+ function handleQuote(editor) {
32160
+ const text = getLineTextBeforeCursor(editor);
32161
+ if (!text || !QUOTE_PATTERN.test(text)) {
32162
+ return false;
32163
+ }
32164
+ let isValidContext = false;
32165
+ editor.getEditorState().read(() => {
32166
+ const selection = $getSelection();
32167
+ if (!$isRangeSelection(selection))
32168
+ return;
32169
+ const anchorNode = selection.anchor.getNode();
32170
+ if (!$isTextNode(anchorNode))
32171
+ return;
32172
+ const parent = anchorNode.getParent();
32173
+ if (!parent || parent.getType() !== "paragraph")
32174
+ return;
32175
+ if (isInsideListItem(parent))
32176
+ return;
32177
+ const children = parent.getChildren();
32178
+ if (children.length !== 1 || children[0] !== anchorNode)
32179
+ return;
32180
+ const fullText = anchorNode.getTextContent();
32181
+ const match = fullText.match(QUOTE_PATTERN);
32182
+ if (match && match.index === 0) {
32183
+ isValidContext = true;
32184
+ }
32185
+ });
32186
+ if (!isValidContext) {
32187
+ return false;
32188
+ }
32189
+ editor.update(() => {
32190
+ const selection = $getSelection();
32191
+ if (!$isRangeSelection(selection))
32192
+ return;
32193
+ const anchorNode = selection.anchor.getNode();
32194
+ if (!$isTextNode(anchorNode))
32195
+ return;
32196
+ const parent = anchorNode.getParent();
32197
+ if (parent && parent.getType() === "paragraph") {
32198
+ const fullText = anchorNode.getTextContent();
32199
+ const match = text.match(QUOTE_PATTERN);
32200
+ const remainingText = match ? fullText.slice(match[0].length) : "";
32201
+ const quoteNode = $createQuoteNode();
32202
+ if (remainingText) {
32203
+ quoteNode.append($createTextNode(remainingText));
32204
+ }
32205
+ parent.replace(quoteNode);
32206
+ quoteNode.selectEnd();
32207
+ }
32208
+ });
32209
+ return true;
32210
+ }
32211
+ function handleCodeBlock(editor) {
32212
+ const text = getLineTextBeforeCursor(editor);
32213
+ if (!text || !CODE_BLOCK_PATTERN.test(text)) {
32214
+ return false;
32215
+ }
32216
+ if (!isAtBlockStart(editor, text.length)) {
32217
+ return false;
32218
+ }
32219
+ editor.update(() => {
32220
+ const selection = $getSelection();
32221
+ if (!$isRangeSelection(selection))
32222
+ return;
32223
+ const anchorNode = selection.anchor.getNode();
32224
+ const parent = anchorNode.getParent();
32225
+ if (parent && parent.getType() === "paragraph") {
32226
+ const codeNode = $createCodeNode();
32227
+ parent.replace(codeNode);
32228
+ const paragraphNode = $createParagraphNode();
32229
+ codeNode.insertAfter(paragraphNode);
32230
+ codeNode.selectEnd();
32231
+ }
32232
+ });
32233
+ return true;
32234
+ }
32235
+ function handleMarkdownShortcuts(editor) {
32236
+ if (handleHorizontalRule(editor))
32237
+ return true;
32238
+ if (handleHeading(editor))
32239
+ return true;
32240
+ if (handleBulletList(editor))
32241
+ return true;
32242
+ if (handleNumberedList(editor))
32243
+ return true;
32244
+ if (handleChecklist(editor))
32245
+ return true;
32246
+ if (handleQuote(editor))
32247
+ return true;
32248
+ if (handleCodeBlock(editor))
32249
+ return true;
32250
+ return false;
32251
+ }
32252
+ function MarkdownShortcutsPlugin() {
32253
+ const [editor] = useLexicalComposerContext();
32254
+ useEffect$1(() => {
32255
+ const removeTextListener = editor.registerTextContentListener(() => {
32256
+ const text = getLineTextBeforeCursor(editor);
32257
+ if (text && HORIZONTAL_RULE_PATTERNS.test(text)) {
32258
+ setTimeout(() => {
32259
+ handleHorizontalRule(editor);
32260
+ }, 0);
32261
+ }
32262
+ });
32263
+ const removeEnterListener = editor.registerCommand(
32264
+ KEY_ENTER_COMMAND,
32265
+ (event) => {
32266
+ const handled = handleMarkdownShortcuts(editor);
32267
+ if (handled && event) {
32268
+ event.preventDefault();
32269
+ return true;
32270
+ }
32271
+ return false;
32272
+ },
32273
+ COMMAND_PRIORITY_HIGH
32274
+ );
32275
+ const removeBackspaceListener = editor.registerCommand(
32276
+ KEY_BACKSPACE_COMMAND,
32277
+ (event) => {
32278
+ const selection = $getSelection();
32279
+ if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
32280
+ return false;
32281
+ }
32282
+ const anchor = selection.anchor;
32283
+ const anchorNode = anchor.getNode();
32284
+ if (anchor.offset !== 0) {
32285
+ return false;
32286
+ }
32287
+ let listItem = null;
32288
+ let current = anchorNode;
32289
+ while (current !== null) {
32290
+ if ($isListItemNode(current)) {
32291
+ listItem = current;
32292
+ break;
32293
+ }
32294
+ current = current.getParent();
32295
+ }
32296
+ if (!listItem) {
32297
+ return false;
32298
+ }
32299
+ const listItemChildren = listItem.getChildren();
32300
+ let isAtStart = false;
32301
+ if (listItemChildren.length === 0) {
32302
+ isAtStart = true;
32303
+ } else {
32304
+ const firstChild = listItemChildren[0];
32305
+ if (firstChild === anchorNode) {
32306
+ isAtStart = true;
32307
+ } else {
32308
+ const firstChildType = firstChild.getType();
32309
+ if (firstChildType === "paragraph" || firstChildType === "heading") {
32310
+ const parent = anchorNode.getParent();
32311
+ if (parent && parent === firstChild) {
32312
+ const siblings = parent.getChildren();
32313
+ if (siblings.length > 0 && siblings[0] === anchorNode) {
32314
+ isAtStart = true;
32315
+ } else if (siblings.length === 0) {
32316
+ isAtStart = true;
32317
+ }
32318
+ }
32319
+ }
32320
+ }
32321
+ }
32322
+ if (isAtStart) {
32323
+ const listNode = listItem.getParent();
32324
+ if (listNode && $isListNode(listNode)) {
32325
+ const paragraphNode = $createParagraphNode();
32326
+ const children = listItem.getChildren();
32327
+ for (const child of children) {
32328
+ const childType = child.getType();
32329
+ if (childType === "paragraph" || childType === "heading") {
32330
+ const elementChild = child;
32331
+ const innerChildren = elementChild.getChildren();
32332
+ for (const innerChild of innerChildren) {
32333
+ paragraphNode.append(innerChild);
32334
+ }
32335
+ } else {
32336
+ paragraphNode.append(child);
32337
+ }
32338
+ }
32339
+ const listChildren = listNode.getChildren();
32340
+ const isFirstItem = listChildren.length > 0 && listChildren[0] === listItem;
32341
+ if (isFirstItem) {
32342
+ listNode.insertBefore(paragraphNode);
32343
+ } else {
32344
+ listItem.insertBefore(paragraphNode);
32345
+ }
32346
+ listItem.remove();
32347
+ if (listNode.getChildrenSize() === 0) {
32348
+ listNode.remove();
32349
+ }
32350
+ paragraphNode.selectEnd();
32351
+ }
32352
+ if (event) {
32353
+ event.preventDefault();
32354
+ }
32355
+ return true;
32356
+ }
32357
+ return false;
32358
+ },
32359
+ COMMAND_PRIORITY_HIGH
32360
+ );
32361
+ const removeUpdateListener = editor.registerUpdateListener(
32362
+ ({ editorState, tags }) => {
32363
+ if (tags.has("history-merge"))
32364
+ return;
32365
+ editorState.read(() => {
32366
+ const selection = $getSelection();
32367
+ if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
32368
+ return;
32369
+ }
32370
+ const text = getLineTextBeforeCursor(editor);
32371
+ if (!text)
32372
+ return;
32373
+ if (text.endsWith(" ")) {
32374
+ if (HEADING_PATTERN.test(text)) {
32375
+ setTimeout(() => handleHeading(editor), 0);
32376
+ return;
32377
+ }
32378
+ if (BULLET_LIST_PATTERN.test(text)) {
32379
+ setTimeout(() => handleBulletList(editor), 0);
32380
+ return;
32381
+ }
32382
+ if (NUMBERED_LIST_PATTERN.test(text)) {
32383
+ setTimeout(() => handleNumberedList(editor), 0);
32384
+ return;
32385
+ }
32386
+ if (CHECKLIST_PATTERN.test(text)) {
32387
+ setTimeout(() => handleChecklist(editor), 0);
32388
+ return;
32389
+ }
32390
+ if (QUOTE_PATTERN.test(text)) {
32391
+ setTimeout(() => handleQuote(editor), 0);
32392
+ return;
32393
+ }
32394
+ }
32395
+ if (CODE_BLOCK_PATTERN.test(text)) {
32396
+ setTimeout(() => handleCodeBlock(editor), 0);
32397
+ return;
32398
+ }
32399
+ });
32400
+ }
32401
+ );
32402
+ return () => {
32403
+ removeTextListener();
32404
+ removeEnterListener();
32405
+ removeBackspaceListener();
32406
+ removeUpdateListener();
32407
+ };
32408
+ }, [editor]);
32409
+ return null;
32410
+ }
31837
32411
  const index$2 = "";
31838
32412
  const PUNCTUATION = `\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%'"~=<>_:;`;
31839
32413
  const NAME = "\\b[A-Z][^\\s" + PUNCTUATION + "]";
@@ -32012,6 +32586,11 @@ function detectCSSAlignment(element) {
32012
32586
  while (current && current !== document.body) {
32013
32587
  const style = current.style;
32014
32588
  const computedStyle = window.getComputedStyle(current);
32589
+ const floatValue = style.cssFloat || style.float || computedStyle.cssFloat || computedStyle.float;
32590
+ if (floatValue === "left")
32591
+ return "left";
32592
+ if (floatValue === "right")
32593
+ return "right";
32015
32594
  const textAlign = style.textAlign || computedStyle.textAlign;
32016
32595
  if (textAlign === "center")
32017
32596
  return "center";
@@ -32033,29 +32612,52 @@ function detectCSSAlignment(element) {
32033
32612
  }
32034
32613
  return null;
32035
32614
  }
32615
+ const DEFAULT_IMAGE_DIMENSIONS = {
32616
+ // For side-by-side/floated images - smaller default since they share space with text
32617
+ floated: { width: 300, height: 200 },
32618
+ // For centered/standalone images - larger default for prominence
32619
+ centered: { width: 600, height: 400 },
32620
+ // For inline images without explicit layout
32621
+ inline: { width: 400, height: 300 },
32622
+ // Maximum reasonable dimensions to cap oversized images
32623
+ maxWidth: 800,
32624
+ maxHeight: 600
32625
+ };
32036
32626
  function getImageDimensions(imgElement) {
32037
32627
  let width = parseInt(imgElement.getAttribute("width") || "0");
32038
32628
  let height = parseInt(imgElement.getAttribute("height") || "0");
32039
32629
  if (width === 0) {
32040
32630
  const styleWidth = imgElement.style.width;
32041
- if (styleWidth && styleWidth.endsWith("px")) {
32042
- width = parseInt(styleWidth);
32631
+ if (styleWidth) {
32632
+ const parsed = parseInt(styleWidth);
32633
+ if (!isNaN(parsed) && parsed > 0) {
32634
+ width = parsed;
32635
+ }
32043
32636
  }
32044
32637
  }
32045
32638
  if (height === 0) {
32046
32639
  const styleHeight = imgElement.style.height;
32047
- if (styleHeight && styleHeight.endsWith("px")) {
32048
- height = parseInt(styleHeight);
32640
+ if (styleHeight) {
32641
+ const parsed = parseInt(styleHeight);
32642
+ if (!isNaN(parsed) && parsed > 0) {
32643
+ height = parsed;
32644
+ }
32049
32645
  }
32050
32646
  }
32051
32647
  if (width === 0 || height === 0) {
32052
32648
  try {
32053
32649
  const computed = window.getComputedStyle(imgElement);
32054
32650
  if (width === 0 && computed.width && computed.width !== "auto") {
32055
- width = parseInt(computed.width);
32651
+ const parsed = parseInt(computed.width);
32652
+ if (!isNaN(parsed) && parsed > 0) {
32653
+ width = parsed;
32654
+ }
32056
32655
  }
32057
32656
  if (height === 0 && computed.height && computed.height !== "auto") {
32058
- height = parseInt(computed.height);
32657
+ const parsed = parseInt(computed.height);
32658
+ if (!isNaN(parsed) && parsed > 0) {
32659
+ height = parsed;
32660
+ }
32059
32661
  }
32060
32662
  } catch {
32061
32663
  }
@@ -32070,6 +32672,33 @@ function getImageDimensions(imgElement) {
32070
32672
  }
32071
32673
  return { width, height };
32072
32674
  }
32675
+ function getImageDimensionsWithDefaults(imgElement, layoutContext = "inline") {
32676
+ const { width, height } = getImageDimensions(imgElement);
32677
+ if (width > 0 && height > 0) {
32678
+ const aspectRatio = width / height;
32679
+ let finalWidth = width;
32680
+ let finalHeight = height;
32681
+ if (finalWidth > DEFAULT_IMAGE_DIMENSIONS.maxWidth) {
32682
+ finalWidth = DEFAULT_IMAGE_DIMENSIONS.maxWidth;
32683
+ finalHeight = Math.round(finalWidth / aspectRatio);
32684
+ }
32685
+ if (finalHeight > DEFAULT_IMAGE_DIMENSIONS.maxHeight) {
32686
+ finalHeight = DEFAULT_IMAGE_DIMENSIONS.maxHeight;
32687
+ finalWidth = Math.round(finalHeight * aspectRatio);
32688
+ }
32689
+ return { width: finalWidth, height: finalHeight };
32690
+ }
32691
+ if (width > 0) {
32692
+ const cappedWidth = Math.min(width, DEFAULT_IMAGE_DIMENSIONS.maxWidth);
32693
+ return { width: cappedWidth, height: Math.round(cappedWidth * 0.625) };
32694
+ }
32695
+ if (height > 0) {
32696
+ const cappedHeight = Math.min(height, DEFAULT_IMAGE_DIMENSIONS.maxHeight);
32697
+ return { width: Math.round(cappedHeight * 1.6), height: cappedHeight };
32698
+ }
32699
+ const defaults = DEFAULT_IMAGE_DIMENSIONS[layoutContext];
32700
+ return { width: defaults.width, height: defaults.height };
32701
+ }
32073
32702
  function shouldCenterImage(imgElement) {
32074
32703
  var _a;
32075
32704
  const { width, height } = getImageDimensions(imgElement);
@@ -32172,15 +32801,205 @@ function detectClassBasedAlignment(element) {
32172
32801
  }
32173
32802
  return null;
32174
32803
  }
32804
+ function isImageContainerClass(className) {
32805
+ const imagePatterns = [
32806
+ "media",
32807
+ "image",
32808
+ "img",
32809
+ "photo",
32810
+ "picture",
32811
+ "thumbnail",
32812
+ "thumb",
32813
+ "visual",
32814
+ "graphic",
32815
+ "illustration",
32816
+ "figure",
32817
+ "avatar",
32818
+ "hero",
32819
+ "banner",
32820
+ "cover",
32821
+ "poster",
32822
+ "artwork",
32823
+ "gallery",
32824
+ "featured",
32825
+ "wp-block-image",
32826
+ "wp-image",
32827
+ "attachment",
32828
+ "featured-image"
32829
+ ];
32830
+ const lowerClass = className.toLowerCase();
32831
+ return imagePatterns.some((pattern) => lowerClass.includes(pattern));
32832
+ }
32833
+ function detectWordPressAlignment(element) {
32834
+ const className = element.className || "";
32835
+ const lowerClass = className.toLowerCase();
32836
+ if (lowerClass.includes("alignleft") || lowerClass.includes("align-left")) {
32837
+ return "left";
32838
+ }
32839
+ if (lowerClass.includes("alignright") || lowerClass.includes("align-right")) {
32840
+ return "right";
32841
+ }
32842
+ if (lowerClass.includes("aligncenter") || lowerClass.includes("align-center")) {
32843
+ return "center";
32844
+ }
32845
+ if (lowerClass.includes("alignnone") || lowerClass.includes("align-none")) {
32846
+ return "left";
32847
+ }
32848
+ let parent = element.parentElement;
32849
+ let depth = 0;
32850
+ while (parent && depth < 5) {
32851
+ const parentClass = parent.className || "";
32852
+ const parentLower = parentClass.toLowerCase();
32853
+ if (parentLower.includes("alignleft") || parentLower.includes("align-left")) {
32854
+ return "left";
32855
+ }
32856
+ if (parentLower.includes("alignright") || parentLower.includes("align-right")) {
32857
+ return "right";
32858
+ }
32859
+ if (parentLower.includes("aligncenter") || parentLower.includes("align-center")) {
32860
+ return "center";
32861
+ }
32862
+ parent = parent.parentElement;
32863
+ depth++;
32864
+ }
32865
+ return null;
32866
+ }
32867
+ function isContentContainerClass(className) {
32868
+ const contentPatterns = [
32869
+ "content",
32870
+ "text",
32871
+ "body",
32872
+ "copy",
32873
+ "description",
32874
+ "details",
32875
+ "info",
32876
+ "meta",
32877
+ "caption",
32878
+ "excerpt",
32879
+ "summary",
32880
+ "article",
32881
+ "prose",
32882
+ "entry",
32883
+ "post",
32884
+ "main",
32885
+ "primary"
32886
+ ];
32887
+ const lowerClass = className.toLowerCase();
32888
+ return contentPatterns.some((pattern) => lowerClass.includes(pattern));
32889
+ }
32890
+ function containsImage(element) {
32891
+ return element.querySelector("img") !== null || element.tagName.toLowerCase() === "img";
32892
+ }
32893
+ function hasSubstantialTextContent(element) {
32894
+ var _a;
32895
+ const text = ((_a = element.textContent) == null ? void 0 : _a.trim()) || "";
32896
+ return text.length > 30;
32897
+ }
32898
+ function detectBootstrapColumn(element) {
32899
+ const className = element.className || "";
32900
+ const colMatch = className.match(/\bcol(-[a-z]{2})?(-\d+)?\b/);
32901
+ if (!colMatch)
32902
+ return null;
32903
+ const parent = element.parentElement;
32904
+ if (!parent)
32905
+ return null;
32906
+ const parentClass = parent.className || "";
32907
+ if (!parentClass.includes("row"))
32908
+ return null;
32909
+ const siblings = Array.from(parent.children).filter((child) => {
32910
+ const cls = child.className || "";
32911
+ return cls.match(/\bcol(-[a-z]{2})?(-\d+)?\b/);
32912
+ });
32913
+ const index2 = siblings.indexOf(element);
32914
+ if (index2 === -1)
32915
+ return null;
32916
+ return index2 < siblings.length / 2 ? "left" : "right";
32917
+ }
32918
+ function detectSideBySideLayout(imgElement) {
32919
+ const ancestors = [];
32920
+ let current = imgElement;
32921
+ while (current && current !== document.body && ancestors.length < 10) {
32922
+ ancestors.push(current);
32923
+ current = current.parentElement;
32924
+ }
32925
+ for (let i2 = 0; i2 < ancestors.length; i2++) {
32926
+ const ancestor = ancestors[i2];
32927
+ const parent = ancestor.parentElement;
32928
+ if (!parent || parent === document.body)
32929
+ continue;
32930
+ const bootstrapPos = detectBootstrapColumn(ancestor);
32931
+ if (bootstrapPos) {
32932
+ const siblings2 = Array.from(parent.children);
32933
+ const hasContentSibling = siblings2.some((sibling) => {
32934
+ if (sibling === ancestor)
32935
+ return false;
32936
+ return hasSubstantialTextContent(sibling) && !containsImage(sibling);
32937
+ });
32938
+ if (hasContentSibling) {
32939
+ return bootstrapPos;
32940
+ }
32941
+ }
32942
+ const ancestorClass = ancestor.className || "";
32943
+ const isMediaContainer = isImageContainerClass(ancestorClass);
32944
+ if (isMediaContainer) {
32945
+ const siblings2 = Array.from(parent.children).filter((child) => {
32946
+ var _a;
32947
+ const tag = (_a = child.tagName) == null ? void 0 : _a.toLowerCase();
32948
+ return tag !== "script" && tag !== "style" && tag !== "noscript";
32949
+ });
32950
+ if (siblings2.length >= 2) {
32951
+ const ancestorIndex = siblings2.indexOf(ancestor);
32952
+ const contentSiblingIndex = siblings2.findIndex((sibling, index2) => {
32953
+ if (index2 === ancestorIndex)
32954
+ return false;
32955
+ const siblingClass = sibling.className || "";
32956
+ const hasContentClass = isContentContainerClass(siblingClass);
32957
+ const hasText = hasSubstantialTextContent(sibling);
32958
+ const hasNoImage = !containsImage(sibling);
32959
+ return (hasContentClass || hasText) && hasNoImage;
32960
+ });
32961
+ if (contentSiblingIndex !== -1) {
32962
+ return ancestorIndex < contentSiblingIndex ? "left" : "right";
32963
+ }
32964
+ }
32965
+ }
32966
+ const siblings = Array.from(parent.children).filter((child) => {
32967
+ var _a;
32968
+ const tag = (_a = child.tagName) == null ? void 0 : _a.toLowerCase();
32969
+ return tag !== "script" && tag !== "style" && tag !== "noscript" && tag !== "br";
32970
+ });
32971
+ if (siblings.length === 2) {
32972
+ const ancestorIndex = siblings.indexOf(ancestor);
32973
+ if (ancestorIndex !== -1) {
32974
+ const otherSibling = siblings[1 - ancestorIndex];
32975
+ const ancestorHasImage = containsImage(ancestor);
32976
+ const otherHasImage = containsImage(otherSibling);
32977
+ const otherHasText = hasSubstantialTextContent(otherSibling);
32978
+ if (ancestorHasImage && !otherHasImage && otherHasText) {
32979
+ return ancestorIndex === 0 ? "left" : "right";
32980
+ }
32981
+ }
32982
+ }
32983
+ }
32984
+ return null;
32985
+ }
32175
32986
  function detectImageAlignment(imgElement) {
32176
32987
  const classAlignment = detectClassBasedAlignment(imgElement);
32177
32988
  if (classAlignment) {
32178
32989
  return classAlignment;
32179
32990
  }
32991
+ const wpAlignment = detectWordPressAlignment(imgElement);
32992
+ if (wpAlignment) {
32993
+ return wpAlignment;
32994
+ }
32180
32995
  const cssAlignment = detectCSSAlignment(imgElement);
32181
32996
  if (cssAlignment) {
32182
32997
  return cssAlignment;
32183
32998
  }
32999
+ const sideBySideAlignment = detectSideBySideLayout(imgElement);
33000
+ if (sideBySideAlignment) {
33001
+ return sideBySideAlignment;
33002
+ }
32184
33003
  if (shouldCenterImage(imgElement)) {
32185
33004
  return "center";
32186
33005
  }
@@ -32502,7 +33321,7 @@ const defaultPasteContext = {
32502
33321
  };
32503
33322
  let currentPasteContext = defaultPasteContext;
32504
33323
  function processNode(domNode, parentElement = null) {
32505
- var _a;
33324
+ var _a, _b, _c;
32506
33325
  const results = [];
32507
33326
  if (domNode.nodeType === Node.TEXT_NODE) {
32508
33327
  const text = domNode.textContent || "";
@@ -32528,17 +33347,22 @@ function processNode(domNode, parentElement = null) {
32528
33347
  const paragraph = $createParagraphNode();
32529
33348
  const styleInfo = getStyleInfoFromElement(element);
32530
33349
  const hasExplicitFontSize = styleInfo.fontSize && styleInfo.fontSize !== "16px";
33350
+ let overflowNodes = [];
32531
33351
  if (!hasExplicitFontSize && currentPasteContext.isCKEditor) {
32532
33352
  processChildrenWithStyle(element, paragraph, {
32533
33353
  fontSize: DEFAULT_PARAGRAPH_FONT_SIZE,
32534
33354
  lineHeight: DEFAULT_PARAGRAPH_LINE_HEIGHT
32535
33355
  });
32536
33356
  } else {
32537
- processChildren(element, paragraph);
33357
+ const result = processChildrenWithImageSeparation(element, paragraph);
33358
+ overflowNodes = result.overflowNodes;
32538
33359
  }
32539
33360
  if (paragraph.getChildrenSize() > 0 || tagName === "p") {
32540
33361
  results.push(paragraph);
32541
33362
  }
33363
+ if (overflowNodes.length > 0) {
33364
+ results.push(...overflowNodes);
33365
+ }
32542
33366
  break;
32543
33367
  }
32544
33368
  case "h1":
@@ -32601,7 +33425,41 @@ function processNode(domNode, parentElement = null) {
32601
33425
  }
32602
33426
  case "a": {
32603
33427
  const href = element.getAttribute("href") || "";
32604
- if (href) {
33428
+ const containedImg = element.querySelector("img");
33429
+ if (containedImg) {
33430
+ const src = containedImg.getAttribute("src") || "";
33431
+ if (src && !src.startsWith("file:///")) {
33432
+ const alt = containedImg.getAttribute("alt") || "";
33433
+ const alignment = detectImageAlignment(containedImg);
33434
+ const layoutContext = isFloatAlignment(alignment) ? "floated" : alignment === "center" ? "centered" : "inline";
33435
+ const { width, height } = getImageDimensionsWithDefaults(containedImg, layoutContext);
33436
+ const position = alignmentToPosition(alignment);
33437
+ const imageNode = $createImageNode({
33438
+ src,
33439
+ altText: alt,
33440
+ width,
33441
+ height,
33442
+ position: isFloatAlignment(alignment) ? position : "none",
33443
+ linkUrl: href
33444
+ // Store the original link URL
33445
+ });
33446
+ if (alignment === "center") {
33447
+ const paragraph = $createParagraphNode();
33448
+ paragraph.setFormat("center");
33449
+ paragraph.append(imageNode);
33450
+ results.push(paragraph);
33451
+ } else {
33452
+ results.push(imageNode);
33453
+ }
33454
+ }
33455
+ const textContent = (_a = element.textContent) == null ? void 0 : _a.replace(containedImg.alt || "", "").trim();
33456
+ if (textContent && textContent.length > 0) {
33457
+ const linkNode = $createLinkNode(href, { target: "_blank", rel: "noopener" });
33458
+ const textNode = $createTextNode(textContent);
33459
+ linkNode.append(textNode);
33460
+ results.push(linkNode);
33461
+ }
33462
+ } else if (href) {
32605
33463
  const linkNode = $createLinkNode(href, { target: "_blank", rel: "noopener" });
32606
33464
  processChildren(element, linkNode);
32607
33465
  results.push(linkNode);
@@ -32615,9 +33473,9 @@ function processNode(domNode, parentElement = null) {
32615
33473
  const src = element.getAttribute("src") || "";
32616
33474
  if (src && !src.startsWith("file:///")) {
32617
33475
  const alt = element.getAttribute("alt") || "";
32618
- const width = parseInt(element.getAttribute("width") || "0") || void 0;
32619
- const height = parseInt(element.getAttribute("height") || "0") || void 0;
32620
33476
  const alignment = detectImageAlignment(element);
33477
+ const layoutContext = isFloatAlignment(alignment) ? "floated" : alignment === "center" ? "centered" : "inline";
33478
+ const { width, height } = getImageDimensionsWithDefaults(element, layoutContext);
32621
33479
  const position = alignmentToPosition(alignment);
32622
33480
  const imageNode = $createImageNode({
32623
33481
  src,
@@ -32648,13 +33506,13 @@ function processNode(domNode, parentElement = null) {
32648
33506
  const position = alignmentToPosition(alignment);
32649
33507
  const isFloat = isFloatAlignment(alignment);
32650
33508
  const figcaption = element.querySelector("figcaption");
32651
- const captionText = ((_a = figcaption == null ? void 0 : figcaption.textContent) == null ? void 0 : _a.trim()) || "";
33509
+ const captionText = ((_b = figcaption == null ? void 0 : figcaption.textContent) == null ? void 0 : _b.trim()) || "";
32652
33510
  if (img) {
32653
33511
  const src = img.getAttribute("src") || "";
32654
33512
  if (src && !src.startsWith("file:///")) {
32655
33513
  const alt = img.getAttribute("alt") || "";
32656
- const width = parseInt(img.getAttribute("width") || "0") || void 0;
32657
- const height = parseInt(img.getAttribute("height") || "0") || void 0;
33514
+ const layoutContext = isFloat ? "floated" : alignment === "center" ? "centered" : "inline";
33515
+ const { width, height } = getImageDimensionsWithDefaults(img, layoutContext);
32658
33516
  const imageNode = $createImageNode({
32659
33517
  src,
32660
33518
  altText: alt,
@@ -32693,6 +33551,43 @@ function processNode(domNode, parentElement = null) {
32693
33551
  }
32694
33552
  break;
32695
33553
  }
33554
+ case "code": {
33555
+ const className = element.className || "";
33556
+ const isBlockCode = className.includes("PlaygroundEditorTheme__code") || className.includes("code-block") || element.hasAttribute("data-language") || element.hasAttribute("data-highlight-language");
33557
+ if (isBlockCode) {
33558
+ const language = element.getAttribute("data-language") || element.getAttribute("data-highlight-language") || void 0;
33559
+ const codeNode = $createCodeNode(language);
33560
+ const textContent = element.textContent || "";
33561
+ if (textContent) {
33562
+ codeNode.append($createTextNode(textContent));
33563
+ }
33564
+ results.push(codeNode);
33565
+ } else {
33566
+ const children = processChildren(element);
33567
+ results.push(...children);
33568
+ }
33569
+ break;
33570
+ }
33571
+ case "pre": {
33572
+ const codeChild = element.querySelector("code");
33573
+ if (codeChild) {
33574
+ const language = codeChild.getAttribute("data-language") || codeChild.getAttribute("data-highlight-language") || ((_c = codeChild.className.match(/language-(\w+)/)) == null ? void 0 : _c[1]) || void 0;
33575
+ const codeNode = $createCodeNode(language);
33576
+ const textContent = codeChild.textContent || "";
33577
+ if (textContent) {
33578
+ codeNode.append($createTextNode(textContent));
33579
+ }
33580
+ results.push(codeNode);
33581
+ } else {
33582
+ const codeNode = $createCodeNode();
33583
+ const textContent = element.textContent || "";
33584
+ if (textContent) {
33585
+ codeNode.append($createTextNode(textContent));
33586
+ }
33587
+ results.push(codeNode);
33588
+ }
33589
+ break;
33590
+ }
32696
33591
  case "strong":
32697
33592
  case "b":
32698
33593
  case "em":
@@ -32701,7 +33596,6 @@ function processNode(domNode, parentElement = null) {
32701
33596
  case "s":
32702
33597
  case "strike":
32703
33598
  case "del":
32704
- case "code":
32705
33599
  case "sub":
32706
33600
  case "sup":
32707
33601
  case "mark":
@@ -32749,6 +33643,60 @@ function processChildren(element, parentNode) {
32749
33643
  }
32750
33644
  return results;
32751
33645
  }
33646
+ function processChildrenWithImageSeparation(element, parentNode) {
33647
+ const overflowNodes = [];
33648
+ let hasTextContent = false;
33649
+ const childNodes = element.childNodes;
33650
+ for (let i2 = 0; i2 < childNodes.length; i2++) {
33651
+ const child = childNodes[i2];
33652
+ if (child.nodeType === Node.ELEMENT_NODE) {
33653
+ const childElement = child;
33654
+ const tagName = childElement.tagName.toLowerCase();
33655
+ if (tagName === "img") {
33656
+ if (hasTextContent) {
33657
+ const nodes2 = processNode(child, element);
33658
+ nodes2.forEach((node) => {
33659
+ if ($isImageNode(node)) {
33660
+ const imageParagraph = $createParagraphNode();
33661
+ imageParagraph.append(node);
33662
+ overflowNodes.push(imageParagraph);
33663
+ } else if (node instanceof ParagraphNode) {
33664
+ overflowNodes.push(node);
33665
+ } else {
33666
+ overflowNodes.push(node);
33667
+ }
33668
+ });
33669
+ continue;
33670
+ }
33671
+ }
33672
+ }
33673
+ const nodes = processNode(child, element);
33674
+ nodes.forEach((node) => {
33675
+ if ($isTextNode(node) && node.getTextContent().trim().length > 0) {
33676
+ hasTextContent = true;
33677
+ }
33678
+ if ($isImageNode(node) && hasTextContent) {
33679
+ const imageParagraph = $createParagraphNode();
33680
+ imageParagraph.append(node);
33681
+ overflowNodes.push(imageParagraph);
33682
+ } else if (node instanceof ParagraphNode && hasTextContent) {
33683
+ const children = node.getChildren();
33684
+ const hasOnlyImage = children.length === 1 && $isImageNode(children[0]);
33685
+ if (hasOnlyImage) {
33686
+ overflowNodes.push(node);
33687
+ } else {
33688
+ parentNode.append(node);
33689
+ }
33690
+ } else {
33691
+ parentNode.append(node);
33692
+ if ($isTextNode(node) && node.getTextContent().trim().length > 0) {
33693
+ hasTextContent = true;
33694
+ }
33695
+ }
33696
+ });
33697
+ }
33698
+ return { overflowNodes };
33699
+ }
32752
33700
  function processChildrenWithStyle(element, parentNode, defaultStyles) {
32753
33701
  const childNodes = element.childNodes;
32754
33702
  for (let i2 = 0; i2 < childNodes.length; i2++) {
@@ -33017,56 +33965,7 @@ function RichTextPastePlugin() {
33017
33965
  return true;
33018
33966
  });
33019
33967
  if (filteredNodes.length > 0) {
33020
- const anchorNode = selection.anchor.getNode();
33021
- const anchorParent = anchorNode.getParent();
33022
- const isInsideParagraphWithContent = anchorParent instanceof ElementNode && anchorParent.getType() === "paragraph" && anchorParent.getTextContent().trim().length > 0;
33023
- if (isInsideParagraphWithContent) {
33024
- for (const node of filteredNodes) {
33025
- if ($isImageNode(node)) {
33026
- const currentSelection = $getSelection();
33027
- if ($isRangeSelection(currentSelection)) {
33028
- const currentAnchor = currentSelection.anchor.getNode();
33029
- const currentParent = currentAnchor.getParent();
33030
- if (currentParent instanceof ElementNode && currentParent.getType() === "paragraph") {
33031
- const imageParagraph = $createParagraphNode();
33032
- imageParagraph.append(node);
33033
- currentParent.insertAfter(imageParagraph);
33034
- imageParagraph.selectEnd();
33035
- } else {
33036
- currentSelection.insertNodes([node]);
33037
- }
33038
- }
33039
- } else if (node instanceof ParagraphNode) {
33040
- const children = node.getChildren();
33041
- const hasOnlyImage = children.length === 1 && $isImageNode(children[0]);
33042
- if (hasOnlyImage) {
33043
- const currentSelection = $getSelection();
33044
- if ($isRangeSelection(currentSelection)) {
33045
- const currentAnchor = currentSelection.anchor.getNode();
33046
- const currentParent = currentAnchor.getParent();
33047
- if (currentParent instanceof ElementNode && currentParent.getType() === "paragraph") {
33048
- currentParent.insertAfter(node);
33049
- node.selectEnd();
33050
- } else {
33051
- currentSelection.insertNodes([node]);
33052
- }
33053
- }
33054
- } else {
33055
- const currentSelection = $getSelection();
33056
- if ($isRangeSelection(currentSelection)) {
33057
- currentSelection.insertNodes([node]);
33058
- }
33059
- }
33060
- } else {
33061
- const currentSelection = $getSelection();
33062
- if ($isRangeSelection(currentSelection)) {
33063
- currentSelection.insertNodes([node]);
33064
- }
33065
- }
33066
- }
33067
- } else {
33068
- selection.insertNodes(filteredNodes);
33069
- }
33968
+ selection.insertNodes(filteredNodes);
33070
33969
  }
33071
33970
  }
33072
33971
  } catch (error) {
@@ -33087,6 +33986,651 @@ function RichTextPastePlugin() {
33087
33986
  }, [editor]);
33088
33987
  return null;
33089
33988
  }
33989
+ function htmlContainsImages(html) {
33990
+ if (!html)
33991
+ return false;
33992
+ return /<img\s/i.test(html) || /data:image\//i.test(html);
33993
+ }
33994
+ function PasteOptionsMenu({
33995
+ position,
33996
+ currentMode,
33997
+ onSelectMode,
33998
+ onClose,
33999
+ hasHtml
34000
+ }) {
34001
+ const menuRef = useRef(null);
34002
+ const [isOpen, setIsOpen] = useState$1(false);
34003
+ const [menuPosition, setMenuPosition] = useState$1(position);
34004
+ useEffect$1(() => {
34005
+ setMenuPosition(position);
34006
+ }, [position]);
34007
+ useEffect$1(() => {
34008
+ const handleClickOutside = (e) => {
34009
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
34010
+ onClose();
34011
+ }
34012
+ };
34013
+ document.addEventListener("mousedown", handleClickOutside);
34014
+ return () => document.removeEventListener("mousedown", handleClickOutside);
34015
+ }, [onClose]);
34016
+ const allOptions = [
34017
+ {
34018
+ mode: "rich",
34019
+ label: "Use rich text",
34020
+ icon: /* @__PURE__ */ jsx(Type, { className: "cteditor-size-4" })
34021
+ },
34022
+ {
34023
+ mode: "markdown",
34024
+ label: "Use Markdown",
34025
+ icon: /* @__PURE__ */ jsx(Hash, { className: "cteditor-size-4" })
34026
+ },
34027
+ {
34028
+ mode: "plain",
34029
+ label: "Use plain text",
34030
+ icon: /* @__PURE__ */ jsx(FileText, { className: "cteditor-size-4" })
34031
+ }
34032
+ ];
34033
+ const options = hasHtml ? allOptions : allOptions.filter((option) => option.mode !== "rich");
34034
+ const currentOption = options.find((o) => o.mode === currentMode);
34035
+ const menuStyle = {
34036
+ position: "fixed",
34037
+ left: Math.min(menuPosition.x, window.innerWidth - 200),
34038
+ top: Math.min(menuPosition.y + 5, window.innerHeight - 150),
34039
+ zIndex: 1e3
34040
+ };
34041
+ return /* @__PURE__ */ jsxs("div", { ref: menuRef, style: menuStyle, className: "cteditor-relative", children: [
34042
+ /* @__PURE__ */ jsxs(
34043
+ "button",
34044
+ {
34045
+ onClick: () => setIsOpen(!isOpen),
34046
+ className: "cteditor-flex cteditor-items-center cteditor-gap-1.5 cteditor-px-2 cteditor-py-1 cteditor-text-xs cteditor-bg-background cteditor-border cteditor-border-border cteditor-rounded-md cteditor-shadow-lg hover:cteditor-bg-accent cteditor-transition-colors",
34047
+ children: [
34048
+ currentOption == null ? void 0 : currentOption.icon,
34049
+ /* @__PURE__ */ jsx(
34050
+ ChevronDown,
34051
+ {
34052
+ className: `cteditor-size-3 cteditor-transition-transform ${isOpen ? "cteditor-rotate-180" : ""}`
34053
+ }
34054
+ )
34055
+ ]
34056
+ }
34057
+ ),
34058
+ isOpen && /* @__PURE__ */ jsx("div", { className: "cteditor-absolute cteditor-top-full cteditor-left-0 cteditor-mt-1 cteditor-w-44 cteditor-bg-background cteditor-border cteditor-border-border cteditor-rounded-md cteditor-shadow-xl cteditor-overflow-hidden", children: options.map((option) => /* @__PURE__ */ jsxs(
34059
+ "button",
34060
+ {
34061
+ onClick: () => {
34062
+ onSelectMode(option.mode);
34063
+ setIsOpen(false);
34064
+ },
34065
+ className: `cteditor-w-full cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-px-3 cteditor-py-2 cteditor-text-xs hover:cteditor-bg-accent cteditor-transition-colors ${currentMode === option.mode ? "cteditor-bg-primary/10 cteditor-text-primary" : ""}`,
34066
+ children: [
34067
+ option.icon,
34068
+ /* @__PURE__ */ jsx("span", { className: "cteditor-flex-1 cteditor-text-left", children: option.label }),
34069
+ currentMode === option.mode && /* @__PURE__ */ jsx(Check, { className: "cteditor-size-3 cteditor-text-primary" })
34070
+ ]
34071
+ },
34072
+ option.mode
34073
+ )) })
34074
+ ] });
34075
+ }
34076
+ function processInlineMarkdown(text) {
34077
+ if (!text) {
34078
+ return [];
34079
+ }
34080
+ const nodes = [];
34081
+ const tripleBacktickPattern = /```([^`]+)```/g;
34082
+ if (tripleBacktickPattern.test(text)) {
34083
+ tripleBacktickPattern.lastIndex = 0;
34084
+ let lastIndex = 0;
34085
+ let match;
34086
+ while ((match = tripleBacktickPattern.exec(text)) !== null) {
34087
+ if (match.index > lastIndex) {
34088
+ const beforeText = text.slice(lastIndex, match.index);
34089
+ const beforeNodes = processSimpleInlineMarkdown(beforeText);
34090
+ nodes.push(...beforeNodes);
34091
+ }
34092
+ const codeContent = match[1];
34093
+ const codeNode = $createTextNode(codeContent);
34094
+ codeNode.toggleFormat("code");
34095
+ nodes.push(codeNode);
34096
+ lastIndex = match.index + match[0].length;
34097
+ }
34098
+ if (lastIndex < text.length) {
34099
+ const afterText = text.slice(lastIndex);
34100
+ const afterNodes = processSimpleInlineMarkdown(afterText);
34101
+ nodes.push(...afterNodes);
34102
+ }
34103
+ return nodes;
34104
+ }
34105
+ return processSimpleInlineMarkdown(text);
34106
+ }
34107
+ function processSimpleInlineMarkdown(text) {
34108
+ if (!text) {
34109
+ return [];
34110
+ }
34111
+ let processedText = text;
34112
+ let hasBold = false;
34113
+ let hasItalic = false;
34114
+ let hasCode = false;
34115
+ let hasStrikethrough = false;
34116
+ if (/\*\*(.+?)\*\*/.test(processedText)) {
34117
+ hasBold = true;
34118
+ processedText = processedText.replace(/\*\*(.+?)\*\*/g, "$1");
34119
+ }
34120
+ if (/__(.+?)__/.test(processedText)) {
34121
+ hasBold = true;
34122
+ processedText = processedText.replace(/__(.+?)__/g, "$1");
34123
+ }
34124
+ if (!hasBold && /^\*([^*]+)\*$/.test(processedText)) {
34125
+ hasItalic = true;
34126
+ processedText = processedText.replace(/^\*([^*]+)\*$/, "$1");
34127
+ } else if (/(?:^|[^*])\*([^*]+)\*(?:[^*]|$)/.test(processedText)) {
34128
+ hasItalic = true;
34129
+ processedText = processedText.replace(/\*([^*]+)\*/g, "$1");
34130
+ }
34131
+ if (!hasBold && /^_([^_]+)_$/.test(processedText)) {
34132
+ hasItalic = true;
34133
+ processedText = processedText.replace(/^_([^_]+)_$/, "$1");
34134
+ } else if (/(?:^|[^_])_([^_]+)_(?:[^_]|$)/.test(processedText)) {
34135
+ hasItalic = true;
34136
+ processedText = processedText.replace(/_([^_]+)_/g, "$1");
34137
+ }
34138
+ if (new RegExp("(?<!`)`([^`]+)`(?!`)").test(processedText)) {
34139
+ hasCode = true;
34140
+ processedText = processedText.replace(new RegExp("(?<!`)`([^`]+)`(?!`)", "g"), "$1");
34141
+ }
34142
+ if (/~~(.+?)~~/.test(processedText)) {
34143
+ hasStrikethrough = true;
34144
+ processedText = processedText.replace(/~~(.+?)~~/g, "$1");
34145
+ }
34146
+ processedText = processedText.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
34147
+ const textNode = $createTextNode(processedText);
34148
+ if (hasBold)
34149
+ textNode.toggleFormat("bold");
34150
+ if (hasItalic)
34151
+ textNode.toggleFormat("italic");
34152
+ if (hasCode)
34153
+ textNode.toggleFormat("code");
34154
+ if (hasStrikethrough)
34155
+ textNode.toggleFormat("strikethrough");
34156
+ return [textNode];
34157
+ }
34158
+ function convertMarkdownToNodes(text, editor) {
34159
+ const nodes = [];
34160
+ const lines = text.split("\n");
34161
+ let i2 = 0;
34162
+ while (i2 < lines.length) {
34163
+ const line = lines[i2];
34164
+ if (line.trim() === "") {
34165
+ i2++;
34166
+ continue;
34167
+ }
34168
+ if (/^(---|___|\*\*\*)$/.test(line.trim())) {
34169
+ const placeholder = $createParagraphNode();
34170
+ placeholder.append($createTextNode("___MARKDOWN_HR___"));
34171
+ nodes.push(placeholder);
34172
+ i2++;
34173
+ continue;
34174
+ }
34175
+ const singleLineCodeMatch = line.trim().match(/^```(.+?)```$/);
34176
+ if (singleLineCodeMatch) {
34177
+ const codeContent = singleLineCodeMatch[1];
34178
+ const codeNode = $createCodeNode();
34179
+ codeNode.append($createTextNode(codeContent));
34180
+ nodes.push(codeNode);
34181
+ const afterParagraph = $createParagraphNode();
34182
+ nodes.push(afterParagraph);
34183
+ i2++;
34184
+ continue;
34185
+ }
34186
+ if (line.trim().startsWith("```")) {
34187
+ const codeLines = [];
34188
+ const langMatch = line.trim().match(/^```(\w*)$/);
34189
+ i2++;
34190
+ while (i2 < lines.length && !lines[i2].trim().startsWith("```")) {
34191
+ codeLines.push(lines[i2]);
34192
+ i2++;
34193
+ }
34194
+ if (i2 < lines.length)
34195
+ i2++;
34196
+ const codeNode = $createCodeNode((langMatch == null ? void 0 : langMatch[1]) || void 0);
34197
+ codeNode.append($createTextNode(codeLines.join("\n")));
34198
+ nodes.push(codeNode);
34199
+ const afterParagraph = $createParagraphNode();
34200
+ nodes.push(afterParagraph);
34201
+ continue;
34202
+ }
34203
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
34204
+ if (headingMatch) {
34205
+ const level = headingMatch[1].length;
34206
+ const headingNode = $createHeadingNode(
34207
+ `h${level}`
34208
+ );
34209
+ const textNodes2 = processInlineMarkdown(headingMatch[2].trim());
34210
+ textNodes2.forEach((node) => headingNode.append(node));
34211
+ nodes.push(headingNode);
34212
+ i2++;
34213
+ continue;
34214
+ }
34215
+ if (/^[*\-+]\s+/.test(line)) {
34216
+ const listNode = $createListNode("bullet");
34217
+ while (i2 < lines.length && /^[*\-+]\s+/.test(lines[i2])) {
34218
+ const listItemNode = $createListItemNode();
34219
+ const itemText = lines[i2].replace(/^[*\-+]\s+/, "");
34220
+ if (itemText) {
34221
+ const textNodes2 = processInlineMarkdown(itemText);
34222
+ if (textNodes2.length > 0) {
34223
+ textNodes2.forEach((node) => listItemNode.append(node));
34224
+ } else {
34225
+ listItemNode.append($createTextNode(itemText));
34226
+ }
34227
+ }
34228
+ listNode.append(listItemNode);
34229
+ i2++;
34230
+ }
34231
+ nodes.push(listNode);
34232
+ continue;
34233
+ }
34234
+ if (/^\d+[.)]\s+/.test(line)) {
34235
+ const listNode = $createListNode("number");
34236
+ while (i2 < lines.length && /^\d+[.)]\s+/.test(lines[i2])) {
34237
+ const listItemNode = $createListItemNode();
34238
+ const itemText = lines[i2].replace(/^\d+[.)]\s+/, "");
34239
+ if (itemText) {
34240
+ const textNodes2 = processInlineMarkdown(itemText);
34241
+ if (textNodes2.length > 0) {
34242
+ textNodes2.forEach((node) => listItemNode.append(node));
34243
+ } else {
34244
+ listItemNode.append($createTextNode(itemText));
34245
+ }
34246
+ }
34247
+ listNode.append(listItemNode);
34248
+ i2++;
34249
+ }
34250
+ nodes.push(listNode);
34251
+ continue;
34252
+ }
34253
+ if (/^\[(x|\s)?\]\s+/i.test(line)) {
34254
+ const listNode = $createListNode("check");
34255
+ while (i2 < lines.length && /^\[(x|\s)?\]\s+/i.test(lines[i2])) {
34256
+ const listItemNode = $createListItemNode();
34257
+ const isChecked = /^\[x\]/i.test(lines[i2]);
34258
+ const itemText = lines[i2].replace(/^\[(x|\s)?\]\s+/i, "");
34259
+ if (itemText) {
34260
+ const textNodes2 = processInlineMarkdown(itemText);
34261
+ if (textNodes2.length > 0) {
34262
+ textNodes2.forEach((node) => listItemNode.append(node));
34263
+ } else {
34264
+ listItemNode.append($createTextNode(itemText));
34265
+ }
34266
+ }
34267
+ if (isChecked) {
34268
+ listItemNode.setChecked(true);
34269
+ }
34270
+ listNode.append(listItemNode);
34271
+ i2++;
34272
+ }
34273
+ nodes.push(listNode);
34274
+ continue;
34275
+ }
34276
+ if (/^>\s*/.test(line)) {
34277
+ const quoteNode = $createQuoteNode();
34278
+ const quoteLines = [];
34279
+ while (i2 < lines.length && /^>\s*/.test(lines[i2])) {
34280
+ quoteLines.push(lines[i2].replace(/^>\s*/, ""));
34281
+ i2++;
34282
+ }
34283
+ const quoteText = quoteLines.join("\n");
34284
+ if (quoteText) {
34285
+ const textNodes2 = processInlineMarkdown(quoteText);
34286
+ if (textNodes2.length > 0) {
34287
+ textNodes2.forEach((node) => quoteNode.append(node));
34288
+ } else {
34289
+ quoteNode.append($createTextNode(quoteText));
34290
+ }
34291
+ }
34292
+ nodes.push(quoteNode);
34293
+ continue;
34294
+ }
34295
+ const paragraph = $createParagraphNode();
34296
+ const textNodes = processInlineMarkdown(line);
34297
+ textNodes.forEach((node) => paragraph.append(node));
34298
+ nodes.push(paragraph);
34299
+ i2++;
34300
+ }
34301
+ return nodes;
34302
+ }
34303
+ function convertPlainTextToNodes(text) {
34304
+ const nodes = [];
34305
+ const paragraphs = text.split(/\n\n+/);
34306
+ for (const para of paragraphs) {
34307
+ if (para.trim() || para === "") {
34308
+ const paragraph = $createParagraphNode();
34309
+ const lines = para.split(/\n/);
34310
+ lines.forEach((line, index2) => {
34311
+ if (line) {
34312
+ paragraph.append($createTextNode(line));
34313
+ }
34314
+ if (index2 < lines.length - 1) {
34315
+ paragraph.append($createLineBreakNode());
34316
+ }
34317
+ });
34318
+ if (paragraph.getChildrenSize() > 0) {
34319
+ nodes.push(paragraph);
34320
+ }
34321
+ }
34322
+ }
34323
+ if (nodes.length === 0) {
34324
+ nodes.push($createParagraphNode());
34325
+ }
34326
+ return nodes;
34327
+ }
34328
+ function applyMarkdownToNodes(nodes, _editor) {
34329
+ const processTextNode = (node) => {
34330
+ const text = node.getTextContent();
34331
+ const style = node.getStyle();
34332
+ const format = node.getFormat();
34333
+ const markdownPattern = new RegExp("(```([^`]+)```)|(`([^`]+)`)|(\\*\\*(.+?)\\*\\*)|((?<!\\*)\\*([^*]+)\\*(?!\\*))|(~~(.+?)~~)", "g");
34334
+ if (!markdownPattern.test(text)) {
34335
+ return [node];
34336
+ }
34337
+ markdownPattern.lastIndex = 0;
34338
+ const resultNodes = [];
34339
+ let lastIndex = 0;
34340
+ let match;
34341
+ while ((match = markdownPattern.exec(text)) !== null) {
34342
+ if (match.index > lastIndex) {
34343
+ const beforeText = text.slice(lastIndex, match.index);
34344
+ const beforeNode = $createTextNode(beforeText);
34345
+ if (style)
34346
+ beforeNode.setStyle(style);
34347
+ if (format)
34348
+ beforeNode.setFormat(format);
34349
+ resultNodes.push(beforeNode);
34350
+ }
34351
+ let content = "";
34352
+ let nodeFormat = format;
34353
+ if (match[1]) {
34354
+ content = match[2];
34355
+ nodeFormat = format | 16;
34356
+ } else if (match[3]) {
34357
+ content = match[4];
34358
+ nodeFormat = format | 16;
34359
+ } else if (match[5]) {
34360
+ content = match[6];
34361
+ nodeFormat = format | 1;
34362
+ } else if (match[7]) {
34363
+ content = match[8];
34364
+ nodeFormat = format | 2;
34365
+ } else if (match[9]) {
34366
+ content = match[10];
34367
+ nodeFormat = format | 4;
34368
+ }
34369
+ if (content) {
34370
+ const formattedNode = $createTextNode(content);
34371
+ if (style)
34372
+ formattedNode.setStyle(style);
34373
+ formattedNode.setFormat(nodeFormat);
34374
+ resultNodes.push(formattedNode);
34375
+ }
34376
+ lastIndex = match.index + match[0].length;
34377
+ }
34378
+ if (lastIndex < text.length) {
34379
+ const afterText = text.slice(lastIndex);
34380
+ const afterNode = $createTextNode(afterText);
34381
+ if (style)
34382
+ afterNode.setStyle(style);
34383
+ if (format)
34384
+ afterNode.setFormat(format);
34385
+ resultNodes.push(afterNode);
34386
+ }
34387
+ return resultNodes.length > 0 ? resultNodes : [node];
34388
+ };
34389
+ const processNode2 = (node) => {
34390
+ if ($isElementNode(node)) {
34391
+ const children = node.getChildren();
34392
+ for (let i2 = children.length - 1; i2 >= 0; i2--) {
34393
+ const child = children[i2];
34394
+ if ($isTextNode(child)) {
34395
+ const replacementNodes = processTextNode(child);
34396
+ if (replacementNodes.length > 1 || replacementNodes[0] !== child) {
34397
+ for (const newNode of replacementNodes) {
34398
+ child.insertBefore(newNode);
34399
+ }
34400
+ child.remove();
34401
+ }
34402
+ } else if ($isElementNode(child)) {
34403
+ processNode2(child);
34404
+ }
34405
+ }
34406
+ }
34407
+ };
34408
+ nodes.forEach((node) => processNode2(node));
34409
+ return nodes;
34410
+ }
34411
+ function getNodeDOMPosition(editor) {
34412
+ const domSelection = window.getSelection();
34413
+ if (!domSelection || domSelection.rangeCount === 0) {
34414
+ return null;
34415
+ }
34416
+ const range = domSelection.getRangeAt(0);
34417
+ let rect = range.getBoundingClientRect();
34418
+ if (rect.width === 0 && rect.height === 0) {
34419
+ const anchorNode = domSelection.anchorNode;
34420
+ if (anchorNode) {
34421
+ const element = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;
34422
+ if (element) {
34423
+ rect = element.getBoundingClientRect();
34424
+ }
34425
+ }
34426
+ }
34427
+ if (rect.right === 0 && rect.bottom === 0) {
34428
+ const rootElement = editor.getRootElement();
34429
+ if (rootElement) {
34430
+ const rootRect = rootElement.getBoundingClientRect();
34431
+ return {
34432
+ x: rootRect.left + 20,
34433
+ y: Math.min(rootRect.top + 100, window.innerHeight - 150)
34434
+ };
34435
+ }
34436
+ return null;
34437
+ }
34438
+ return {
34439
+ x: rect.right,
34440
+ y: rect.bottom
34441
+ };
34442
+ }
34443
+ function handleHorizontalRulePlaceholders(editor) {
34444
+ editor.update(
34445
+ () => {
34446
+ const root2 = $getRoot();
34447
+ const children = root2.getChildren();
34448
+ for (const child of children) {
34449
+ if ($isParagraphNode(child)) {
34450
+ const textContent = child.getTextContent();
34451
+ if (textContent === "___MARKDOWN_HR___") {
34452
+ editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, void 0);
34453
+ child.remove();
34454
+ }
34455
+ }
34456
+ }
34457
+ },
34458
+ { tag: "paste-options" }
34459
+ );
34460
+ }
34461
+ function PasteOptionsPlugin() {
34462
+ const [editor] = useLexicalComposerContext();
34463
+ const [pasteData, setPasteData] = useState$1(null);
34464
+ const [currentMode, setCurrentMode] = useState$1("rich");
34465
+ const [showMenu, setShowMenu] = useState$1(false);
34466
+ const [menuPosition, setMenuPosition] = useState$1({ x: 0, y: 0 });
34467
+ useEffect$1(() => {
34468
+ if (!showMenu)
34469
+ return;
34470
+ const handleScroll2 = () => {
34471
+ const newPosition = getNodeDOMPosition(editor);
34472
+ if (newPosition) {
34473
+ setMenuPosition(newPosition);
34474
+ setPasteData(
34475
+ (prev) => prev ? { ...prev, position: newPosition } : null
34476
+ );
34477
+ }
34478
+ };
34479
+ window.addEventListener("scroll", handleScroll2, true);
34480
+ return () => window.removeEventListener("scroll", handleScroll2, true);
34481
+ }, [editor, showMenu]);
34482
+ useEffect$1(() => {
34483
+ return editor.registerCommand(
34484
+ KEY_ESCAPE_COMMAND,
34485
+ () => {
34486
+ if (showMenu) {
34487
+ setShowMenu(false);
34488
+ setPasteData(null);
34489
+ return true;
34490
+ }
34491
+ return false;
34492
+ },
34493
+ COMMAND_PRIORITY_CRITICAL
34494
+ );
34495
+ }, [editor, showMenu]);
34496
+ useEffect$1(() => {
34497
+ if (!showMenu)
34498
+ return;
34499
+ const removeListener = editor.registerUpdateListener(
34500
+ ({ tags, dirtyElements, dirtyLeaves }) => {
34501
+ if (!tags.has("paste") && !tags.has("history-merge") && !tags.has("paste-options")) {
34502
+ if (dirtyElements.size > 0 || dirtyLeaves.size > 0) {
34503
+ setShowMenu(false);
34504
+ setPasteData(null);
34505
+ }
34506
+ }
34507
+ }
34508
+ );
34509
+ return removeListener;
34510
+ }, [editor, showMenu]);
34511
+ useEffect$1(() => {
34512
+ const handlePaste = (event) => {
34513
+ const clipboardData = event.clipboardData;
34514
+ if (!clipboardData)
34515
+ return;
34516
+ const html = clipboardData.getData("text/html");
34517
+ const plain = clipboardData.getData("text/plain");
34518
+ if (!html && !plain)
34519
+ return;
34520
+ if (htmlContainsImages(html)) {
34521
+ return;
34522
+ }
34523
+ const isPlainTextPaste = !html && plain;
34524
+ const initialMode = isPlainTextPaste ? "plain" : "rich";
34525
+ setTimeout(() => {
34526
+ editor.getEditorState().read(() => {
34527
+ const selection = $getSelection();
34528
+ if (!$isRangeSelection(selection))
34529
+ return;
34530
+ const position = getNodeDOMPosition(editor);
34531
+ if (!position)
34532
+ return;
34533
+ setPasteData({
34534
+ html,
34535
+ plain,
34536
+ position,
34537
+ initialMode
34538
+ });
34539
+ setCurrentMode(initialMode);
34540
+ setMenuPosition(position);
34541
+ setShowMenu(true);
34542
+ });
34543
+ }, 150);
34544
+ };
34545
+ const rootElement = editor.getRootElement();
34546
+ if (rootElement) {
34547
+ rootElement.addEventListener("paste", handlePaste);
34548
+ return () => rootElement.removeEventListener("paste", handlePaste);
34549
+ }
34550
+ }, [editor]);
34551
+ const handleSelectMode = useCallback(
34552
+ (mode) => {
34553
+ if (!pasteData) {
34554
+ return;
34555
+ }
34556
+ if (mode === currentMode) {
34557
+ setShowMenu(false);
34558
+ setPasteData(null);
34559
+ return;
34560
+ }
34561
+ editor.dispatchCommand(UNDO_COMMAND, void 0);
34562
+ setTimeout(() => {
34563
+ editor.update(
34564
+ () => {
34565
+ const selection = $getSelection();
34566
+ if (!$isRangeSelection(selection))
34567
+ return;
34568
+ let nodes = [];
34569
+ if (mode === "plain") {
34570
+ nodes = convertPlainTextToNodes(pasteData.plain);
34571
+ } else if (mode === "markdown") {
34572
+ if (pasteData.html) {
34573
+ nodes = convertHTMLToNodesWithStyles(pasteData.html, editor);
34574
+ nodes = applyMarkdownToNodes(nodes);
34575
+ } else {
34576
+ nodes = convertMarkdownToNodes(pasteData.plain);
34577
+ }
34578
+ } else if (mode === "rich") {
34579
+ if (pasteData.html) {
34580
+ const parser = new DOMParser();
34581
+ const doc = parser.parseFromString(pasteData.html, "text/html");
34582
+ nodes = $generateNodesFromDOM(editor, doc);
34583
+ } else {
34584
+ nodes = convertPlainTextToNodes(pasteData.plain);
34585
+ }
34586
+ }
34587
+ if (nodes.length > 0) {
34588
+ const filteredNodes = nodes.filter((node) => {
34589
+ const textContent = node.getTextContent();
34590
+ return textContent.trim().length > 0 || node.getType() !== "paragraph";
34591
+ });
34592
+ if (filteredNodes.length > 0) {
34593
+ selection.insertNodes(filteredNodes);
34594
+ } else if (nodes.length > 0) {
34595
+ selection.insertNodes(nodes);
34596
+ }
34597
+ }
34598
+ },
34599
+ { tag: "paste-options" }
34600
+ );
34601
+ if (mode === "markdown") {
34602
+ setTimeout(() => {
34603
+ handleHorizontalRulePlaceholders(editor);
34604
+ }, 50);
34605
+ }
34606
+ }, 50);
34607
+ setCurrentMode(mode);
34608
+ setShowMenu(false);
34609
+ setPasteData(null);
34610
+ },
34611
+ [editor, pasteData, currentMode]
34612
+ );
34613
+ const handleClose = useCallback(() => {
34614
+ setShowMenu(false);
34615
+ setPasteData(null);
34616
+ }, []);
34617
+ if (!showMenu || !pasteData) {
34618
+ return null;
34619
+ }
34620
+ return createPortal(
34621
+ /* @__PURE__ */ jsx(
34622
+ PasteOptionsMenu,
34623
+ {
34624
+ position: menuPosition,
34625
+ currentMode,
34626
+ onSelectMode: handleSelectMode,
34627
+ onClose: handleClose,
34628
+ hasHtml: Boolean(pasteData.html)
34629
+ }
34630
+ ),
34631
+ document.body
34632
+ );
34633
+ }
33090
34634
  function getOptionMeta(label) {
33091
34635
  const lower = label.toLowerCase();
33092
34636
  if (lower.startsWith("paragraph"))
@@ -34721,6 +36265,7 @@ function TableActionMenu({
34721
36265
  },
34722
36266
  [editor, tableCellNode]
34723
36267
  );
36268
+ const menuItemClass = " cteditor-group cteditor-flex cteditor-items-center cteditor-gap-1.5 cteditor-px-2 cteditor-py-1 cteditor-rounded-sm cteditor-transition-all cteditor-duration-200 cteditor-cursor-pointer cteditor-text-xs hover:cteditor-bg-foreground/10";
34724
36269
  let mergeCellButton = null;
34725
36270
  if (cellMerge) {
34726
36271
  if (canMergeCells) {
@@ -34728,10 +36273,10 @@ function TableActionMenu({
34728
36273
  "button",
34729
36274
  {
34730
36275
  type: "button",
34731
- className: "item",
36276
+ className: menuItemClass,
34732
36277
  onClick: () => mergeTableCellsAtSelection(),
34733
36278
  "data-test-id": "table-merge-cells",
34734
- children: /* @__PURE__ */ jsx("span", { className: "cteditor-text-[11px] cteditor-text-muted-foreground cteditor-font-medium cteditor-tracking-wider cteditor-block cteditor-pb-1", children: "Merge cells" })
36279
+ children: /* @__PURE__ */ jsx("span", { className: "text", children: "Merge cells" })
34735
36280
  }
34736
36281
  );
34737
36282
  } else if (canUnmergeCell) {
@@ -34739,15 +36284,14 @@ function TableActionMenu({
34739
36284
  "button",
34740
36285
  {
34741
36286
  type: "button",
34742
- className: "item",
36287
+ className: menuItemClass,
34743
36288
  onClick: () => unmergeTableCellsAtSelection(),
34744
36289
  "data-test-id": "table-unmerge-cells",
34745
- children: /* @__PURE__ */ jsx("span", { className: "cteditor-text-[11px] cteditor-text-muted-foreground cteditor-font-medium cteditor-tracking-wider cteditor-block cteditor-pb-1", children: "Unmerge cells" })
36290
+ children: /* @__PURE__ */ jsx("span", { className: "text", children: "Unmerge cells" })
34746
36291
  }
34747
36292
  );
34748
36293
  }
34749
36294
  }
34750
- const menuItemClass = " cteditor-group cteditor-flex cteditor-items-center cteditor-gap-1.5 cteditor-px-2 cteditor-py-1 cteditor-rounded-sm cteditor-transition-all cteditor-duration-200 cteditor-cursor-pointer cteditor-text-xs hover:cteditor-bg-foreground/10";
34751
36295
  return createPortal(
34752
36296
  /* @__PURE__ */ jsxs(
34753
36297
  "div",
@@ -37419,9 +38963,57 @@ function processHtmlForExport(html, tableStyleMap, codeBlockStyles) {
37419
38963
  const wrapper = doc.createElement("div");
37420
38964
  wrapper.style.padding = "1em";
37421
38965
  wrapper.style.minHeight = "100%";
38966
+ wrapper.className = "editor-content-wrapper";
38967
+ const styleTag = doc.createElement("style");
38968
+ styleTag.textContent = `
38969
+ /* Responsive image styles - WYSIWYG for mobile */
38970
+ @media screen and (max-width: 768px) {
38971
+ /* Floated images stack on mobile - no text wrap */
38972
+ .image-float-left,
38973
+ .image-float-right,
38974
+ img[style*="float: left"],
38975
+ img[style*="float: right"] {
38976
+ float: none !important;
38977
+ clear: both !important;
38978
+ display: block !important;
38979
+ margin: 1em auto !important;
38980
+ max-width: 100% !important;
38981
+ /* On mobile, allow width to shrink but keep height proportional to width */
38982
+ width: auto !important;
38983
+ height: auto !important;
38984
+ }
38985
+
38986
+ /* Floated image containers (with captions) also stack */
38987
+ .image-float-container,
38988
+ .image-float-container-left,
38989
+ .image-float-container-right,
38990
+ p[style*="float: left"],
38991
+ p[style*="float: right"] {
38992
+ float: none !important;
38993
+ clear: both !important;
38994
+ max-width: 100% !important;
38995
+ margin: 1em 0 !important;
38996
+ }
38997
+
38998
+ /* Clear floats properly */
38999
+ .editor-content-wrapper::after {
39000
+ content: "";
39001
+ display: table;
39002
+ clear: both;
39003
+ }
39004
+ }
39005
+
39006
+ /* Clearfix for floated content */
39007
+ .editor-content-wrapper::after {
39008
+ content: "";
39009
+ display: table;
39010
+ clear: both;
39011
+ }
39012
+ `;
37422
39013
  while (doc.body.firstChild) {
37423
39014
  wrapper.appendChild(doc.body.firstChild);
37424
39015
  }
39016
+ wrapper.insertBefore(styleTag, wrapper.firstChild);
37425
39017
  return wrapper.outerHTML;
37426
39018
  }
37427
39019
  function cleanupHeaderCellStructure(container) {
@@ -37492,12 +39084,21 @@ function applyGenericSafeStyles(container, codeBlockStyles) {
37492
39084
  container.querySelectorAll("img").forEach((img) => {
37493
39085
  const position = img.getAttribute("data-position");
37494
39086
  const parent = img.parentElement;
37495
- img.style.cssText += "; max-width: 100%; height: auto;";
39087
+ const explicitWidth = img.getAttribute("width");
39088
+ const explicitHeight = img.getAttribute("height");
39089
+ const hasExplicitDimensions = explicitWidth && explicitHeight && explicitWidth !== "inherit" && explicitHeight !== "inherit";
39090
+ if (hasExplicitDimensions) {
39091
+ img.style.cssText += `; max-width: 100%; width: ${explicitWidth}px; height: ${explicitHeight}px;`;
39092
+ } else {
39093
+ img.style.cssText += "; max-width: 100%; height: auto;";
39094
+ }
37496
39095
  const hasCaption = parent && parent.tagName.toLowerCase() === "p" && parent.querySelector("em, i");
37497
39096
  if (position === "left" || position === "right") {
37498
39097
  const floatDir = position === "left" ? "left" : "right";
37499
39098
  const marginDir = position === "left" ? "right" : "left";
39099
+ img.classList.add("image-float-" + floatDir);
37500
39100
  if (hasCaption && parent) {
39101
+ parent.classList.add("image-float-container", "image-float-container-" + floatDir);
37501
39102
  parent.style.cssText += `; float: ${floatDir}; clear: ${floatDir}; max-width: 50%; margin-${marginDir}: 1em; margin-bottom: 0.5em; text-align: center; background-color: #f5f5f5; padding: 0.5em; border-radius: 4px;`;
37502
39103
  img.style.cssText += "; display: block; margin: 0 auto;";
37503
39104
  const caption = parent.querySelector("em, i");
@@ -37509,10 +39110,20 @@ function applyGenericSafeStyles(container, codeBlockStyles) {
37509
39110
  }
37510
39111
  } else if (position === "full") {
37511
39112
  img.style.cssText += "; display: block; width: 100%; margin: 1em 0;";
39113
+ } else if (position === "inline-left") {
39114
+ img.classList.add("image-inline-left");
39115
+ img.style.cssText += "; display: block; margin: 1em 0; text-align: left;";
39116
+ } else if (position === "inline-center") {
39117
+ img.classList.add("image-inline-center");
39118
+ img.style.cssText += "; display: block; margin: 1em auto;";
39119
+ } else if (position === "inline-right") {
39120
+ img.classList.add("image-inline-right");
39121
+ img.style.cssText += "; display: block; margin: 1em 0 1em auto;";
37512
39122
  } else {
37513
- img.style.cssText += "; display: block;";
39123
+ img.style.cssText += "; display: inline-block; vertical-align: middle;";
37514
39124
  if (parent && parent.style.textAlign === "center") {
37515
39125
  img.style.margin = "0 auto";
39126
+ img.style.display = "block";
37516
39127
  }
37517
39128
  }
37518
39129
  img.removeAttribute("data-position");
@@ -37864,24 +39475,52 @@ function preprocessInitialContent(html) {
37864
39475
  });
37865
39476
  const images = doc.querySelectorAll("img");
37866
39477
  images.forEach((img) => {
39478
+ const htmlImg = img;
37867
39479
  const parent = img.parentElement;
37868
39480
  if (!parent)
37869
39481
  return;
37870
- const imgFloat = img.style.float;
37871
- const parentFloat = parent.style.float;
37872
- const floatDir = imgFloat || parentFloat;
37873
- if (floatDir === "left" || floatDir === "right") {
37874
- img.setAttribute("data-position", floatDir);
37875
- if (parentFloat && parent.tagName.toLowerCase() === "p") {
37876
- parent.style.textAlign = floatDir;
37877
- parent.style.removeProperty("float");
37878
- parent.style.removeProperty("clear");
37879
- parent.style.removeProperty("max-width");
37880
- parent.style.removeProperty("background-color");
37881
- parent.style.removeProperty("padding");
37882
- parent.style.removeProperty("border-radius");
39482
+ if (htmlImg.classList.contains("image-inline-left")) {
39483
+ img.setAttribute("data-position", "inline-left");
39484
+ htmlImg.classList.remove("image-inline-left");
39485
+ } else if (htmlImg.classList.contains("image-inline-center")) {
39486
+ img.setAttribute("data-position", "inline-center");
39487
+ htmlImg.classList.remove("image-inline-center");
39488
+ } else if (htmlImg.classList.contains("image-inline-right")) {
39489
+ img.setAttribute("data-position", "inline-right");
39490
+ htmlImg.classList.remove("image-inline-right");
39491
+ } else if (htmlImg.classList.contains("image-float-left")) {
39492
+ img.setAttribute("data-position", "left");
39493
+ htmlImg.classList.remove("image-float-left");
39494
+ } else if (htmlImg.classList.contains("image-float-right")) {
39495
+ img.setAttribute("data-position", "right");
39496
+ htmlImg.classList.remove("image-float-right");
39497
+ } else {
39498
+ const imgFloat = htmlImg.style.float;
39499
+ const parentFloat = parent.style.float;
39500
+ const floatDir = imgFloat || parentFloat;
39501
+ if (floatDir === "left" || floatDir === "right") {
39502
+ img.setAttribute("data-position", floatDir);
39503
+ if (parentFloat && parent.tagName.toLowerCase() === "p") {
39504
+ parent.style.textAlign = floatDir;
39505
+ parent.style.removeProperty("float");
39506
+ parent.style.removeProperty("clear");
39507
+ parent.style.removeProperty("max-width");
39508
+ parent.style.removeProperty("background-color");
39509
+ parent.style.removeProperty("padding");
39510
+ parent.style.removeProperty("border-radius");
39511
+ }
39512
+ } else {
39513
+ const margin = htmlImg.style.margin;
39514
+ if (margin === "1em auto" || htmlImg.style.marginLeft === "auto" && htmlImg.style.marginRight === "auto") {
39515
+ img.setAttribute("data-position", "inline-center");
39516
+ } else if (htmlImg.style.marginLeft === "auto" && htmlImg.style.marginRight !== "auto") {
39517
+ img.setAttribute("data-position", "inline-right");
39518
+ }
37883
39519
  }
37884
39520
  }
39521
+ if (parent.classList.contains("image-float-container")) {
39522
+ parent.classList.remove("image-float-container", "image-float-container-left", "image-float-container-right");
39523
+ }
37885
39524
  });
37886
39525
  const styledElements = doc.querySelectorAll("span[style], b[style], strong[style], i[style], em[style]");
37887
39526
  styledElements.forEach((el) => {
@@ -38561,6 +40200,7 @@ const ConfigurableEditor = ({
38561
40200
  /* @__PURE__ */ jsx(CodeBlockNormalizerPlugin, {}),
38562
40201
  /* @__PURE__ */ jsx(CodeBlockSelectAllPlugin, {}),
38563
40202
  /* @__PURE__ */ jsx(SlashCommandPlugin, {}),
40203
+ /* @__PURE__ */ jsx(MarkdownShortcutsPlugin, {}),
38564
40204
  /* @__PURE__ */ jsx(CombinedPluginWrapper, {}),
38565
40205
  /* @__PURE__ */ jsx(OnChangeWrapper, { onChange }),
38566
40206
  /* @__PURE__ */ jsx(InitialContentPlugin, { initialContent }),
@@ -38571,6 +40211,7 @@ const ConfigurableEditor = ({
38571
40211
  /* @__PURE__ */ jsx(LinkPreviewPlugin, {}),
38572
40212
  /* @__PURE__ */ jsx(DragDropPaste, {}),
38573
40213
  /* @__PURE__ */ jsx(RichTextPastePlugin, {}),
40214
+ /* @__PURE__ */ jsx(PasteOptionsPlugin, {}),
38574
40215
  /* @__PURE__ */ jsx(FilePlugin, {}),
38575
40216
  /* @__PURE__ */ jsx(HorizontalRulePlugin, {}),
38576
40217
  /* @__PURE__ */ jsx(CustomHorizontalRulePlugin, {}),
@@ -38759,11 +40400,12 @@ const ConfigurableEditorWithAuth = ({
38759
40400
  };
38760
40401
  export {
38761
40402
  $isFileNode as $,
38762
- AiJsonResponse as A,
40403
+ AlignLeft as A,
38763
40404
  Button as B,
38764
40405
  ConfigurableEditorWithAuth as C,
38765
40406
  Download as D,
38766
40407
  ExternalLink as E,
40408
+ FileText as F,
38767
40409
  HtmlViewProvider as H,
38768
40410
  LocalStoragePlugin$1 as L,
38769
40411
  Sparkles as S,
@@ -38779,12 +40421,16 @@ export {
38779
40421
  DialogFooter as i,
38780
40422
  initialConfig as j,
38781
40423
  $isImageNode as k,
38782
- EditorProvider as l,
38783
- useEditor as m,
38784
- ConfigurableEditor as n,
38785
- editorConfig as o,
40424
+ AlignCenter as l,
40425
+ AlignRight as m,
40426
+ Type as n,
40427
+ AiJsonResponse as o,
40428
+ EditorProvider as p,
40429
+ useEditor as q,
40430
+ ConfigurableEditor as r,
40431
+ editorConfig as s,
38786
40432
  toast as t,
38787
40433
  useHtmlView as u,
38788
40434
  verifyApiKey as v
38789
40435
  };
38790
- //# sourceMappingURL=index-d1d21414.js.map
40436
+ //# sourceMappingURL=index-0533674e.js.map