@blocklet/editor 2.1.120 → 2.1.122

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.
@@ -16,6 +16,7 @@ export declare class EditorTranslator {
16
16
  private editor;
17
17
  private options;
18
18
  private originalEditorState;
19
+ private preprocessEditorState;
19
20
  private nodeKeyToSidMap;
20
21
  private sidToNodeKeyMap;
21
22
  private translations;
@@ -32,5 +33,6 @@ export declare class EditorTranslator {
32
33
  }): Promise<void>;
33
34
  applyTranslations(): void;
34
35
  restore(sid?: string): void;
36
+ preprocessNodes(): Promise<void>;
35
37
  }
36
38
  export declare function useEditorTranslator(options: EditorTranslatorOptions): EditorTranslator;
@@ -1,13 +1,17 @@
1
1
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
2
- import { $getNodeByKey } from 'lexical';
2
+ import { $createParagraphNode, $getNodeByKey } from 'lexical';
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { $createNodeKeyToSidMap, $createSidToNodeKeyMap, $nodeToHtml, $findTranslatableElementNodes, $htmlToNodes, } from '../translation/translation-utils';
5
5
  import { $createEmojiNode } from '../../main/nodes/EmojiNode';
6
6
  import { $createTranslationNode } from './TranslationNode';
7
+ import { $isExcalidrawNode } from '../../main/nodes/ExcalidrawNode';
8
+ import { $isImageNode } from '../../main/nodes/ImageNode';
9
+ import { $isPdfNode } from '../PdfPlugin/PdfNode';
7
10
  export class EditorTranslator {
8
11
  editor;
9
12
  options;
10
13
  originalEditorState;
14
+ preprocessEditorState = null;
11
15
  nodeKeyToSidMap = new Map();
12
16
  sidToNodeKeyMap = new Map();
13
17
  translations = [];
@@ -32,13 +36,14 @@ export class EditorTranslator {
32
36
  updateDisplayMode() {
33
37
  // Warning: flushSync was called from inside a lifecycle method
34
38
  setTimeout(() => {
35
- this.editor.setEditorState(this.originalEditorState);
39
+ this.editor.setEditorState(this.preprocessEditorState || this.originalEditorState);
36
40
  this.applyTranslations();
37
41
  }, 10);
38
42
  }
39
43
  async translate({ targetLanguage, translateService, detectLanguage, useCache, }) {
40
44
  // 翻译前备份 editor state (fix 恢复原文时图片路径错误的问题)
41
- this.originalEditorState = this.editor.getEditorState();
45
+ this.originalEditorState = this.editor.getEditorState().clone();
46
+ await this.preprocessNodes();
42
47
  this.nodeKeyToSidMap = this.editor.getEditorState().read(() => $createNodeKeyToSidMap());
43
48
  this.sidToNodeKeyMap = this.editor.getEditorState().read(() => $createSidToNodeKeyMap());
44
49
  let nodes = [];
@@ -115,6 +120,7 @@ export class EditorTranslator {
115
120
  this.editor.update(() => {
116
121
  if (!sid) {
117
122
  this.editor.setEditorState(this.originalEditorState);
123
+ this.translations = [];
118
124
  }
119
125
  else if (this.options.displayMode === 'translationOnly') {
120
126
  const nodeKey = this.sidToNodeKeyMap.get(sid);
@@ -131,6 +137,37 @@ export class EditorTranslator {
131
137
  }
132
138
  });
133
139
  }
140
+ async preprocessNodes() {
141
+ const isSpecialNode = (node) => {
142
+ return $isExcalidrawNode(node) || $isImageNode(node) || $isPdfNode(node);
143
+ };
144
+ this.editor.update(() => {
145
+ $findTranslatableElementNodes().forEach((node) => {
146
+ // 如果 children 中即包含特殊结点, 也包含普通结点, 则将特殊结点与普通结点分开
147
+ const children = node.getChildren();
148
+ if (!children.some(isSpecialNode) || children.every(isSpecialNode)) {
149
+ return;
150
+ }
151
+ const normalNodes = [];
152
+ children.forEach((child) => {
153
+ if (isSpecialNode(child)) {
154
+ if (normalNodes.length > 0) {
155
+ node.insertBefore($createParagraphNode().append(...normalNodes));
156
+ normalNodes.length = 0;
157
+ }
158
+ node.insertBefore($createParagraphNode().append(child));
159
+ }
160
+ else {
161
+ normalNodes.push(child);
162
+ }
163
+ });
164
+ }, { discrete: true });
165
+ });
166
+ // 延时 10ms, 否则获取的 node-key <=> sid 映射不准确
167
+ // eslint-disable-next-line no-promise-executor-return
168
+ await new Promise((resolve) => setTimeout(resolve, 10));
169
+ this.preprocessEditorState = this.editor.getEditorState().clone();
170
+ }
134
171
  }
135
172
  export function useEditorTranslator(options) {
136
173
  const [editor] = useLexicalComposerContext();
@@ -72,10 +72,28 @@ function InternalInlineTranslationPlugin({ translateService, detectLanguage, onT
72
72
  document.removeEventListener('keydown', handler);
73
73
  };
74
74
  }, [editor, editorTranslator]);
75
+ // 对于翻译后的内容,禁止 checkbox 点击交互
76
+ useEffect(() => {
77
+ const onClick = (event) => {
78
+ const target = event.target;
79
+ if (editorTranslator.isTranslated && target.closest('li[role="checkbox"]')) {
80
+ event.preventDefault();
81
+ event.stopPropagation();
82
+ }
83
+ };
84
+ return editor.registerRootListener((rootElement, prevRootElement) => {
85
+ if (prevRootElement) {
86
+ prevRootElement.removeEventListener('click', onClick, { capture: true });
87
+ }
88
+ if (rootElement) {
89
+ rootElement.addEventListener('click', onClick, { capture: true });
90
+ }
91
+ });
92
+ }, [editor, editorTranslator]);
75
93
  if (editor.isEditable()) {
76
94
  return null;
77
95
  }
78
- return status === 'completed' ? (_jsx(Box, { sx: { mb: 0.5 }, children: _jsxs(Box, { sx: {
96
+ return status === 'completed' && editorTranslator.isTranslated ? (_jsx(Box, { sx: { mb: 0.5 }, children: _jsxs(Box, { className: "inline-translation-badge", sx: {
79
97
  display: 'inline-block',
80
98
  px: 1,
81
99
  fontSize: 12,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/editor",
3
- "version": "2.1.120",
3
+ "version": "2.1.122",
4
4
  "main": "lib/index.js",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -66,7 +66,7 @@
66
66
  "ufo": "^1.5.4",
67
67
  "url-join": "^4.0.1",
68
68
  "zustand": "^4.5.5",
69
- "@blocklet/pdf": "^2.1.120"
69
+ "@blocklet/pdf": "^2.1.122"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@babel/core": "^7.25.2",