@ctzhian/tiptap 1.13.1 → 1.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToAr
6
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
7
  import { Box, Divider, Stack, Typography } from "@mui/material";
8
8
  import React from "react";
9
- import { AddCircleFillIcon, ArrowDownSLineIcon, AttachmentLineIcon, BoldIcon, CheckboxCircleFillIcon, CloseCircleFillIcon, CodeBoxLineIcon, CodeLineIcon, CodeSSlashLineIcon, DoubleQuotesLIcon, ErrorWarningFillIcon, Folder2LineIcon, FormulaIcon, FunctionsIcon, H1Icon, H2Icon, H3Icon, H4Icon, H5Icon, H6Icon, ImageLineIcon, Information2FillIcon, Information2LineIcon, ItalicIcon, LinkIcon, ListCheck3Icon, ListOrdered2Icon, ListUnorderedIcon, MarkPenLineIcon, MenuFold2FillIcon, MovieLineIcon, Music2LineIcon, SeparatorIcon, SquareRootIcon, StrikethroughIcon, SubscriptIcon, SuperscriptIcon, Table2Icon, UnderlineIcon, UserSmileFillIcon } from "../component/Icons";
9
+ import { AddCircleFillIcon, ArrowDownSLineIcon, AttachmentLineIcon, BoldIcon, CheckboxCircleFillIcon, CloseCircleFillIcon, CodeBoxLineIcon, CodeLineIcon, CodeSSlashLineIcon, DoubleQuotesLIcon, ErrorWarningFillIcon, FlowChartIcon, Folder2LineIcon, FormulaIcon, FunctionsIcon, H1Icon, H2Icon, H3Icon, H4Icon, H5Icon, H6Icon, ImageLineIcon, Information2FillIcon, Information2LineIcon, ItalicIcon, LinkIcon, ListCheck3Icon, ListOrdered2Icon, ListUnorderedIcon, MarkPenLineIcon, MenuFold2FillIcon, MovieLineIcon, Music2LineIcon, SeparatorIcon, SquareRootIcon, StrikethroughIcon, SubscriptIcon, SuperscriptIcon, Table2Icon, UnderlineIcon, UserSmileFillIcon } from "../component/Icons";
10
10
  import Menu from "../component/Menu";
11
11
  import { ToolbarItem } from "../component/Toolbar";
12
12
  import TableSizePicker from "../component/Toolbar/TableSizePicker";
@@ -674,8 +674,23 @@ var EditorMarkdownToolbar = function EditorMarkdownToolbar(_ref) {
674
674
  fontSize: '12px',
675
675
  color: 'text.disabled'
676
676
  }
677
- }, "\u7A0B\u5E8F\u5458\u4E13\u7528"),
678
- key: 'programmer'
677
+ }, "\u4E13\u4E1A"),
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
+ }
679
694
  }, {
680
695
  label: '代码',
681
696
  key: 'code',
@@ -123,9 +123,9 @@ var Reader = function Reader() {
123
123
  // contentType: 'markdown'
124
124
  // }).run()
125
125
  },
126
- onTocUpdate: function onTocUpdate(toc) {
127
- console.log('toc', toc);
128
- },
126
+ // onTocUpdate: (toc) => {
127
+ // console.log('toc', toc)
128
+ // },
129
129
  content: mdContent
130
130
  }),
131
131
  editor = _useTiptap.editor;
@@ -22,20 +22,15 @@ var ReadonlyImage = function ReadonlyImage(_ref) {
22
22
  maxWidth: '100%',
23
23
  height: 'auto',
24
24
  cursor: 'pointer'
25
- },
26
- onError: function onError(e) {
27
- console.error('Image load error:', e);
28
25
  }
29
26
  })), attrs.title && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(Box, {
30
27
  component: "span",
28
+ className: "editor-image-title",
31
29
  sx: {
32
30
  position: 'relative',
33
- left: '50%',
34
- transform: 'translateX(-50%)',
35
31
  display: 'inline-block',
36
32
  fontSize: '0.75rem',
37
- color: 'text.tertiary',
38
- mt: 1.5
33
+ color: 'text.tertiary'
39
34
  }
40
35
  }, attrs.title))));
41
36
  };
@@ -134,10 +134,7 @@ var ImageViewWrapper = function ImageViewWrapper(_ref) {
134
134
  }
135
135
  return attrs.width;
136
136
  };
137
-
138
- // 自动获取图片尺寸并设置
139
137
  useEffect(function () {
140
- // 当有 src 但没有 width 时,自动获取图片尺寸
141
138
  if (attrs.src && (!attrs.width || attrs.width <= 0)) {
142
139
  getImageDimensions(attrs.src).then(function (dimensions) {
143
140
  updateAttributes({
@@ -145,11 +142,9 @@ var ImageViewWrapper = function ImageViewWrapper(_ref) {
145
142
  width: dimensions.width
146
143
  });
147
144
  }).catch(function (error) {
148
- console.warn('无法获取图片尺寸,使用默认宽度:', error);
149
- // 如果无法获取尺寸,设置默认宽度
150
145
  updateAttributes({
151
146
  src: attrs.src,
152
- width: 400 // 默认宽度
147
+ width: 400
153
148
  });
154
149
  });
155
150
  }
@@ -488,6 +483,7 @@ var ImageViewWrapper = function ImageViewWrapper(_ref) {
488
483
  }
489
484
  }))), attrs.title && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(Box, {
490
485
  component: "span",
486
+ className: "editor-image-title",
491
487
  sx: {
492
488
  display: 'inline-block',
493
489
  fontSize: '0.75rem',
@@ -1,4 +1,4 @@
1
1
  import { UploadFunction } from "../../type";
2
2
  export declare const FileHandlerExtension: (props: {
3
3
  onUpload?: UploadFunction;
4
- }) => import("@tiptap/core").Extension<Omit<import("@tiptap/extension-file-handler").FileHandlePluginOptions, "editor" | "key">, any>;
4
+ }) => import("@tiptap/core").Extension<Omit<import("@tiptap/extension-file-handler").FileHandlePluginOptions, "key" | "editor">, any>;
@@ -73,7 +73,7 @@ export var FileHandlerExtension = function FileHandlerExtension(props) {
73
73
  chain.setTextSelection(progressPos);
74
74
  }
75
75
  _context.t0 = fileType;
76
- _context.next = _context.t0 === 'image' ? 18 : _context.t0 === 'video' ? 32 : 34;
76
+ _context.next = _context.t0 === 'image' ? 18 : _context.t0 === 'video' ? 31 : 33;
77
77
  break;
78
78
  case 18:
79
79
  _context.prev = 18;
@@ -83,14 +83,13 @@ export var FileHandlerExtension = function FileHandlerExtension(props) {
83
83
  dimensions = _context.sent;
84
84
  chain.setImage({
85
85
  src: url,
86
- width: Math.min(dimensions.width, 760) // 使用原始宽度,但不超过760px
86
+ width: Math.min(dimensions.width, 760)
87
87
  }).run();
88
- _context.next = 31;
88
+ _context.next = 30;
89
89
  break;
90
90
  case 25:
91
91
  _context.prev = 25;
92
92
  _context.t1 = _context["catch"](18);
93
- console.warn('无法获取图片尺寸,使用默认宽度:', _context.t1);
94
93
  fallbackChain = editor.chain().focus();
95
94
  if (progressPos !== null) {
96
95
  fallbackChain.setTextSelection(progressPos);
@@ -99,28 +98,28 @@ export var FileHandlerExtension = function FileHandlerExtension(props) {
99
98
  src: url,
100
99
  width: 760
101
100
  }).run();
101
+ case 30:
102
+ return _context.abrupt("break", 35);
102
103
  case 31:
103
- return _context.abrupt("break", 36);
104
- case 32:
105
104
  chain.setVideo({
106
105
  src: url,
107
106
  width: 760,
108
107
  controls: true,
109
108
  autoplay: false
110
109
  }).run();
111
- return _context.abrupt("break", 36);
112
- case 34:
110
+ return _context.abrupt("break", 35);
111
+ case 33:
113
112
  chain.setBlockAttachment({
114
113
  url: url,
115
114
  title: file.name,
116
115
  size: formatFileSize(file.size)
117
116
  }).run();
118
- return _context.abrupt("break", 36);
119
- case 36:
120
- _context.next = 54;
117
+ return _context.abrupt("break", 35);
118
+ case 35:
119
+ _context.next = 53;
121
120
  break;
122
- case 38:
123
- _context.prev = 38;
121
+ case 37:
122
+ _context.prev = 37;
124
123
  _context.t2 = _context["catch"](6);
125
124
  console.error('文件上传失败:', _context.t2);
126
125
  if (isImage) {
@@ -134,34 +133,34 @@ export var FileHandlerExtension = function FileHandlerExtension(props) {
134
133
  _chain.setTextSelection(_progressPos);
135
134
  }
136
135
  _context.t3 = fileType;
137
- _context.next = _context.t3 === 'image' ? 48 : _context.t3 === 'video' ? 50 : 52;
136
+ _context.next = _context.t3 === 'image' ? 47 : _context.t3 === 'video' ? 49 : 51;
138
137
  break;
139
- case 48:
138
+ case 47:
140
139
  _chain.setImage({
141
140
  src: '',
142
141
  width: 760
143
142
  }).run();
144
- return _context.abrupt("break", 54);
145
- case 50:
143
+ return _context.abrupt("break", 53);
144
+ case 49:
146
145
  _chain.setVideo({
147
146
  src: '',
148
147
  width: 760,
149
148
  controls: true,
150
149
  autoplay: false
151
150
  }).run();
152
- return _context.abrupt("break", 54);
153
- case 52:
151
+ return _context.abrupt("break", 53);
152
+ case 51:
154
153
  _chain.setBlockAttachment({
155
154
  url: 'error',
156
155
  title: "\u4E0A\u4F20\u5931\u8D25: ".concat(file.name),
157
156
  size: formatFileSize(file.size)
158
157
  }).run();
159
- return _context.abrupt("break", 54);
160
- case 54:
158
+ return _context.abrupt("break", 53);
159
+ case 53:
161
160
  case "end":
162
161
  return _context.stop();
163
162
  }
164
- }, _loop, null, [[6, 38], [18, 25]]);
163
+ }, _loop, null, [[6, 37], [18, 25]]);
165
164
  });
166
165
  i = 0;
167
166
  case 5:
@@ -185,141 +184,5 @@ export var FileHandlerExtension = function FileHandlerExtension(props) {
185
184
  }
186
185
  return onDrop;
187
186
  }()
188
- // onPaste: async (editor, files, pasteContent) => {
189
- // if (!props.onUpload || files.length === 0 || !!pasteContent) return false;
190
- // const { from } = editor.state.selection;
191
- // if (files.length > 0) {
192
- // const findNodePosition = (typeName: string, tempId: string) => {
193
- // let targetPos: number | null = null;
194
- // editor.state.doc.descendants((node, position) => {
195
- // if (node.type.name === typeName && node.attrs.tempId === tempId) {
196
- // targetPos = position;
197
- // return false;
198
- // }
199
- // return undefined;
200
- // });
201
- // return targetPos;
202
- // };
203
- // for (let i = 0; i < files.length; i++) {
204
- // const file = files[i];
205
- // const fileType = getFileType(file);
206
- // const tempId = `upload-${Date.now()}-${i}`;
207
- // const insertPosition = from + i;
208
- // const isImage = fileType === 'image';
209
- // const progressNodeType = isImage ? 'inlineUploadProgress' : 'uploadProgress';
210
- // try {
211
- // editor.chain().insertContentAt(insertPosition, {
212
- // type: progressNodeType,
213
- // attrs: {
214
- // fileName: file.name,
215
- // fileType,
216
- // progress: 0,
217
- // tempId,
218
- // },
219
- // }).focus().run();
220
-
221
- // const progressPos = findNodePosition(progressNodeType, tempId);
222
-
223
- // const url = await props.onUpload(file, (progressEvent) => {
224
- // const progressValue = progressEvent.progress;
225
- // if (isImage) {
226
- // editor.chain().updateInlineUploadProgress(tempId, progressValue).focus().run();
227
- // } else {
228
- // editor.chain().updateUploadProgress(tempId, progressValue).focus().run();
229
- // }
230
- // });
231
-
232
- // if (isImage) {
233
- // editor.chain().removeInlineUploadProgress(tempId).focus().run();
234
- // } else {
235
- // editor.chain().removeUploadProgress(tempId).focus().run();
236
- // }
237
-
238
- // const chain = editor.chain().focus();
239
- // if (progressPos !== null) {
240
- // chain.setTextSelection(progressPos);
241
- // }
242
-
243
- // switch (fileType) {
244
- // case 'image':
245
- // try {
246
- // const dimensions = await getImageDimensionsFromFile(file);
247
- // chain.setImage({
248
- // src: url,
249
- // width: Math.min(dimensions.width, 760) // 使用原始宽度,但不超过760px
250
- // }).run();
251
- // } catch (error) {
252
- // console.warn('无法获取图片尺寸,使用默认宽度:', error);
253
- // const fallbackChain = editor.chain().focus();
254
- // if (progressPos !== null) {
255
- // fallbackChain.setTextSelection(progressPos);
256
- // }
257
- // fallbackChain.setImage({
258
- // src: url,
259
- // width: 760
260
- // }).run();
261
- // }
262
- // break;
263
- // case 'video':
264
- // chain.setVideo({
265
- // src: url,
266
- // width: 760,
267
- // controls: true,
268
- // autoplay: false
269
- // }).run();
270
- // break;
271
- // default:
272
- // chain.setBlockAttachment({
273
- // url: url,
274
- // title: file.name,
275
- // size: formatFileSize(file.size)
276
- // }).run();
277
- // break;
278
- // }
279
- // } catch (error) {
280
- // console.error('文件上传失败:', error);
281
- // const tempId = `upload-${Date.now()}-${i}`;
282
- // const isImage = fileType === 'image';
283
- // const progressNodeType = isImage ? 'inlineUploadProgress' : 'uploadProgress';
284
- // const progressPos = findNodePosition(progressNodeType, tempId);
285
-
286
- // if (isImage) {
287
- // editor.chain().removeInlineUploadProgress(tempId).focus().run();
288
- // } else {
289
- // editor.chain().removeUploadProgress(tempId).focus().run();
290
- // }
291
-
292
- // const chain = editor.chain().focus();
293
- // if (progressPos !== null) {
294
- // chain.setTextSelection(progressPos);
295
- // }
296
- // switch (fileType) {
297
- // case 'image':
298
- // chain.setImage({
299
- // src: '',
300
- // width: 760
301
- // }).run();
302
- // break;
303
- // case 'video':
304
- // chain.setVideo({
305
- // src: '',
306
- // width: 760,
307
- // controls: true,
308
- // autoplay: false
309
- // }).run();
310
- // break;
311
- // default:
312
- // chain.setBlockAttachment({
313
- // url: 'error',
314
- // title: `上传失败: ${file.name}`,
315
- // size: formatFileSize(file.size)
316
- // }).run();
317
- // break;
318
- // }
319
- // }
320
- // }
321
- // }
322
- // return true;
323
- // },
324
187
  });
325
188
  };
@@ -40,7 +40,7 @@ var customImage = function customImage(props) {
40
40
  key: new PluginKey('imagePasteHandler'),
41
41
  props: {
42
42
  handlePaste: function handlePaste(view, event) {
43
- var _event$clipboardData;
43
+ var _event$clipboardData, _event$clipboardData2, _event$clipboardData3;
44
44
  if (!props.onUpload) return false;
45
45
  var items = Array.from(((_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.items) || []);
46
46
  var imageFiles = items.map(function (item) {
@@ -49,6 +49,23 @@ var customImage = function customImage(props) {
49
49
  return file !== null && getFileType(file) === 'image';
50
50
  });
51
51
  if (imageFiles.length === 0) return false;
52
+ var htmlData = (_event$clipboardData2 = event.clipboardData) === null || _event$clipboardData2 === void 0 ? void 0 : _event$clipboardData2.getData('text/html');
53
+ if (htmlData && htmlData.trim().length > 0) {
54
+ var htmlLower = htmlData.toLowerCase();
55
+ if (htmlLower.includes('<table') || htmlLower.includes('<tr') || htmlLower.includes('<td') || htmlLower.includes('<th')) {
56
+ return false;
57
+ }
58
+ }
59
+ var textData = (_event$clipboardData3 = event.clipboardData) === null || _event$clipboardData3 === void 0 ? void 0 : _event$clipboardData3.getData('text/plain');
60
+ if (textData && textData.trim().length > 0) {
61
+ var trimmedText = textData.trim();
62
+ var hasTab = trimmedText.includes('\t');
63
+ var lineCount = trimmedText.split('\n').length;
64
+ var isLikelyFileName = /\.(jpg|jpeg|png|gif|webp|svg|bmp)$/i.test(trimmedText);
65
+ if ((hasTab || lineCount > 2) && !isLikelyFileName) {
66
+ return false;
67
+ }
68
+ }
52
69
  var from = view.state.selection.from;
53
70
  var editor = _this2.editor;
54
71
  var findNodePosition = function findNodePosition(typeName, tempId) {
@@ -111,14 +128,13 @@ var customImage = function customImage(props) {
111
128
  dimensions = _context.sent;
112
129
  chain.setImage({
113
130
  src: url,
114
- width: Math.min(dimensions.width, 760) // 使用原始宽度,但不超过760px
131
+ width: Math.min(dimensions.width, 760)
115
132
  }).run();
116
- _context.next = 25;
133
+ _context.next = 24;
117
134
  break;
118
135
  case 19:
119
136
  _context.prev = 19;
120
137
  _context.t0 = _context["catch"](12);
121
- console.warn('无法获取图片尺寸,使用默认宽度:', _context.t0);
122
138
  fallbackChain = editor.chain().focus();
123
139
  if (progressPos !== null) {
124
140
  fallbackChain.setTextSelection(progressPos);
@@ -127,13 +143,12 @@ var customImage = function customImage(props) {
127
143
  src: url,
128
144
  width: 760
129
145
  }).run();
130
- case 25:
131
- _context.next = 35;
146
+ case 24:
147
+ _context.next = 33;
132
148
  break;
133
- case 27:
134
- _context.prev = 27;
149
+ case 26:
150
+ _context.prev = 26;
135
151
  _context.t1 = _context["catch"](3);
136
- console.error('图片上传失败:', _context.t1);
137
152
  editor.chain().removeInlineUploadProgress(tempId).focus().run();
138
153
  _progressPos = findNodePosition('inlineUploadProgress', tempId);
139
154
  _chain = editor.chain().focus();
@@ -144,11 +159,11 @@ var customImage = function customImage(props) {
144
159
  src: '',
145
160
  width: 760
146
161
  }).run();
147
- case 35:
162
+ case 33:
148
163
  case "end":
149
164
  return _context.stop();
150
165
  }
151
- }, _loop, null, [[3, 27], [12, 19]]);
166
+ }, _loop, null, [[3, 26], [12, 19]]);
152
167
  });
153
168
  i = 0;
154
169
  case 4:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctzhian/tiptap",
3
- "version": "1.13.1",
3
+ "version": "1.13.3",
4
4
  "description": "基于 Tiptap 二次开发的编辑器组件",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",