@lobehub/editor 1.10.0 → 1.12.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/editor-kernel/inode/helper.d.ts +9 -6
- package/es/editor-kernel/inode/helper.js +27 -0
- package/es/editor-kernel/inode/text-node.d.ts +2 -9
- package/es/plugins/code/plugin/index.d.ts +1 -1
- package/es/plugins/code/plugin/index.js +12 -1
- package/es/plugins/codeblock/command/index.d.ts +6 -0
- package/es/plugins/codeblock/command/index.js +1 -0
- package/es/plugins/codeblock/plugin/CodeHighlighterShiki.d.ts +7 -0
- package/es/plugins/codeblock/plugin/CodeHighlighterShiki.js +59 -2
- package/es/plugins/codeblock/plugin/FacadeShiki.d.ts +8 -1
- package/es/plugins/codeblock/plugin/FacadeShiki.js +95 -6
- package/es/plugins/codeblock/plugin/index.js +74 -29
- package/es/plugins/common/data-source/json-data-source.d.ts +2 -2
- package/es/plugins/common/data-source/json-data-source.js +2 -10
- package/es/plugins/common/index.d.ts +1 -1
- package/es/plugins/common/index.js +1 -1
- package/es/plugins/common/node/cursor.d.ts +3 -1
- package/es/plugins/common/node/cursor.js +9 -0
- package/es/plugins/common/plugin/index.d.ts +1 -1
- package/es/plugins/common/plugin/index.js +28 -1
- package/es/plugins/common/plugin/mdReader.d.ts +2 -0
- package/es/plugins/common/plugin/mdReader.js +59 -0
- package/es/plugins/common/react/ReactPlainText.d.ts +1 -1
- package/es/plugins/common/utils/index.d.ts +2 -2
- package/es/plugins/hr/plugin/index.js +26 -22
- package/es/plugins/link/plugin/index.js +42 -26
- package/es/plugins/list/plugin/index.js +121 -63
- package/es/plugins/list/utils/index.d.ts +3 -3
- package/es/plugins/markdown/data-source/markdown/parse.d.ts +10 -0
- package/es/plugins/markdown/data-source/markdown/parse.js +82 -0
- package/es/plugins/markdown/data-source/markdown/supersub.d.ts +1 -0
- package/es/plugins/markdown/data-source/markdown/supersub.js +14 -0
- package/es/plugins/markdown/data-source/markdown-data-source.d.ts +4 -4
- package/es/plugins/markdown/data-source/markdown-data-source.js +8 -2
- package/es/plugins/markdown/plugin/index.js +135 -2
- package/es/plugins/markdown/service/shortcut.d.ts +15 -85
- package/es/plugins/markdown/service/shortcut.js +34 -293
- package/es/plugins/markdown/service/transformers.d.ts +60 -0
- package/es/plugins/markdown/service/transformers.js +286 -0
- package/es/plugins/markdown/utils/index.d.ts +45 -1
- package/es/plugins/markdown/utils/index.js +147 -1
- package/es/plugins/markdown/utils/logger.d.ts +7 -0
- package/es/plugins/markdown/utils/logger.js +2 -0
- package/es/plugins/math/plugin/index.js +64 -45
- package/es/plugins/table/plugin/index.js +71 -26
- package/es/react/hooks/useEditorState/index.js +43 -21
- package/es/types/global.d.ts +64 -0
- package/package.json +2 -1
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { IElementNode } from './i-element-node';
|
|
2
|
-
import { INode } from './i-node';
|
|
3
|
-
import { IParagraphNode } from './paragraph-node';
|
|
4
|
-
import { IRootNode } from './root-node';
|
|
5
|
-
import { ITextNode } from './text-node';
|
|
1
|
+
import type { IElementNode } from './i-element-node';
|
|
2
|
+
import type { INode } from './i-node';
|
|
3
|
+
import type { IParagraphNode } from './paragraph-node';
|
|
4
|
+
import type { IRootNode } from './root-node';
|
|
5
|
+
import type { ITextNode } from './text-node';
|
|
6
6
|
export declare const INodeHelper: {
|
|
7
7
|
appendChild(parent: IElementNode, ...child: INode[]): void;
|
|
8
|
+
createElementNode(type: string, attrs?: Record<string, unknown>): IElementNode;
|
|
9
|
+
createLikeTextNode(type: string, text: string, attrs?: Record<string, unknown>): ITextNode;
|
|
8
10
|
createParagraph(attrs?: Record<string, unknown>): IParagraphNode;
|
|
9
11
|
createRootNode(attrs?: Record<string, unknown>): IRootNode;
|
|
10
12
|
createTextNode(text: string, attrs?: Record<string, unknown>): ITextNode;
|
|
13
|
+
createTypeNode(type: string, attrs?: Record<string, unknown>): INode;
|
|
11
14
|
isParagraphNode(node: INode): node is IParagraphNode;
|
|
12
15
|
isRootNode(node: INode): node is IRootNode;
|
|
13
|
-
isTextNode(node: INode): node is
|
|
16
|
+
isTextNode(node: INode): node is import("lexical").SerializedTextNode;
|
|
14
17
|
};
|
|
@@ -22,6 +22,26 @@ export var INodeHelper = {
|
|
|
22
22
|
}
|
|
23
23
|
(_parent$children = parent.children).push.apply(_parent$children, child);
|
|
24
24
|
},
|
|
25
|
+
createElementNode: function createElementNode(type) {
|
|
26
|
+
var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
27
|
+
return _objectSpread(_objectSpread(_objectSpread({}, BaseContent), {}, {
|
|
28
|
+
children: []
|
|
29
|
+
}, attrs), {}, {
|
|
30
|
+
type: type
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
createLikeTextNode: function createLikeTextNode(type, text) {
|
|
34
|
+
var attrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
35
|
+
return _objectSpread(_objectSpread(_objectSpread({}, BaseContent), {}, {
|
|
36
|
+
detail: 0,
|
|
37
|
+
format: 0,
|
|
38
|
+
mode: 'normal',
|
|
39
|
+
style: ''
|
|
40
|
+
}, attrs), {}, {
|
|
41
|
+
text: text,
|
|
42
|
+
type: type
|
|
43
|
+
});
|
|
44
|
+
},
|
|
25
45
|
createParagraph: function createParagraph() {
|
|
26
46
|
var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
27
47
|
return _objectSpread(_objectSpread(_objectSpread({}, BaseContent), {}, {
|
|
@@ -43,6 +63,7 @@ export var INodeHelper = {
|
|
|
43
63
|
var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
44
64
|
return _objectSpread(_objectSpread(_objectSpread({}, BaseContent), {}, {
|
|
45
65
|
detail: 0,
|
|
66
|
+
format: 0,
|
|
46
67
|
mode: 'normal',
|
|
47
68
|
style: ''
|
|
48
69
|
}, attrs), {}, {
|
|
@@ -50,6 +71,12 @@ export var INodeHelper = {
|
|
|
50
71
|
type: 'text'
|
|
51
72
|
});
|
|
52
73
|
},
|
|
74
|
+
createTypeNode: function createTypeNode(type) {
|
|
75
|
+
var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
76
|
+
return _objectSpread(_objectSpread(_objectSpread({}, BaseContent), attrs), {}, {
|
|
77
|
+
type: type
|
|
78
|
+
});
|
|
79
|
+
},
|
|
53
80
|
isParagraphNode: function isParagraphNode(node) {
|
|
54
81
|
return node.type === 'paragraph';
|
|
55
82
|
},
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { INode } from './i-node';
|
|
1
|
+
import type { SerializedTextNode } from 'lexical';
|
|
3
2
|
/**
|
|
4
3
|
* Text node
|
|
5
4
|
*/
|
|
6
|
-
export
|
|
7
|
-
detail: number;
|
|
8
|
-
mode: TextModeType;
|
|
9
|
-
style: string;
|
|
10
|
-
text: string;
|
|
11
|
-
type: 'text';
|
|
12
|
-
}
|
|
5
|
+
export type ITextNode = SerializedTextNode;
|
|
@@ -14,8 +14,9 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
|
|
|
14
14
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
15
15
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
16
16
|
import { $setSelection } from 'lexical';
|
|
17
|
+
import { INodeHelper } from "../../../editor-kernel/inode/helper";
|
|
17
18
|
import { KernelPlugin } from "../../../editor-kernel/plugin";
|
|
18
|
-
import { $createCursorNode } from "../../common";
|
|
19
|
+
import { $createCursorNode, cursorNodeSerialized } from "../../common";
|
|
19
20
|
import { IMarkdownShortCutService } from "../../markdown/service/shortcut";
|
|
20
21
|
import { registerCodeInlineCommand } from "../command";
|
|
21
22
|
import { $createCodeNode, CodeNode } from "../node/code";
|
|
@@ -61,6 +62,16 @@ export var CodePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
61
62
|
tag: '`',
|
|
62
63
|
type: 'text-format'
|
|
63
64
|
}]);
|
|
65
|
+
markdownService.registerMarkdownReader('inlineCode', function (node) {
|
|
66
|
+
return [INodeHelper.createElementNode('codeInline', {
|
|
67
|
+
children: [cursorNodeSerialized, INodeHelper.createTextNode(node.value || '', {})],
|
|
68
|
+
direction: 'ltr',
|
|
69
|
+
format: '',
|
|
70
|
+
indent: 0,
|
|
71
|
+
type: 'codeInline',
|
|
72
|
+
version: 1
|
|
73
|
+
}), cursorNodeSerialized];
|
|
74
|
+
});
|
|
64
75
|
}
|
|
65
76
|
}]);
|
|
66
77
|
return CodePlugin;
|
|
@@ -2,6 +2,12 @@ import { CodeNode } from '@lexical/code';
|
|
|
2
2
|
import { LexicalEditor, LexicalNode } from 'lexical';
|
|
3
3
|
export declare const CustomShikiTokenizer: {
|
|
4
4
|
$tokenize: (codeNode: CodeNode, language?: string | undefined) => LexicalNode[];
|
|
5
|
+
$tokenizeSerialized: (code: string, language?: string | undefined, theme?: string | {
|
|
6
|
+
dark: string;
|
|
7
|
+
light: string;
|
|
8
|
+
} | undefined, defaultColorReplacements?: {
|
|
9
|
+
current?: import("../plugin/FacadeShiki").AllColorReplacements | undefined;
|
|
10
|
+
} | undefined) => import("lexical").SerializedLexicalNode[];
|
|
5
11
|
defaultColorReplacements: {
|
|
6
12
|
current?: import("../plugin/FacadeShiki").AllColorReplacements | undefined;
|
|
7
13
|
} | undefined;
|
|
@@ -10,6 +10,7 @@ import { $getRoot, $getSelection, $isElementNode, $isRangeSelection, COMMAND_PRI
|
|
|
10
10
|
import { ShikiTokenizer } from "../plugin/CodeHighlighterShiki";
|
|
11
11
|
export var CustomShikiTokenizer = {
|
|
12
12
|
$tokenize: ShikiTokenizer.$tokenize,
|
|
13
|
+
$tokenizeSerialized: ShikiTokenizer.$tokenizeSerialized,
|
|
13
14
|
defaultColorReplacements: ShikiTokenizer.defaultColorReplacements,
|
|
14
15
|
defaultLanguage: ShikiTokenizer.defaultLanguage,
|
|
15
16
|
defaultTheme: ShikiTokenizer.defaultTheme
|
|
@@ -7,9 +7,16 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { CodeNode } from '@lexical/code';
|
|
9
9
|
import type { LexicalEditor, LexicalNode } from 'lexical';
|
|
10
|
+
import { INode } from "../../../editor-kernel/inode";
|
|
10
11
|
import { AllColorReplacements } from './FacadeShiki';
|
|
11
12
|
export interface Tokenizer {
|
|
12
13
|
$tokenize(codeNode: CodeNode, language?: string): LexicalNode[];
|
|
14
|
+
$tokenizeSerialized(code: string, language?: string, theme?: string | {
|
|
15
|
+
dark: string;
|
|
16
|
+
light: string;
|
|
17
|
+
}, defaultColorReplacements?: {
|
|
18
|
+
current?: AllColorReplacements;
|
|
19
|
+
}): INode[];
|
|
13
20
|
defaultColorReplacements?: {
|
|
14
21
|
current?: AllColorReplacements;
|
|
15
22
|
};
|
|
@@ -15,13 +15,20 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
|
|
|
15
15
|
import { $getEndOfCodeInLine, $getFirstCodeNodeOfLine, $getLastCodeNodeOfLine, $getStartOfCodeInLine, $isCodeHighlightNode, $isCodeNode, CodeHighlightNode, CodeNode, DEFAULT_CODE_LANGUAGE } from '@lexical/code';
|
|
16
16
|
import { mergeRegister } from '@lexical/utils';
|
|
17
17
|
import { $createLineBreakNode, $createPoint, $createTabNode, $createTextNode, $getCaretRange, $getCaretRangeInDirection, $getNodeByKey, $getSelection, $getSiblingCaret, $getTextPointCaret, $insertNodes, $isLineBreakNode, $isRangeSelection, $isTabNode, $isTextNode, $normalizeCaret, $setSelectionFromCaretRange, COMMAND_PRIORITY_LOW, INDENT_CONTENT_COMMAND, INSERT_TAB_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_TAB_COMMAND, MOVE_TO_END, MOVE_TO_START, OUTDENT_CONTENT_COMMAND, TextNode } from 'lexical';
|
|
18
|
-
import { $getHighlightNodes, isCodeLanguageLoaded, isCodeThemeLoaded, loadCodeLanguage, loadCodeTheme } from "./FacadeShiki";
|
|
18
|
+
import { $getHighlightNodes, getHighlightSerializeNode, isCodeLanguageLoaded, isCodeThemeLoaded, loadCodeLanguage, loadCodeTheme } from "./FacadeShiki";
|
|
19
19
|
import invariant from "./invariant";
|
|
20
20
|
var DEFAULT_CODE_THEME = 'slack-ochin';
|
|
21
21
|
export var ShikiTokenizer = {
|
|
22
22
|
$tokenize: function $tokenize(codeNode, language) {
|
|
23
23
|
return $getHighlightNodes(codeNode, language || this.defaultLanguage, this.defaultColorReplacements);
|
|
24
24
|
},
|
|
25
|
+
$tokenizeSerialized: function $tokenizeSerialized(code, language, theme, defaultColorReplacements) {
|
|
26
|
+
return getHighlightSerializeNode(code, language || this.defaultLanguage,
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
28
|
+
toCodeTheme({
|
|
29
|
+
defaultTheme: theme || this.defaultTheme
|
|
30
|
+
}), defaultColorReplacements || ShikiTokenizer.defaultColorReplacements);
|
|
31
|
+
},
|
|
25
32
|
defaultColorReplacements: undefined,
|
|
26
33
|
defaultLanguage: DEFAULT_CODE_LANGUAGE,
|
|
27
34
|
defaultTheme: DEFAULT_CODE_THEME
|
|
@@ -77,7 +84,9 @@ function updateCodeGutter(node, editor) {
|
|
|
77
84
|
// in both cases we'll rerun whole reformatting over CodeNode, which is redundant.
|
|
78
85
|
// Especially when pasting code into CodeBlock.
|
|
79
86
|
|
|
87
|
+
var MAX_CONCURRENT_HIGHLIGHTING = 2;
|
|
80
88
|
var nodesCurrentlyHighlighting = new Set();
|
|
89
|
+
var waitingNodesCurrentlyHighlighting = new Set();
|
|
81
90
|
function codeNodeTransform(node, editor, tokenizer) {
|
|
82
91
|
var nodeKey = node.getKey();
|
|
83
92
|
|
|
@@ -118,6 +127,10 @@ function codeNodeTransform(node, editor, tokenizer) {
|
|
|
118
127
|
if (nodesCurrentlyHighlighting.has(nodeKey)) {
|
|
119
128
|
return;
|
|
120
129
|
}
|
|
130
|
+
if (nodesCurrentlyHighlighting.size > MAX_CONCURRENT_HIGHLIGHTING) {
|
|
131
|
+
waitingNodesCurrentlyHighlighting.add(nodeKey);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
121
134
|
nodesCurrentlyHighlighting.add(nodeKey);
|
|
122
135
|
|
|
123
136
|
// Using nested update call to pass `skipTransforms` since we don't want
|
|
@@ -146,6 +159,16 @@ function codeNodeTransform(node, editor, tokenizer) {
|
|
|
146
159
|
}, {
|
|
147
160
|
onUpdate: function onUpdate() {
|
|
148
161
|
nodesCurrentlyHighlighting.delete(nodeKey);
|
|
162
|
+
if (nodesCurrentlyHighlighting.size < MAX_CONCURRENT_HIGHLIGHTING && waitingNodesCurrentlyHighlighting.size) {
|
|
163
|
+
var next = waitingNodesCurrentlyHighlighting.values().next().value;
|
|
164
|
+
if (!next) return;
|
|
165
|
+
waitingNodesCurrentlyHighlighting.delete(next);
|
|
166
|
+
requestAnimationFrame(function () {
|
|
167
|
+
editor.read(function () {
|
|
168
|
+
codeNodeTransform($getNodeByKey(next), editor, tokenizer);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
}
|
|
149
172
|
},
|
|
150
173
|
skipTransforms: true
|
|
151
174
|
});
|
|
@@ -614,7 +637,41 @@ export function registerCodeHighlighting(editor, tokenizer) {
|
|
|
614
637
|
}
|
|
615
638
|
|
|
616
639
|
// Add the rest of the registrations
|
|
617
|
-
registrations.push(editor.
|
|
640
|
+
registrations.push(editor.registerMutationListener(CodeNode, function (mutations) {
|
|
641
|
+
editor.update(function () {
|
|
642
|
+
var _iterator4 = _createForOfIteratorHelper(mutations),
|
|
643
|
+
_step4;
|
|
644
|
+
try {
|
|
645
|
+
var _loop = function _loop() {
|
|
646
|
+
var _step4$value = _slicedToArray(_step4.value, 2),
|
|
647
|
+
key = _step4$value[0],
|
|
648
|
+
type = _step4$value[1];
|
|
649
|
+
if (type !== 'destroyed') {
|
|
650
|
+
var node = $getNodeByKey(key);
|
|
651
|
+
if (node !== null) {
|
|
652
|
+
var _codeNode2$getTheme;
|
|
653
|
+
var _codeNode2 = node;
|
|
654
|
+
if ((_codeNode2$getTheme = _codeNode2.getTheme()) !== null && _codeNode2$getTheme !== void 0 && _codeNode2$getTheme.endsWith(' needUpdate')) {
|
|
655
|
+
editor.update(function () {
|
|
656
|
+
var _codeNode2$getTheme2;
|
|
657
|
+
_codeNode2.setTheme(((_codeNode2$getTheme2 = _codeNode2.getTheme()) === null || _codeNode2$getTheme2 === void 0 ? void 0 : _codeNode2$getTheme2.replace(' needUpdate', '')) || '');
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
664
|
+
_loop();
|
|
665
|
+
}
|
|
666
|
+
} catch (err) {
|
|
667
|
+
_iterator4.e(err);
|
|
668
|
+
} finally {
|
|
669
|
+
_iterator4.f();
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
}, {
|
|
673
|
+
skipInitialization: false
|
|
674
|
+
}), editor.registerNodeTransform(CodeNode, function (node) {
|
|
618
675
|
return codeNodeTransform(node, editor, tokenizer);
|
|
619
676
|
}), editor.registerNodeTransform(TextNode, function (node) {
|
|
620
677
|
return $textNodeTransform(node, editor, tokenizer);
|
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
import type { CodeNode } from '@lexical/code';
|
|
9
|
-
import type { LexicalEditor, LexicalNode, NodeKey } from 'lexical';
|
|
9
|
+
import type { LexicalEditor, LexicalNode, NodeKey, SerializedTextNode, Spread } from 'lexical';
|
|
10
|
+
import { INode } from "../../../editor-kernel/inode";
|
|
10
11
|
export type ColorReplacements = Record<string, string>;
|
|
11
12
|
export type ScopedColorReplacements = Record<string, ColorReplacements>;
|
|
12
13
|
export type AllColorReplacements = ColorReplacements | ScopedColorReplacements;
|
|
14
|
+
export type SerializedCodeHighlightNode = Spread<{
|
|
15
|
+
highlightType: string | null | undefined;
|
|
16
|
+
}, SerializedTextNode>;
|
|
13
17
|
/**
|
|
14
18
|
* Creates a simple color replacement map
|
|
15
19
|
* @param replacements - Object mapping from old color to new color
|
|
@@ -35,6 +39,9 @@ export declare function loadCodeTheme(theme: string, editor?: LexicalEditor, cod
|
|
|
35
39
|
export declare function getCodeLanguageOptions(): [string, string][];
|
|
36
40
|
export declare function getCodeThemeOptions(): [string, string][];
|
|
37
41
|
export declare function normalizeCodeLanguage(language: string): string;
|
|
42
|
+
export declare function getHighlightSerializeNode(code: string, language: string, theme?: string, colorReplacements?: {
|
|
43
|
+
current?: AllColorReplacements;
|
|
44
|
+
}): INode[];
|
|
38
45
|
export declare function $getHighlightNodes(codeNode: CodeNode, language: string, colorReplacements?: {
|
|
39
46
|
current?: AllColorReplacements;
|
|
40
47
|
}): LexicalNode[];
|
|
@@ -15,6 +15,7 @@ import { createHighlighterCoreSync, isSpecialLang, isSpecialTheme, stringifyToke
|
|
|
15
15
|
import { createJavaScriptRegexEngine } from '@shikijs/engine-javascript';
|
|
16
16
|
import { $createLineBreakNode, $createTabNode, $getNodeByKey } from 'lexical';
|
|
17
17
|
import { bundledLanguagesInfo, bundledThemesInfo } from 'shiki';
|
|
18
|
+
import { INodeHelper } from "../../../editor-kernel/inode/helper";
|
|
18
19
|
|
|
19
20
|
// Color replacements types for Shiki
|
|
20
21
|
|
|
@@ -227,11 +228,14 @@ function getTokenStyleObject(token) {
|
|
|
227
228
|
}
|
|
228
229
|
return style;
|
|
229
230
|
}
|
|
230
|
-
function
|
|
231
|
+
function mapTokensToLexicalSerialized(tokens, diff, colorReplacements) {
|
|
231
232
|
var nodes = [];
|
|
232
233
|
tokens.forEach(function (line, idx) {
|
|
233
234
|
if (idx) {
|
|
234
|
-
nodes.push(
|
|
235
|
+
nodes.push({
|
|
236
|
+
type: 'linebreak',
|
|
237
|
+
version: 1
|
|
238
|
+
});
|
|
235
239
|
}
|
|
236
240
|
line.forEach(function (token, tidx) {
|
|
237
241
|
var text = token.content;
|
|
@@ -242,18 +246,20 @@ function mapTokensToLexicalStructure(tokens, diff, colorReplacements) {
|
|
|
242
246
|
var prefixTypes = ['inserted', 'deleted', 'inserted', 'deleted', 'unchanged'];
|
|
243
247
|
var prefixIndex = prefixes.indexOf(text[0]);
|
|
244
248
|
if (prefixIndex !== -1) {
|
|
245
|
-
nodes.push(
|
|
249
|
+
nodes.push(INodeHelper.createLikeTextNode('code-highlight', prefixes[prefixIndex], {
|
|
250
|
+
highlightType: prefixTypes[prefixIndex]
|
|
251
|
+
}));
|
|
246
252
|
text = text.slice(1);
|
|
247
253
|
}
|
|
248
254
|
}
|
|
249
255
|
var parts = text.split('\t');
|
|
250
256
|
parts.forEach(function (part, pidx) {
|
|
251
257
|
if (pidx) {
|
|
252
|
-
nodes.push(
|
|
258
|
+
nodes.push(INodeHelper.createLikeTextNode('tab', '\t'));
|
|
253
259
|
}
|
|
254
260
|
if (part !== '') {
|
|
255
261
|
var _token$htmlStyle, _token$htmlStyle2;
|
|
256
|
-
var node =
|
|
262
|
+
var node = INodeHelper.createLikeTextNode('code-highlight', part);
|
|
257
263
|
if ((_token$htmlStyle = token.htmlStyle) !== null && _token$htmlStyle !== void 0 && _token$htmlStyle['--shiki-light'] && colorReplacements !== null && colorReplacements !== void 0 && colorReplacements['light']) {
|
|
258
264
|
var newColor = colorReplacements['light'][token.htmlStyle['--shiki-light'].toLowerCase()];
|
|
259
265
|
if (newColor) {
|
|
@@ -267,6 +273,54 @@ function mapTokensToLexicalStructure(tokens, diff, colorReplacements) {
|
|
|
267
273
|
}
|
|
268
274
|
}
|
|
269
275
|
var style = stringifyTokenStyle(token.htmlStyle || getTokenStyleObject(token));
|
|
276
|
+
node.style = style;
|
|
277
|
+
nodes.push(node);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
return nodes;
|
|
283
|
+
}
|
|
284
|
+
function mapTokensToLexicalStructure(tokens, diff, colorReplacements) {
|
|
285
|
+
var nodes = [];
|
|
286
|
+
tokens.forEach(function (line, idx) {
|
|
287
|
+
if (idx) {
|
|
288
|
+
nodes.push($createLineBreakNode());
|
|
289
|
+
}
|
|
290
|
+
line.forEach(function (token, tidx) {
|
|
291
|
+
var text = token.content;
|
|
292
|
+
|
|
293
|
+
// implement diff-xxxx languages
|
|
294
|
+
if (diff && tidx === 0 && text.length > 0) {
|
|
295
|
+
var prefixes = ['+', '-', '>', '<', ' '];
|
|
296
|
+
var prefixTypes = ['inserted', 'deleted', 'inserted', 'deleted', 'unchanged'];
|
|
297
|
+
var prefixIndex = prefixes.indexOf(text[0]);
|
|
298
|
+
if (prefixIndex !== -1) {
|
|
299
|
+
nodes.push($createCodeHighlightNode(prefixes[prefixIndex], prefixTypes[prefixIndex]));
|
|
300
|
+
text = text.slice(1);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
var parts = text.split('\t');
|
|
304
|
+
parts.forEach(function (part, pidx) {
|
|
305
|
+
if (pidx) {
|
|
306
|
+
nodes.push($createTabNode());
|
|
307
|
+
}
|
|
308
|
+
if (part !== '') {
|
|
309
|
+
var _token$htmlStyle3, _token$htmlStyle4;
|
|
310
|
+
var node = $createCodeHighlightNode(part);
|
|
311
|
+
if ((_token$htmlStyle3 = token.htmlStyle) !== null && _token$htmlStyle3 !== void 0 && _token$htmlStyle3['--shiki-light'] && colorReplacements !== null && colorReplacements !== void 0 && colorReplacements['light']) {
|
|
312
|
+
var newColor = colorReplacements['light'][token.htmlStyle['--shiki-light'].toLowerCase()];
|
|
313
|
+
if (newColor) {
|
|
314
|
+
token.htmlStyle['--shiki-light'] = newColor;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if ((_token$htmlStyle4 = token.htmlStyle) !== null && _token$htmlStyle4 !== void 0 && _token$htmlStyle4['--shiki-dark'] && colorReplacements !== null && colorReplacements !== void 0 && colorReplacements['dark']) {
|
|
318
|
+
var _newColor2 = colorReplacements['dark'][token.htmlStyle['--shiki-dark'].toLowerCase()];
|
|
319
|
+
if (_newColor2) {
|
|
320
|
+
token.htmlStyle['--shiki-dark'] = _newColor2;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
var style = stringifyTokenStyle(token.htmlStyle || getTokenStyleObject(token));
|
|
270
324
|
node.setStyle(style);
|
|
271
325
|
nodes.push(node);
|
|
272
326
|
}
|
|
@@ -275,8 +329,43 @@ function mapTokensToLexicalStructure(tokens, diff, colorReplacements) {
|
|
|
275
329
|
});
|
|
276
330
|
return nodes;
|
|
277
331
|
}
|
|
332
|
+
var DIFF_LANGUAGE_REGEX = /^diff-([\w-]+)/i;
|
|
333
|
+
export function getHighlightSerializeNode(code, language) {
|
|
334
|
+
var theme = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'poimandres';
|
|
335
|
+
var colorReplacements = arguments.length > 3 ? arguments[3] : undefined;
|
|
336
|
+
// Implementation goes here
|
|
337
|
+
|
|
338
|
+
var diffLanguageMatch = DIFF_LANGUAGE_REGEX.exec(language);
|
|
339
|
+
var themes = theme.split(' ');
|
|
340
|
+
|
|
341
|
+
// Build the options for codeToTokens
|
|
342
|
+
var options = themes.length > 1 ? {
|
|
343
|
+
defaultColor: false,
|
|
344
|
+
lang: diffLanguageMatch ? diffLanguageMatch[1] : language,
|
|
345
|
+
themes: {
|
|
346
|
+
dark: themes[1],
|
|
347
|
+
light: themes[0]
|
|
348
|
+
}
|
|
349
|
+
} : {
|
|
350
|
+
lang: language,
|
|
351
|
+
theme: themes[0]
|
|
352
|
+
};
|
|
353
|
+
var newColorReplacements = {};
|
|
354
|
+
if (colorReplacements !== null && colorReplacements !== void 0 && colorReplacements.current && themes.length > 1) {
|
|
355
|
+
if (colorReplacements.current[themes[0]]) {
|
|
356
|
+
newColorReplacements['light'] = colorReplacements.current[themes[0]];
|
|
357
|
+
}
|
|
358
|
+
if (colorReplacements.current[themes[1]]) {
|
|
359
|
+
newColorReplacements['dark'] = colorReplacements.current[themes[1]];
|
|
360
|
+
}
|
|
361
|
+
} else if (colorReplacements !== null && colorReplacements !== void 0 && colorReplacements.current) {
|
|
362
|
+
options.colorReplacements = resolveColorReplacements(colorReplacements.current, themes[0]);
|
|
363
|
+
}
|
|
364
|
+
var tokensResult = shiki.codeToTokens(code, options);
|
|
365
|
+
var tokens = tokensResult.tokens;
|
|
366
|
+
return mapTokensToLexicalSerialized(tokens, !!diffLanguageMatch, newColorReplacements);
|
|
367
|
+
}
|
|
278
368
|
export function $getHighlightNodes(codeNode, language, colorReplacements) {
|
|
279
|
-
var DIFF_LANGUAGE_REGEX = /^diff-([\w-]+)/i;
|
|
280
369
|
var diffLanguageMatch = DIFF_LANGUAGE_REGEX.exec(language);
|
|
281
370
|
var code = codeNode.getTextContent();
|
|
282
371
|
var theme = codeNode.getTheme() || 'poimandres';
|
|
@@ -15,6 +15,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
|
15
15
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
16
16
|
import { $createCodeNode, $isCodeHighlightNode, $isCodeNode, CodeHighlightNode, CodeNode } from '@lexical/code';
|
|
17
17
|
import { TabNode } from 'lexical';
|
|
18
|
+
import { INodeHelper } from "../../../editor-kernel/inode/helper";
|
|
18
19
|
import { KernelPlugin } from "../../../editor-kernel/plugin";
|
|
19
20
|
import { IMarkdownShortCutService } from "../../markdown";
|
|
20
21
|
import { CustomShikiTokenizer, registerCodeCommand } from "../command";
|
|
@@ -47,11 +48,20 @@ CodeNode.importDOM = function () {
|
|
|
47
48
|
// Custom logic for handling imported DOM
|
|
48
49
|
return node;
|
|
49
50
|
};
|
|
51
|
+
function toMarkdownTheme(theme) {
|
|
52
|
+
if (!theme) {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
if (typeof theme === 'string') {
|
|
56
|
+
return theme;
|
|
57
|
+
}
|
|
58
|
+
return "".concat(theme.light, " ").concat(theme.dark);
|
|
59
|
+
}
|
|
50
60
|
export var CodeblockPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
51
61
|
_inherits(CodeblockPlugin, _KernelPlugin);
|
|
52
62
|
var _super = _createSuper(CodeblockPlugin);
|
|
53
63
|
function CodeblockPlugin(kernel) {
|
|
54
|
-
var _config$theme, _this$config, _this$config3
|
|
64
|
+
var _config$theme, _this$config, _this$config3;
|
|
55
65
|
var _this;
|
|
56
66
|
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
57
67
|
_classCallCheck(this, CodeblockPlugin);
|
|
@@ -71,34 +81,6 @@ export var CodeblockPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
71
81
|
var _this$config4;
|
|
72
82
|
CustomShikiTokenizer.defaultColorReplacements = (_this$config4 = _this.config) === null || _this$config4 === void 0 ? void 0 : _this$config4.colorReplacements;
|
|
73
83
|
}
|
|
74
|
-
(_kernel$requireServic = kernel.requireService(IMarkdownShortCutService)) === null || _kernel$requireServic === void 0 || _kernel$requireServic.registerMarkdownShortCut({
|
|
75
|
-
regExp: /^(```|···)(.+)?$/,
|
|
76
|
-
replace: function replace(parentNode, _, match) {
|
|
77
|
-
var code = $createCodeNode(getCodeLanguageByInput(match[2]), toCodeTheme(CustomShikiTokenizer));
|
|
78
|
-
parentNode.replace(code);
|
|
79
|
-
code.selectStart();
|
|
80
|
-
},
|
|
81
|
-
trigger: 'enter',
|
|
82
|
-
type: 'element'
|
|
83
|
-
});
|
|
84
|
-
(_kernel$requireServic2 = kernel.requireService(IMarkdownShortCutService)) === null || _kernel$requireServic2 === void 0 || _kernel$requireServic2.registerMarkdownWriter(CodeNode.getType(), function (ctx, node) {
|
|
85
|
-
if ($isCodeNode(node)) {
|
|
86
|
-
ctx.wrap('```' + (node.getLanguage() || '') + '\n', '\n```\n');
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
(_kernel$requireServic3 = kernel.requireService(IMarkdownShortCutService)) === null || _kernel$requireServic3 === void 0 || _kernel$requireServic3.registerMarkdownWriter(TabNode.getType(), function (ctx) {
|
|
90
|
-
ctx.appendLine(' ');
|
|
91
|
-
});
|
|
92
|
-
(_kernel$requireServic4 = kernel.requireService(IMarkdownShortCutService)) === null || _kernel$requireServic4 === void 0 || _kernel$requireServic4.registerMarkdownWriter(CodeHighlightNode.getType(), function (ctx, node) {
|
|
93
|
-
if ($isCodeHighlightNode(node)) {
|
|
94
|
-
ctx.appendLine(node.getTextContent());
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
(_kernel$requireServic5 = kernel.requireService(IMarkdownShortCutService)) === null || _kernel$requireServic5 === void 0 || _kernel$requireServic5.registerMarkdownWriter('linebreak', function (ctx, node) {
|
|
98
|
-
if ($isCodeNode(node.getParent())) {
|
|
99
|
-
ctx.appendLine('\n');
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
84
|
return _this;
|
|
103
85
|
}
|
|
104
86
|
_createClass(CodeblockPlugin, [{
|
|
@@ -111,6 +93,69 @@ export var CodeblockPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
111
93
|
this.register(registerCodeHighlighting(editor));
|
|
112
94
|
}
|
|
113
95
|
this.register(registerCodeCommand(editor));
|
|
96
|
+
this.registerMarkdown();
|
|
97
|
+
}
|
|
98
|
+
}, {
|
|
99
|
+
key: "registerMarkdown",
|
|
100
|
+
value: function registerMarkdown() {
|
|
101
|
+
var _this2 = this;
|
|
102
|
+
var kernel = this.kernel;
|
|
103
|
+
var markdownService = kernel.requireService(IMarkdownShortCutService);
|
|
104
|
+
if (!markdownService) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
markdownService.registerMarkdownShortCut({
|
|
108
|
+
regExp: /^(```|···)(.+)?$/,
|
|
109
|
+
replace: function replace(parentNode, _, match) {
|
|
110
|
+
var code = $createCodeNode(getCodeLanguageByInput(match[2]), toCodeTheme(CustomShikiTokenizer));
|
|
111
|
+
parentNode.replace(code);
|
|
112
|
+
code.selectStart();
|
|
113
|
+
},
|
|
114
|
+
trigger: 'enter',
|
|
115
|
+
type: 'element'
|
|
116
|
+
});
|
|
117
|
+
markdownService.registerMarkdownWriter(CodeNode.getType(), function (ctx, node) {
|
|
118
|
+
if ($isCodeNode(node)) {
|
|
119
|
+
ctx.wrap('```' + (node.getLanguage() || '') + '\n', '\n```\n');
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
markdownService.registerMarkdownWriter(TabNode.getType(), function (ctx) {
|
|
123
|
+
ctx.appendLine(' ');
|
|
124
|
+
});
|
|
125
|
+
markdownService.registerMarkdownWriter(CodeHighlightNode.getType(), function (ctx, node) {
|
|
126
|
+
if ($isCodeHighlightNode(node)) {
|
|
127
|
+
ctx.appendLine(node.getTextContent());
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
markdownService.registerMarkdownWriter('linebreak', function (ctx, node) {
|
|
131
|
+
if ($isCodeNode(node.getParent())) {
|
|
132
|
+
ctx.appendLine('\n');
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
markdownService.registerMarkdownReader('code', function (node) {
|
|
136
|
+
var _this2$config;
|
|
137
|
+
var language = node.lang ? getCodeLanguageByInput(node.lang) : 'plaintext';
|
|
138
|
+
return INodeHelper.createElementNode('code', {
|
|
139
|
+
children: node.value.split('\n').flatMap(function (text, index, arr) {
|
|
140
|
+
var textNode = INodeHelper.createTextNode(text);
|
|
141
|
+
textNode.type = 'code-highlight';
|
|
142
|
+
if (index === arr.length - 1) {
|
|
143
|
+
return textNode;
|
|
144
|
+
}
|
|
145
|
+
return [textNode, {
|
|
146
|
+
type: 'linebreak',
|
|
147
|
+
version: 1
|
|
148
|
+
}];
|
|
149
|
+
}).flat(),
|
|
150
|
+
direction: 'ltr',
|
|
151
|
+
format: '',
|
|
152
|
+
indent: 0,
|
|
153
|
+
language: language,
|
|
154
|
+
textStyle: '--shiki-dark:var(--color-info);--shiki-light:var(--color-info)',
|
|
155
|
+
theme: "".concat(toMarkdownTheme((_this2$config = _this2.config) === null || _this2$config === void 0 ? void 0 : _this2$config.shikiTheme), " needUpdate"),
|
|
156
|
+
version: 1
|
|
157
|
+
});
|
|
158
|
+
});
|
|
114
159
|
}
|
|
115
160
|
}]);
|
|
116
161
|
return CodeblockPlugin;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LexicalEditor } from 'lexical';
|
|
1
|
+
import type { LexicalEditor } from 'lexical';
|
|
2
2
|
import { DataSource } from "../../../editor-kernel";
|
|
3
|
-
import { IWriteOptions } from "../../../editor-kernel/data-source";
|
|
3
|
+
import type { IWriteOptions } from "../../../editor-kernel/data-source";
|
|
4
4
|
export default class JSONDataSource extends DataSource {
|
|
5
5
|
read(editor: LexicalEditor, data: any): void;
|
|
6
6
|
write(editor: LexicalEditor, options?: IWriteOptions): any;
|
|
@@ -24,15 +24,7 @@ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.g
|
|
|
24
24
|
import { $isTableSelection } from '@lexical/table';
|
|
25
25
|
import { $getCharacterOffsets, $getNodeByKey, $getSelection, $isElementNode, $isRangeSelection, $isTextNode, IS_CODE } from 'lexical';
|
|
26
26
|
import { DataSource } from "../../../editor-kernel";
|
|
27
|
-
|
|
28
|
-
detail: 0,
|
|
29
|
-
format: 0,
|
|
30
|
-
mode: 'normal',
|
|
31
|
-
style: '',
|
|
32
|
-
text: "\uFEFF",
|
|
33
|
-
type: 'cursor',
|
|
34
|
-
version: 1
|
|
35
|
-
};
|
|
27
|
+
import { cursorNodeSerialized } from "../node/cursor";
|
|
36
28
|
var JSONDataSource = /*#__PURE__*/function (_DataSource) {
|
|
37
29
|
_inherits(JSONDataSource, _DataSource);
|
|
38
30
|
var _super = _createSuper(JSONDataSource);
|
|
@@ -66,7 +58,7 @@ var JSONDataSource = /*#__PURE__*/function (_DataSource) {
|
|
|
66
58
|
type: 'codeInline',
|
|
67
59
|
version: 1
|
|
68
60
|
};
|
|
69
|
-
node.children.splice(i + 1, 0,
|
|
61
|
+
node.children.splice(i + 1, 0, cursorNodeSerialized);
|
|
70
62
|
}
|
|
71
63
|
}
|
|
72
64
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { INSERT_HEADING_COMMAND, INSERT_QUOTE_COMMAND } from './command';
|
|
2
|
-
export { $createCursorNode, $isCardLikeElementNode, $isCursorNode, CardLikeElementNode, } from './node/cursor';
|
|
2
|
+
export { $createCursorNode, $isCardLikeElementNode, $isCursorNode, CardLikeElementNode, cursorNodeSerialized, } from './node/cursor';
|
|
3
3
|
export * from './plugin';
|
|
4
4
|
export * from './react';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { INSERT_HEADING_COMMAND, INSERT_QUOTE_COMMAND } from "./command";
|
|
2
|
-
export { $createCursorNode, $isCardLikeElementNode, $isCursorNode, CardLikeElementNode } from "./node/cursor";
|
|
2
|
+
export { $createCursorNode, $isCardLikeElementNode, $isCursorNode, CardLikeElementNode, cursorNodeSerialized } from "./node/cursor";
|
|
3
3
|
export * from "./plugin";
|
|
4
4
|
export * from "./react";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LexicalEditor, LexicalNode, SerializedLexicalNode } from 'lexical';
|
|
2
|
+
import { ElementNode, TextNode } from 'lexical';
|
|
2
3
|
export declare class CardLikeElementNode extends ElementNode {
|
|
3
4
|
isCardLike(): boolean;
|
|
4
5
|
}
|
|
6
|
+
export declare const cursorNodeSerialized: SerializedLexicalNode;
|
|
5
7
|
export declare class CursorNode extends TextNode {
|
|
6
8
|
static getType(): string;
|
|
7
9
|
isUnmergeable(): boolean;
|
|
@@ -37,6 +37,15 @@ export var CardLikeElementNode = /*#__PURE__*/function (_ElementNode) {
|
|
|
37
37
|
}]);
|
|
38
38
|
return CardLikeElementNode;
|
|
39
39
|
}(ElementNode);
|
|
40
|
+
export var cursorNodeSerialized = {
|
|
41
|
+
detail: 0,
|
|
42
|
+
format: 0,
|
|
43
|
+
mode: 'normal',
|
|
44
|
+
style: '',
|
|
45
|
+
text: "\uFEFF",
|
|
46
|
+
type: 'cursor',
|
|
47
|
+
version: 1
|
|
48
|
+
};
|
|
40
49
|
export var CursorNode = /*#__PURE__*/function (_TextNode) {
|
|
41
50
|
_inherits(CursorNode, _TextNode);
|
|
42
51
|
var _super2 = _createSuper(CursorNode);
|