@lobehub/editor 1.11.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.
Files changed (48) hide show
  1. package/es/editor-kernel/inode/helper.d.ts +9 -6
  2. package/es/editor-kernel/inode/helper.js +27 -0
  3. package/es/editor-kernel/inode/text-node.d.ts +2 -9
  4. package/es/plugins/code/plugin/index.d.ts +1 -1
  5. package/es/plugins/code/plugin/index.js +12 -1
  6. package/es/plugins/codeblock/command/index.d.ts +6 -0
  7. package/es/plugins/codeblock/command/index.js +1 -0
  8. package/es/plugins/codeblock/plugin/CodeHighlighterShiki.d.ts +7 -0
  9. package/es/plugins/codeblock/plugin/CodeHighlighterShiki.js +43 -2
  10. package/es/plugins/codeblock/plugin/FacadeShiki.d.ts +8 -1
  11. package/es/plugins/codeblock/plugin/FacadeShiki.js +95 -6
  12. package/es/plugins/codeblock/plugin/index.js +74 -29
  13. package/es/plugins/common/data-source/json-data-source.d.ts +2 -2
  14. package/es/plugins/common/data-source/json-data-source.js +2 -10
  15. package/es/plugins/common/index.d.ts +1 -1
  16. package/es/plugins/common/index.js +1 -1
  17. package/es/plugins/common/node/cursor.d.ts +3 -1
  18. package/es/plugins/common/node/cursor.js +9 -0
  19. package/es/plugins/common/plugin/index.d.ts +1 -1
  20. package/es/plugins/common/plugin/index.js +28 -1
  21. package/es/plugins/common/plugin/mdReader.d.ts +2 -0
  22. package/es/plugins/common/plugin/mdReader.js +59 -0
  23. package/es/plugins/common/react/ReactPlainText.d.ts +1 -1
  24. package/es/plugins/common/utils/index.d.ts +2 -2
  25. package/es/plugins/hr/plugin/index.js +26 -22
  26. package/es/plugins/link/plugin/index.js +42 -26
  27. package/es/plugins/list/plugin/index.js +121 -63
  28. package/es/plugins/list/utils/index.d.ts +3 -3
  29. package/es/plugins/markdown/data-source/markdown/parse.d.ts +10 -0
  30. package/es/plugins/markdown/data-source/markdown/parse.js +82 -0
  31. package/es/plugins/markdown/data-source/markdown/supersub.d.ts +1 -0
  32. package/es/plugins/markdown/data-source/markdown/supersub.js +14 -0
  33. package/es/plugins/markdown/data-source/markdown-data-source.d.ts +4 -4
  34. package/es/plugins/markdown/data-source/markdown-data-source.js +8 -2
  35. package/es/plugins/markdown/plugin/index.js +135 -2
  36. package/es/plugins/markdown/service/shortcut.d.ts +15 -85
  37. package/es/plugins/markdown/service/shortcut.js +34 -293
  38. package/es/plugins/markdown/service/transformers.d.ts +60 -0
  39. package/es/plugins/markdown/service/transformers.js +286 -0
  40. package/es/plugins/markdown/utils/index.d.ts +45 -1
  41. package/es/plugins/markdown/utils/index.js +147 -1
  42. package/es/plugins/markdown/utils/logger.d.ts +7 -0
  43. package/es/plugins/markdown/utils/logger.js +2 -0
  44. package/es/plugins/math/plugin/index.js +64 -45
  45. package/es/plugins/table/plugin/index.js +71 -26
  46. package/es/react/hooks/useEditorState/index.js +43 -21
  47. package/es/types/global.d.ts +64 -0
  48. 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 ITextNode;
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 { TextModeType } from 'lexical';
2
- import { INode } from './i-node';
1
+ import type { SerializedTextNode } from 'lexical';
3
2
  /**
4
3
  * Text node
5
4
  */
6
- export interface ITextNode extends INode {
7
- detail: number;
8
- mode: TextModeType;
9
- style: string;
10
- text: string;
11
- type: 'text';
12
- }
5
+ export type ITextNode = SerializedTextNode;
@@ -1,4 +1,4 @@
1
- import { IEditorPluginConstructor } from "../../../types";
1
+ import type { IEditorPluginConstructor } from "../../../types";
2
2
  export interface CodePluginOptions {
3
3
  enableHotkey?: boolean;
4
4
  theme?: string;
@@ -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
@@ -630,7 +637,41 @@ export function registerCodeHighlighting(editor, tokenizer) {
630
637
  }
631
638
 
632
639
  // Add the rest of the registrations
633
- registrations.push(editor.registerNodeTransform(CodeNode, function (node) {
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) {
634
675
  return codeNodeTransform(node, editor, tokenizer);
635
676
  }), editor.registerNodeTransform(TextNode, function (node) {
636
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 mapTokensToLexicalStructure(tokens, diff, colorReplacements) {
231
+ function mapTokensToLexicalSerialized(tokens, diff, colorReplacements) {
231
232
  var nodes = [];
232
233
  tokens.forEach(function (line, idx) {
233
234
  if (idx) {
234
- nodes.push($createLineBreakNode());
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($createCodeHighlightNode(prefixes[prefixIndex], prefixTypes[prefixIndex]));
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($createTabNode());
258
+ nodes.push(INodeHelper.createLikeTextNode('tab', '\t'));
253
259
  }
254
260
  if (part !== '') {
255
261
  var _token$htmlStyle, _token$htmlStyle2;
256
- var node = $createCodeHighlightNode(part);
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, _kernel$requireServic, _kernel$requireServic2, _kernel$requireServic3, _kernel$requireServic4, _kernel$requireServic5;
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
- var cursorNode = {
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, cursorNode);
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 { ElementNode, LexicalEditor, LexicalNode, TextNode } from 'lexical';
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);
@@ -1,4 +1,4 @@
1
- import { IEditorPluginConstructor } from "../../../types";
1
+ import type { IEditorPluginConstructor } from "../../../types";
2
2
  export interface CommonPluginOptions {
3
3
  enableHotkey?: boolean;
4
4
  theme?: {