@mdxeditor/editor 0.14.2 → 0.15.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/dist/directive-editors/AdmonitionDirectiveDescriptor.js +1 -0
- package/dist/importMarkdownToLexical.d.ts +3 -3
- package/dist/plugins/core/MdastInlineCodeVisitor.js +18 -2
- package/dist/plugins/core/index.js +26 -1
- package/dist/plugins/headings/index.d.ts +102 -2
- package/dist/plugins/headings/index.js +39 -2
- package/dist/plugins/link-dialog/index.js +9 -4
- package/dist/utils/detectMac.d.ts +1 -0
- package/dist/utils/detectMac.js +8 -1
- package/package.json +1 -1
|
@@ -16,6 +16,7 @@ const AdmonitionDirectiveDescriptor = {
|
|
|
16
16
|
return /* @__PURE__ */ React__default.createElement("div", { className: theme.admonition[mdastNode.name] }, /* @__PURE__ */ React__default.createElement(
|
|
17
17
|
NestedLexicalEditor,
|
|
18
18
|
{
|
|
19
|
+
block: true,
|
|
19
20
|
focusEmitter,
|
|
20
21
|
getContent: (node) => node.children,
|
|
21
22
|
getUpdatedMdastNode: (mdastNode2, children) => ({ ...mdastNode2, children })
|
|
@@ -2,7 +2,7 @@ import { LexicalNode, RootNode as LexicalRootNode } from 'lexical';
|
|
|
2
2
|
import * as Mdast from 'mdast';
|
|
3
3
|
import { fromMarkdown } from 'mdast-util-from-markdown';
|
|
4
4
|
import { ParseOptions } from 'micromark-util-types';
|
|
5
|
-
import { IS_BOLD, IS_ITALIC, IS_UNDERLINE } from './FormatConstants';
|
|
5
|
+
import { IS_BOLD, IS_CODE, IS_ITALIC, IS_UNDERLINE } from './FormatConstants';
|
|
6
6
|
/** @internal */
|
|
7
7
|
export type MdastExtensions = NonNullable<Parameters<typeof fromMarkdown>[1]>['mdastExtensions'];
|
|
8
8
|
/**
|
|
@@ -21,12 +21,12 @@ export interface MdastVisitActions {
|
|
|
21
21
|
* Adds formatting as a context for the current node and its children.
|
|
22
22
|
* This is necessary due to mdast treating formatting as a node, while lexical considering it an attribute of a node.
|
|
23
23
|
*/
|
|
24
|
-
addFormatting(format: typeof IS_BOLD | typeof IS_ITALIC | typeof IS_UNDERLINE, node?: Mdast.Content): void;
|
|
24
|
+
addFormatting(format: typeof IS_BOLD | typeof IS_ITALIC | typeof IS_UNDERLINE | typeof IS_CODE, node?: Mdast.Content): void;
|
|
25
25
|
/**
|
|
26
26
|
* Adds formatting as a context for the current node and its children.
|
|
27
27
|
* This is necessary due to mdast treating formatting as a node, while lexical considering it an attribute of a node.
|
|
28
28
|
*/
|
|
29
|
-
removeFormatting(format: typeof IS_BOLD | typeof IS_ITALIC | typeof IS_UNDERLINE, node?: Mdast.Content): void;
|
|
29
|
+
removeFormatting(format: typeof IS_BOLD | typeof IS_ITALIC | typeof IS_UNDERLINE | typeof IS_CODE, node?: Mdast.Content): void;
|
|
30
30
|
/**
|
|
31
31
|
* Access the current formatting context.
|
|
32
32
|
*/
|
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import { $createTextNode } from "lexical";
|
|
2
2
|
import { IS_CODE } from "../../FormatConstants.js";
|
|
3
|
+
function isOpeningCodeNode(node) {
|
|
4
|
+
return node.type === "html" && node.value === "<code>";
|
|
5
|
+
}
|
|
6
|
+
function isClosingCodeNode(node) {
|
|
7
|
+
return node.type === "html" && node.value === "</code>";
|
|
8
|
+
}
|
|
3
9
|
const MdastInlineCodeVisitor = {
|
|
4
|
-
testNode:
|
|
5
|
-
|
|
10
|
+
testNode: (node) => {
|
|
11
|
+
return node.type === "inlineCode" || isOpeningCodeNode(node) || isClosingCodeNode(node);
|
|
12
|
+
},
|
|
13
|
+
visitNode({ mdastNode, actions, mdastParent }) {
|
|
14
|
+
if (isOpeningCodeNode(mdastNode)) {
|
|
15
|
+
actions.addFormatting(IS_CODE, mdastParent);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (isClosingCodeNode(mdastNode)) {
|
|
19
|
+
actions.removeFormatting(IS_CODE, mdastParent);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
6
22
|
actions.addAndStepInto($createTextNode(mdastNode.value).setFormat(IS_CODE));
|
|
7
23
|
}
|
|
8
24
|
};
|
|
@@ -2,7 +2,7 @@ import { createEmptyHistoryState } from "@lexical/react/LexicalHistoryPlugin.js"
|
|
|
2
2
|
import { $isHeadingNode } from "@lexical/rich-text";
|
|
3
3
|
import { $setBlocksType } from "@lexical/selection";
|
|
4
4
|
import { $findMatchingParent, $wrapNodeInElement, $insertNodeToNearestRoot } from "@lexical/utils";
|
|
5
|
-
import { createCommand, SELECTION_CHANGE_COMMAND, $getRoot, COMMAND_PRIORITY_CRITICAL, BLUR_COMMAND, FORMAT_TEXT_COMMAND, $isRootOrShadowRoot, $getSelection, $isRangeSelection, $insertNodes, $createParagraphNode, ParagraphNode, TextNode } from "lexical";
|
|
5
|
+
import { createCommand, SELECTION_CHANGE_COMMAND, $getRoot, COMMAND_PRIORITY_CRITICAL, BLUR_COMMAND, KEY_DOWN_COMMAND, COMMAND_PRIORITY_LOW, FORMAT_TEXT_COMMAND, $isRootOrShadowRoot, $getSelection, $isRangeSelection, $insertNodes, $createParagraphNode, ParagraphNode, TextNode } from "lexical";
|
|
6
6
|
import { exportMarkdownFromLexical } from "../../exportMarkdownFromLexical.js";
|
|
7
7
|
import { importMarkdownToLexical } from "../../importMarkdownToLexical.js";
|
|
8
8
|
import { LexicalLinebreakVisitor } from "./LexicalLinebreakVisitor.js";
|
|
@@ -16,6 +16,7 @@ import { MdastRootVisitor } from "./MdastRootVisitor.js";
|
|
|
16
16
|
import { MdastTextVisitor } from "./MdastTextVisitor.js";
|
|
17
17
|
import { SharedHistoryPlugin } from "./SharedHistoryPlugin.js";
|
|
18
18
|
import { noop } from "../../utils/fp.js";
|
|
19
|
+
import { controlOrMeta } from "../../utils/detectMac.js";
|
|
19
20
|
import { system } from "../../gurx/realmFactory.js";
|
|
20
21
|
import { realmPlugin } from "../../gurx/react.js";
|
|
21
22
|
const NESTED_EDITOR_UPDATED_COMMAND = createCommand("NESTED_EDITOR_UPDATED_COMMAND");
|
|
@@ -185,6 +186,30 @@ const coreSystem = system((r) => {
|
|
|
185
186
|
COMMAND_PRIORITY_CRITICAL
|
|
186
187
|
);
|
|
187
188
|
});
|
|
189
|
+
r.pub(createRootEditorSubscription, (theRootEditor) => {
|
|
190
|
+
return theRootEditor.registerCommand(
|
|
191
|
+
KEY_DOWN_COMMAND,
|
|
192
|
+
(event) => {
|
|
193
|
+
const { keyCode, ctrlKey, metaKey } = event;
|
|
194
|
+
if (keyCode === 65 && controlOrMeta(metaKey, ctrlKey)) {
|
|
195
|
+
event.preventDefault();
|
|
196
|
+
theRootEditor.update(() => {
|
|
197
|
+
var _a;
|
|
198
|
+
const root = $getRoot();
|
|
199
|
+
const skipFirstChild = ((_a = root.getFirstChild()) == null ? void 0 : _a.getType()) === "frontmatter";
|
|
200
|
+
root.select(skipFirstChild ? 1 : 0, root.getChildrenSize());
|
|
201
|
+
const rootElement = theRootEditor.getRootElement();
|
|
202
|
+
rootElement.focus({
|
|
203
|
+
preventScroll: true
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
return false;
|
|
209
|
+
},
|
|
210
|
+
COMMAND_PRIORITY_LOW
|
|
211
|
+
);
|
|
212
|
+
});
|
|
188
213
|
const composerChildren = r.node([]);
|
|
189
214
|
const addComposerChild = createAppendNodeFor(composerChildren);
|
|
190
215
|
const topAreaChildren = r.node([]);
|
|
@@ -64,7 +64,57 @@ export declare const headingsSystem: SystemSpec<[SystemSpec<[], (r: Realm) => {
|
|
|
64
64
|
applyBlockType: RealmNode<BlockType>;
|
|
65
65
|
convertSelectionToNode: RealmNode<() => ElementNode>;
|
|
66
66
|
insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
|
|
67
|
-
}>], (
|
|
67
|
+
}>], (r: Realm, [{ createRootEditorSubscription, convertSelectionToNode }]: [{
|
|
68
|
+
activeEditor: RealmNode<LexicalEditor | null>;
|
|
69
|
+
inFocus: RealmNode<boolean>;
|
|
70
|
+
historyState: RealmNode<HistoryState>;
|
|
71
|
+
currentSelection: RealmNode<RangeSelection | null>;
|
|
72
|
+
jsxIsAvailable: RealmNode<boolean>;
|
|
73
|
+
jsxComponentDescriptors: RealmNode<JsxComponentDescriptor[]>;
|
|
74
|
+
initialRootEditorState: RealmNode<InitialEditorStateType>;
|
|
75
|
+
rootEditor: RealmNode<LexicalEditor | null>;
|
|
76
|
+
createRootEditorSubscription: RealmNode<EditorSubscription>;
|
|
77
|
+
createActiveEditorSubscription: RealmNode<EditorSubscription>;
|
|
78
|
+
importVisitors: RealmNode<MdastImportVisitor<Content>[]>;
|
|
79
|
+
syntaxExtensions: RealmNode<Extension[]>;
|
|
80
|
+
mdastExtensions: RealmNode<(Partial<Config> | Partial<Config>[])[] | null | undefined>;
|
|
81
|
+
usedLexicalNodes: RealmNode<Klass<LexicalNode>[]>;
|
|
82
|
+
addImportVisitor: RealmNode<MdastImportVisitor<Content>>;
|
|
83
|
+
addLexicalNode: RealmNode<Klass<LexicalNode>>;
|
|
84
|
+
addSyntaxExtension: RealmNode<Extension>;
|
|
85
|
+
addMdastExtension: RealmNode<Partial<Config> | Partial<Config>[]>;
|
|
86
|
+
toMarkdownExtensions: RealmNode<Options[]>;
|
|
87
|
+
toMarkdownOptions: RealmNode<Options>;
|
|
88
|
+
addToMarkdownExtension: RealmNode<Options>;
|
|
89
|
+
addExportVisitor: RealmNode<LexicalVisitor>;
|
|
90
|
+
exportVisitors: RealmNode<LexicalVisitor[]>;
|
|
91
|
+
initialMarkdown: RealmNode<string>;
|
|
92
|
+
setMarkdown: RealmNode<string>;
|
|
93
|
+
markdown: RealmNode<string>;
|
|
94
|
+
editorRootElementRef: RealmNode<RefObject<HTMLDivElement> | null>;
|
|
95
|
+
contentEditableClassName: RealmNode<string>;
|
|
96
|
+
placeholder: RealmNode<ReactNode>;
|
|
97
|
+
autoFocus: RealmNode<boolean>;
|
|
98
|
+
composerChildren: RealmNode<ComponentType<{}>[]>;
|
|
99
|
+
addComposerChild: RealmNode<ComponentType<{}>>;
|
|
100
|
+
topAreaChildren: RealmNode<ComponentType<{}>[]>;
|
|
101
|
+
addTopAreaChild: RealmNode<ComponentType<{}>>;
|
|
102
|
+
nestedEditorChildren: RealmNode<ComponentType<{}>[]>;
|
|
103
|
+
addNestedEditorChild: RealmNode<ComponentType<{}>>;
|
|
104
|
+
editorWrappers: RealmNode<ComponentType<{
|
|
105
|
+
children: ReactNode;
|
|
106
|
+
}>[]>;
|
|
107
|
+
addEditorWrapper: RealmNode<ComponentType<{
|
|
108
|
+
children: ReactNode;
|
|
109
|
+
}>>;
|
|
110
|
+
currentFormat: RealmNode<number>;
|
|
111
|
+
editorInFocus: RealmNode<EditorInFocus | null>;
|
|
112
|
+
applyFormat: RealmNode<TextFormatType>;
|
|
113
|
+
currentBlockType: RealmNode<BlockType>;
|
|
114
|
+
applyBlockType: RealmNode<BlockType>;
|
|
115
|
+
convertSelectionToNode: RealmNode<() => ElementNode>;
|
|
116
|
+
insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
|
|
117
|
+
}]) => {}>;
|
|
68
118
|
/**
|
|
69
119
|
* @internal
|
|
70
120
|
*/
|
|
@@ -118,4 +168,54 @@ export declare const headingsPlugin: PluginConstructor<SystemSpec<[SystemSpec<[]
|
|
|
118
168
|
applyBlockType: RealmNode<BlockType>;
|
|
119
169
|
convertSelectionToNode: RealmNode<() => ElementNode>;
|
|
120
170
|
insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
|
|
121
|
-
}>], (
|
|
171
|
+
}>], (r: Realm, [{ createRootEditorSubscription, convertSelectionToNode }]: [{
|
|
172
|
+
activeEditor: RealmNode<LexicalEditor | null>;
|
|
173
|
+
inFocus: RealmNode<boolean>;
|
|
174
|
+
historyState: RealmNode<HistoryState>;
|
|
175
|
+
currentSelection: RealmNode<RangeSelection | null>;
|
|
176
|
+
jsxIsAvailable: RealmNode<boolean>;
|
|
177
|
+
jsxComponentDescriptors: RealmNode<JsxComponentDescriptor[]>;
|
|
178
|
+
initialRootEditorState: RealmNode<InitialEditorStateType>;
|
|
179
|
+
rootEditor: RealmNode<LexicalEditor | null>;
|
|
180
|
+
createRootEditorSubscription: RealmNode<EditorSubscription>;
|
|
181
|
+
createActiveEditorSubscription: RealmNode<EditorSubscription>;
|
|
182
|
+
importVisitors: RealmNode<MdastImportVisitor<Content>[]>;
|
|
183
|
+
syntaxExtensions: RealmNode<Extension[]>;
|
|
184
|
+
mdastExtensions: RealmNode<(Partial<Config> | Partial<Config>[])[] | null | undefined>;
|
|
185
|
+
usedLexicalNodes: RealmNode<Klass<LexicalNode>[]>;
|
|
186
|
+
addImportVisitor: RealmNode<MdastImportVisitor<Content>>;
|
|
187
|
+
addLexicalNode: RealmNode<Klass<LexicalNode>>;
|
|
188
|
+
addSyntaxExtension: RealmNode<Extension>;
|
|
189
|
+
addMdastExtension: RealmNode<Partial<Config> | Partial<Config>[]>;
|
|
190
|
+
toMarkdownExtensions: RealmNode<Options[]>;
|
|
191
|
+
toMarkdownOptions: RealmNode<Options>;
|
|
192
|
+
addToMarkdownExtension: RealmNode<Options>;
|
|
193
|
+
addExportVisitor: RealmNode<LexicalVisitor>;
|
|
194
|
+
exportVisitors: RealmNode<LexicalVisitor[]>;
|
|
195
|
+
initialMarkdown: RealmNode<string>;
|
|
196
|
+
setMarkdown: RealmNode<string>;
|
|
197
|
+
markdown: RealmNode<string>;
|
|
198
|
+
editorRootElementRef: RealmNode<RefObject<HTMLDivElement> | null>;
|
|
199
|
+
contentEditableClassName: RealmNode<string>;
|
|
200
|
+
placeholder: RealmNode<ReactNode>;
|
|
201
|
+
autoFocus: RealmNode<boolean>;
|
|
202
|
+
composerChildren: RealmNode<ComponentType<{}>[]>;
|
|
203
|
+
addComposerChild: RealmNode<ComponentType<{}>>;
|
|
204
|
+
topAreaChildren: RealmNode<ComponentType<{}>[]>;
|
|
205
|
+
addTopAreaChild: RealmNode<ComponentType<{}>>;
|
|
206
|
+
nestedEditorChildren: RealmNode<ComponentType<{}>[]>;
|
|
207
|
+
addNestedEditorChild: RealmNode<ComponentType<{}>>;
|
|
208
|
+
editorWrappers: RealmNode<ComponentType<{
|
|
209
|
+
children: ReactNode;
|
|
210
|
+
}>[]>;
|
|
211
|
+
addEditorWrapper: RealmNode<ComponentType<{
|
|
212
|
+
children: ReactNode;
|
|
213
|
+
}>>;
|
|
214
|
+
currentFormat: RealmNode<number>;
|
|
215
|
+
editorInFocus: RealmNode<EditorInFocus | null>;
|
|
216
|
+
applyFormat: RealmNode<TextFormatType>;
|
|
217
|
+
currentBlockType: RealmNode<BlockType>;
|
|
218
|
+
applyBlockType: RealmNode<BlockType>;
|
|
219
|
+
convertSelectionToNode: RealmNode<() => ElementNode>;
|
|
220
|
+
insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
|
|
221
|
+
}]) => {}>, object>;
|
|
@@ -1,10 +1,47 @@
|
|
|
1
1
|
import { coreSystem } from "../core/index.js";
|
|
2
2
|
import { MdastHeadingVisitor } from "./MdastHeadingVisitor.js";
|
|
3
|
-
import { HeadingNode } from "@lexical/rich-text";
|
|
3
|
+
import { $createHeadingNode, HeadingNode } from "@lexical/rich-text";
|
|
4
4
|
import { LexicalHeadingVisitor } from "./LexicalHeadingVisitor.js";
|
|
5
|
+
import { KEY_DOWN_COMMAND, $createParagraphNode, COMMAND_PRIORITY_LOW } from "lexical";
|
|
6
|
+
import { controlOrMeta } from "../../utils/detectMac.js";
|
|
5
7
|
import { system } from "../../gurx/realmFactory.js";
|
|
6
8
|
import { realmPlugin } from "../../gurx/react.js";
|
|
7
|
-
const
|
|
9
|
+
const FORMATTING_KEYS = [48, 49, 50, 51, 52, 53, 54];
|
|
10
|
+
const CODE_TO_HEADING_MAP = {
|
|
11
|
+
49: "h1",
|
|
12
|
+
50: "h2",
|
|
13
|
+
51: "h3",
|
|
14
|
+
52: "h4",
|
|
15
|
+
53: "h5",
|
|
16
|
+
54: "h6"
|
|
17
|
+
};
|
|
18
|
+
const headingsSystem = system(
|
|
19
|
+
(r, [{ createRootEditorSubscription, convertSelectionToNode }]) => {
|
|
20
|
+
r.pub(createRootEditorSubscription, (theRootEditor) => {
|
|
21
|
+
return theRootEditor.registerCommand(
|
|
22
|
+
KEY_DOWN_COMMAND,
|
|
23
|
+
(event) => {
|
|
24
|
+
const { keyCode, ctrlKey, metaKey, altKey } = event;
|
|
25
|
+
if (FORMATTING_KEYS.includes(keyCode) && controlOrMeta(metaKey, ctrlKey) && altKey) {
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
theRootEditor.update(() => {
|
|
28
|
+
if (keyCode === 48) {
|
|
29
|
+
r.pub(convertSelectionToNode, () => $createParagraphNode());
|
|
30
|
+
} else {
|
|
31
|
+
r.pub(convertSelectionToNode, () => $createHeadingNode(CODE_TO_HEADING_MAP[keyCode]));
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
},
|
|
38
|
+
COMMAND_PRIORITY_LOW
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
return {};
|
|
42
|
+
},
|
|
43
|
+
[coreSystem]
|
|
44
|
+
);
|
|
8
45
|
const [headingsPlugin] = realmPlugin({
|
|
9
46
|
id: "headings",
|
|
10
47
|
systemSpec: headingsSystem,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TOGGLE_LINK_COMMAND, $isLinkNode } from "@lexical/link";
|
|
2
|
-
import { $isRangeSelection, KEY_ESCAPE_COMMAND, COMMAND_PRIORITY_LOW, KEY_MODIFIER_COMMAND, COMMAND_PRIORITY_HIGH } from "lexical";
|
|
2
|
+
import { $isRangeSelection, KEY_ESCAPE_COMMAND, COMMAND_PRIORITY_LOW, KEY_MODIFIER_COMMAND, $getSelection, COMMAND_PRIORITY_HIGH } from "lexical";
|
|
3
3
|
import { IS_APPLE } from "../../utils/detectMac.js";
|
|
4
4
|
import { getSelectionRectangle, getSelectedNode } from "../../utils/lexicalHelpers.js";
|
|
5
5
|
import { coreSystem } from "../core/index.js";
|
|
@@ -83,9 +83,14 @@ const linkDialogSystem = system(
|
|
|
83
83
|
KEY_MODIFIER_COMMAND,
|
|
84
84
|
(event) => {
|
|
85
85
|
if (event.key === "k" && (IS_APPLE ? event.metaKey : event.ctrlKey)) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
const selection = $getSelection();
|
|
87
|
+
if ($isRangeSelection(selection) && !selection.isCollapsed()) {
|
|
88
|
+
r.pub(openLinkEditDialog, true);
|
|
89
|
+
event.stopPropagation();
|
|
90
|
+
return true;
|
|
91
|
+
} else {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
89
94
|
}
|
|
90
95
|
return false;
|
|
91
96
|
},
|
package/dist/utils/detectMac.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
const CAN_USE_DOM = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
|
|
2
2
|
const IS_APPLE = CAN_USE_DOM && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
|
3
|
+
function controlOrMeta(metaKey, ctrlKey) {
|
|
4
|
+
if (IS_APPLE) {
|
|
5
|
+
return metaKey;
|
|
6
|
+
}
|
|
7
|
+
return ctrlKey;
|
|
8
|
+
}
|
|
3
9
|
export {
|
|
4
10
|
CAN_USE_DOM,
|
|
5
|
-
IS_APPLE
|
|
11
|
+
IS_APPLE,
|
|
12
|
+
controlOrMeta
|
|
6
13
|
};
|