@ctzhian/tiptap 2.12.8 → 2.13.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.
@@ -5,6 +5,7 @@ interface AttachmentContentProps {
5
5
  type: 'icon' | 'block';
6
6
  isPdf: boolean;
7
7
  editable?: boolean;
8
+ updateAttributes?: (attrs: Partial<AttachmentAttributes>) => void;
8
9
  }
9
10
  /**
10
11
  * 附件内容组件
@@ -16,8 +16,8 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
16
16
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
17
17
  import { Download2LineIcon, FileIcon } from "../../../component/Icons";
18
18
  import { EyeLineIcon } from "../../../component/Icons/eye-line-icon";
19
- import { Box, IconButton, Stack } from "@mui/material";
20
- import React, { useState } from "react";
19
+ import { alpha, Box, IconButton, Stack, useTheme } from "@mui/material";
20
+ import React, { useCallback, useEffect, useRef, useState } from "react";
21
21
  /**
22
22
  * 附件内容组件
23
23
  * 用于渲染附件的实际内容,支持编辑和只读模式
@@ -27,11 +27,23 @@ export var AttachmentContent = function AttachmentContent(_ref) {
27
27
  type = _ref.type,
28
28
  isPdf = _ref.isPdf,
29
29
  _ref$editable = _ref.editable,
30
- editable = _ref$editable === void 0 ? false : _ref$editable;
30
+ editable = _ref$editable === void 0 ? false : _ref$editable,
31
+ updateAttributes = _ref.updateAttributes;
32
+ var theme = useTheme();
31
33
  var _useState = useState(false),
32
34
  _useState2 = _slicedToArray(_useState, 2),
33
35
  isHovered = _useState2[0],
34
36
  setIsHovered = _useState2[1];
37
+ var _useState3 = useState(false),
38
+ _useState4 = _slicedToArray(_useState3, 2),
39
+ isDragging = _useState4[0],
40
+ setIsDragging = _useState4[1];
41
+ var _useState5 = useState(null),
42
+ _useState6 = _slicedToArray(_useState5, 2),
43
+ dragCorner = _useState6[0],
44
+ setDragCorner = _useState6[1];
45
+ var dragStartYRef = useRef(0);
46
+ var dragStartHeightRef = useRef(0);
35
47
  var handlePreview = function handlePreview(e) {
36
48
  e.preventDefault();
37
49
  e.stopPropagation();
@@ -92,6 +104,52 @@ export var AttachmentContent = function AttachmentContent(_ref) {
92
104
  return _ref2.apply(this, arguments);
93
105
  };
94
106
  }();
107
+
108
+ // 拖拽调整高度
109
+ var handleMouseDown = function handleMouseDown(e, corner) {
110
+ e.preventDefault();
111
+ e.stopPropagation();
112
+ setIsDragging(true);
113
+ setDragCorner(corner);
114
+ dragStartYRef.current = e.clientY;
115
+ dragStartHeightRef.current = attrs.height || 300;
116
+ };
117
+ var handleMouseMove = useCallback(function (e) {
118
+ if (!isDragging || !dragCorner) return;
119
+ var deltaY = e.clientY - dragStartYRef.current;
120
+ var newHeight;
121
+
122
+ // 根据不同的角计算高度变化
123
+ if (dragCorner === 'bottom-left' || dragCorner === 'bottom-right') {
124
+ // 下角:向下拉伸,高度增加
125
+ newHeight = dragStartHeightRef.current + deltaY;
126
+ } else {
127
+ // 上角:向上拉伸,高度增加(deltaY 为负时高度增加)
128
+ newHeight = dragStartHeightRef.current - deltaY;
129
+ }
130
+
131
+ // 限制高度范围:最小 200px,最大 1000px
132
+ newHeight = Math.max(200, Math.min(1000, newHeight));
133
+ if (updateAttributes) {
134
+ updateAttributes({
135
+ height: newHeight
136
+ });
137
+ }
138
+ }, [isDragging, dragCorner, updateAttributes]);
139
+ var handleMouseUp = useCallback(function () {
140
+ setIsDragging(false);
141
+ setDragCorner(null);
142
+ }, []);
143
+ useEffect(function () {
144
+ if (isDragging) {
145
+ document.addEventListener('mousemove', handleMouseMove);
146
+ document.addEventListener('mouseup', handleMouseUp);
147
+ return function () {
148
+ document.removeEventListener('mousemove', handleMouseMove);
149
+ document.removeEventListener('mouseup', handleMouseUp);
150
+ };
151
+ }
152
+ }, [isDragging, handleMouseMove, handleMouseUp]);
95
153
  var blockStyles = editable ? {
96
154
  display: 'flex',
97
155
  border: '1px solid',
@@ -149,32 +207,117 @@ export var AttachmentContent = function AttachmentContent(_ref) {
149
207
  color: 'primary.main',
150
208
  cursor: 'pointer'
151
209
  };
152
- return /*#__PURE__*/React.createElement(React.Fragment, null, type === 'block' ? attrs.view === '1' && isPdf && attrs.url && attrs.url !== 'error' ? /*#__PURE__*/React.createElement(Box, _extends({
153
- sx: _objectSpread(_objectSpread({}, blockStyles), {}, {
154
- p: 0,
155
- overflow: 'hidden'
156
- })
157
- }, !editable && {
158
- 'data-title': attrs.title,
159
- 'data-type': type
160
- }, {
210
+ return /*#__PURE__*/React.createElement(React.Fragment, null, type === 'block' ? attrs.view === '1' && isPdf && attrs.url && attrs.url !== 'error' ? /*#__PURE__*/React.createElement(Box, {
211
+ sx: {
212
+ position: 'relative'
213
+ },
161
214
  onMouseEnter: function onMouseEnter() {
162
215
  return setIsHovered(true);
163
216
  },
164
217
  onMouseLeave: function onMouseLeave() {
165
218
  return setIsHovered(false);
166
219
  }
220
+ }, /*#__PURE__*/React.createElement(Box, _extends({
221
+ sx: _objectSpread(_objectSpread({}, blockStyles), {}, {
222
+ p: 0,
223
+ overflow: 'hidden',
224
+ height: "".concat(attrs.height || 300, "px")
225
+ })
226
+ }, !editable && {
227
+ 'data-title': attrs.title,
228
+ 'data-type': type
167
229
  }), /*#__PURE__*/React.createElement("iframe", {
168
230
  src: attrs.url + '#navpanes=0&toolbar=1',
169
231
  width: "100%",
170
- height: "300px",
232
+ height: "100%",
171
233
  allowFullScreen: true,
172
234
  style: {
173
235
  border: 'none',
174
- display: 'block'
236
+ display: 'block',
237
+ pointerEvents: isDragging ? 'none' : 'auto'
175
238
  },
176
239
  title: attrs.title
177
- })) : /*#__PURE__*/React.createElement(Box, _extends({}, !editable && {
240
+ })), editable && (isHovered || isDragging) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Box, {
241
+ onMouseDown: function onMouseDown(e) {
242
+ return handleMouseDown(e, 'top-left');
243
+ },
244
+ sx: {
245
+ position: 'absolute',
246
+ left: -4,
247
+ top: -4,
248
+ width: 12,
249
+ height: 12,
250
+ bgcolor: 'background.default',
251
+ cursor: 'ns-resize',
252
+ borderRadius: '50%',
253
+ border: '2px solid',
254
+ borderColor: isDragging && dragCorner === 'top-left' ? 'primary.main' : alpha(theme.palette.primary.main, 0.3),
255
+ '&:hover': {
256
+ borderColor: 'primary.main'
257
+ },
258
+ transition: 'background-color 0.2s ease'
259
+ }
260
+ }), /*#__PURE__*/React.createElement(Box, {
261
+ onMouseDown: function onMouseDown(e) {
262
+ return handleMouseDown(e, 'top-right');
263
+ },
264
+ sx: {
265
+ position: 'absolute',
266
+ right: -4,
267
+ top: -4,
268
+ width: 12,
269
+ height: 12,
270
+ bgcolor: 'background.default',
271
+ cursor: 'ns-resize',
272
+ borderRadius: '50%',
273
+ border: '2px solid',
274
+ borderColor: isDragging && dragCorner === 'top-right' ? 'primary.main' : alpha(theme.palette.primary.main, 0.3),
275
+ '&:hover': {
276
+ borderColor: 'primary.main'
277
+ },
278
+ transition: 'background-color 0.2s ease'
279
+ }
280
+ }), /*#__PURE__*/React.createElement(Box, {
281
+ onMouseDown: function onMouseDown(e) {
282
+ return handleMouseDown(e, 'bottom-left');
283
+ },
284
+ sx: {
285
+ position: 'absolute',
286
+ left: -4,
287
+ bottom: -2,
288
+ width: 12,
289
+ height: 12,
290
+ cursor: 'ns-resize',
291
+ borderRadius: '50%',
292
+ border: '2px solid',
293
+ bgcolor: 'background.default',
294
+ borderColor: isDragging && dragCorner === 'bottom-left' ? 'primary.main' : alpha(theme.palette.primary.main, 0.3),
295
+ '&:hover': {
296
+ borderColor: 'primary.main'
297
+ },
298
+ transition: 'background-color 0.2s ease'
299
+ }
300
+ }), /*#__PURE__*/React.createElement(Box, {
301
+ onMouseDown: function onMouseDown(e) {
302
+ return handleMouseDown(e, 'bottom-right');
303
+ },
304
+ sx: {
305
+ position: 'absolute',
306
+ right: -4,
307
+ bottom: -2,
308
+ width: 12,
309
+ height: 12,
310
+ bgcolor: 'background.default',
311
+ cursor: 'ns-resize',
312
+ borderRadius: '50%',
313
+ border: '2px solid',
314
+ borderColor: isDragging && dragCorner === 'bottom-right' ? 'primary.main' : alpha(theme.palette.primary.main, 0.3),
315
+ '&:hover': {
316
+ borderColor: 'primary.main'
317
+ },
318
+ transition: 'background-color 0.2s ease'
319
+ }
320
+ }))) : /*#__PURE__*/React.createElement(Box, _extends({}, !editable && {
178
321
  'data-title': attrs.title,
179
322
  'data-type': attrs.type
180
323
  }, {
@@ -7,6 +7,7 @@ export interface AttachmentAttributes {
7
7
  type: string;
8
8
  size: string;
9
9
  view?: string;
10
+ height?: number;
10
11
  }
11
12
  declare const AttachmentViewWrapper: React.FC<NodeViewProps & EditorFnProps & {
12
13
  attachmentType?: 'icon' | 'block';
@@ -258,7 +258,8 @@ var AttachmentViewWrapper = function AttachmentViewWrapper(_ref) {
258
258
  isPdf: isPdf,
259
259
  attrs: attrs,
260
260
  type: attachmentDisplayType === 'block' ? 'block' : 'icon',
261
- editable: true
261
+ editable: true,
262
+ updateAttributes: updateAttributes
262
263
  }))), /*#__PURE__*/React.createElement(FloatingPopover, {
263
264
  open: Boolean(anchorEl),
264
265
  anchorEl: anchorEl,
@@ -21,6 +21,7 @@ declare module '@tiptap/core' {
21
21
  title: string;
22
22
  size: string;
23
23
  view?: '0' | '1';
24
+ height?: number;
24
25
  }) => ReturnType;
25
26
  };
26
27
  }
@@ -175,6 +175,18 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
175
175
  };
176
176
  }
177
177
  },
178
+ height: {
179
+ default: 300,
180
+ parseHTML: function parseHTML(element) {
181
+ var height = element.getAttribute('data-height');
182
+ return height ? parseInt(height, 10) : 300;
183
+ },
184
+ renderHTML: function renderHTML(attributes) {
185
+ return {
186
+ 'data-height': attributes.height || 300
187
+ };
188
+ }
189
+ },
178
190
  url: {
179
191
  default: '',
180
192
  parseHTML: function parseHTML(element) {
@@ -228,8 +240,10 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
228
240
  getAttrs: function getAttrs(dom) {
229
241
  if (!(dom instanceof HTMLElement)) return false;
230
242
  var viewAttr = dom.getAttribute('data-view');
243
+ var heightAttr = dom.getAttribute('data-height');
231
244
  return {
232
245
  view: viewAttr !== null ? viewAttr : '0',
246
+ height: heightAttr ? parseInt(heightAttr, 10) : 300,
233
247
  url: dom.getAttribute('data-url') || '',
234
248
  title: dom.getAttribute('data-title') || '',
235
249
  size: dom.getAttribute('data-size') || '0',
@@ -243,6 +257,7 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
243
257
  var download = dom.getAttribute('download');
244
258
  var type = dom.getAttribute('type');
245
259
  var view = dom.getAttribute('data-view') || '0';
260
+ var heightAttr = dom.getAttribute('data-height');
246
261
 
247
262
  // 只解析 type="block" 的带 download 的 <a> 标签
248
263
  if (download === null || type !== 'block') {
@@ -252,6 +267,7 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
252
267
  var title = dom.textContent || dom.getAttribute('title') || dom.getAttribute('download') || '';
253
268
  return {
254
269
  view: view,
270
+ height: heightAttr ? parseInt(heightAttr, 10) : 300,
255
271
  url: href,
256
272
  title: title,
257
273
  size: '0',
@@ -270,9 +286,10 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
270
286
  var _ref5 = node.attrs,
271
287
  url = _ref5.url,
272
288
  title = _ref5.title,
273
- view = _ref5.view;
289
+ view = _ref5.view,
290
+ height = _ref5.height;
274
291
  if (!url) return '';
275
- return "<a href=\"".concat(url, "\" data-view=\"").concat(view, "\" type=\"block\" target=\"_blank\" download=\"").concat(title, "\">").concat(title, "</a>");
292
+ return "<a href=\"".concat(url, "\" data-view=\"").concat(view, "\" data-height=\"").concat(height || 300, "\" type=\"block\" target=\"_blank\" download=\"").concat(title, "\">").concat(title, "</a>");
276
293
  },
277
294
  addCommands: function addCommands() {
278
295
  var _this3 = this;
@@ -284,6 +301,7 @@ export var BlockAttachmentExtension = function BlockAttachmentExtension(props) {
284
301
  type: _this3.name,
285
302
  attrs: {
286
303
  view: options.view || '0',
304
+ height: options.height || 300,
287
305
  url: options.url || '',
288
306
  title: options.title || '',
289
307
  size: options.size || '0',
@@ -31,66 +31,56 @@ function _downloadImageAsFile() {
31
31
  while (1) switch (_context5.prev = _context5.next) {
32
32
  case 0:
33
33
  _context5.prev = 0;
34
- console.log("[\u4E0B\u8F7D] \u5F00\u59CB\u4E0B\u8F7D\u56FE\u7247 ".concat(index + 1, ": ").concat(url.substring(0, 100)));
35
-
36
- // 尝试不带 credentials 下载
37
- _context5.next = 4;
34
+ _context5.next = 3;
38
35
  return fetch(url, {
39
36
  mode: 'cors',
40
37
  credentials: 'omit'
41
38
  });
42
- case 4:
39
+ case 3:
43
40
  response = _context5.sent;
44
41
  if (response.ok) {
45
- _context5.next = 13;
42
+ _context5.next = 11;
46
43
  break;
47
44
  }
48
- console.warn("[\u4E0B\u8F7D] \u56FE\u7247 ".concat(index + 1, " \u76F4\u63A5\u4E0B\u8F7D\u5931\u8D25 (").concat(response.status, ")\uFF0C\u5C1D\u8BD5\u65E0\u9650\u5236\u6A21\u5F0F"));
49
- // 再试一次,允许跨域
50
- _context5.next = 9;
45
+ _context5.next = 7;
51
46
  return fetch(url, {
52
47
  mode: 'no-cors'
53
48
  });
54
- case 9:
49
+ case 7:
55
50
  response = _context5.sent;
56
51
  if (!(response.type === 'opaque')) {
57
- _context5.next = 13;
52
+ _context5.next = 11;
58
53
  break;
59
54
  }
60
- console.error("[\u4E0B\u8F7D] \u56FE\u7247 ".concat(index + 1, " \u88ABCORS\u963B\u6B62\uFF0C\u65E0\u6CD5\u4E0B\u8F7D"));
55
+ console.error("[\u56FE\u7247\u4E0B\u8F7D] \u56FE\u7247 ".concat(index + 1, " \u88ABCORS\u963B\u6B62\uFF0C\u65E0\u6CD5\u4E0B\u8F7D"));
61
56
  return _context5.abrupt("return", null);
62
- case 13:
63
- _context5.next = 15;
57
+ case 11:
58
+ _context5.next = 13;
64
59
  return response.blob();
65
- case 15:
60
+ case 13:
66
61
  blob = _context5.sent;
67
62
  if (!(blob.size === 0)) {
68
- _context5.next = 19;
63
+ _context5.next = 17;
69
64
  break;
70
65
  }
71
- console.error("[\u4E0B\u8F7D] \u56FE\u7247 ".concat(index + 1, " blob\u4E3A\u7A7A"));
66
+ console.error("[\u56FE\u7247\u4E0B\u8F7D] \u56FE\u7247 ".concat(index + 1, " blob\u4E3A\u7A7A"));
72
67
  return _context5.abrupt("return", null);
73
- case 19:
68
+ case 17:
74
69
  fileName = "image-".concat(index + 1, ".").concat(blob.type.split('/')[1] || 'png');
75
70
  file = new File([blob], fileName, {
76
71
  type: blob.type
77
- });
78
- console.log("[\u4E0B\u8F7D] \u56FE\u7247 ".concat(index + 1, " \u4E0B\u8F7D\u6210\u529F:"), {
79
- name: file.name,
80
- type: file.type,
81
- size: file.size
82
- });
72
+ }); // console.log(`[下载] 图片 ${index + 1} 下载成功:`, { name: file.name, type: file.type, size: file.size });
83
73
  return _context5.abrupt("return", file);
84
- case 25:
85
- _context5.prev = 25;
74
+ case 22:
75
+ _context5.prev = 22;
86
76
  _context5.t0 = _context5["catch"](0);
87
- console.error("[\u4E0B\u8F7D] \u56FE\u7247 ".concat(index + 1, " \u4E0B\u8F7D\u5F02\u5E38:"), _context5.t0);
77
+ console.error("[\u56FE\u7247\u4E0B\u8F7D] \u56FE\u7247 ".concat(index + 1, " \u4E0B\u8F7D\u5F02\u5E38:"), _context5.t0);
88
78
  return _context5.abrupt("return", null);
89
- case 29:
79
+ case 26:
90
80
  case "end":
91
81
  return _context5.stop();
92
82
  }
93
- }, _callee5, null, [[0, 25]]);
83
+ }, _callee5, null, [[0, 22]]);
94
84
  }));
95
85
  return _downloadImageAsFile.apply(this, arguments);
96
86
  }
@@ -212,48 +202,15 @@ var customImage = function customImage(props) {
212
202
  key: new PluginKey('imagePasteHandler'),
213
203
  props: {
214
204
  handlePaste: function handlePaste(view, event) {
215
- var _event$clipboardData, _event$clipboardData2, _event$clipboardData3;
205
+ var _event$clipboardData, _event$clipboardData2;
216
206
  if (!props.onUpload) return false;
217
207
  var items = Array.from(((_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.items) || []);
218
- console.log('=== 图片粘贴调试 ===');
219
- console.log('1. clipboardData.items:', items.map(function (item) {
220
- return {
221
- kind: item.kind,
222
- type: item.type
223
- };
224
- }));
225
208
  var imageFiles = items.map(function (item) {
226
209
  return item.getAsFile();
227
210
  }).filter(function (file) {
228
211
  return file !== null && getFileType(file) === 'image';
229
212
  });
230
- console.log('2. 提取到的图片文件:', imageFiles.map(function (f) {
231
- return {
232
- name: f.name,
233
- type: f.type,
234
- size: f.size
235
- };
236
- }));
237
213
  var htmlData = (_event$clipboardData2 = event.clipboardData) === null || _event$clipboardData2 === void 0 ? void 0 : _event$clipboardData2.getData('text/html');
238
- var textData = (_event$clipboardData3 = event.clipboardData) === null || _event$clipboardData3 === void 0 ? void 0 : _event$clipboardData3.getData('text/plain');
239
- console.log('3. 完整 HTML 内容:');
240
- console.log(htmlData || '(无)');
241
- console.log('4. 完整纯文本内容:');
242
- console.log(textData || '(无)');
243
-
244
- // 从 HTML 中提取所有 img 标签
245
- var imgMatches = (htmlData === null || htmlData === void 0 ? void 0 : htmlData.matchAll(/<img[^>]+>/gi)) || [];
246
- var imgTags = Array.from(imgMatches);
247
- console.log('5. HTML 中的 img 标签数量:', imgTags.length);
248
- imgTags.forEach(function (match, i) {
249
- var _srcMatch$;
250
- var imgTag = match[0];
251
- var srcMatch = imgTag.match(/src=["']([^"']+)["']/i);
252
- console.log(" \u56FE\u7247 ".concat(i + 1, ":"), {
253
- tag: imgTag.substring(0, 100),
254
- src: (srcMatch === null || srcMatch === void 0 || (_srcMatch$ = srcMatch[1]) === null || _srcMatch$ === void 0 ? void 0 : _srcMatch$.substring(0, 100)) || '无src'
255
- });
256
- });
257
214
 
258
215
  // 提前声明变量和函数,避免在异步回调中出现 TDZ 错误
259
216
  var _view$state$selection = view.state.selection,
@@ -279,39 +236,33 @@ var customImage = function customImage(props) {
279
236
  return _regeneratorRuntime().wrap(function _callee$(_context) {
280
237
  while (1) switch (_context.prev = _context.next) {
281
238
  case 0:
282
- console.log("[\u4E0A\u4F20] \u5F00\u59CB\u4E0A\u4F20: ".concat(file.name, ", tempId: ").concat(tempId));
283
- _context.prev = 1;
239
+ _context.prev = 0;
284
240
  progressPos = findNodePosition('inlineUploadProgress', tempId);
285
- console.log("[\u4E0A\u4F20] \u627E\u5230 progress \u8282\u70B9\u4F4D\u7F6E: ".concat(progressPos));
286
- _context.next = 6;
241
+ _context.next = 4;
287
242
  return props.onUpload(file, function (progressEvent) {
288
- console.log("[\u4E0A\u4F20] ".concat(file.name, " \u8FDB\u5EA6: ").concat(Math.round(progressEvent.progress * 100), "%"));
289
243
  editor.chain().updateInlineUploadProgress(tempId, progressEvent.progress).focus().run();
290
244
  });
291
- case 6:
245
+ case 4:
292
246
  url = _context.sent;
293
- console.log("[\u4E0A\u4F20] ".concat(file.name, " \u4E0A\u4F20\u5B8C\u6210\uFF0CURL: ").concat(url));
294
247
  editor.chain().removeInlineUploadProgress(tempId).focus().run();
295
248
  chain = editor.chain().focus();
296
249
  if (progressPos !== null) {
297
250
  chain.setTextSelection(progressPos);
298
251
  }
299
- _context.prev = 11;
300
- _context.next = 14;
252
+ _context.prev = 8;
253
+ _context.next = 11;
301
254
  return getImageDimensionsFromFile(file);
302
- case 14:
255
+ case 11:
303
256
  dimensions = _context.sent;
304
- console.log("[\u4E0A\u4F20] ".concat(file.name, " \u5C3A\u5BF8: ").concat(dimensions.width, "x").concat(dimensions.height));
305
257
  chain.setImage({
306
258
  src: url,
307
259
  width: Math.min(dimensions.width, 760)
308
260
  }).run();
309
- _context.next = 25;
261
+ _context.next = 20;
310
262
  break;
311
- case 19:
312
- _context.prev = 19;
313
- _context.t0 = _context["catch"](11);
314
- console.log("[\u4E0A\u4F20] ".concat(file.name, " \u83B7\u53D6\u5C3A\u5BF8\u5931\u8D25\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u5BBD\u5EA6"));
263
+ case 15:
264
+ _context.prev = 15;
265
+ _context.t0 = _context["catch"](8);
315
266
  fallbackChain = editor.chain().focus();
316
267
  if (progressPos !== null) {
317
268
  fallbackChain.setTextSelection(progressPos);
@@ -320,14 +271,13 @@ var customImage = function customImage(props) {
320
271
  src: url,
321
272
  width: 760
322
273
  }).run();
323
- case 25:
324
- console.log("[\u4E0A\u4F20] ".concat(file.name, " \u5B8C\u6210\u6240\u6709\u5904\u7406"));
325
- _context.next = 36;
274
+ case 20:
275
+ _context.next = 30;
326
276
  break;
327
- case 28:
328
- _context.prev = 28;
329
- _context.t1 = _context["catch"](1);
330
- console.error("[\u4E0A\u4F20] ".concat(file.name, " \u4E0A\u4F20\u5931\u8D25:"), _context.t1);
277
+ case 22:
278
+ _context.prev = 22;
279
+ _context.t1 = _context["catch"](0);
280
+ console.error("[\u56FE\u7247\u4E0A\u4F20] ".concat(file.name, " \u4E0A\u4F20\u5931\u8D25:"), _context.t1);
331
281
  editor.chain().removeInlineUploadProgress(tempId).focus().run();
332
282
  _progressPos = findNodePosition('inlineUploadProgress', tempId);
333
283
  _chain = editor.chain().focus();
@@ -338,11 +288,11 @@ var customImage = function customImage(props) {
338
288
  src: '',
339
289
  width: 760
340
290
  }).run();
341
- case 36:
291
+ case 30:
342
292
  case "end":
343
293
  return _context.stop();
344
294
  }
345
- }, _callee, null, [[1, 28], [11, 19]]);
295
+ }, _callee, null, [[0, 22], [8, 15]]);
346
296
  }));
347
297
  return function uploadSingleImage(_x3, _x4) {
348
298
  return _ref.apply(this, arguments);
@@ -350,7 +300,7 @@ var customImage = function customImage(props) {
350
300
  }();
351
301
  var processImagePaste = /*#__PURE__*/function () {
352
302
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(files, html, fromPos, toPos) {
353
- var _htmlTrimmed$match, _htmlTrimmed$match2;
303
+ var _htmlTrimmed$match;
354
304
  var htmlTrimmed, hasRichHtml, _parsed$content, extensions, parsed, tempIds, fileIndex, modifiedDoc, finalDoc, i, useSimpleInsert;
355
305
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
356
306
  while (1) switch (_context2.prev = _context2.next) {
@@ -371,19 +321,12 @@ var customImage = function customImage(props) {
371
321
  }]
372
322
  };
373
323
  });
374
- console.log('简单插入内容:', JSON.stringify(content, null, 2));
375
- console.log('插入位置:', {
376
- from: fromPos,
377
- to: toPos
378
- });
379
324
  editor.chain().insertContentAt({
380
325
  from: fromPos,
381
326
  to: toPos
382
327
  }, content).focus().run();
383
- console.log('开始触发上传');
384
328
  files.forEach(function (file, i) {
385
329
  var tempId = "upload-".concat(baseTime, "-").concat(i);
386
- console.log("\u89E6\u53D1\u4E0A\u4F20: ".concat(file.name, ", tempId: ").concat(tempId));
387
330
  uploadSingleImage(file, tempId);
388
331
  });
389
332
  };
@@ -395,77 +338,59 @@ var customImage = function customImage(props) {
395
338
  case 3:
396
339
  htmlTrimmed = (html === null || html === void 0 ? void 0 : html.trim()) || '';
397
340
  hasRichHtml = htmlTrimmed.length > 0 && (htmlTrimmed.includes('<p') || htmlTrimmed.includes('<div') || htmlTrimmed.includes('<br') || htmlTrimmed.includes('<span') || ((_htmlTrimmed$match = htmlTrimmed.match(/<img/gi)) === null || _htmlTrimmed$match === void 0 ? void 0 : _htmlTrimmed$match.length) !== 1);
398
- console.log('hasRichHtml 判断:', {
399
- htmlLength: htmlTrimmed.length,
400
- hasPTag: htmlTrimmed.includes('<p'),
401
- hasDivTag: htmlTrimmed.includes('<div'),
402
- hasBrTag: htmlTrimmed.includes('<br'),
403
- hasSpanTag: htmlTrimmed.includes('<span'),
404
- imgCount: ((_htmlTrimmed$match2 = htmlTrimmed.match(/<img/gi)) === null || _htmlTrimmed$match2 === void 0 ? void 0 : _htmlTrimmed$match2.length) || 0,
405
- result: hasRichHtml
406
- });
407
341
  if (!hasRichHtml) {
408
- _context2.next = 40;
342
+ _context2.next = 31;
409
343
  break;
410
344
  }
411
- console.log('走富文本解析路径');
412
- _context2.prev = 8;
345
+ _context2.prev = 6;
413
346
  extensions = editor.extensionManager.extensions;
414
347
  parsed = generateJSON(htmlTrimmed, extensions);
415
- console.log('解析后的 JSON:', JSON.stringify(parsed, null, 2));
416
348
  if (parsed !== null && parsed !== void 0 && (_parsed$content = parsed.content) !== null && _parsed$content !== void 0 && _parsed$content.length) {
417
- _context2.next = 14;
349
+ _context2.next = 11;
418
350
  break;
419
351
  }
420
352
  throw new Error('Empty parsed content');
421
- case 14:
353
+ case 11:
422
354
  tempIds = [];
423
355
  fileIndex = {
424
356
  current: 0
425
357
  };
426
358
  modifiedDoc = replaceImagesWithProgressNodes(parsed, files, fileIndex, tempIds);
427
359
  finalDoc = appendExtraImagesToDoc(modifiedDoc, files, fileIndex.current, tempIds);
428
- console.log('替换后的文档:', JSON.stringify(finalDoc, null, 2));
429
- console.log('tempIds:', tempIds);
430
- console.log('开始插入内容');
431
360
  editor.chain().insertContentAt({
432
361
  from: fromPos,
433
362
  to: toPos
434
363
  }, finalDoc).focus().run();
435
- console.log('开始上传图片');
436
364
  i = 0;
437
- case 24:
365
+ case 17:
438
366
  if (!(i < tempIds.length)) {
439
- _context2.next = 31;
367
+ _context2.next = 23;
440
368
  break;
441
369
  }
442
- console.log("\u4E0A\u4F20\u7B2C ".concat(i + 1, "/").concat(tempIds.length, " \u5F20\u56FE\u7247, tempId: ").concat(tempIds[i]));
443
- _context2.next = 28;
370
+ _context2.next = 20;
444
371
  return uploadSingleImage(files[i], tempIds[i]);
445
- case 28:
372
+ case 20:
446
373
  i++;
447
- _context2.next = 24;
374
+ _context2.next = 17;
448
375
  break;
449
- case 31:
450
- console.log('所有图片上传完成');
451
- _context2.next = 38;
376
+ case 23:
377
+ _context2.next = 29;
452
378
  break;
453
- case 34:
454
- _context2.prev = 34;
455
- _context2.t0 = _context2["catch"](8);
456
- console.error('富文本解析失败,fallback 到简单插入:', _context2.t0);
379
+ case 25:
380
+ _context2.prev = 25;
381
+ _context2.t0 = _context2["catch"](6);
382
+ console.error('[图片粘贴] 富文本解析失败,使用简单插入:', _context2.t0);
457
383
  useSimpleInsert(files, fromPos, toPos);
458
- case 38:
459
- _context2.next = 42;
384
+ case 29:
385
+ _context2.next = 32;
460
386
  break;
461
- case 40:
462
- console.log('走简单插入路径');
387
+ case 31:
463
388
  useSimpleInsert(files, fromPos, toPos);
464
- case 42:
389
+ case 32:
465
390
  case "end":
466
391
  return _context2.stop();
467
392
  }
468
- }, _callee2, null, [[8, 34]]);
393
+ }, _callee2, null, [[6, 25]]);
469
394
  }));
470
395
  return function processImagePaste(_x5, _x6, _x7, _x8) {
471
396
  return _ref2.apply(this, arguments);
@@ -475,11 +400,8 @@ var customImage = function customImage(props) {
475
400
  // 如果没有 File 对象,尝试从 HTML 中提取图片 URL
476
401
  var finalImageFiles = imageFiles;
477
402
  if (imageFiles.length === 0 && htmlData) {
478
- console.log('6. 没有图片 File 对象');
479
403
  var imageUrls = extractImageUrls(htmlData);
480
- console.log('7. 从 HTML 中提取到的图片 URL:', imageUrls);
481
404
  if (imageUrls.length > 0) {
482
- console.log('8. 开始下载图片...');
483
405
  event.preventDefault(); // 阻止默认粘贴行为
484
406
 
485
407
  // 异步下载所有图片
@@ -497,68 +419,54 @@ var customImage = function customImage(props) {
497
419
  validFiles = downloadedFiles.filter(function (f) {
498
420
  return f !== null;
499
421
  });
500
- console.log('9. 下载完成,有效文件数:', validFiles.length);
501
422
  if (!(validFiles.length === 0)) {
502
- _context3.next = 24;
423
+ _context3.next = 19;
503
424
  break;
504
425
  }
505
- console.log('10. 没有成功下载任何图片(可能是CORS限制)');
506
- console.log('11. 降级方案:保留原图URL,不上传到服务器');
507
-
508
- // 降级方案:直接粘贴原始HTML,使用原图URL
509
- _context3.prev = 8;
426
+ _context3.prev = 5;
510
427
  extensions = editor.extensionManager.extensions;
511
428
  parsed = generateJSON(htmlData, extensions);
512
429
  if (!(parsed !== null && parsed !== void 0 && (_parsed$content2 = parsed.content) !== null && _parsed$content2 !== void 0 && _parsed$content2.length)) {
513
- _context3.next = 16;
430
+ _context3.next = 12;
514
431
  break;
515
432
  }
516
433
  editor.chain().insertContentAt({
517
434
  from: from,
518
435
  to: to
519
436
  }, parsed).focus().run();
520
- console.log('12. 已插入原始内容,图片使用原URL');
521
- _context3.next = 17;
437
+ _context3.next = 13;
522
438
  break;
523
- case 16:
439
+ case 12:
524
440
  throw new Error('解析失败');
525
- case 17:
526
- _context3.next = 23;
441
+ case 13:
442
+ _context3.next = 18;
527
443
  break;
528
- case 19:
529
- _context3.prev = 19;
530
- _context3.t0 = _context3["catch"](8);
531
- console.log('13. 解析失败,使用默认粘贴');
532
- // 最后兜底:返回false让浏览器处理默认粘贴
444
+ case 15:
445
+ _context3.prev = 15;
446
+ _context3.t0 = _context3["catch"](5);
533
447
  return _context3.abrupt("return");
534
- case 23:
448
+ case 18:
535
449
  return _context3.abrupt("return");
536
- case 24:
537
- // 使用下载的文件继续处理
538
- finalImageFiles = validFiles;
539
- console.log('11. 开始处理下载的图片');
540
- _context3.next = 28;
450
+ case 19:
451
+ _context3.next = 21;
541
452
  return processImagePaste(validFiles, htmlData, from, to);
542
- case 28:
453
+ case 21:
543
454
  case "end":
544
455
  return _context3.stop();
545
456
  }
546
- }, _callee3, null, [[8, 19]]);
457
+ }, _callee3, null, [[5, 15]]);
547
458
  }))();
548
459
  return true; // 已处理
549
460
  } else {
550
- console.log('8. HTML 中没有可下载的图片 URL,退出处理');
551
461
  return false;
552
462
  }
553
463
  }
554
464
  if (imageFiles.length === 0) {
555
- console.log('6. 没有图片,退出处理');
556
465
  return false;
557
466
  }
558
467
  if (htmlData && htmlData.trim().length > 0) {
559
468
  var htmlLower = htmlData.toLowerCase();
560
469
  if (htmlLower.includes('<table') || htmlLower.includes('<tr') || htmlLower.includes('<td') || htmlLower.includes('<th')) {
561
- console.log('检测到表格,退出处理');
562
470
  return false;
563
471
  }
564
472
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctzhian/tiptap",
3
- "version": "2.12.8",
3
+ "version": "2.13.0",
4
4
  "description": "基于 Tiptap 二次开发的编辑器组件",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",