@ctzhian/tiptap 1.1.2 → 1.2.1

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.
@@ -81,7 +81,7 @@ var Reader = function Reader() {
81
81
  }
82
82
  return onUpload;
83
83
  }(),
84
- content: "<blockquote><p>\u98DE\u673A\u554A\u6B7B\u4E86\u6253\u98DE\u673A\u554A\u6536\u5230\u4E86</p></blockquote><p></p>"
84
+ content: "<p>\u98DE\u673A\u554A\u6536\u5230\u5566\u653E\u5047\u5566\u5927\u6C34\u98DE\u673A\u963F\u62C9\u5C71\u53E3\u7684\u98DE\u673A\u963F\u91CC\u65AF\u987F\u6FC0\u53D1\u4E86\u5F00\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002</p><ul class=\"bullet-list\" data-type=\"bulletList\"><li><p>\u98DE\u673A\u963F\u91CC\u65AF\u987F\u6FC0\u53D1\u62C9\u4E0A\u770B\u89E3\u653E\u62C9\u5361\u4E0A\u98DE\u673A\u62C9\u4E0A\u98DE\u673A\u62C9\u5361\u4E0A\u6253\u98DE\u673A</p></li><li><p>\u53D1\u5723\u8BDE\u8282\u8DEF\u53E3\u53D1\u751F\u89E3\u653E\u4E86\u4E09\u5927\u89E3\u653E\u62C9\u5361\u4E0A\u6253\u98DE\u673A\u62C9\u5C4E</p></li><li><p>\u53D1\u5723\u8BDE\u8282\u8DEF\u53E3\u98DE\u673A\u554A\u6B7B\u4E86\u70B9\u5F00\u98DE\u673A\u963F\u91CC</p></li></ul><p>\u53D1\u5927\u6C34\u516D\u5757\u8179\u808C\u963F\u62C9\u5C71\u53E3\u98DE\u673A\u4E0A\u4E86\u5927\u5F00\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u98DE\u673A\u554A\u6570\u91CF\u98DE\u673A\u554A\u6B7B\u4E86</p><p>\u53D1\u5927\u6C34\u516D\u5757\u8179\u808C\u963F\u62C9\u5C71\u53E3\u98DE\u673A\u4E0A\u4E86\u5927\u5F00\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566</p><blockquote><p>\u53D1\u62C9\u5361\u4E0A\u5927\u89E3\u653E\u62C9\u5C4E\u7684\u98DE\u673A\uFF1B\u963F\u675C\u91CC\u65AF\u89E3\u653E\u770B\u62C9\u4E0A\u5047\u53D1\uFF1B\u5E08\u5085\u3002</p></blockquote><div class=\"cq-alert\" data-id=\"alert_5ahr0ijo1l9\" data-variant=\"info\" data-type=\"icon\" data-node=\"alert\">\u53D1\u751F\u6C5F\u4E1C\u7236\u8001\u770B\u89C1\u554A\u4E0A\uFF1B\u98DE\u673A\u554A\u4E0A\uFF1B\u53D1\u751F\uFF1B\u98DE\u673A\u554A\u4E0A\u6765\u7684\u7684\u98DE\u673A\u554A\u4E0A\u6D6A\u8D39\u3002\u673A\u554A\u4E0A\uFF1B\u53D1\u751F\uFF1B\u98DE\u673A\u554A\u4E0A\u6765\u7684\u98DE\u673A\u554A\u4E0A\u6765\u7684\u98DE\u673A\u554A\u4E0A\u6D6A\u8D39\u3002\u673A\u554A\u4E0A\uFF1B\u53D1\u751F\uFF1B\u98DE\u673A\u554A\u4E0A\u6765\u7684\u98DE\u673A\u554A\u4E0A\u6765\u7684\u98DE\u673A\u554A\u4E0A\u6D6A\u8D39\u3002</div><p>\u98DE\u673A\u554A\u6536\u5230\u5566\u653E\u5047\u5566\u5927\u6C34\u98DE\u673A\u963F\u62C9\u5C71\u53E3\u7684\u98DE\u673A\u963F\u91CC\u65AF\u987F\u6FC0\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002\u53D1\u4E86\u5F00\u59CB\u51CF\u80A5\u554A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u98DE\u673A\u963F\u91CC\u7684\u662F\u98DE\u673A\u963F\u91CC\u65AF\u987F\u98DE\u673A\u5566\u3002</p>"
85
85
  }),
86
86
  editor = _useTiptap.editor;
87
87
  return /*#__PURE__*/React.createElement(EditorThemeProvider, {
@@ -45,7 +45,7 @@ var SelectionText = function SelectionText(_ref) {
45
45
  superscript: editor.isActive('superscript'),
46
46
  subscript: editor.isActive('subscript')
47
47
  });
48
- setHideColor(editor.isActive('code') || editor.isActive('codeBlock') || editor.isActive('inlineMath') || editor.isActive('blockMath'));
48
+ setHideColor(editor.isActive('codeBlock') || editor.isActive('horizontalRule') || editor.isActive('inlineMath') || editor.isActive('blockMath'));
49
49
  };
50
50
  useEffect(function () {
51
51
  editor.on('selectionUpdate', updateSelection);
@@ -69,7 +69,7 @@ var SelectionText = function SelectionText(_ref) {
69
69
  var editorProps = _ref2.editor,
70
70
  from = _ref2.from,
71
71
  to = _ref2.to;
72
- if (editorProps.state.selection.empty || editorProps.isActive('code') || editorProps.isActive('image') || editorProps.isActive('video') || editorProps.isActive('audio') || editorProps.isActive('emoji') || editorProps.isActive('codeBlock') || editorProps.isActive('blockLink') || editorProps.isActive('inlineLink') || editorProps.isActive('blockAttachment') || editorProps.isActive('inlineAttachment')) {
72
+ if (editorProps.state.selection.empty || editorProps.isActive('image') || editorProps.isActive('video') || editorProps.isActive('audio') || editorProps.isActive('emoji') || editorProps.isActive('codeBlock') || editorProps.isActive('blockLink') || editorProps.isActive('inlineLink') || editorProps.isActive('blockAttachment') || editorProps.isActive('inlineAttachment') || editorProps.isActive('horizontalRule')) {
73
73
  return false;
74
74
  }
75
75
  return true;
@@ -17,9 +17,9 @@ import { NODE_TYPE_LABEL, NodeTypeEnum } from "../../contants/enums";
17
17
  import { Box, Divider, Stack, Typography, useTheme } from '@mui/material';
18
18
  import DragHandle from '@tiptap/extension-drag-handle-react';
19
19
  import { Fragment, Slice } from '@tiptap/pm/model';
20
- import { TextSelection } from '@tiptap/pm/state';
20
+ import { NodeSelection } from '@tiptap/pm/state';
21
21
  import React, { useCallback, useState } from 'react';
22
- import { downloadFiles, filterResourcesByType, getAllResources } from "../../util";
22
+ import { convertNodeAt, downloadFiles, filterResourcesByType, getAllResources } from "../../util";
23
23
  import { FileCopyLineIcon } from "../Icons/file-copy-line-icon";
24
24
  import Menu from "../Menu";
25
25
  import { ToolbarItem } from "../Toolbar";
@@ -178,10 +178,13 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
178
178
  state = _current$editor.state,
179
179
  view = _current$editor.view;
180
180
  var tr = state.tr;
181
- var resolved = tr.doc.resolve(Math.min(current.pos + 1, tr.doc.content.size));
182
- tr.setSelection(TextSelection.near(resolved));
183
- view.dispatch(tr);
184
- view.focus();
181
+ var pos = current.pos;
182
+ if (pos >= 0) {
183
+ var selection = NodeSelection.create(tr.doc, pos);
184
+ tr.setSelection(selection);
185
+ view.dispatch(tr);
186
+ view.focus();
187
+ }
185
188
  };
186
189
  var hasMarksDeep = function hasMarksDeep(node) {
187
190
  var _content;
@@ -243,16 +246,6 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
243
246
  vertical: 'top',
244
247
  horizontal: 'left'
245
248
  },
246
- childrenProps: {
247
- anchorOrigin: {
248
- vertical: 'center',
249
- horizontal: 'right'
250
- },
251
- transformOrigin: {
252
- vertical: 'center',
253
- horizontal: 'left'
254
- }
255
- },
256
249
  arrowIcon: /*#__PURE__*/React.createElement(ArrowDownSLineIcon, {
257
250
  sx: {
258
251
  fontSize: '1rem',
@@ -272,7 +265,7 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
272
265
  }].concat(_toConsumableArray(currentNode !== null && currentNode !== void 0 && currentNode.color ? [{
273
266
  key: 'color',
274
267
  label: '颜色',
275
- maxHeight: 480,
268
+ maxHeight: 400,
276
269
  icon: /*#__PURE__*/React.createElement(BrushLineIcon, {
277
270
  sx: {
278
271
  fontSize: '1rem'
@@ -553,7 +546,14 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
553
546
  }
554
547
  }),
555
548
  onClick: function onClick() {
556
- if (current.node && current.pos !== undefined) {
549
+ if (!current.node) return;
550
+ var type = current.node.type.name;
551
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
552
+ if (groupTypes.includes(type)) {
553
+ convertNodeAt(current.editor, current.pos, current.node, {
554
+ type: 'paragraph'
555
+ });
556
+ } else {
557
557
  selectCurrentNode();
558
558
  cancelNodeType();
559
559
  current.editor.commands.setParagraph();
@@ -569,7 +569,15 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
569
569
  }
570
570
  }),
571
571
  onClick: function onClick() {
572
- if (current.node && current.pos !== undefined) {
572
+ if (!current.node) return;
573
+ var type = current.node.type.name;
574
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
575
+ if (groupTypes.includes(type)) {
576
+ convertNodeAt(current.editor, current.pos, current.node, {
577
+ type: 'heading',
578
+ level: 1
579
+ });
580
+ } else {
573
581
  selectCurrentNode();
574
582
  cancelNodeType();
575
583
  current.editor.commands.setHeading({
@@ -587,7 +595,15 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
587
595
  }
588
596
  }),
589
597
  onClick: function onClick() {
590
- if (current.node && current.pos !== undefined) {
598
+ if (!current.node) return;
599
+ var type = current.node.type.name;
600
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
601
+ if (groupTypes.includes(type)) {
602
+ convertNodeAt(current.editor, current.pos, current.node, {
603
+ type: 'heading',
604
+ level: 2
605
+ });
606
+ } else {
591
607
  selectCurrentNode();
592
608
  cancelNodeType();
593
609
  current.editor.commands.setHeading({
@@ -605,7 +621,15 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
605
621
  }
606
622
  }),
607
623
  onClick: function onClick() {
608
- if (current.node && current.pos !== undefined) {
624
+ if (!current.node) return;
625
+ var type = current.node.type.name;
626
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
627
+ if (groupTypes.includes(type)) {
628
+ convertNodeAt(current.editor, current.pos, current.node, {
629
+ type: 'heading',
630
+ level: 3
631
+ });
632
+ } else {
609
633
  selectCurrentNode();
610
634
  cancelNodeType();
611
635
  current.editor.commands.setHeading({
@@ -630,7 +654,14 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
630
654
  }
631
655
  }),
632
656
  onClick: function onClick() {
633
- if (current.node && current.pos !== undefined) {
657
+ if (!current.node) return;
658
+ var type = current.node.type.name;
659
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
660
+ if (groupTypes.includes(type)) {
661
+ convertNodeAt(current.editor, current.pos, current.node, {
662
+ type: 'orderedList'
663
+ });
664
+ } else {
634
665
  selectCurrentNode();
635
666
  cancelNodeType();
636
667
  current.editor.commands.toggleOrderedList();
@@ -646,7 +677,14 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
646
677
  }
647
678
  }),
648
679
  onClick: function onClick() {
649
- if (current.node && current.pos !== undefined) {
680
+ if (!current.node) return;
681
+ var type = current.node.type.name;
682
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
683
+ if (groupTypes.includes(type)) {
684
+ convertNodeAt(current.editor, current.pos, current.node, {
685
+ type: 'bulletList'
686
+ });
687
+ } else {
650
688
  selectCurrentNode();
651
689
  cancelNodeType();
652
690
  current.editor.commands.toggleBulletList();
@@ -662,7 +700,14 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
662
700
  }
663
701
  }),
664
702
  onClick: function onClick() {
665
- if (current.node && current.pos !== undefined) {
703
+ if (!current.node) return;
704
+ var type = current.node.type.name;
705
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
706
+ if (groupTypes.includes(type)) {
707
+ convertNodeAt(current.editor, current.pos, current.node, {
708
+ type: 'taskList'
709
+ });
710
+ } else {
666
711
  selectCurrentNode();
667
712
  cancelNodeType();
668
713
  current.editor.commands.toggleTaskList();
@@ -685,7 +730,14 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
685
730
  }
686
731
  }),
687
732
  onClick: function onClick() {
688
- if (current.node && current.pos !== undefined) {
733
+ if (!current.node) return;
734
+ var type = current.node.type.name;
735
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
736
+ if (groupTypes.includes(type)) {
737
+ convertNodeAt(current.editor, current.pos, current.node, {
738
+ type: 'blockquote'
739
+ });
740
+ } else {
689
741
  selectCurrentNode();
690
742
  cancelNodeType();
691
743
  current.editor.commands.toggleBlockquote();
@@ -701,7 +753,14 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
701
753
  }
702
754
  }),
703
755
  onClick: function onClick() {
704
- if (current.node && current.pos !== undefined) {
756
+ if (!current.node) return;
757
+ var type = current.node.type.name;
758
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
759
+ if (groupTypes.includes(type)) {
760
+ convertNodeAt(current.editor, current.pos, current.node, {
761
+ type: 'codeBlock'
762
+ });
763
+ } else {
705
764
  selectCurrentNode();
706
765
  cancelNodeType();
707
766
  current.editor.commands.toggleCodeBlock();
@@ -717,7 +776,18 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
717
776
  }
718
777
  }),
719
778
  onClick: function onClick() {
720
- if (current.node && current.pos !== undefined) {
779
+ if (!current.node) return;
780
+ var type = current.node.type.name;
781
+ var groupTypes = [NodeTypeEnum.BulletList, NodeTypeEnum.OrderedList, NodeTypeEnum.TaskList, NodeTypeEnum.Blockquote, NodeTypeEnum.CodeBlock, NodeTypeEnum.Alert];
782
+ if (groupTypes.includes(type)) {
783
+ convertNodeAt(current.editor, current.pos, current.node, {
784
+ type: 'alert',
785
+ attrs: {
786
+ variant: 'info',
787
+ type: 'icon'
788
+ }
789
+ });
790
+ } else {
721
791
  selectCurrentNode();
722
792
  cancelNodeType();
723
793
  current.editor.commands.toggleAlert({
@@ -1084,8 +1154,6 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
1084
1154
  var afterPos = current.pos + current.node.nodeSize;
1085
1155
  current.editor.chain().focus().insertContentAt(afterPos, {
1086
1156
  type: 'paragraph'
1087
- }, {
1088
- updateSelection: true
1089
1157
  }).run();
1090
1158
  }
1091
1159
  },
@@ -1099,7 +1167,8 @@ var CustomDragHandle = function CustomDragHandle(_ref2) {
1099
1167
  key: 'insert-divider',
1100
1168
  onClick: function onClick() {
1101
1169
  if (current.node && current.pos !== undefined) {
1102
- current.editor.chain().focus().insertContent({
1170
+ var afterPos = current.pos + current.node.nodeSize;
1171
+ current.editor.chain().focus().insertContentAt(afterPos, {
1103
1172
  type: 'horizontalRule'
1104
1173
  }).run();
1105
1174
  }
@@ -1,9 +1,11 @@
1
+ import { Strategy } from '@floating-ui/dom';
1
2
  import React from 'react';
2
3
  export interface FloatingPopoverProps {
3
4
  open: boolean;
4
5
  anchorEl: HTMLElement | null;
5
6
  onClose: () => void;
6
7
  children: React.ReactNode;
8
+ strategy?: Strategy;
7
9
  placement?: 'top' | 'bottom' | 'left' | 'right';
8
10
  offset?: number;
9
11
  className?: string;
@@ -13,11 +13,14 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
13
13
  import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom';
14
14
  import { Paper } from '@mui/material';
15
15
  import React, { useEffect, useRef, useState } from 'react';
16
+ import { createPortal } from 'react-dom';
16
17
  export var FloatingPopover = function FloatingPopover(_ref) {
17
18
  var open = _ref.open,
18
19
  anchorEl = _ref.anchorEl,
19
20
  onClose = _ref.onClose,
20
21
  children = _ref.children,
22
+ _ref$strategy = _ref.strategy,
23
+ strategy = _ref$strategy === void 0 ? 'absolute' : _ref$strategy,
21
24
  _ref$placement = _ref.placement,
22
25
  placement = _ref$placement === void 0 ? 'bottom' : _ref$placement,
23
26
  _ref$offset = _ref.offset,
@@ -38,6 +41,7 @@ export var FloatingPopover = function FloatingPopover(_ref) {
38
41
  if (!popoverRef.current) return;
39
42
  computePosition(anchorEl, popoverRef.current, {
40
43
  placement: placement,
44
+ strategy: strategy,
41
45
  middleware: [offset(offsetValue), flip(), shift({
42
46
  padding: 8
43
47
  })]
@@ -78,7 +82,7 @@ export var FloatingPopover = function FloatingPopover(_ref) {
78
82
  };
79
83
  }, [open, onClose, anchorEl]);
80
84
  if (!open) return null;
81
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
85
+ return /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
82
86
  style: {
83
87
  position: 'fixed',
84
88
  top: 0,
@@ -92,13 +96,13 @@ export var FloatingPopover = function FloatingPopover(_ref) {
92
96
  ref: popoverRef,
93
97
  className: className,
94
98
  style: _objectSpread({
95
- position: 'absolute',
99
+ position: strategy,
96
100
  left: position.x,
97
101
  top: position.y,
98
102
  zIndex: 1300,
99
103
  borderRadius: 'var(--mui-shape-borderRadius)'
100
104
  }, style),
101
105
  elevation: 8
102
- }, children));
106
+ }, children)), document.body);
103
107
  };
104
108
  export default FloatingPopover;
@@ -35,7 +35,7 @@ var EditorFontSize = function EditorFontSize(_ref) {
35
35
  var headingLevel = headingAttrs.level;
36
36
  switch (headingLevel) {
37
37
  case 1:
38
- fontSize = '28';
38
+ fontSize = '30';
39
39
  break;
40
40
  case 2:
41
41
  fontSize = '24';
@@ -47,10 +47,10 @@ var EditorFontSize = function EditorFontSize(_ref) {
47
47
  fontSize = '18';
48
48
  break;
49
49
  case 5:
50
- fontSize = '16';
50
+ fontSize = '18';
51
51
  break;
52
52
  case 6:
53
- fontSize = '14';
53
+ fontSize = '16';
54
54
  break;
55
55
  default:
56
56
  fontSize = defaultFontSize;
@@ -94,7 +94,7 @@ var LinkViewWrapper = function LinkViewWrapper(_ref) {
94
94
  };
95
95
  var handleDeleteLink = function handleDeleteLink() {
96
96
  editor.commands.deleteNode(node.type);
97
- editor.commands.insertContent("[".concat(attrs.title || getLinkTitle(attrs.href), "](").concat(attrs.href, ")"));
97
+ editor.commands.insertContent(attrs.title || getLinkTitle(attrs.href));
98
98
  };
99
99
  var handleCopyLink = useCallback( /*#__PURE__*/function () {
100
100
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(event) {
@@ -14,6 +14,7 @@ import { CharacterCount, Placeholder } from '@tiptap/extensions';
14
14
  import StarterKit from '@tiptap/starter-kit';
15
15
  import { PLACEHOLDER } from "../contants/placeholder";
16
16
  import { SlashCommands, StructuredDiffExtension } from "./extension";
17
+ import { CodeExtension } from "./mark/Code";
17
18
  import { AlertExtension, AudioExtension, BlockAttachmentExtension, BlockLinkExtension, CodeBlockLowlightExtension, CustomBlockMathExtension, CustomInlineMathExtension, DetailsContentExtension, DetailsExtension, DetailsSummaryExtension, EmojiExtension, FileHandlerExtension, ImageExtension, InlineAttachmentExtension, InlineLinkExtension, ListExtension, MentionExtension, TableExtension, TableOfContents, UploadProgressExtension, VerticalAlign, VideoExtension, YoutubeExtension } from "./node";
18
19
  export var getExtensions = function getExtensions(_ref) {
19
20
  var limit = _ref.limit,
@@ -28,6 +29,7 @@ export var getExtensions = function getExtensions(_ref) {
28
29
  onTocUpdate = _ref.onTocUpdate;
29
30
  var defaultExtensions = [StarterKit.configure({
30
31
  link: false,
32
+ code: false,
31
33
  codeBlock: false,
32
34
  listItem: false,
33
35
  orderedList: false,
@@ -45,7 +47,7 @@ export var getExtensions = function getExtensions(_ref) {
45
47
  defaultAlignment: null
46
48
  }), CodeBlockLowlightExtension, CharacterCount.configure({
47
49
  limit: limit !== null && limit !== void 0 ? limit : null
48
- }), Subscript, Superscript, TextStyleKit, AlertExtension, Highlight.configure({
50
+ }), Subscript, Superscript, TextStyleKit, CodeExtension, AlertExtension, Highlight.configure({
49
51
  multicolor: true
50
52
  }), Placeholder.configure({
51
53
  emptyNodeClass: 'custom-placeholder-node',
@@ -0,0 +1,2 @@
1
+ export declare const CodeExtension: import("@tiptap/core").Mark<import("@tiptap/extension-code").CodeOptions, any>;
2
+ export default CodeExtension;
@@ -0,0 +1,9 @@
1
+ import Code from '@tiptap/extension-code';
2
+
3
+ // 允许与 textStyle 等标记共存,以便字号/颜色等样式可应用到 code 文本
4
+ export var CodeExtension = Code.extend({
5
+ // 默认 `@tiptap/extension-code` 的 excludes 为 '_'(排除所有其他 mark)
6
+ // 这里清空以允许共存,从而让 textStyle 的 fontSize 生效
7
+ excludes: ''
8
+ });
9
+ export default CodeExtension;
package/dist/index.css CHANGED
@@ -11,7 +11,7 @@
11
11
  }
12
12
 
13
13
  .tiptap.ProseMirror :first-child {
14
- margin-top: 0;
14
+ margin-top: 0 !important;
15
15
  }
16
16
 
17
17
  .tiptap.ProseMirror a {
@@ -331,7 +331,6 @@
331
331
  border-bottom: 1px solid var(--mui-palette-divider);
332
332
  border-right: 1px solid transparent;
333
333
  box-sizing: border-box;
334
- min-width: 1rem;
335
334
  padding: 12px 16px;
336
335
  position: relative;
337
336
  vertical-align: top;
@@ -1,2 +1,3 @@
1
+ import { Strategy } from "@floating-ui/dom";
1
2
  import { Editor } from "@tiptap/core";
2
- export declare const updatePosition: (editor: Editor, element: HTMLElement) => void;
3
+ export declare const updatePosition: (editor: Editor, element: HTMLElement, strategy?: Strategy) => void;
@@ -1,6 +1,7 @@
1
1
  import { computePosition, flip, shift } from "@floating-ui/dom";
2
2
  import { posToDOMRect } from "@tiptap/core";
3
3
  export var updatePosition = function updatePosition(editor, element) {
4
+ var strategy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'absolute';
4
5
  var virtualElement = {
5
6
  getBoundingClientRect: function getBoundingClientRect() {
6
7
  return posToDOMRect(editor.view, editor.state.selection.from, editor.state.selection.to);
@@ -8,7 +9,7 @@ export var updatePosition = function updatePosition(editor, element) {
8
9
  };
9
10
  computePosition(virtualElement, element, {
10
11
  placement: 'bottom-start',
11
- strategy: 'absolute',
12
+ strategy: strategy,
12
13
  middleware: [shift(), flip()]
13
14
  }).then(function (_ref) {
14
15
  var x = _ref.x,
@@ -1,6 +1,7 @@
1
1
  export * from './fileDownload';
2
2
  export * from './fileHandler';
3
3
  export * from './floating';
4
+ export * from './linewiseConvert';
4
5
  export * from './migrateMathStrings';
5
6
  export * from './resourceExtractor';
6
7
  export * from './shortcutKey';
@@ -1,6 +1,7 @@
1
1
  export * from "./fileDownload";
2
2
  export * from "./fileHandler";
3
3
  export * from "./floating";
4
+ export * from "./linewiseConvert";
4
5
  export * from "./migrateMathStrings";
5
6
  export * from "./resourceExtractor";
6
7
  export * from "./shortcutKey";
@@ -0,0 +1,42 @@
1
+ import { Fragment, Node as PMNode } from '@tiptap/pm/model';
2
+ import { Editor } from '@tiptap/react';
3
+ export type LinewiseTarget = {
4
+ type: 'paragraph';
5
+ } | {
6
+ type: 'heading';
7
+ level: 1 | 2 | 3 | 4 | 5 | 6;
8
+ } | {
9
+ type: 'orderedList';
10
+ } | {
11
+ type: 'bulletList';
12
+ } | {
13
+ type: 'taskList';
14
+ } | {
15
+ type: 'blockquote';
16
+ } | {
17
+ type: 'codeBlock';
18
+ } | {
19
+ type: 'alert';
20
+ attrs?: {
21
+ variant?: string;
22
+ type?: 'icon' | 'text';
23
+ };
24
+ };
25
+ /**
26
+ * 提取节点的“行”文本:
27
+ * - paragraph/heading:单行
28
+ * - blockquote:子块逐段(按段)
29
+ * - codeBlock:按换行
30
+ * - alert:按换行
31
+ * - list(ordered/bullet/task):每个 listItem 作为一行(包含其文本内容)
32
+ * - 其他:作为单行处理
33
+ */
34
+ export declare function extractLinesFromNode(node: PMNode): string[];
35
+ /**
36
+ * 根据目标类型,构造对应的节点或片段。
37
+ */
38
+ export declare function buildNodeFromLines(editor: Editor, lines: string[], target: LinewiseTarget): PMNode | Fragment;
39
+ /**
40
+ * 将给定位置的节点转换为目标类型(按行规则)。
41
+ */
42
+ export declare function convertNodeAt(editor: Editor, pos: number, node: PMNode, target: LinewiseTarget): void;
@@ -0,0 +1,170 @@
1
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
2
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
5
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
6
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
7
+ import { Fragment } from '@tiptap/pm/model';
8
+ /**
9
+ * 提取节点的“行”文本:
10
+ * - paragraph/heading:单行
11
+ * - blockquote:子块逐段(按段)
12
+ * - codeBlock:按换行
13
+ * - alert:按换行
14
+ * - list(ordered/bullet/task):每个 listItem 作为一行(包含其文本内容)
15
+ * - 其他:作为单行处理
16
+ */
17
+ export function extractLinesFromNode(node) {
18
+ var type = node.type.name;
19
+
20
+ // Helper: split textContent by \n and去除首尾空白但保留空行的结构
21
+ var splitByNewline = function splitByNewline(text) {
22
+ return text.split('\n');
23
+ };
24
+ if (type === 'paragraph' || type === 'heading') {
25
+ return [node.textContent];
26
+ }
27
+ if (type === 'blockquote') {
28
+ var lines = [];
29
+ node.forEach(function (child) {
30
+ var text = child.textContent;
31
+ if (text.includes('\n')) {
32
+ lines.push.apply(lines, _toConsumableArray(splitByNewline(text)));
33
+ } else {
34
+ lines.push(text);
35
+ }
36
+ });
37
+ return lines;
38
+ }
39
+ if (type === 'codeBlock') {
40
+ return splitByNewline(node.textContent);
41
+ }
42
+ if (type === 'alert') {
43
+ return splitByNewline(node.textContent);
44
+ }
45
+ if (type === 'orderedList' || type === 'bulletList' || type === 'taskList') {
46
+ var _lines = [];
47
+ node.forEach(function (listItem) {
48
+ var text = listItem.textContent;
49
+ if (text.includes('\n')) {
50
+ _lines.push.apply(_lines, _toConsumableArray(splitByNewline(text)));
51
+ } else {
52
+ _lines.push(text);
53
+ }
54
+ });
55
+ return _lines;
56
+ }
57
+ return [node.textContent];
58
+ }
59
+
60
+ /**
61
+ * 根据目标类型,构造对应的节点或片段。
62
+ */
63
+ export function buildNodeFromLines(editor, lines, target) {
64
+ var schema = editor.schema;
65
+ var createParagraph = function createParagraph(text) {
66
+ return schema.nodes.paragraph.create(undefined, text ? schema.text(text) : undefined);
67
+ };
68
+ var createHeading = function createHeading(text, level) {
69
+ return schema.nodes.heading.create({
70
+ level: level
71
+ }, text ? schema.text(text) : undefined);
72
+ };
73
+ var createListItem = function createListItem(text) {
74
+ return schema.nodes.listItem.create(undefined, createParagraph(text));
75
+ };
76
+ var createTaskItem = function createTaskItem(text) {
77
+ return schema.nodes.taskItem ? schema.nodes.taskItem.create({
78
+ checked: false
79
+ }, createParagraph(text)) : createListItem(text);
80
+ };
81
+ switch (target.type) {
82
+ case 'paragraph':
83
+ {
84
+ var nodes = lines.map(function (l) {
85
+ return createParagraph(l);
86
+ });
87
+ return Fragment.fromArray(nodes);
88
+ }
89
+ case 'heading':
90
+ {
91
+ var _nodes = lines.map(function (l) {
92
+ return createHeading(l, target.level);
93
+ });
94
+ return Fragment.fromArray(_nodes);
95
+ }
96
+ case 'orderedList':
97
+ {
98
+ var items = lines.map(function (l) {
99
+ return createListItem(l);
100
+ });
101
+ return schema.nodes.orderedList.create(undefined, Fragment.fromArray(items));
102
+ }
103
+ case 'bulletList':
104
+ {
105
+ var _items = lines.map(function (l) {
106
+ return createListItem(l);
107
+ });
108
+ return schema.nodes.bulletList.create(undefined, Fragment.fromArray(_items));
109
+ }
110
+ case 'taskList':
111
+ {
112
+ var _items2 = lines.map(function (l) {
113
+ return createTaskItem(l);
114
+ });
115
+ if (schema.nodes.taskList) {
116
+ return schema.nodes.taskList.create(undefined, Fragment.fromArray(_items2));
117
+ }
118
+ return schema.nodes.bulletList.create(undefined, Fragment.fromArray(_items2));
119
+ }
120
+ case 'blockquote':
121
+ {
122
+ var paragraphs = lines.map(function (l) {
123
+ return createParagraph(l);
124
+ });
125
+ return schema.nodes.blockquote.create(undefined, Fragment.fromArray(paragraphs));
126
+ }
127
+ case 'codeBlock':
128
+ {
129
+ var text = lines.join('\n');
130
+ return schema.nodes.codeBlock.create(undefined, text ? schema.text(text) : undefined);
131
+ }
132
+ case 'alert':
133
+ {
134
+ var attrs = target.attrs || {
135
+ variant: 'info',
136
+ type: 'icon'
137
+ };
138
+ // 使用 hardBreak 分隔行
139
+ var pieces = [];
140
+ lines.forEach(function (l, i) {
141
+ if (l) pieces.push(schema.text(l));
142
+ if (i < lines.length - 1) {
143
+ if (schema.nodes.hardBreak) {
144
+ pieces.push(schema.nodes.hardBreak.create());
145
+ } else {
146
+ // 退化:用文本换行符
147
+ pieces.push(schema.text('\n'));
148
+ }
149
+ }
150
+ });
151
+ var content = pieces.length > 0 ? Fragment.fromArray(pieces) : undefined;
152
+ return schema.nodes.alert.create(attrs, content);
153
+ }
154
+ }
155
+ }
156
+
157
+ /**
158
+ * 将给定位置的节点转换为目标类型(按行规则)。
159
+ */
160
+ export function convertNodeAt(editor, pos, node, target) {
161
+ var lines = extractLinesFromNode(node);
162
+ var replacement = buildNodeFromLines(editor, lines, target);
163
+ var from = pos;
164
+ var to = pos + node.nodeSize;
165
+ var tr = editor.state.tr;
166
+ // Fragment 或 Node 均可传入 replaceWith
167
+ tr.replaceWith(from, to, replacement);
168
+ editor.view.dispatch(tr);
169
+ editor.view.focus();
170
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctzhian/tiptap",
3
- "version": "1.1.2",
3
+ "version": "1.2.1",
4
4
  "description": "基于 Tiptap 二次开发的编辑器组件",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -83,6 +83,7 @@
83
83
  "@floating-ui/dom": "^1.7.2",
84
84
  "@tiptap/core": "^3.4.2",
85
85
  "@tiptap/extension-bubble-menu": "^3.4.2",
86
+ "@tiptap/extension-code": "^3.4.3",
86
87
  "@tiptap/extension-code-block-lowlight": "^3.4.2",
87
88
  "@tiptap/extension-details": "^3.4.2",
88
89
  "@tiptap/extension-drag-handle-react": "^3.4.2",