@ctzhian/tiptap 2.7.4 → 2.8.0

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.
@@ -137,7 +137,7 @@ var Reader = function Reader() {
137
137
  }();
138
138
  var _useTiptap = useTiptap({
139
139
  editable: EDITABLE,
140
- content: content,
140
+ content: '<div data-type=\"flow\" data-code=\"mindmap\n root((mindmap))\n Origins\n Long history\n ::icon(fa fa-book)\n Popularisation\n British popular psychology author Tony Buzan\n Research\n On effectiveness&lt;br/&gt;and features\n On Automatic creation\n Uses\n Creative techniques\n Strategic planning\n Argument mapping\n Tools\n Pen and paper\n Mermaid\" data-width=\"600\" data-align=\"center\" class=\"flow-wrapper\"></div><p></p>',
141
141
  contentType: DEFAULT_CONTENT_TYPE,
142
142
  exclude: ['invisibleCharacters'],
143
143
  onError: handleError,
@@ -676,21 +676,6 @@ var EditorMarkdownToolbar = function EditorMarkdownToolbar(_ref) {
676
676
  }
677
677
  }, "\u4E13\u4E1A"),
678
678
  key: 'professional'
679
- }, {
680
- label: '流程图',
681
- key: 'flowchart',
682
- icon: /*#__PURE__*/React.createElement(FlowChartIcon, {
683
- sx: {
684
- fontSize: '1rem'
685
- }
686
- }),
687
- onClick: function onClick() {
688
- return handleInsertBlock({
689
- text: '```mermaid\n\n```',
690
- row: 1,
691
- wrap: true
692
- });
693
- }
694
679
  }, {
695
680
  label: '代码',
696
681
  key: 'code',
@@ -765,6 +750,21 @@ var EditorMarkdownToolbar = function EditorMarkdownToolbar(_ref) {
765
750
  });
766
751
  }
767
752
  }]
753
+ }, {
754
+ label: 'Mermaid 流程图',
755
+ key: 'flowchart',
756
+ icon: /*#__PURE__*/React.createElement(FlowChartIcon, {
757
+ sx: {
758
+ fontSize: '1rem'
759
+ }
760
+ }),
761
+ onClick: function onClick() {
762
+ return handleInsertBlock({
763
+ text: '```mermaid\n\n```',
764
+ row: 1,
765
+ wrap: true
766
+ });
767
+ }
768
768
  }]
769
769
  }), /*#__PURE__*/React.createElement(Divider, {
770
770
  sx: {
@@ -115,6 +115,7 @@
115
115
  .tiptap.ProseMirror .react-renderer.node-codeBlock,
116
116
  .tiptap.ProseMirror .react-renderer.node-blockLink,
117
117
  .tiptap.ProseMirror .react-renderer.node-flipGrid,
118
+ .tiptap.ProseMirror .react-renderer.node-flow,
118
119
  .tiptap.ProseMirror .react-renderer.node-blockAttachment {
119
120
  display: block;
120
121
  margin: 1rem 0;
@@ -332,7 +332,7 @@ var EditorInsert = function EditorInsert(_ref) {
332
332
  }, "\u4E13\u4E1A"),
333
333
  key: 'programmer'
334
334
  }, {
335
- label: '流程图',
335
+ label: 'Mermaid 流程图',
336
336
  key: 'flow',
337
337
  icon: /*#__PURE__*/React.createElement(FlowChartIcon, {
338
338
  sx: {
@@ -213,7 +213,7 @@ export var slashCommands = [{
213
213
  editor.chain().focus().deleteRange(range).setDetails().run();
214
214
  }
215
215
  }, {
216
- title: '流程图',
216
+ title: 'Mermaid 流程图',
217
217
  icon: /*#__PURE__*/React.createElement(FlowChartIcon, {
218
218
  sx: {
219
219
  fontSize: '1rem'
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ interface FlowDiagramProps {
3
+ code: string;
4
+ onError?: (error: Error) => void;
5
+ }
6
+ declare const FlowDiagram: React.FC<FlowDiagramProps>;
7
+ export default FlowDiagram;
@@ -0,0 +1,52 @@
1
+ import { Box } from "@mui/material";
2
+ import React from "react";
3
+ import { useMermaidRender } from "./useMermaidRender";
4
+ var FlowDiagram = function FlowDiagram(_ref) {
5
+ var code = _ref.code,
6
+ onError = _ref.onError;
7
+ var _useMermaidRender = useMermaidRender({
8
+ code: code,
9
+ onError: onError,
10
+ showLoading: true,
11
+ idPrefix: 'mermaid'
12
+ }),
13
+ svgContent = _useMermaidRender.svgContent,
14
+ error = _useMermaidRender.error,
15
+ loading = _useMermaidRender.loading;
16
+ return /*#__PURE__*/React.createElement(Box, {
17
+ sx: {
18
+ width: '100%',
19
+ minHeight: loading ? '100px' : 'auto',
20
+ display: 'flex',
21
+ alignItems: 'center',
22
+ justifyContent: 'center',
23
+ '& svg': {
24
+ maxWidth: '100%',
25
+ height: 'auto'
26
+ }
27
+ }
28
+ }, loading && !error && /*#__PURE__*/React.createElement(Box, {
29
+ sx: {
30
+ color: 'text.secondary',
31
+ fontSize: '14px'
32
+ }
33
+ }, "\u6B63\u5728\u6E32\u67D3..."), error && /*#__PURE__*/React.createElement(Box, {
34
+ sx: {
35
+ color: 'error.main',
36
+ padding: '20px',
37
+ textAlign: 'center',
38
+ fontSize: '14px'
39
+ }
40
+ }, error), svgContent && !error && /*#__PURE__*/React.createElement(Box, {
41
+ dangerouslySetInnerHTML: {
42
+ __html: svgContent
43
+ },
44
+ sx: {
45
+ width: '100%',
46
+ display: 'flex',
47
+ alignItems: 'center',
48
+ justifyContent: 'center'
49
+ }
50
+ }));
51
+ };
52
+ export default FlowDiagram;
@@ -73,7 +73,7 @@ var InsertFlow = function InsertFlow(_ref) {
73
73
  flexGrow: 1,
74
74
  textAlign: 'left'
75
75
  }
76
- }, "\u70B9\u51FB\u6B64\u5904\u5D4C\u5165\u6216\u7C98\u8D34\u6D41\u7A0B\u56FE\u4EE3\u7801")), /*#__PURE__*/React.createElement(FloatingPopover, {
76
+ }, "\u70B9\u51FB\u6B64\u5904\u8F93\u5165\u6216\u7C98\u8D34 Mermaid \u6D41\u7A0B\u56FE\u4EE3\u7801")), /*#__PURE__*/React.createElement(FloatingPopover, {
77
77
  open: Boolean(anchorEl),
78
78
  anchorEl: anchorEl,
79
79
  onClose: handleClosePopover,
@@ -18,6 +18,10 @@ var ReadonlyFlow = function ReadonlyFlow(_ref) {
18
18
  }
19
19
  return /*#__PURE__*/React.createElement(NodeViewWrapper, {
20
20
  className: "flow-wrapper"
21
+ }, /*#__PURE__*/React.createElement(Box, {
22
+ sx: {
23
+ textAlign: attrs.align || undefined
24
+ }
21
25
  }, /*#__PURE__*/React.createElement(Box, {
22
26
  sx: {
23
27
  position: 'relative',
@@ -25,7 +29,7 @@ var ReadonlyFlow = function ReadonlyFlow(_ref) {
25
29
  border: '1px solid',
26
30
  borderColor: 'divider',
27
31
  borderRadius: 'var(--mui-shape-borderRadius)',
28
- width: attrs.width || '100%',
32
+ width: typeof attrs.width === 'string' && attrs.width.endsWith('%') ? attrs.width : typeof attrs.width === 'number' ? "".concat(attrs.width, "px") : typeof attrs.width === 'string' && attrs.width && !isNaN(parseFloat(attrs.width)) ? "".concat(attrs.width, "px") : attrs.width || '100%',
29
33
  height: 'auto'
30
34
  }
31
35
  }, /*#__PURE__*/React.createElement(Box, {
@@ -60,6 +64,6 @@ var ReadonlyFlow = function ReadonlyFlow(_ref) {
60
64
  height: 'auto'
61
65
  }
62
66
  }
63
- }))));
67
+ })))));
64
68
  };
65
69
  export default ReadonlyFlow;
@@ -4,6 +4,7 @@ import React from "react";
4
4
  export interface FlowAttributes {
5
5
  code: string;
6
6
  width?: string | number;
7
+ align?: 'left' | 'center' | 'right' | null;
7
8
  }
8
9
  declare const FlowViewWrapper: React.FC<NodeViewProps & EditorFnProps>;
9
10
  export default FlowViewWrapper;
@@ -4,16 +4,17 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
4
4
  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; }
5
5
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
6
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
- import { DeleteLineIcon, EditLineIcon } from "../../../component/Icons";
7
+ import { ActionDropdown } from "../../../component";
8
+ import { AlignCenterIcon, AlignLeftIcon, AlignRightIcon, DeleteLineIcon, EditLineIcon } from "../../../component/Icons";
8
9
  import { ToolbarItem } from "../../../component/Toolbar";
9
- import { alpha, Box, Stack, useTheme } from "@mui/material";
10
+ import { alpha, Box, Divider, Stack, useTheme } from "@mui/material";
10
11
  import { NodeViewWrapper } from '@tiptap/react';
11
12
  import React, { useCallback, useEffect, useRef, useState } from "react";
12
13
  import { HoverPopover } from "../../../component/HoverPopover";
13
14
  import EditFlow from "./Edit";
15
+ import FlowDiagram from "./FlowDiagram";
14
16
  import InsertFlow from "./Insert";
15
17
  import ReadonlyFlow from "./Readonly";
16
- import { useMermaidRender } from "./useMermaidRender";
17
18
  var FlowViewWrapper = function FlowViewWrapper(_ref) {
18
19
  var editor = _ref.editor,
19
20
  node = _ref.node,
@@ -48,6 +49,23 @@ var FlowViewWrapper = function FlowViewWrapper(_ref) {
48
49
  var flowWrapperRef = useRef(null);
49
50
  var flowContentRef = useRef(null);
50
51
  var editButtonRef = useRef(null);
52
+ var isPercentWidth = function isPercentWidth() {
53
+ if (!attrs.width) return true;
54
+ if (typeof attrs.width === 'string' && attrs.width.endsWith('%')) {
55
+ return true;
56
+ }
57
+ return false;
58
+ };
59
+ var getCurrentWidthPercent = function getCurrentWidthPercent() {
60
+ if (isPercentWidth()) {
61
+ if (!attrs.width) return '100';
62
+ if (typeof attrs.width === 'string' && attrs.width.endsWith('%')) {
63
+ return attrs.width.replace('%', '');
64
+ }
65
+ return '100';
66
+ }
67
+ return 'pixel';
68
+ };
51
69
  var getCurrentDisplayWidth = function getCurrentDisplayWidth() {
52
70
  if (flowWrapperRef.current) {
53
71
  return flowWrapperRef.current.offsetWidth;
@@ -71,18 +89,6 @@ var FlowViewWrapper = function FlowViewWrapper(_ref) {
71
89
  }
72
90
  return containerSize * (defaultPercent / 100);
73
91
  };
74
-
75
- // 将像素值转换回字符串格式
76
- var formatValue = function formatValue(pixels, original) {
77
- if (typeof original === 'string' && original.endsWith('%')) {
78
- var _flowWrapperRef$curre;
79
- // 如果原来是百分比,保持百分比格式
80
- var containerWidth = ((_flowWrapperRef$curre = flowWrapperRef.current) === null || _flowWrapperRef$curre === void 0 || (_flowWrapperRef$curre = _flowWrapperRef$curre.parentElement) === null || _flowWrapperRef$curre === void 0 ? void 0 : _flowWrapperRef$curre.clientWidth) || 800;
81
- var percent = Math.round(pixels / containerWidth * 100);
82
- return "".concat(percent, "%");
83
- }
84
- return "".concat(Math.round(pixels), "px");
85
- };
86
92
  var handleMouseDown = function handleMouseDown(e, corner) {
87
93
  e.preventDefault();
88
94
  e.stopPropagation();
@@ -101,11 +107,13 @@ var FlowViewWrapper = function FlowViewWrapper(_ref) {
101
107
  newWidth = dragStartWidthRef.current - deltaX;
102
108
  }
103
109
  newWidth = Math.max(200, Math.min(1920, newWidth));
110
+ // 手动调整宽度时,改为固定宽度(像素值)
104
111
  _updateAttributes({
105
- width: formatValue(newWidth, attrs.width),
106
- code: attrs.code
112
+ width: Math.round(newWidth),
113
+ code: attrs.code,
114
+ align: attrs.align
107
115
  });
108
- }, [isDragging, dragCorner, attrs.width, _updateAttributes]);
116
+ }, [isDragging, dragCorner, attrs.code, _updateAttributes]);
109
117
  var handleMouseUp = useCallback(function () {
110
118
  setIsDragging(false);
111
119
  setDragCorner(null);
@@ -144,7 +152,8 @@ var FlowViewWrapper = function FlowViewWrapper(_ref) {
144
152
  }, /*#__PURE__*/React.createElement(Box, {
145
153
  ref: flowContentRef,
146
154
  sx: {
147
- position: 'relative'
155
+ position: 'relative',
156
+ textAlign: attrs.align || undefined
148
157
  },
149
158
  onMouseEnter: function onMouseEnter() {
150
159
  return setIsHovering(true);
@@ -157,10 +166,11 @@ var FlowViewWrapper = function FlowViewWrapper(_ref) {
157
166
  sx: {
158
167
  position: 'relative',
159
168
  border: '2px solid',
169
+ display: 'inline-block',
160
170
  borderColor: isHovering || isDragging ? alpha(theme.palette.primary.main, 0.3) : 'transparent',
161
171
  borderRadius: 'var(--mui-shape-borderRadius)',
162
172
  bgcolor: 'background.paper',
163
- width: attrs.width || '100%',
173
+ width: typeof attrs.width === 'string' && attrs.width.endsWith('%') ? attrs.width : typeof attrs.width === 'number' ? "".concat(attrs.width, "px") : typeof attrs.width === 'string' && attrs.width && !isNaN(parseFloat(attrs.width)) ? "".concat(attrs.width, "px") : attrs.width || '100%',
164
174
  height: 'auto',
165
175
  transition: 'border-color 0.2s ease'
166
176
  }
@@ -184,6 +194,109 @@ var FlowViewWrapper = function FlowViewWrapper(_ref) {
184
194
  }),
185
195
  tip: "\u7F16\u8F91\u6D41\u7A0B\u56FE",
186
196
  onClick: handleShowPopover
197
+ }), /*#__PURE__*/React.createElement(Divider, {
198
+ orientation: "vertical",
199
+ flexItem: true,
200
+ sx: {
201
+ height: '1rem',
202
+ mx: 0.5,
203
+ alignSelf: 'center',
204
+ borderColor: 'divider'
205
+ }
206
+ }), /*#__PURE__*/React.createElement(ToolbarItem, {
207
+ icon: /*#__PURE__*/React.createElement(AlignLeftIcon, {
208
+ sx: {
209
+ fontSize: '1rem'
210
+ }
211
+ }),
212
+ tip: "\u5DE6\u4FA7\u5BF9\u9F50",
213
+ className: attrs.align === 'left' ? 'tool-active' : '',
214
+ onClick: function onClick() {
215
+ return _updateAttributes({
216
+ align: attrs.align === 'left' ? null : 'left',
217
+ code: attrs.code,
218
+ width: attrs.width
219
+ });
220
+ }
221
+ }), /*#__PURE__*/React.createElement(ToolbarItem, {
222
+ icon: /*#__PURE__*/React.createElement(AlignCenterIcon, {
223
+ sx: {
224
+ fontSize: '1rem'
225
+ }
226
+ }),
227
+ tip: "\u5C45\u4E2D\u5BF9\u9F50",
228
+ className: attrs.align === 'center' ? 'tool-active' : '',
229
+ onClick: function onClick() {
230
+ return _updateAttributes({
231
+ align: attrs.align === 'center' ? null : 'center',
232
+ code: attrs.code,
233
+ width: attrs.width
234
+ });
235
+ }
236
+ }), /*#__PURE__*/React.createElement(ToolbarItem, {
237
+ icon: /*#__PURE__*/React.createElement(AlignRightIcon, {
238
+ sx: {
239
+ fontSize: '1rem'
240
+ }
241
+ }),
242
+ tip: "\u53F3\u4FA7\u5BF9\u9F50",
243
+ className: attrs.align === 'right' ? 'tool-active' : '',
244
+ onClick: function onClick() {
245
+ return _updateAttributes({
246
+ align: attrs.align === 'right' ? null : 'right',
247
+ code: attrs.code,
248
+ width: attrs.width
249
+ });
250
+ }
251
+ }), /*#__PURE__*/React.createElement(Divider, {
252
+ orientation: "vertical",
253
+ flexItem: true,
254
+ sx: {
255
+ height: '1rem',
256
+ mx: 0.5,
257
+ alignSelf: 'center',
258
+ borderColor: 'divider'
259
+ }
260
+ }), /*#__PURE__*/React.createElement(ActionDropdown, {
261
+ id: "flow-width-dropdown",
262
+ selected: getCurrentWidthPercent(),
263
+ defaultDisplay: !isPercentWidth() ? {
264
+ label: '固定宽度'
265
+ } : undefined,
266
+ list: [{
267
+ key: '50',
268
+ label: '自适应宽度(50%)',
269
+ onClick: function onClick() {
270
+ return _updateAttributes({
271
+ width: '50%'
272
+ });
273
+ }
274
+ }, {
275
+ key: '75',
276
+ label: '自适应宽度(75%)',
277
+ onClick: function onClick() {
278
+ return _updateAttributes({
279
+ width: '75%'
280
+ });
281
+ }
282
+ }, {
283
+ key: '100',
284
+ label: '自适应宽度(100%)',
285
+ onClick: function onClick() {
286
+ return _updateAttributes({
287
+ width: '100%'
288
+ });
289
+ }
290
+ }]
291
+ }), /*#__PURE__*/React.createElement(Divider, {
292
+ orientation: "vertical",
293
+ flexItem: true,
294
+ sx: {
295
+ height: '1rem',
296
+ mx: 0.5,
297
+ alignSelf: 'center',
298
+ borderColor: 'divider'
299
+ }
187
300
  }), /*#__PURE__*/React.createElement(ToolbarItem, {
188
301
  icon: /*#__PURE__*/React.createElement(DeleteLineIcon, {
189
302
  sx: {
@@ -300,52 +413,4 @@ var FlowViewWrapper = function FlowViewWrapper(_ref) {
300
413
  onCancel: handleEditCancel
301
414
  }));
302
415
  };
303
- var FlowDiagram = function FlowDiagram(_ref2) {
304
- var code = _ref2.code,
305
- onError = _ref2.onError;
306
- var _useMermaidRender = useMermaidRender({
307
- code: code,
308
- onError: onError,
309
- showLoading: true,
310
- idPrefix: 'mermaid'
311
- }),
312
- svgContent = _useMermaidRender.svgContent,
313
- error = _useMermaidRender.error,
314
- loading = _useMermaidRender.loading;
315
- return /*#__PURE__*/React.createElement(Box, {
316
- sx: {
317
- width: '100%',
318
- minHeight: loading ? '100px' : 'auto',
319
- display: 'flex',
320
- alignItems: 'center',
321
- justifyContent: 'center',
322
- '& svg': {
323
- maxWidth: '100%',
324
- height: 'auto'
325
- }
326
- }
327
- }, loading && !error && /*#__PURE__*/React.createElement(Box, {
328
- sx: {
329
- color: 'text.secondary',
330
- fontSize: '14px'
331
- }
332
- }, "\u6B63\u5728\u6E32\u67D3..."), error && /*#__PURE__*/React.createElement(Box, {
333
- sx: {
334
- color: 'error.main',
335
- padding: '20px',
336
- textAlign: 'center',
337
- fontSize: '14px'
338
- }
339
- }, error), svgContent && !error && /*#__PURE__*/React.createElement(Box, {
340
- dangerouslySetInnerHTML: {
341
- __html: svgContent
342
- },
343
- sx: {
344
- width: '100%',
345
- display: 'flex',
346
- alignItems: 'center',
347
- justifyContent: 'center'
348
- }
349
- }));
350
- };
351
416
  export default FlowViewWrapper;
@@ -86,7 +86,7 @@ export var useMermaidRender = function useMermaidRender(_ref) {
86
86
  _context.next = 17;
87
87
  break;
88
88
  case 16:
89
- throw new Error('渲染结果为空,请检查流程图代码是否正确');
89
+ throw new Error('Mermaid 流程图渲染结果为空,请检查流程图代码是否正确');
90
90
  case 17:
91
91
  _context.next = 28;
92
92
  break;
@@ -99,7 +99,7 @@ export var useMermaidRender = function useMermaidRender(_ref) {
99
99
  }
100
100
  return _context.abrupt("return");
101
101
  case 23:
102
- errorMessage = _context.t0.message || '流程图渲染失败';
102
+ errorMessage = _context.t0.message || 'Mermaid 流程图渲染失败';
103
103
  setError(errorMessage);
104
104
  setLoading(false);
105
105
  setSvgContent('');
@@ -1,4 +1,13 @@
1
- export declare const initMermaid: () => void;
1
+ import { type MermaidConfig } from 'mermaid';
2
+ /**
3
+ * 初始化 mermaid(只执行一次)
4
+ * @param config 可选的 mermaid 配置,会与默认配置合并
5
+ */
6
+ export declare const initMermaid: (config?: MermaidConfig) => void;
7
+ /**
8
+ * 获取当前 mermaid 配置
9
+ */
10
+ export declare const getMermaidConfig: () => MermaidConfig | null;
2
11
  /**
3
12
  * 生成唯一的 mermaid 渲染 ID
4
13
  */
@@ -1,27 +1,62 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
1
7
  import mermaid from 'mermaid';
8
+ import { v4 as uuidv4 } from 'uuid';
9
+
10
+ /**
11
+ * 默认 mermaid 配置
12
+ */
13
+ var defaultMermaidConfig = {
14
+ startOnLoad: false,
15
+ theme: 'default',
16
+ securityLevel: 'loose',
17
+ look: 'handDrawn' // 启用手绘效果
18
+ };
19
+
20
+ /**
21
+ * 全局 mermaid 配置
22
+ */
23
+ var globalMermaidConfig = null;
2
24
 
3
25
  /**
4
26
  * 初始化 mermaid(只执行一次)
27
+ * @param config 可选的 mermaid 配置,会与默认配置合并
5
28
  */
6
- var mermaidInitialized = false;
7
- export var initMermaid = function initMermaid() {
8
- if (!mermaidInitialized) {
9
- mermaid.initialize({
10
- startOnLoad: false,
11
- theme: 'default',
12
- securityLevel: 'loose',
13
- fontFamily: 'inherit'
29
+ export var initMermaid = function initMermaid(config) {
30
+ if (!globalMermaidConfig) {
31
+ var mergedConfig = _objectSpread(_objectSpread(_objectSpread({}, defaultMermaidConfig), config), {}, {
32
+ // 深度合并 flowchart 配置
33
+ flowchart: _objectSpread(_objectSpread({}, defaultMermaidConfig.flowchart), config === null || config === void 0 ? void 0 : config.flowchart)
34
+ });
35
+ mermaid.initialize(mergedConfig);
36
+ globalMermaidConfig = mergedConfig;
37
+ } else if (config) {
38
+ // 如果已经初始化过,但传入了新配置,则更新配置
39
+ var _mergedConfig = _objectSpread(_objectSpread(_objectSpread({}, globalMermaidConfig), config), {}, {
40
+ flowchart: _objectSpread(_objectSpread({}, globalMermaidConfig.flowchart), config === null || config === void 0 ? void 0 : config.flowchart)
14
41
  });
15
- mermaidInitialized = true;
42
+ mermaid.initialize(_mergedConfig);
43
+ globalMermaidConfig = _mergedConfig;
16
44
  }
17
45
  };
18
46
 
47
+ /**
48
+ * 获取当前 mermaid 配置
49
+ */
50
+ export var getMermaidConfig = function getMermaidConfig() {
51
+ return globalMermaidConfig;
52
+ };
53
+
19
54
  /**
20
55
  * 生成唯一的 mermaid 渲染 ID
21
56
  */
22
57
  export var generateMermaidId = function generateMermaidId() {
23
58
  var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'mermaid';
24
- return "".concat(prefix, "-").concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
59
+ return "".concat(prefix, "-").concat(uuidv4());
25
60
  };
26
61
 
27
62
  /**
@@ -148,7 +148,7 @@ var ImageViewWrapper = function ImageViewWrapper(_ref) {
148
148
  width: dimensions.width
149
149
  });
150
150
  } catch (error) {
151
- console.warn('Failed to update image dimensions:', error);
151
+ // console.warn('Failed to update image dimensions:', error)
152
152
  }
153
153
  }).catch(function (error) {
154
154
  try {
@@ -161,7 +161,7 @@ var ImageViewWrapper = function ImageViewWrapper(_ref) {
161
161
  width: 400
162
162
  });
163
163
  } catch (updateError) {
164
- console.warn('Failed to update image attributes with fallback width:', updateError);
164
+ // console.warn('Failed to update image attributes with fallback width:', updateError)
165
165
  }
166
166
  });
167
167
  }
@@ -1,2 +1,2 @@
1
1
  import { GetExtensionsProps } from '../type';
2
- export declare const getExtensions: ({ limit, exclude, extensions: extensionsProps, editable, mentionItems, baseUrl, onMentionFilter, onUpload, onError, onTocUpdate, onAiWritingGetSuggestion, onValidateUrl, placeholder, youtubeOptions, tableOfContentsOptions, }: GetExtensionsProps) => any;
2
+ export declare const getExtensions: ({ limit, exclude, extensions: extensionsProps, editable, mentionItems, baseUrl, onMentionFilter, onUpload, onError, onTocUpdate, onAiWritingGetSuggestion, onValidateUrl, placeholder, mermaidOptions, youtubeOptions, tableOfContentsOptions, }: GetExtensionsProps) => any;
@@ -30,6 +30,7 @@ export var getExtensions = function getExtensions(_ref) {
30
30
  onAiWritingGetSuggestion = _ref.onAiWritingGetSuggestion,
31
31
  onValidateUrl = _ref.onValidateUrl,
32
32
  _placeholder = _ref.placeholder,
33
+ mermaidOptions = _ref.mermaidOptions,
33
34
  youtubeOptions = _ref.youtubeOptions,
34
35
  tableOfContentsOptions = _ref.tableOfContentsOptions;
35
36
  var defaultExtensions = [ImeComposition, StarterKit.configure({
@@ -46,7 +47,9 @@ export var getExtensions = function getExtensions(_ref) {
46
47
  color: 'var(--mui-palette-primary-main)',
47
48
  width: 2
48
49
  }
49
- }), YamlFormat, TextStyleKit, CodeExtension, ListExtension, EmojiExtension, AlertExtension, CustomSubscript, DetailsExtension, CustomSuperscript, DetailsContentExtension, DetailsSummaryExtension, CodeBlockLowlightExtension, InlineUploadProgressExtension, CustomHorizontalRule].concat(_toConsumableArray(TableExtension({
50
+ }), YamlFormat, TextStyleKit, CodeExtension, FlowExtension({
51
+ mermaidOptions: mermaidOptions
52
+ }), ListExtension, EmojiExtension, AlertExtension, CustomSubscript, DetailsExtension, CustomSuperscript, DetailsContentExtension, DetailsSummaryExtension, CodeBlockLowlightExtension, InlineUploadProgressExtension, CustomHorizontalRule].concat(_toConsumableArray(TableExtension({
50
53
  editable: editable
51
54
  })), [FlipGridColumnExtension, FlipGridExtension, CustomBlockMathExtension({
52
55
  onError: onError
@@ -1,15 +1,22 @@
1
1
  import { EditorFnProps } from "../../../type";
2
2
  import { Node } from '@tiptap/core';
3
+ import { MermaidConfig } from 'mermaid';
3
4
  declare module '@tiptap/core' {
4
5
  interface Commands<ReturnType> {
5
6
  flow: {
6
7
  setFlow: (options: {
7
8
  code?: string;
8
9
  width?: string | number;
10
+ align?: 'left' | 'center' | 'right' | null;
9
11
  }) => ReturnType;
10
12
  };
11
13
  }
12
14
  }
13
- export type FlowExtensionProps = EditorFnProps;
15
+ export type FlowExtensionProps = EditorFnProps & {
16
+ /**
17
+ * Mermaid 配置选项
18
+ */
19
+ mermaidOptions?: MermaidConfig;
20
+ };
14
21
  export declare const FlowExtension: (props: FlowExtensionProps) => Node<any, any>;
15
22
  export default FlowExtension;
@@ -7,7 +7,12 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
7
7
  import { mergeAttributes, Node } from '@tiptap/core';
8
8
  import { ReactNodeViewRenderer } from '@tiptap/react';
9
9
  import FlowViewWrapper from "../../component/Flow";
10
+ import { initMermaid } from "../../component/Flow/utils";
10
11
  export var FlowExtension = function FlowExtension(props) {
12
+ // 初始化 mermaid 配置(如果提供了配置)
13
+ if (props.mermaidOptions) {
14
+ initMermaid(props.mermaidOptions);
15
+ }
11
16
  return Node.create({
12
17
  name: 'flow',
13
18
  group: 'block',
@@ -34,7 +39,13 @@ export var FlowExtension = function FlowExtension(props) {
34
39
  width: {
35
40
  default: null,
36
41
  parseHTML: function parseHTML(element) {
37
- return element.getAttribute('data-width') || null;
42
+ var width = element.getAttribute('data-width');
43
+ if (width) {
44
+ if (width.endsWith('%')) return width;
45
+ var numWidth = parseFloat(width);
46
+ return isNaN(numWidth) ? null : numWidth;
47
+ }
48
+ return null;
38
49
  },
39
50
  renderHTML: function renderHTML(attributes) {
40
51
  if (!attributes.width) return {};
@@ -42,6 +53,18 @@ export var FlowExtension = function FlowExtension(props) {
42
53
  'data-width': String(attributes.width)
43
54
  };
44
55
  }
56
+ },
57
+ align: {
58
+ default: null,
59
+ parseHTML: function parseHTML(element) {
60
+ return element.getAttribute('data-align') || null;
61
+ },
62
+ renderHTML: function renderHTML(attributes) {
63
+ if (!attributes.align) return {};
64
+ return {
65
+ 'data-align': attributes.align
66
+ };
67
+ }
45
68
  }
46
69
  };
47
70
  },
@@ -51,10 +74,21 @@ export var FlowExtension = function FlowExtension(props) {
51
74
  getAttrs: function getAttrs(dom) {
52
75
  if (!(dom instanceof HTMLElement)) return false;
53
76
  var code = dom.getAttribute('data-code') || '';
54
- var width = dom.getAttribute('data-width') || null;
77
+ var widthAttr = dom.getAttribute('data-width');
78
+ var width = null;
79
+ if (widthAttr) {
80
+ if (widthAttr.endsWith('%')) {
81
+ width = widthAttr;
82
+ } else {
83
+ var numWidth = parseFloat(widthAttr);
84
+ width = isNaN(numWidth) ? null : numWidth;
85
+ }
86
+ }
87
+ var align = dom.getAttribute('data-align') || null;
55
88
  return {
56
89
  code: code,
57
- width: width
90
+ width: width,
91
+ align: align
58
92
  };
59
93
  }
60
94
  }];
@@ -69,6 +103,8 @@ export var FlowExtension = function FlowExtension(props) {
69
103
  'data-code': attrs.code
70
104
  } : {}, attrs.width ? {
71
105
  'data-width': String(attrs.width)
106
+ } : {}, attrs.align ? {
107
+ 'data-align': attrs.align
72
108
  } : {}, this.options.HTMLAttributes, HTMLAttributes)];
73
109
  },
74
110
  renderMarkdown: function renderMarkdown(node) {
@@ -87,7 +123,8 @@ export var FlowExtension = function FlowExtension(props) {
87
123
  type: _this.name,
88
124
  attrs: {
89
125
  code: options.code || '',
90
- width: options.width || null
126
+ width: options.width || null,
127
+ align: options.align || null
91
128
  }
92
129
  });
93
130
  };
@@ -4,6 +4,7 @@ import { Editor, Extension } from '@tiptap/core';
4
4
  import { TableOfContentsOptions } from '@tiptap/extension-table-of-contents';
5
5
  import { YoutubeOptions } from '@tiptap/extension-youtube';
6
6
  import { UseEditorOptions } from '@tiptap/react';
7
+ import { MermaidConfig } from 'mermaid';
7
8
  export type { Editor } from '@tiptap/react';
8
9
  export interface MenuItem {
9
10
  label?: React.ReactNode;
@@ -108,6 +109,7 @@ export type MentionExtensionProps = {
108
109
  }) => Promise<MentionItems>;
109
110
  };
110
111
  export type NodeOrMetaOrSuggestionOrExtensionOptions = {
112
+ mermaidOptions?: Partial<MermaidConfig>;
111
113
  youtubeOptions?: Partial<YoutubeOptions>;
112
114
  tableOfContentsOptions?: Partial<TableOfContentsOptions>;
113
115
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctzhian/tiptap",
3
- "version": "2.7.4",
3
+ "version": "2.8.0",
4
4
  "description": "基于 Tiptap 二次开发的编辑器组件",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -82,37 +82,37 @@
82
82
  "dependencies": {
83
83
  "@floating-ui/dom": "^1.7.2",
84
84
  "@floating-ui/react": "^0.27.16",
85
- "@tiptap/core": "3.11.1",
86
- "@tiptap/extension-bubble-menu": "3.11.1",
87
- "@tiptap/extension-code": "3.11.1",
88
- "@tiptap/extension-code-block-lowlight": "3.11.1",
89
- "@tiptap/extension-details": "3.11.1",
90
- "@tiptap/extension-drag-handle-react": "3.11.1",
91
- "@tiptap/extension-emoji": "3.11.1",
92
- "@tiptap/extension-file-handler": "3.11.1",
93
- "@tiptap/extension-highlight": "3.11.1",
94
- "@tiptap/extension-horizontal-rule": "3.11.1",
95
- "@tiptap/extension-image": "3.11.1",
96
- "@tiptap/extension-invisible-characters": "3.11.1",
97
- "@tiptap/extension-list": "3.11.1",
98
- "@tiptap/extension-mathematics": "3.11.1",
99
- "@tiptap/extension-mention": "3.11.1",
100
- "@tiptap/extension-subscript": "3.11.1",
101
- "@tiptap/extension-superscript": "3.11.1",
102
- "@tiptap/extension-table": "3.11.1",
103
- "@tiptap/extension-table-of-contents": "3.11.1",
104
- "@tiptap/extension-text-align": "3.11.1",
105
- "@tiptap/extension-text-style": "3.11.1",
106
- "@tiptap/extension-unique-id": "3.11.1",
107
- "@tiptap/extension-youtube": "3.11.1",
108
- "@tiptap/extensions": "3.11.1",
109
- "@tiptap/html": "3.11.1",
110
- "@tiptap/markdown": "3.11.1",
111
- "@tiptap/pm": "3.11.1",
112
- "@tiptap/react": "3.11.1",
113
- "@tiptap/starter-kit": "3.11.1",
114
- "@tiptap/static-renderer": "3.11.1",
115
- "@tiptap/suggestion": "3.11.1",
85
+ "@tiptap/core": "^3.13.0",
86
+ "@tiptap/extension-bubble-menu": "^3.13.0",
87
+ "@tiptap/extension-code": "^3.13.0",
88
+ "@tiptap/extension-code-block-lowlight": "^3.13.0",
89
+ "@tiptap/extension-details": "^3.13.0",
90
+ "@tiptap/extension-drag-handle-react": "^3.13.0",
91
+ "@tiptap/extension-emoji": "^3.13.0",
92
+ "@tiptap/extension-file-handler": "^3.13.0",
93
+ "@tiptap/extension-highlight": "^3.13.0",
94
+ "@tiptap/extension-horizontal-rule": "^3.13.0",
95
+ "@tiptap/extension-image": "^3.13.0",
96
+ "@tiptap/extension-invisible-characters": "^3.13.0",
97
+ "@tiptap/extension-list": "^3.13.0",
98
+ "@tiptap/extension-mathematics": "^3.13.0",
99
+ "@tiptap/extension-mention": "^3.13.0",
100
+ "@tiptap/extension-subscript": "^3.13.0",
101
+ "@tiptap/extension-superscript": "^3.13.0",
102
+ "@tiptap/extension-table": "^3.13.0",
103
+ "@tiptap/extension-table-of-contents": "^3.13.0",
104
+ "@tiptap/extension-text-align": "^3.13.0",
105
+ "@tiptap/extension-text-style": "^3.13.0",
106
+ "@tiptap/extension-unique-id": "^3.13.0",
107
+ "@tiptap/extension-youtube": "^3.13.0",
108
+ "@tiptap/extensions": "^3.13.0",
109
+ "@tiptap/html": "^3.13.0",
110
+ "@tiptap/markdown": "^3.13.0",
111
+ "@tiptap/pm": "^3.13.0",
112
+ "@tiptap/react": "^3.13.0",
113
+ "@tiptap/starter-kit": "^3.13.0",
114
+ "@tiptap/static-renderer": "^3.13.0",
115
+ "@tiptap/suggestion": "^3.13.0",
116
116
  "ace-builds": "^1.43.4",
117
117
  "core-js": "^3.46.0",
118
118
  "diff-match-patch": "^1.0.5",
@@ -121,7 +121,7 @@
121
121
  "katex": "^0.16.22",
122
122
  "linkifyjs": "^4.3.2",
123
123
  "lowlight": "^3.3.0",
124
- "mermaid": "^10.9.5",
124
+ "mermaid": "^11.12.2",
125
125
  "react-ace": "^14.0.1",
126
126
  "react-colorful": "^5.6.1",
127
127
  "react-image-crop": "^11.0.10",