@lobehub/editor 3.3.1 → 3.3.2
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.
- package/es/plugins/codemirror-block/command/index.js +35 -4
- package/es/plugins/codemirror-block/index.d.ts +1 -0
- package/es/plugins/codemirror-block/index.js +5 -0
- package/es/plugins/codemirror-block/react/CodemirrorNode.js +8 -0
- package/es/plugins/codemirror-block/react/style.js +1 -1
- package/es/react/hooks/useEditorState/index.js +47 -12
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { mergeRegister } from '@lexical/utils';
|
|
2
|
-
import { $getNodeByKey, $insertNodes, $setSelection, COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical';
|
|
3
|
-
import {
|
|
1
|
+
import { $findMatchingParent, mergeRegister } from '@lexical/utils';
|
|
2
|
+
import { $getNodeByKey, $getSelection, $insertNodes, $isRangeSelection, $setSelection, COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical';
|
|
3
|
+
import { UPDATE_CODEBLOCK_LANG } from "../../codeblock";
|
|
4
|
+
import { $createCodeMirrorNode, $isCodeMirrorNode } from "../node/CodeMirrorNode";
|
|
4
5
|
export var INSERT_CODEMIRROR_COMMAND = createCommand('INSERT_CODEMIRROR_COMMAND');
|
|
5
6
|
export var SELECT_BEFORE_CODEMIRROR_COMMAND = createCommand('SELECT_BEFORE_CODEMIRROR_COMMAND');
|
|
6
7
|
export var SELECT_AFTER_CODEMIRROR_COMMAND = createCommand('SELECT_AFTER_CODEMIRROR_COMMAND');
|
|
@@ -12,7 +13,37 @@ export function registerCodeMirrorCommand(editor) {
|
|
|
12
13
|
});
|
|
13
14
|
return true;
|
|
14
15
|
}, COMMAND_PRIORITY_EDITOR // Priority
|
|
15
|
-
), editor.registerCommand(
|
|
16
|
+
), editor.registerCommand(UPDATE_CODEBLOCK_LANG, function (payload) {
|
|
17
|
+
var codeMirrorNode = editor.getEditorState().read(function () {
|
|
18
|
+
var selection = $getSelection();
|
|
19
|
+
if ($isRangeSelection(selection)) {
|
|
20
|
+
if (selection.isCollapsed()) {
|
|
21
|
+
var node = $findMatchingParent(selection.anchor.getNode(), $isCodeMirrorNode);
|
|
22
|
+
return node;
|
|
23
|
+
} else {
|
|
24
|
+
var anchor = $findMatchingParent(selection.anchor.getNode(), $isCodeMirrorNode);
|
|
25
|
+
var focus = $findMatchingParent(selection.focus.getNode(), $isCodeMirrorNode);
|
|
26
|
+
if (anchor && focus && anchor === focus) {
|
|
27
|
+
return anchor;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
});
|
|
34
|
+
if (!codeMirrorNode) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
// Need to defer execution due to possible transform execution order confusion from selection changes
|
|
38
|
+
queueMicrotask(function () {
|
|
39
|
+
editor.update(function () {
|
|
40
|
+
if ($isCodeMirrorNode(codeMirrorNode)) {
|
|
41
|
+
codeMirrorNode.setLang(payload.lang);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
return true;
|
|
46
|
+
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(SELECT_BEFORE_CODEMIRROR_COMMAND, function (payload) {
|
|
16
47
|
editor.update(function () {
|
|
17
48
|
var node = $getNodeByKey(payload.key);
|
|
18
49
|
if (!node) {
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
+
// Export commands explicitly to avoid conflicts with codeblock plugin
|
|
2
|
+
export { INSERT_CODEMIRROR_COMMAND, SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND
|
|
3
|
+
// UPDATE_CODEBLOCK_LANG is already exported by codeblock plugin
|
|
4
|
+
// Both plugins can use the same command for consistency
|
|
5
|
+
} from "./command";
|
|
1
6
|
export * from "./plugin";
|
|
2
7
|
export * from "./react";
|
|
@@ -165,9 +165,17 @@ var ReactCodemirrorNode = function ReactCodemirrorNode(_ref) {
|
|
|
165
165
|
}
|
|
166
166
|
}, [isSelected, isNodeSelected, editor]);
|
|
167
167
|
useEffect(function () {
|
|
168
|
+
// 防止重复初始化:如果已经有实例,直接返回
|
|
169
|
+
if (instanceRef.current) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
168
172
|
if (ref.current) {
|
|
169
173
|
var dom = ref.current;
|
|
170
174
|
loadCodeMirror().then(function (CodeMirror) {
|
|
175
|
+
// 双重检查:在异步操作后再次确认没有重复初始化
|
|
176
|
+
if (instanceRef.current) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
171
179
|
var instance = CodeMirror.fromTextArea(dom, {
|
|
172
180
|
// keep options alphabetically ordered
|
|
173
181
|
indentWithTabs: useTabs,
|
|
@@ -4,5 +4,5 @@ import { createStaticStyles } from 'antd-style';
|
|
|
4
4
|
export var styles = createStaticStyles(function (_ref) {
|
|
5
5
|
var css = _ref.css,
|
|
6
6
|
cssVar = _ref.cssVar;
|
|
7
|
-
return css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n cursor: pointer;\n\n position: relative;\n\n overflow: hidden;\n display: flex;\n flex-direction: column;\n align-items: center;\n\n width: 100%;\n\n background: ", ";\n\n .cm-hidden-actions {\n opacity: 0;\n transition: opacity 0.2s ease-in-out;\n }\n\n .cm-language-select {\n opacity: 0.5;\n filter: grayscale(100%);\n transition:\n opacity,\n grayscale 0.2s ease-in-out;\n }\n\n &.selected {\n user-select: none;\n }\n\n &.selected::after {\n pointer-events: none;\n content: '';\n\n position: absolute;\n z-index: 10;\n inset: 0;\n\n width: 100%;\n height: 100%;\n\n opacity: 0.2;\n background: ", ";\n\n transition: all 0.3s;\n }\n\n .cm-container {\n position: relative;\n width: 100%;\n border-block-start: 1px solid ", ";\n }\n\n .cm-container-collapsed {\n overflow: hidden;\n height: 0;\n border-block-start: none;\n }\n\n .cm-textarea {\n height: 44px;\n opacity: 0;\n }\n\n &:hover {\n .cm-hidden-actions {\n opacity: 1;\n }\n\n .cm-language-select {\n opacity: 1;\n filter: grayscale(0);\n }\n }\n "])), cssVar.colorFillQuaternary, cssVar.yellow, cssVar.colorFillQuaternary);
|
|
7
|
+
return css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n cursor: pointer;\n\n position: relative;\n\n overflow: hidden;\n display: flex;\n flex-direction: column;\n align-items: center;\n\n width: 100%;\n margin-block: calc(var(--lobe-markdown-margin-multiple) * 0.5em);\n border-radius: var(--lobe-markdown-border-radius);\n\n background: ", ";\n\n .cm-hidden-actions {\n opacity: 0;\n transition: opacity 0.2s ease-in-out;\n }\n\n .cm-language-select {\n opacity: 0.5;\n filter: grayscale(100%);\n transition:\n opacity,\n grayscale 0.2s ease-in-out;\n }\n\n &.selected {\n user-select: none;\n }\n\n &.selected::after {\n pointer-events: none;\n content: '';\n\n position: absolute;\n z-index: 10;\n inset: 0;\n\n width: 100%;\n height: 100%;\n\n opacity: 0.2;\n background: ", ";\n\n transition: all 0.3s;\n }\n\n .cm-container {\n position: relative;\n width: 100%;\n border-block-start: 1px solid ", ";\n }\n\n .cm-container-collapsed {\n overflow: hidden;\n height: 0;\n border-block-start: none;\n }\n\n .cm-textarea {\n height: 44px;\n opacity: 0;\n }\n\n &:hover {\n .cm-hidden-actions {\n opacity: 1;\n }\n\n .cm-language-select {\n opacity: 1;\n filter: grayscale(0);\n }\n }\n "])), cssVar.colorFillQuaternary, cssVar.yellow, cssVar.colorFillQuaternary);
|
|
8
8
|
});
|
|
@@ -16,6 +16,7 @@ import { noop } from "../../../editor-kernel";
|
|
|
16
16
|
import { INSERT_CODEINLINE_COMMAND } from "../../../plugins/code";
|
|
17
17
|
import { $isSelectionInCodeInline } from "../../../plugins/code/node/code";
|
|
18
18
|
import { UPDATE_CODEBLOCK_LANG } from "../../../plugins/codeblock";
|
|
19
|
+
import { $createCodeMirrorNode, $isCodeMirrorNode } from "../../../plugins/codemirror-block/node/CodeMirrorNode";
|
|
19
20
|
import { $isRootTextContentEmpty } from "../../../plugins/common/utils";
|
|
20
21
|
import { INSERT_LINK_HIGHLIGHT_COMMAND } from "../../../plugins/link-highlight/command";
|
|
21
22
|
import { $isLinkHighlightNode } from "../../../plugins/link-highlight/node/link-highlight";
|
|
@@ -137,9 +138,18 @@ export function useEditorState(editor) {
|
|
|
137
138
|
var parent = node.getParent();
|
|
138
139
|
// Check for both Link and LinkHighlight nodes
|
|
139
140
|
setIsLink($isLinkNode(parent) || $isLinkNode(node) || $isLinkHighlightNode(parent) || $isLinkHighlightNode(node));
|
|
140
|
-
|
|
141
|
+
// Support both CodeNode (from codeblock plugin) and CodeMirrorNode (from codemirror-block plugin)
|
|
142
|
+
var isLexicalCodeBlock = $isCodeNode(element) && $isCodeNode(focusElement) && elementKey === focusElement.getKey();
|
|
143
|
+
var isCodeMirrorBlock = $isCodeMirrorNode(element) && $isCodeMirrorNode(focusElement) && elementKey === focusElement.getKey();
|
|
144
|
+
var isCodeBlock = isLexicalCodeBlock || isCodeMirrorBlock;
|
|
141
145
|
setIsInCodeblok(isCodeBlock);
|
|
142
|
-
|
|
146
|
+
if (isLexicalCodeBlock) {
|
|
147
|
+
setCodeblockLang(element.getLanguage());
|
|
148
|
+
} else if (isCodeMirrorBlock) {
|
|
149
|
+
setCodeblockLang(element.lang);
|
|
150
|
+
} else {
|
|
151
|
+
setCodeblockLang('');
|
|
152
|
+
}
|
|
143
153
|
var _isBlockquote = $isQuoteNode(element) && $isQuoteNode(focusElement) && elementKey === focusElement.getKey();
|
|
144
154
|
setIsInBlockquote(_isBlockquote);
|
|
145
155
|
if (elementDOM !== null) {
|
|
@@ -222,21 +232,46 @@ export function useEditorState(editor) {
|
|
|
222
232
|
if (blockType !== 'code') {
|
|
223
233
|
var _editor$getLexicalEdi2;
|
|
224
234
|
editor === null || editor === void 0 || (_editor$getLexicalEdi2 = editor.getLexicalEditor()) === null || _editor$getLexicalEdi2 === void 0 || _editor$getLexicalEdi2.update(function () {
|
|
235
|
+
var _lexicalEditor$_nodes;
|
|
225
236
|
var selection = $getSelection();
|
|
226
237
|
if (!selection) {
|
|
227
238
|
return;
|
|
228
239
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
240
|
+
|
|
241
|
+
// Try to use CodeMirrorNode if available, otherwise fall back to CodeNode
|
|
242
|
+
var lexicalEditor = editor === null || editor === void 0 ? void 0 : editor.getLexicalEditor();
|
|
243
|
+
var hasCodeMirrorNode = lexicalEditor ? lexicalEditor._nodes.has('code') && ((_lexicalEditor$_nodes = lexicalEditor._nodes.get('code')) === null || _lexicalEditor$_nodes === void 0 ? void 0 : _lexicalEditor$_nodes.klass.name) === 'CodeMirrorNode' : false;
|
|
244
|
+
if (hasCodeMirrorNode) {
|
|
245
|
+
// Use CodeMirrorNode
|
|
246
|
+
if (!$isRangeSelection(selection) || selection.isCollapsed()) {
|
|
247
|
+
var textContent = selection.getTextContent();
|
|
248
|
+
var codeMirrorNode = $createCodeMirrorNode('plain', textContent);
|
|
249
|
+
var nodeSelection = $createNodeSelection();
|
|
250
|
+
nodeSelection.add(codeMirrorNode.getKey());
|
|
251
|
+
selection.insertNodes([codeMirrorNode]);
|
|
252
|
+
$setSelection(nodeSelection);
|
|
253
|
+
} else {
|
|
254
|
+
var _textContent = selection.getTextContent();
|
|
255
|
+
var _codeMirrorNode = $createCodeMirrorNode('plain', _textContent);
|
|
256
|
+
selection.insertNodes([_codeMirrorNode]);
|
|
257
|
+
var _nodeSelection = $createNodeSelection();
|
|
258
|
+
_nodeSelection.add(_codeMirrorNode.getKey());
|
|
259
|
+
$setSelection(_nodeSelection);
|
|
260
|
+
}
|
|
233
261
|
} else {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
262
|
+
// Use original CodeNode
|
|
263
|
+
if (!$isRangeSelection(selection) || selection.isCollapsed()) {
|
|
264
|
+
$setBlocksType(selection, function () {
|
|
265
|
+
return $createCodeNode();
|
|
266
|
+
});
|
|
267
|
+
} else {
|
|
268
|
+
var _textContent2 = selection.getTextContent();
|
|
269
|
+
var codeNode = $createCodeNode();
|
|
270
|
+
selection.insertNodes([codeNode]);
|
|
271
|
+
selection = $getSelection();
|
|
272
|
+
if ($isRangeSelection(selection)) {
|
|
273
|
+
selection.insertRawText(_textContent2);
|
|
274
|
+
}
|
|
240
275
|
}
|
|
241
276
|
}
|
|
242
277
|
});
|
package/package.json
CHANGED