@lobehub/editor 3.2.2 → 3.3.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.
Files changed (41) hide show
  1. package/es/editor-kernel/react/useLexicalNodeSelection.d.ts +1 -1
  2. package/es/editor-kernel/react/useLexicalNodeSelection.js +22 -1
  3. package/es/index.d.ts +1 -0
  4. package/es/index.js +1 -0
  5. package/es/locale/index.d.ts +10 -0
  6. package/es/locale/index.js +10 -0
  7. package/es/plugins/codemirror-block/command/index.d.ts +9 -0
  8. package/es/plugins/codemirror-block/command/index.js +46 -0
  9. package/es/plugins/codemirror-block/index.d.ts +2 -0
  10. package/es/plugins/codemirror-block/index.js +2 -0
  11. package/es/plugins/codemirror-block/lib/index.d.ts +58 -0
  12. package/es/plugins/codemirror-block/lib/index.js +40 -0
  13. package/es/plugins/codemirror-block/lib/mode.d.ts +25 -0
  14. package/es/plugins/codemirror-block/lib/mode.js +416 -0
  15. package/es/plugins/codemirror-block/node/CodeMirrorNode.d.ts +46 -0
  16. package/es/plugins/codemirror-block/node/CodeMirrorNode.js +343 -0
  17. package/es/plugins/codemirror-block/plugin/index.d.ts +8 -0
  18. package/es/plugins/codemirror-block/plugin/index.js +113 -0
  19. package/es/plugins/codemirror-block/react/CodemirrorNode.d.ts +10 -0
  20. package/es/plugins/codemirror-block/react/CodemirrorNode.js +323 -0
  21. package/es/plugins/codemirror-block/react/ReactCodemirrorNode.d.ts +4 -0
  22. package/es/plugins/codemirror-block/react/ReactCodemirrorNode.js +34 -0
  23. package/es/plugins/codemirror-block/react/components/CopyButton.d.ts +5 -0
  24. package/es/plugins/codemirror-block/react/components/CopyButton.js +35 -0
  25. package/es/plugins/codemirror-block/react/components/LanguageSelect.d.ts +8 -0
  26. package/es/plugins/codemirror-block/react/components/LanguageSelect.js +77 -0
  27. package/es/plugins/codemirror-block/react/components/MoreOptions.d.ts +16 -0
  28. package/es/plugins/codemirror-block/react/components/MoreOptions.js +79 -0
  29. package/es/plugins/codemirror-block/react/components/Toolbar.d.ts +16 -0
  30. package/es/plugins/codemirror-block/react/components/Toolbar.js +56 -0
  31. package/es/plugins/codemirror-block/react/components/style.d.ts +3 -0
  32. package/es/plugins/codemirror-block/react/components/style.js +9 -0
  33. package/es/plugins/codemirror-block/react/index.d.ts +1 -0
  34. package/es/plugins/codemirror-block/react/index.js +1 -0
  35. package/es/plugins/codemirror-block/react/style.d.ts +1 -0
  36. package/es/plugins/codemirror-block/react/style.js +8 -0
  37. package/es/plugins/codemirror-block/react/theme.d.ts +133 -0
  38. package/es/plugins/codemirror-block/react/theme.js +158 -0
  39. package/es/plugins/codemirror-block/react/type.d.ts +3 -0
  40. package/es/plugins/codemirror-block/react/type.js +1 -0
  41. package/package.json +4 -2
@@ -0,0 +1,323 @@
1
+ 'use client';
2
+
3
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
+ 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; }
5
+ 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); } }
6
+ 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); }); }; }
7
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
8
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
9
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
10
+ 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; }
11
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
12
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
13
+ import { mergeRegister } from '@lexical/utils';
14
+ import { Block } from '@lobehub/ui';
15
+ import { message } from 'antd';
16
+ import { cx } from 'antd-style';
17
+ import { debounce } from 'es-toolkit/compat';
18
+ import { $getSelection, $setSelection, COMMAND_PRIORITY_CRITICAL, KEY_DOWN_COMMAND } from 'lexical';
19
+ import { useCallback, useEffect, useRef, useState } from 'react';
20
+ import { useLexicalNodeSelection } from "../../../editor-kernel/react/useLexicalNodeSelection";
21
+ import { useTranslation } from "../../../editor-kernel/react/useTranslation";
22
+ import { lobeTheme } from "./theme";
23
+ import { SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND } from "../command";
24
+ import { loadCodeMirror } from "../lib";
25
+ import { Toolbar } from "./components/Toolbar";
26
+ import { styles } from "./style";
27
+ import { jsx as _jsx } from "react/jsx-runtime";
28
+ import { jsxs as _jsxs } from "react/jsx-runtime";
29
+ var ReactCodemirrorNode = function ReactCodemirrorNode(_ref) {
30
+ var _node$options$tabSize, _node$options$indentW, _node$options$lineNum;
31
+ var node = _ref.node,
32
+ className = _ref.className,
33
+ editor = _ref.editor;
34
+ var ref = useRef(null);
35
+ var keydownRef = useRef('');
36
+ var instanceRef = useRef(null);
37
+ var isEmptyRef = useRef(false);
38
+ var t = useTranslation();
39
+ var _useLexicalNodeSelect = useLexicalNodeSelection(node.getKey()),
40
+ _useLexicalNodeSelect2 = _slicedToArray(_useLexicalNodeSelect, 4),
41
+ isSelected = _useLexicalNodeSelect2[0],
42
+ setSelected = _useLexicalNodeSelect2[1],
43
+ clearSelection = _useLexicalNodeSelect2[2],
44
+ isNodeSelected = _useLexicalNodeSelect2[3];
45
+ var _useState = useState(node.lang || 'javascript'),
46
+ _useState2 = _slicedToArray(_useState, 2),
47
+ selectedLang = _useState2[0],
48
+ setSelectedLang = _useState2[1];
49
+ // use any to avoid strict typing on optional persistence fields
50
+ var _useState3 = useState((_node$options$tabSize = node.options.tabSize) !== null && _node$options$tabSize !== void 0 ? _node$options$tabSize : 2),
51
+ _useState4 = _slicedToArray(_useState3, 2),
52
+ tabSize = _useState4[0],
53
+ setTabSize = _useState4[1];
54
+ var _useState5 = useState((_node$options$indentW = node.options.indentWithTabs) !== null && _node$options$indentW !== void 0 ? _node$options$indentW : false),
55
+ _useState6 = _slicedToArray(_useState5, 2),
56
+ useTabs = _useState6[0],
57
+ setUseTabs = _useState6[1];
58
+ var _useState7 = useState((_node$options$lineNum = node.options.lineNumbers) !== null && _node$options$lineNum !== void 0 ? _node$options$lineNum : false),
59
+ _useState8 = _slicedToArray(_useState7, 2),
60
+ showLineNumbers = _useState8[0],
61
+ setShowLineNumbers = _useState8[1];
62
+ var _useState9 = useState(true),
63
+ _useState10 = _slicedToArray(_useState9, 2),
64
+ expand = _useState10[0],
65
+ setExpand = _useState10[1];
66
+
67
+ // 复制代码
68
+ var handleCopy = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
69
+ var code;
70
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
71
+ while (1) switch (_context.prev = _context.next) {
72
+ case 0:
73
+ if (!instanceRef.current) {
74
+ _context.next = 10;
75
+ break;
76
+ }
77
+ code = instanceRef.current.getValue();
78
+ _context.prev = 2;
79
+ _context.next = 5;
80
+ return navigator.clipboard.writeText(code);
81
+ case 5:
82
+ _context.next = 10;
83
+ break;
84
+ case 7:
85
+ _context.prev = 7;
86
+ _context.t0 = _context["catch"](2);
87
+ message.error(t('codemirror.copyFailed'));
88
+ case 10:
89
+ case "end":
90
+ return _context.stop();
91
+ }
92
+ }, _callee, null, [[2, 7]]);
93
+ })), [t]);
94
+
95
+ // 更改语言
96
+ var handleLanguageChange = useCallback(function (value) {
97
+ setSelectedLang(value);
98
+ if (instanceRef.current) {
99
+ instanceRef.current.setOption('mode', value);
100
+ }
101
+ editor.update(function () {
102
+ node.setLang(value);
103
+ });
104
+ }, [editor, node]);
105
+
106
+ // 更改 tab 大小
107
+ var handleTabSizeChange = useCallback(function () {
108
+ var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2;
109
+ var v = value === null ? 2 : value;
110
+ setTabSize(v);
111
+ if (instanceRef.current) {
112
+ instanceRef.current.setOption('tabSize', v);
113
+ }
114
+ editor.update(function () {
115
+ node.setTabSize(v);
116
+ });
117
+ }, [editor, node]);
118
+
119
+ // 更改是否使用制表符
120
+ var handleUseTabsChange = useCallback(function (checked) {
121
+ setUseTabs(checked);
122
+ if (instanceRef.current) {
123
+ instanceRef.current.setOption('indentWithTabs', checked);
124
+ }
125
+ editor.update(function () {
126
+ node.setIndentWithTabs(checked);
127
+ });
128
+ }, [editor, node]);
129
+ var handleShowLineNumbersChange = useCallback(function (checked) {
130
+ setShowLineNumbers(checked);
131
+ if (instanceRef.current) {
132
+ instanceRef.current.setOption('lineNumbers', checked);
133
+ }
134
+ editor.update(function () {
135
+ node.setLineNumbers(checked);
136
+ });
137
+ }, [editor, node]);
138
+ useEffect(function () {
139
+ var _instanceRef$current;
140
+ var sel = editor.getEditorState().read(function () {
141
+ return $getSelection();
142
+ });
143
+ // 鼠标主动点击导致的选中,不处理
144
+ if ((_instanceRef$current = instanceRef.current) !== null && _instanceRef$current !== void 0 && _instanceRef$current.view.hasFocus && sel === null) {
145
+ return;
146
+ }
147
+ // 选区移走
148
+ if (!isSelected || !isNodeSelected) {
149
+ if (instanceRef.current) {
150
+ instanceRef.current.blur();
151
+ }
152
+ return;
153
+ }
154
+ // 选中状态下,聚焦 CodeMirror
155
+ if (isSelected && instanceRef.current && isNodeSelected) {
156
+ var _instanceRef$current2;
157
+ // 已经聚焦不在处理
158
+ if ((_instanceRef$current2 = instanceRef.current) !== null && _instanceRef$current2 !== void 0 && _instanceRef$current2.view.hasFocus) {
159
+ return;
160
+ }
161
+ instanceRef.current.focus();
162
+ if (keydownRef.current === 'end') {
163
+ instanceRef.current.setSelectionToEnd();
164
+ }
165
+ }
166
+ }, [isSelected, isNodeSelected, editor]);
167
+ useEffect(function () {
168
+ if (ref.current) {
169
+ var dom = ref.current;
170
+ loadCodeMirror().then(function (CodeMirror) {
171
+ var instance = CodeMirror.fromTextArea(dom, {
172
+ // keep options alphabetically ordered
173
+ indentWithTabs: useTabs,
174
+ lineNumbers: showLineNumbers,
175
+ mode: node.lang,
176
+ tabSize: tabSize,
177
+ theme: 'default',
178
+ value: node.code
179
+ });
180
+ console.info(instance);
181
+ instance.view.dispatch({
182
+ effects: instance.optionHelper.theme.reconfigure(instance.view.constructor.theme(lobeTheme, {
183
+ dark: false
184
+ }))
185
+ });
186
+
187
+ // 初始化 isEmptyRef 的值
188
+ isEmptyRef.current = !node.code.trim();
189
+ instance.on('keydown', function (instance, e) {
190
+ e.stopPropagation();
191
+
192
+ // 当代码块为空且按退格键时,删除代码块节点
193
+ if (e.key === 'Backspace' || e.keyCode === 8) {
194
+ // 检查代码内容是否为空(使用 ref 中存储的状态)
195
+ if (!isEmptyRef.current) {
196
+ return;
197
+ }
198
+ e.preventDefault();
199
+ editor.update(function () {
200
+ var prevNode = node.getPreviousSibling();
201
+ node.remove();
202
+ // 如果有前一个节点,选择它的末尾
203
+ if (prevNode) {
204
+ var prevSelection = prevNode.selectEnd();
205
+ if (prevSelection) {
206
+ $setSelection(prevSelection);
207
+ }
208
+ }
209
+ });
210
+ // 将焦点返回到编辑器
211
+ queueMicrotask(function () {
212
+ editor.focus();
213
+ });
214
+ }
215
+ });
216
+ instance.on('leftOut', function () {
217
+ var _instanceRef$current3;
218
+ (_instanceRef$current3 = instanceRef.current) === null || _instanceRef$current3 === void 0 || _instanceRef$current3.blur();
219
+ editor.dispatchCommand(SELECT_BEFORE_CODEMIRROR_COMMAND, {
220
+ key: node.getKey()
221
+ });
222
+ queueMicrotask(function () {
223
+ editor.focus();
224
+ });
225
+ });
226
+ instance.on('rightOut', function () {
227
+ var _instanceRef$current4;
228
+ (_instanceRef$current4 = instanceRef.current) === null || _instanceRef$current4 === void 0 || _instanceRef$current4.blur();
229
+ editor.dispatchCommand(SELECT_AFTER_CODEMIRROR_COMMAND, {
230
+ key: node.getKey()
231
+ });
232
+ queueMicrotask(function () {
233
+ editor.focus();
234
+ });
235
+ });
236
+ instance.on('change', function () {
237
+ var currentValue = instance.getValue();
238
+ // 立即检查代码是否为空(trim 后为空),用于 keydown 事件判断
239
+ isEmptyRef.current = !currentValue.trim();
240
+ });
241
+ instance.on('change', debounce(function () {
242
+ var currentValue = instance.getValue();
243
+ // 更新代码内容
244
+ editor.update(function () {
245
+ node.setCode(currentValue);
246
+ });
247
+ }));
248
+ instance.on('focus', function () {
249
+ if (editor.getEditorState().read(function () {
250
+ var sel = $getSelection();
251
+ if (!sel) return false;
252
+ if ((sel === null || sel === void 0 ? void 0 : sel.getNodes().length) > 1 || !(sel !== null && sel !== void 0 && sel.getNodes().includes(node))) {
253
+ return true;
254
+ }
255
+ return false;
256
+ })) {
257
+ setSelected(true);
258
+ }
259
+ });
260
+ instanceRef.current = instance;
261
+ if (isSelected) {
262
+ instanceRef.current.focus();
263
+ }
264
+ });
265
+ }
266
+ return function () {
267
+ if (instanceRef.current) {
268
+ instanceRef.current.destroy();
269
+ instanceRef.current = null;
270
+ }
271
+ };
272
+ }, [ref]);
273
+ useEffect(function () {
274
+ return mergeRegister(editor.registerCommand(KEY_DOWN_COMMAND, function (payload) {
275
+ // console.info('KEY_DOWN_COMMAND:', payload, keydownRef.current);
276
+ if (payload.key === 'ArrowLeft' || payload.key === 'ArrowUp') {
277
+ keydownRef.current = 'end';
278
+ } else {
279
+ keydownRef.current = '';
280
+ }
281
+ return false;
282
+ }, COMMAND_PRIORITY_CRITICAL));
283
+ }, [clearSelection, editor, isSelected, node, setSelected]);
284
+ return /*#__PURE__*/_jsxs(Block, {
285
+ className: cx(styles, isSelected && !isNodeSelected && 'selected', className),
286
+ onMouseDown: function onMouseDown(e) {
287
+ return e.stopPropagation();
288
+ },
289
+ onMouseUp: function onMouseUp(e) {
290
+ return e.stopPropagation();
291
+ },
292
+ onSelect: function onSelect(e) {
293
+ return e.stopPropagation();
294
+ },
295
+ variant: 'filled',
296
+ children: [/*#__PURE__*/_jsx(Toolbar, {
297
+ expand: expand,
298
+ onClick: function onClick() {
299
+ return setExpand(!expand);
300
+ },
301
+ onCopy: handleCopy,
302
+ onLanguageChange: handleLanguageChange,
303
+ onShowLineNumbersChange: handleShowLineNumbersChange,
304
+ onTabSizeChange: handleTabSizeChange,
305
+ onUseTabsChange: handleUseTabsChange,
306
+ selectedLang: selectedLang,
307
+ showLineNumbers: showLineNumbers,
308
+ tabSize: tabSize,
309
+ toggleExpand: function toggleExpand() {
310
+ return setExpand(!expand);
311
+ },
312
+ useTabs: useTabs
313
+ }), /*#__PURE__*/_jsx("div", {
314
+ className: cx('cm-container', !expand && 'cm-container-collapsed'),
315
+ children: /*#__PURE__*/_jsx("textarea", {
316
+ className: 'cm-textarea',
317
+ ref: ref
318
+ })
319
+ })]
320
+ });
321
+ };
322
+ ReactCodemirrorNode.displayName = 'ReactCodemirrorNode';
323
+ export default ReactCodemirrorNode;
@@ -0,0 +1,4 @@
1
+ import { type FC } from 'react';
2
+ import { ReactCodemirrorPluginProps } from './type';
3
+ declare const ReactCodemirrorPlugin: FC<ReactCodemirrorPluginProps>;
4
+ export default ReactCodemirrorPlugin;
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+
3
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
4
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
5
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
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
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
8
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
9
+ import { useLayoutEffect } from 'react';
10
+ import { useLexicalComposerContext } from "../../../editor-kernel/react/react-context";
11
+ import { CodemirrorPlugin } from "../plugin";
12
+ import ReactCodemirrorNode from "./CodemirrorNode";
13
+ import { jsx as _jsx } from "react/jsx-runtime";
14
+ var ReactCodemirrorPlugin = function ReactCodemirrorPlugin(_ref) {
15
+ var className = _ref.className;
16
+ var _useLexicalComposerCo = useLexicalComposerContext(),
17
+ _useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
18
+ editor = _useLexicalComposerCo2[0];
19
+ useLayoutEffect(function () {
20
+ editor.registerPlugin(CodemirrorPlugin, {
21
+ decorator: function decorator(node, editor) {
22
+ return /*#__PURE__*/_jsx(ReactCodemirrorNode, {
23
+ className: className,
24
+ editor: editor,
25
+ node: node
26
+ });
27
+ },
28
+ theme: className
29
+ });
30
+ }, [editor, className]);
31
+ return null;
32
+ };
33
+ ReactCodemirrorPlugin.displayName = 'ReactCodemirrorPlugin';
34
+ export default ReactCodemirrorPlugin;
@@ -0,0 +1,5 @@
1
+ import { FC } from 'react';
2
+ declare const CopyButton: FC<{
3
+ onCopy: () => void;
4
+ }>;
5
+ export default CopyButton;
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+
3
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
4
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
5
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
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
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
8
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
9
+ import { ActionIcon } from '@lobehub/ui';
10
+ import { Check, CopyIcon } from 'lucide-react';
11
+ import { useState } from 'react';
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ var CopyButton = function CopyButton(_ref) {
14
+ var onCopy = _ref.onCopy;
15
+ var _useState = useState(false),
16
+ _useState2 = _slicedToArray(_useState, 2),
17
+ copied = _useState2[0],
18
+ setCopied = _useState2[1];
19
+ return /*#__PURE__*/_jsx(ActionIcon, {
20
+ active: copied,
21
+ className: 'cm-hidden-actions',
22
+ icon: copied ? Check : CopyIcon,
23
+ onClick: function onClick() {
24
+ setCopied(true);
25
+ onCopy();
26
+ setTimeout(function () {
27
+ return setCopied(false);
28
+ }, 1000);
29
+ },
30
+ size: 'small',
31
+ title: 'Copy'
32
+ });
33
+ };
34
+ CopyButton.displayName = 'CopyButton';
35
+ export default CopyButton;
@@ -0,0 +1,8 @@
1
+ import { type FC } from 'react';
2
+ export interface LanguageSelectProps {
3
+ /** 语言变更回调 */
4
+ onLanguageChange: (value: string) => void;
5
+ /** 当前选中的语言 */
6
+ selectedLang: string;
7
+ }
8
+ export declare const LanguageSelect: FC<LanguageSelectProps>;
@@ -0,0 +1,77 @@
1
+ 'use client';
2
+
3
+ import { Flexbox, MaterialFileTypeIcon, Select, Text } from '@lobehub/ui';
4
+ import { cx } from 'antd-style';
5
+ import { useMemo } from 'react';
6
+ import { useTranslation } from "../../../../editor-kernel/react/useTranslation";
7
+ import { MODES } from "../../lib/mode";
8
+ import { styles } from "./style";
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ import { jsxs as _jsxs } from "react/jsx-runtime";
11
+ export var LanguageSelect = function LanguageSelect(_ref) {
12
+ var selectedLang = _ref.selectedLang,
13
+ onLanguageChange = _ref.onLanguageChange;
14
+ var t = useTranslation();
15
+ // 语言选项,使用 useMemo 优化性能
16
+ var languageOptions = useMemo(function () {
17
+ return MODES.map(function (mode) {
18
+ var _mode$ext, _mode$ext2;
19
+ return {
20
+ aliases: mode.ext || [],
21
+ label: /*#__PURE__*/_jsxs(Flexbox, {
22
+ align: 'center',
23
+ gap: 4,
24
+ horizontal: true,
25
+ children: [/*#__PURE__*/_jsx(MaterialFileTypeIcon, {
26
+ fallbackUnknownType: false,
27
+ filename: (_mode$ext = mode.ext) !== null && _mode$ext !== void 0 && _mode$ext[0] ? "*.".concat(mode.ext[0]) : "*.".concat(mode.value),
28
+ size: 18,
29
+ type: 'file',
30
+ variant: 'raw'
31
+ }), /*#__PURE__*/_jsx(Text, {
32
+ ellipsis: true,
33
+ fontSize: 13,
34
+ children: mode.name
35
+ })]
36
+ }),
37
+ title: (_mode$ext2 = mode.ext) !== null && _mode$ext2 !== void 0 && _mode$ext2.length ? mode.ext.map(function (ext) {
38
+ return "*.".concat(ext);
39
+ }).join(',') : "*.".concat(mode.value),
40
+ value: mode.value
41
+ };
42
+ });
43
+ }, []);
44
+ return /*#__PURE__*/_jsx(Flexbox, {
45
+ align: 'center',
46
+ className: 'cm-language-select',
47
+ gap: 4,
48
+ horizontal: true,
49
+ onClick: function onClick(e) {
50
+ return e.stopPropagation();
51
+ },
52
+ children: /*#__PURE__*/_jsx(Select, {
53
+ className: cx(styles.container),
54
+ filterOption: function filterOption(input, option) {
55
+ var _option$value, _option$aliases;
56
+ var lang = input.toLowerCase();
57
+ // 支持按值匹配
58
+ if (option !== null && option !== void 0 && (_option$value = option.value) !== null && _option$value !== void 0 && _option$value.toLowerCase().startsWith(lang)) return true;
59
+ // 支持按名称匹配
60
+ if (String(option === null || option === void 0 ? void 0 : option.label).toLowerCase().includes(lang)) return true;
61
+ // 支持按扩展名匹配
62
+ if (option !== null && option !== void 0 && (_option$aliases = option.aliases) !== null && _option$aliases !== void 0 && _option$aliases.some(function (ext) {
63
+ return ext.toLowerCase().startsWith(lang);
64
+ })) return true;
65
+ return false;
66
+ },
67
+ onChange: onLanguageChange,
68
+ options: languageOptions,
69
+ placeholder: t('codemirror.selectLanguage'),
70
+ showSearch: true,
71
+ size: "small",
72
+ value: selectedLang,
73
+ variant: 'borderless'
74
+ })
75
+ });
76
+ };
77
+ LanguageSelect.displayName = 'LanguageSelect';
@@ -0,0 +1,16 @@
1
+ import { type FC } from 'react';
2
+ export interface MoreOptionsProps {
3
+ /** 行号显示变更回调 */
4
+ onShowLineNumbersChange: (checked: boolean) => void;
5
+ /** Tab 大小变更回调 */
6
+ onTabSizeChange: (value: number | null) => void;
7
+ /** 制表符使用变更回调 */
8
+ onUseTabsChange: (checked: boolean) => void;
9
+ /** 是否显示行号 */
10
+ showLineNumbers: boolean;
11
+ /** Tab 大小 */
12
+ tabSize: number;
13
+ /** 是否使用制表符 */
14
+ useTabs: boolean;
15
+ }
16
+ export declare const MoreOptions: FC<MoreOptionsProps>;
@@ -0,0 +1,79 @@
1
+ 'use client';
2
+
3
+ import { ActionIcon, Flexbox, InputNumber, Text } from '@lobehub/ui';
4
+ import { Popover, Switch } from 'antd';
5
+ import { MoreHorizontalIcon } from 'lucide-react';
6
+ import { useCallback } from 'react';
7
+ import { useTranslation } from "../../../../editor-kernel/react/useTranslation";
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ import { jsxs as _jsxs } from "react/jsx-runtime";
10
+ export var MoreOptions = function MoreOptions(_ref) {
11
+ var tabSize = _ref.tabSize,
12
+ onTabSizeChange = _ref.onTabSizeChange,
13
+ useTabs = _ref.useTabs,
14
+ onUseTabsChange = _ref.onUseTabsChange,
15
+ showLineNumbers = _ref.showLineNumbers,
16
+ onShowLineNumbersChange = _ref.onShowLineNumbersChange;
17
+ var t = useTranslation();
18
+ var handleTabSizeChange = useCallback(function () {
19
+ var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2;
20
+ var v = value === null ? 2 : value;
21
+ onTabSizeChange(v);
22
+ }, [onTabSizeChange]);
23
+ return /*#__PURE__*/_jsx(Popover, {
24
+ arrow: false,
25
+ content: /*#__PURE__*/_jsxs(Flexbox, {
26
+ gap: 8,
27
+ style: {
28
+ minWidth: 240
29
+ },
30
+ children: [/*#__PURE__*/_jsxs(Flexbox, {
31
+ align: 'center',
32
+ gap: 8,
33
+ horizontal: true,
34
+ justify: 'space-between',
35
+ children: [/*#__PURE__*/_jsx(Text, {
36
+ children: t('codemirror.tabSize')
37
+ }), /*#__PURE__*/_jsx(InputNumber, {
38
+ max: 8,
39
+ min: 1,
40
+ onChange: handleTabSizeChange,
41
+ size: "small",
42
+ value: tabSize
43
+ })]
44
+ }), /*#__PURE__*/_jsxs(Flexbox, {
45
+ align: 'center',
46
+ gap: 8,
47
+ horizontal: true,
48
+ justify: 'space-between',
49
+ children: [/*#__PURE__*/_jsx(Text, {
50
+ children: t('codemirror.useTabs')
51
+ }), /*#__PURE__*/_jsx(Switch, {
52
+ checked: useTabs,
53
+ onChange: onUseTabsChange,
54
+ size: "small"
55
+ })]
56
+ }), /*#__PURE__*/_jsxs(Flexbox, {
57
+ align: 'center',
58
+ gap: 8,
59
+ horizontal: true,
60
+ justify: 'space-between',
61
+ children: [/*#__PURE__*/_jsx(Text, {
62
+ children: t('codemirror.showLineNumbers')
63
+ }), /*#__PURE__*/_jsx(Switch, {
64
+ checked: showLineNumbers,
65
+ onChange: onShowLineNumbersChange,
66
+ size: "small"
67
+ })]
68
+ })]
69
+ }),
70
+ placement: "bottomRight",
71
+ trigger: "click",
72
+ children: /*#__PURE__*/_jsx(ActionIcon, {
73
+ className: 'cm-hidden-actions',
74
+ icon: MoreHorizontalIcon,
75
+ size: "small"
76
+ })
77
+ });
78
+ };
79
+ MoreOptions.displayName = 'MoreOptions';
@@ -0,0 +1,16 @@
1
+ import { type FC } from 'react';
2
+ export interface ToolbarProps {
3
+ expand?: boolean;
4
+ onClick?: () => void;
5
+ onCopy: () => void;
6
+ onLanguageChange: (value: string) => void;
7
+ onShowLineNumbersChange: (checked: boolean) => void;
8
+ onTabSizeChange: (value: number | null) => void;
9
+ onUseTabsChange: (checked: boolean) => void;
10
+ selectedLang: string;
11
+ showLineNumbers: boolean;
12
+ tabSize: number;
13
+ toggleExpand?: () => void;
14
+ useTabs: boolean;
15
+ }
16
+ export declare const Toolbar: FC<ToolbarProps>;