@lobehub/editor 1.16.3 → 1.17.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.
- package/es/index.d.ts +1 -0
- package/es/index.js +1 -0
- package/es/locale/index.d.ts +6 -0
- package/es/locale/index.js +6 -0
- package/es/plugins/markdown/command/index.d.ts +6 -0
- package/es/plugins/markdown/command/index.js +27 -0
- package/es/plugins/markdown/data-source/markdown/parse.js +4 -0
- package/es/plugins/markdown/index.d.ts +2 -0
- package/es/plugins/markdown/index.js +2 -0
- package/es/plugins/markdown/plugin/index.js +33 -21
- package/es/plugins/markdown/react/index.d.ts +3 -0
- package/es/plugins/markdown/react/index.js +70 -0
- package/es/types/kernel.d.ts +9 -1
- package/package.json +1 -1
package/es/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './plugins/hr';
|
|
|
8
8
|
export * from './plugins/image';
|
|
9
9
|
export * from './plugins/link';
|
|
10
10
|
export * from './plugins/list';
|
|
11
|
+
export * from './plugins/markdown';
|
|
11
12
|
export * from './plugins/math';
|
|
12
13
|
export * from './plugins/mention';
|
|
13
14
|
export * from './plugins/slash';
|
package/es/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./plugins/hr";
|
|
|
8
8
|
export * from "./plugins/image";
|
|
9
9
|
export * from "./plugins/link";
|
|
10
10
|
export * from "./plugins/list";
|
|
11
|
+
export * from "./plugins/markdown";
|
|
11
12
|
export * from "./plugins/math";
|
|
12
13
|
export * from "./plugins/mention";
|
|
13
14
|
export * from "./plugins/slash";
|
package/es/locale/index.d.ts
CHANGED
package/es/locale/index.js
CHANGED
|
@@ -16,6 +16,12 @@ export default {
|
|
|
16
16
|
placeholder: 'Enter link URL',
|
|
17
17
|
unlink: 'Unlink Link'
|
|
18
18
|
},
|
|
19
|
+
markdown: {
|
|
20
|
+
cancel: 'Cancel',
|
|
21
|
+
confirm: 'Confirm',
|
|
22
|
+
parseMessage: 'Convert to markdown format, existing content will be overwritten, confirm? (Auto close in 5 seconds)',
|
|
23
|
+
parseTitle: 'Parse Markdown'
|
|
24
|
+
},
|
|
19
25
|
math: {
|
|
20
26
|
placeholder: 'Enter TeX formula'
|
|
21
27
|
},
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { LexicalEditor } from 'lexical';
|
|
2
|
+
import { MarkdownShortCutService } from '../service/shortcut';
|
|
3
|
+
export declare const INSERT_MARKDOWN_COMMAND: import("lexical").LexicalCommand<{
|
|
4
|
+
markdown: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function registerMarkdownCommand(editor: LexicalEditor, service: MarkdownShortCutService): () => void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { $getSelection, COMMAND_PRIORITY_HIGH, createCommand } from 'lexical';
|
|
2
|
+
import { createDebugLogger } from "../../../utils/debug";
|
|
3
|
+
import { parseMarkdownToLexical } from "../data-source/markdown/parse";
|
|
4
|
+
import { $generateNodesFromSerializedNodes, $insertGeneratedNodes } from "../utils";
|
|
5
|
+
var logger = createDebugLogger('plugin', 'markdown');
|
|
6
|
+
export var INSERT_MARKDOWN_COMMAND = createCommand('INSERT_MARKDOWN_COMMAND');
|
|
7
|
+
export function registerMarkdownCommand(editor, service) {
|
|
8
|
+
return editor.registerCommand(INSERT_MARKDOWN_COMMAND, function (payload) {
|
|
9
|
+
var markdown = payload.markdown;
|
|
10
|
+
logger.debug('INSERT_MARKDOWN_COMMAND payload:', payload);
|
|
11
|
+
editor.update(function () {
|
|
12
|
+
try {
|
|
13
|
+
// Use the markdown data source to parse the content
|
|
14
|
+
var root = parseMarkdownToLexical(markdown, service.markdownReaders);
|
|
15
|
+
var selection = $getSelection();
|
|
16
|
+
var nodes = $generateNodesFromSerializedNodes(root.children);
|
|
17
|
+
logger.debug('INSERT_MARKDOWN_COMMAND nodes:', nodes);
|
|
18
|
+
$insertGeneratedNodes(editor, nodes, selection);
|
|
19
|
+
return true;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
logger.error('Failed to handle markdown paste:', error);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return false;
|
|
25
|
+
}, COMMAND_PRIORITY_HIGH // Priority
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -68,6 +68,10 @@ function convertMdastToLexical(node, index, ctx) {
|
|
|
68
68
|
var htmlStack = []; // 当前循环是否包含 HTML 标签
|
|
69
69
|
_children = node.children.reduce(function (ret, child, index) {
|
|
70
70
|
if (child.type === 'html') {
|
|
71
|
+
var isComment = child.value.startsWith('<!--') && child.value.endsWith('-->');
|
|
72
|
+
if (isComment) {
|
|
73
|
+
return ret;
|
|
74
|
+
}
|
|
71
75
|
var tag = child.value.replaceAll(/^<\/?|>$/g, '');
|
|
72
76
|
var isEndTag = child.value.startsWith('</');
|
|
73
77
|
if (selfClosingHtmlTags.has(tag)) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export { INSERT_MARKDOWN_COMMAND } from './command';
|
|
1
2
|
export { MarkdownPlugin } from './plugin';
|
|
3
|
+
export { default as ReactMarkdownPlugin } from './react';
|
|
2
4
|
export type { MARKDOWN_READER_LEVEL } from './service/shortcut';
|
|
3
5
|
export { IMarkdownShortCutService, MARKDOWN_READER_LEVEL_HIGH, MARKDOWN_READER_LEVEL_NORMAL, MARKDOWN_WRITER_LEVEL_MAX, } from './service/shortcut';
|
|
4
6
|
export { isPunctuationChar } from './utils';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { INSERT_MARKDOWN_COMMAND } from "./command";
|
|
1
2
|
export { MarkdownPlugin } from "./plugin";
|
|
3
|
+
export { default as ReactMarkdownPlugin } from "./react";
|
|
2
4
|
export { IMarkdownShortCutService, MARKDOWN_READER_LEVEL_HIGH, MARKDOWN_READER_LEVEL_NORMAL, MARKDOWN_WRITER_LEVEL_MAX } from "./service/shortcut";
|
|
3
5
|
export { isPunctuationChar } from "./utils";
|
|
@@ -17,10 +17,10 @@ import { $isCodeNode } from '@lexical/code';
|
|
|
17
17
|
import { $getNodeByKey, $getSelection, $isRangeSelection, $isTextNode, COLLABORATION_TAG, COMMAND_PRIORITY_CRITICAL, HISTORIC_TAG, KEY_ENTER_COMMAND, PASTE_COMMAND } from 'lexical';
|
|
18
18
|
import { KernelPlugin } from "../../../editor-kernel/plugin";
|
|
19
19
|
import { createDebugLogger } from "../../../utils/debug";
|
|
20
|
+
import { registerMarkdownCommand } from "../command";
|
|
20
21
|
import MarkdownDataSource from "../data-source/markdown-data-source";
|
|
21
|
-
import { parseMarkdownToLexical } from "../data-source/markdown/parse";
|
|
22
22
|
import { IMarkdownShortCutService, MarkdownShortCutService } from "../service/shortcut";
|
|
23
|
-
import {
|
|
23
|
+
import { canContainTransformableMarkdown } from "../utils";
|
|
24
24
|
export var MarkdownPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
25
25
|
_inherits(MarkdownPlugin, _KernelPlugin);
|
|
26
26
|
var _super = _createSuper(MarkdownPlugin);
|
|
@@ -165,10 +165,23 @@ export var MarkdownPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
165
165
|
});
|
|
166
166
|
if (hasMarkdownContent) {
|
|
167
167
|
// Handle markdown paste
|
|
168
|
-
return
|
|
168
|
+
// return this.handleMarkdownPaste(editor, text);
|
|
169
|
+
var cacheState = editor.getEditorState();
|
|
170
|
+
_this2.kernel.emit('markdownParse', {
|
|
171
|
+
cacheState: cacheState,
|
|
172
|
+
markdown: text
|
|
173
|
+
});
|
|
174
|
+
// setTimeout(() => {
|
|
175
|
+
// editor.setEditorState(cacheState);
|
|
176
|
+
// editor.update(() => {
|
|
177
|
+
// this.handleMarkdownPaste(editor, text);
|
|
178
|
+
// });
|
|
179
|
+
// }, 5000);
|
|
180
|
+
return false;
|
|
169
181
|
}
|
|
170
182
|
return false;
|
|
171
183
|
}, COMMAND_PRIORITY_CRITICAL));
|
|
184
|
+
this.register(registerMarkdownCommand(editor, this.service));
|
|
172
185
|
}
|
|
173
186
|
|
|
174
187
|
/**
|
|
@@ -260,24 +273,23 @@ export var MarkdownPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
260
273
|
});
|
|
261
274
|
}
|
|
262
275
|
|
|
263
|
-
/**
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
276
|
+
// /**
|
|
277
|
+
// * Handle markdown paste by parsing and inserting as structured content
|
|
278
|
+
// */
|
|
279
|
+
// private handleMarkdownPaste(editor: LexicalEditor, text: string): boolean {
|
|
280
|
+
// try {
|
|
281
|
+
// // Use the markdown data source to parse the content
|
|
282
|
+
// const root = parseMarkdownToLexical(text, this.service.markdownReaders);
|
|
283
|
+
// const selection = $getSelection();
|
|
284
|
+
// const nodes = $generateNodesFromSerializedNodes(root.children);
|
|
285
|
+
// $insertGeneratedNodes(editor, nodes, selection!);
|
|
286
|
+
// return true;
|
|
287
|
+
// } catch (error) {
|
|
288
|
+
// this.logger.error('Failed to handle markdown paste:', error);
|
|
289
|
+
// }
|
|
290
|
+
|
|
291
|
+
// return false;
|
|
292
|
+
// }
|
|
281
293
|
}]);
|
|
282
294
|
return MarkdownPlugin;
|
|
283
295
|
}(KernelPlugin), _defineProperty(_class, "pluginName", 'MarkdownPlugin'), _class);
|
|
@@ -0,0 +1,70 @@
|
|
|
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 { Button, Space, notification } from 'antd';
|
|
10
|
+
import { UNDO_COMMAND } from 'lexical';
|
|
11
|
+
import { useLayoutEffect } from 'react';
|
|
12
|
+
import { useLexicalComposerContext } from "../../../editor-kernel/react";
|
|
13
|
+
import { useTranslation } from "../../../editor-kernel/react/useTranslation";
|
|
14
|
+
import { INSERT_MARKDOWN_COMMAND } from "../command";
|
|
15
|
+
import { MarkdownPlugin } from "../plugin";
|
|
16
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
17
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
|
+
var ReactMarkdownPlugin = function ReactMarkdownPlugin() {
|
|
19
|
+
var _useLexicalComposerCo = useLexicalComposerContext(),
|
|
20
|
+
_useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
|
|
21
|
+
editor = _useLexicalComposerCo2[0];
|
|
22
|
+
var _notification$useNoti = notification.useNotification(),
|
|
23
|
+
_notification$useNoti2 = _slicedToArray(_notification$useNoti, 2),
|
|
24
|
+
api = _notification$useNoti2[0],
|
|
25
|
+
contextHolder = _notification$useNoti2[1];
|
|
26
|
+
var t = useTranslation();
|
|
27
|
+
useLayoutEffect(function () {
|
|
28
|
+
editor.registerPlugin(MarkdownPlugin);
|
|
29
|
+
var handleEvent = function handleEvent(_ref) {
|
|
30
|
+
var markdown = _ref.markdown;
|
|
31
|
+
var key = "open".concat(Date.now());
|
|
32
|
+
var actions = /*#__PURE__*/_jsxs(Space, {
|
|
33
|
+
children: [/*#__PURE__*/_jsx(Button, {
|
|
34
|
+
onClick: function onClick() {
|
|
35
|
+
return api.destroy();
|
|
36
|
+
},
|
|
37
|
+
size: "small",
|
|
38
|
+
type: "link",
|
|
39
|
+
children: t('markdown.cancel')
|
|
40
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
41
|
+
onClick: function onClick() {
|
|
42
|
+
editor.dispatchCommand(UNDO_COMMAND, undefined);
|
|
43
|
+
editor.dispatchCommand(INSERT_MARKDOWN_COMMAND, {
|
|
44
|
+
markdown: markdown
|
|
45
|
+
});
|
|
46
|
+
api.destroy();
|
|
47
|
+
},
|
|
48
|
+
size: "small",
|
|
49
|
+
type: "primary",
|
|
50
|
+
children: t('markdown.confirm')
|
|
51
|
+
})]
|
|
52
|
+
});
|
|
53
|
+
api.open({
|
|
54
|
+
actions: actions,
|
|
55
|
+
description: t('markdown.parseMessage'),
|
|
56
|
+
duration: 5,
|
|
57
|
+
key: key,
|
|
58
|
+
message: t('markdown.parseTitle'),
|
|
59
|
+
onClose: close
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
editor.on('markdownParse', handleEvent);
|
|
63
|
+
return function () {
|
|
64
|
+
editor.off('markdownParse', handleEvent);
|
|
65
|
+
};
|
|
66
|
+
}, [editor]);
|
|
67
|
+
return contextHolder;
|
|
68
|
+
};
|
|
69
|
+
ReactMarkdownPlugin.displayName = 'ReactMarkdownPlugin';
|
|
70
|
+
export default ReactMarkdownPlugin;
|
package/es/types/kernel.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CommandListener, CommandListenerPriority, CommandPayloadType, DecoratorNode, LexicalCommand, LexicalEditor, LexicalNodeConfig } from 'lexical';
|
|
1
|
+
import type { CommandListener, CommandListenerPriority, CommandPayloadType, DecoratorNode, EditorState, LexicalCommand, LexicalEditor, LexicalNodeConfig } from 'lexical';
|
|
2
2
|
import type DataSource from "../editor-kernel/data-source";
|
|
3
3
|
import { HotkeyId } from "./hotkey";
|
|
4
4
|
import { HotkeyOptions, HotkeysEvent } from "../utils/hotkey/registerHotkey";
|
|
@@ -23,6 +23,13 @@ export interface IKernelEventMap {
|
|
|
23
23
|
* @returns
|
|
24
24
|
*/
|
|
25
25
|
initialized: (editor: LexicalEditor) => void;
|
|
26
|
+
/**
|
|
27
|
+
* handle markdown parse event
|
|
28
|
+
*/
|
|
29
|
+
markdownParse: (params: {
|
|
30
|
+
cacheState: EditorState;
|
|
31
|
+
markdown: string;
|
|
32
|
+
}) => void;
|
|
26
33
|
}
|
|
27
34
|
/**
|
|
28
35
|
* External API
|
|
@@ -175,6 +182,7 @@ export interface IEditor {
|
|
|
175
182
|
* API provided to plugins
|
|
176
183
|
*/
|
|
177
184
|
export interface IEditorKernel extends IEditor {
|
|
185
|
+
emit<T extends keyof IKernelEventMap>(event: T, params: Parameters<IKernelEventMap[T]>[0]): void;
|
|
178
186
|
/**
|
|
179
187
|
* Get editor Node decorator for specific Node rendering
|
|
180
188
|
* @param name
|
package/package.json
CHANGED