@lobehub/editor 3.3.0 → 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.
@@ -1,6 +1,7 @@
1
- import { mergeRegister } from '@lexical/utils';
2
- import { $getNodeByKey, $insertNodes, $setSelection, COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical';
3
- import { $createCodeMirrorNode } from "../node/CodeMirrorNode";
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(SELECT_BEFORE_CODEMIRROR_COMMAND, function (payload) {
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,3 @@
1
+ export { INSERT_CODEMIRROR_COMMAND, SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND, } from './command';
1
2
  export * from './plugin';
2
3
  export * from './react';
@@ -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";
@@ -18,6 +18,7 @@ export interface ICodeMirrorInstance {
18
18
  clearHistory(): void;
19
19
  destroy(): void;
20
20
  focus(): void;
21
+ foldGutter?: boolean;
21
22
  foldLines(): number[];
22
23
  foldLines(lines: number[]): void;
23
24
  formatAll(): void;
@@ -55,4 +56,8 @@ export interface ICodeMirror {
55
56
  fromTextArea: (textarea: HTMLTextAreaElement, options?: Options) => ICodeMirrorInstance;
56
57
  new (dom: HTMLElement, options?: Options): ICodeMirrorInstance;
57
58
  }
58
- export declare function loadCodeMirror(): Promise<ICodeMirror>;
59
+ /**
60
+ * 从 CDN 加载 CodeMirror
61
+ * @param cdnUrl - 可选的自定义 CDN URL
62
+ */
63
+ export declare function loadCodeMirror(cdnUrl?: string): Promise<ICodeMirror>;
@@ -2,39 +2,145 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
2
2
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
3
3
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
4
4
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
5
- var CodeMirrorLoading = false;
5
+ import { createDebugLogger } from "../../../utils/debug";
6
+ var logger = createDebugLogger('plugin', 'codemirror-loader');
7
+
8
+ // CDN URL 配置
9
+ var DEFAULT_CDN_URL = 'https://registry.npmmirror.com/@lobehub/codemirror/1.0.0/files/es/index.js';
10
+ var LOAD_TIMEOUT = 10000; // 10 秒超时
11
+ var POLL_INTERVAL = 50; // 50ms 轮询间隔
12
+
6
13
  export var AllLang = [];
14
+ // 使用 Promise 缓存避免并发重复加载
15
+ var codeMirrorPromise = null;
16
+
17
+ /**
18
+ * 加载 script 标签
19
+ */
20
+ function loadScript(src) {
21
+ return new Promise(function (resolve, reject) {
22
+ // 检查是否已经加载过相同的脚本
23
+ var existingScript = document.querySelector("script[src=\"".concat(src, "\"]"));
24
+ if (existingScript) {
25
+ logger.debug('Script already loaded:', src);
26
+ resolve();
27
+ return;
28
+ }
29
+ logger.debug('Loading script:', src);
30
+ var script = document.createElement('script');
31
+ script.src = src;
32
+ script.type = 'module';
33
+ script.async = true;
34
+ script.addEventListener('load', function () {
35
+ logger.debug('Script loaded successfully:', src);
36
+ resolve();
37
+ });
38
+ script.addEventListener('error', function (error) {
39
+ logger.error('Failed to load script:', src, error);
40
+ reject(new Error("Failed to load script: ".concat(src)));
41
+ });
42
+ document.head.append(script);
43
+ });
44
+ }
45
+
46
+ /**
47
+ * 等待 window.CodeMirror 可用
48
+ */
49
+ function waitForCodeMirror() {
50
+ var timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : LOAD_TIMEOUT;
51
+ return new Promise(function (resolve, reject) {
52
+ var startTime = Date.now();
53
+ var checkCodeMirror = function checkCodeMirror() {
54
+ // @ts-expect-error not error
55
+ if (window.CodeMirror) {
56
+ logger.debug('CodeMirror is ready');
57
+ resolve();
58
+ return;
59
+ }
60
+ if (Date.now() - startTime > timeout) {
61
+ logger.error('Timeout waiting for CodeMirror');
62
+ reject(new Error('Timeout: CodeMirror failed to load from CDN'));
63
+ return;
64
+ }
65
+ setTimeout(checkCodeMirror, POLL_INTERVAL);
66
+ };
67
+ checkCodeMirror();
68
+ });
69
+ }
70
+
71
+ /**
72
+ * 从 CDN 加载 CodeMirror
73
+ * @param cdnUrl - 可选的自定义 CDN URL
74
+ */
7
75
  export function loadCodeMirror() {
8
76
  return _loadCodeMirror.apply(this, arguments);
9
77
  }
10
78
  function _loadCodeMirror() {
11
- _loadCodeMirror = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
12
- return _regeneratorRuntime().wrap(function _callee$(_context) {
13
- while (1) switch (_context.prev = _context.next) {
79
+ _loadCodeMirror = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
80
+ var _window$CodeMirror;
81
+ var cdnUrl,
82
+ _args2 = arguments;
83
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
84
+ while (1) switch (_context2.prev = _context2.next) {
14
85
  case 0:
15
- if (!(!window.CodeMirror && !CodeMirrorLoading)) {
16
- _context.next = 11;
86
+ cdnUrl = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : DEFAULT_CDN_URL;
87
+ if (!((_window$CodeMirror = window.CodeMirror) !== null && _window$CodeMirror !== void 0 && _window$CodeMirror.default)) {
88
+ _context2.next = 4;
89
+ break;
90
+ }
91
+ logger.debug('CodeMirror already available');
92
+ // @ts-expect-error not error
93
+ return _context2.abrupt("return", window.CodeMirror.default);
94
+ case 4:
95
+ if (!codeMirrorPromise) {
96
+ _context2.next = 7;
17
97
  break;
18
98
  }
19
- CodeMirrorLoading = true;
20
- _context.prev = 2;
21
- _context.next = 5;
22
- return import('@lobehub/codemirror');
23
- case 5:
24
- _context.next = 11;
25
- break;
99
+ logger.debug('CodeMirror loading in progress, reusing promise');
100
+ return _context2.abrupt("return", codeMirrorPromise);
26
101
  case 7:
27
- _context.prev = 7;
28
- _context.t0 = _context["catch"](2);
29
- CodeMirrorLoading = false;
30
- throw _context.t0;
31
- case 11:
32
- return _context.abrupt("return", window.CodeMirror.default);
33
- case 12:
102
+ // 创建新的加载 Promise
103
+ codeMirrorPromise = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
104
+ var _window$CodeMirror2;
105
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
106
+ while (1) switch (_context.prev = _context.next) {
107
+ case 0:
108
+ _context.prev = 0;
109
+ logger.debug('Starting CodeMirror load from:', cdnUrl);
110
+ _context.next = 4;
111
+ return loadScript(cdnUrl);
112
+ case 4:
113
+ _context.next = 6;
114
+ return waitForCodeMirror();
115
+ case 6:
116
+ if ((_window$CodeMirror2 = window.CodeMirror) !== null && _window$CodeMirror2 !== void 0 && _window$CodeMirror2.default) {
117
+ _context.next = 8;
118
+ break;
119
+ }
120
+ throw new Error('CodeMirror loaded but not properly initialized');
121
+ case 8:
122
+ logger.debug('CodeMirror loaded successfully');
123
+ // @ts-expect-error not error
124
+ return _context.abrupt("return", window.CodeMirror.default);
125
+ case 12:
126
+ _context.prev = 12;
127
+ _context.t0 = _context["catch"](0);
128
+ // 加载失败时清除缓存,允许重试
129
+ codeMirrorPromise = null;
130
+ logger.error('Failed to load CodeMirror:', _context.t0);
131
+ throw _context.t0;
132
+ case 17:
133
+ case "end":
134
+ return _context.stop();
135
+ }
136
+ }, _callee, null, [[0, 12]]);
137
+ }))();
138
+ return _context2.abrupt("return", codeMirrorPromise);
139
+ case 9:
34
140
  case "end":
35
- return _context.stop();
141
+ return _context2.stop();
36
142
  }
37
- }, _callee, null, [[2, 7]]);
143
+ }, _callee2);
38
144
  }));
39
145
  return _loadCodeMirror.apply(this, arguments);
40
146
  }
@@ -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
- var isCodeBlock = $isCodeNode(element) && $isCodeNode(focusElement) && elementKey === focusElement.getKey();
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
- setCodeblockLang(isCodeBlock ? element.getLanguage() : '');
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
- if (!$isRangeSelection(selection) || selection.isCollapsed()) {
230
- $setBlocksType(selection, function () {
231
- return $createCodeNode();
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
- var textContent = selection.getTextContent();
235
- var codeNode = $createCodeNode();
236
- selection.insertNodes([codeNode]);
237
- selection = $getSelection();
238
- if ($isRangeSelection(selection)) {
239
- selection.insertRawText(textContent);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/editor",
3
- "version": "3.3.0",
3
+ "version": "3.3.2",
4
4
  "description": "A powerful and extensible rich text editor built on Meta's Lexical framework, providing a modern editing experience with React integration.",
5
5
  "keywords": [
6
6
  "lobehub",
@@ -41,7 +41,6 @@
41
41
  "@lexical/selection": "^0.39.0",
42
42
  "@lexical/table": "^0.39.0",
43
43
  "@lexical/utils": "^0.39.0",
44
- "@lobehub/codemirror": "^1.0.0",
45
44
  "@shikijs/core": "^3.20.0",
46
45
  "@shikijs/engine-javascript": "^3.20.0",
47
46
  "@xmldom/xmldom": "^0.8.11",