@gravity-ui/markdown-editor 13.23.0 → 13.24.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/build/cjs/bundle/MarkdownEditorView.css +1 -0
- package/build/cjs/bundle/MarkdownEditorView.d.ts +4 -0
- package/build/cjs/bundle/MarkdownEditorView.js +10 -2
- package/build/cjs/extensions/yfm/Math/commands.d.ts +6 -2
- package/build/cjs/extensions/yfm/Math/commands.js +33 -7
- package/build/cjs/extensions/yfm/Math/index.js +1 -1
- package/build/cjs/extensions/yfm/Math/view-and-edit.js +4 -4
- package/build/cjs/extensions/yfm/YfmCut/YfmCutSpecs/schema.js +6 -6
- package/build/cjs/extensions/yfm/YfmCut/actions/toYfmCut.js +1 -1
- package/build/cjs/extensions/yfm/YfmCut/index.css +12 -0
- package/build/cjs/extensions/yfm/YfmCut/nodeviews/yfm-cut-title.js +2 -1
- package/build/cjs/extensions/yfm/YfmCut/plugins/auto-open.js +3 -1
- package/build/cjs/version.js +1 -1
- package/build/esm/bundle/MarkdownEditorView.css +1 -0
- package/build/esm/bundle/MarkdownEditorView.d.ts +4 -0
- package/build/esm/bundle/MarkdownEditorView.js +10 -2
- package/build/esm/extensions/yfm/Math/commands.d.ts +6 -2
- package/build/esm/extensions/yfm/Math/commands.js +30 -5
- package/build/esm/extensions/yfm/Math/index.js +2 -2
- package/build/esm/extensions/yfm/Math/view-and-edit.js +6 -5
- package/build/esm/extensions/yfm/YfmCut/YfmCutSpecs/schema.js +6 -6
- package/build/esm/extensions/yfm/YfmCut/actions/toYfmCut.js +1 -1
- package/build/esm/extensions/yfm/YfmCut/index.css +12 -0
- package/build/esm/extensions/yfm/YfmCut/nodeviews/yfm-cut-title.js +2 -1
- package/build/esm/extensions/yfm/YfmCut/plugins/auto-open.js +3 -1
- package/build/esm/version.js +1 -1
- package/build/styles.css +13 -0
- package/package.json +3 -3
|
@@ -15,6 +15,8 @@ export declare type MarkdownEditorViewProps = ClassNameProps & {
|
|
|
15
15
|
settingsVisible?: boolean;
|
|
16
16
|
toaster: ToasterPublicMethods;
|
|
17
17
|
stickyToolbar: boolean;
|
|
18
|
+
enableSubmitInPreview?: boolean;
|
|
19
|
+
hidePreviewAfterSubmit?: boolean;
|
|
18
20
|
};
|
|
19
21
|
export declare const MarkdownEditorView: React.ForwardRefExoticComponent<ClassNameProps & {
|
|
20
22
|
editor?: Editor | undefined;
|
|
@@ -27,4 +29,6 @@ export declare const MarkdownEditorView: React.ForwardRefExoticComponent<ClassNa
|
|
|
27
29
|
settingsVisible?: boolean | undefined;
|
|
28
30
|
toaster: ToasterPublicMethods;
|
|
29
31
|
stickyToolbar: boolean;
|
|
32
|
+
enableSubmitInPreview?: boolean | undefined;
|
|
33
|
+
hidePreviewAfterSubmit?: boolean | undefined;
|
|
30
34
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -33,7 +33,7 @@ exports.MarkdownEditorView = react_1.default.forwardRef((props, ref) => {
|
|
|
33
33
|
const editor = ((_a = props.editor) !== null && _a !== void 0 ? _a : context);
|
|
34
34
|
if (!editor)
|
|
35
35
|
throw new Error('[MarkdownEditorView]: an instance of the editor must be passed through the props or context');
|
|
36
|
-
const { autofocus, className, settingsVisible = true, markupToolbarConfig = config_1.mToolbarConfigByPreset[editor.preset], wysiwygToolbarConfig = config_1.wToolbarConfigByPreset[editor.preset], markupHiddenActionsConfig = config_1.mHiddenDataByPreset[editor.preset], wysiwygHiddenActionsConfig = config_1.wHiddenDataByPreset[editor.preset], toaster, stickyToolbar, } = props;
|
|
36
|
+
const { autofocus, className, settingsVisible = true, markupToolbarConfig = config_1.mToolbarConfigByPreset[editor.preset], wysiwygToolbarConfig = config_1.wToolbarConfigByPreset[editor.preset], markupHiddenActionsConfig = config_1.mHiddenDataByPreset[editor.preset], wysiwygHiddenActionsConfig = config_1.wHiddenDataByPreset[editor.preset], toaster, stickyToolbar, enableSubmitInPreview = true, hidePreviewAfterSubmit = false, } = props;
|
|
37
37
|
const rerender = (0, react_use_1.useUpdate)();
|
|
38
38
|
react_1.default.useLayoutEffect(() => {
|
|
39
39
|
editor.on('rerender', rerender);
|
|
@@ -68,7 +68,15 @@ exports.MarkdownEditorView = react_1.default.forwardRef((props, ref) => {
|
|
|
68
68
|
divRef.current.focus();
|
|
69
69
|
}
|
|
70
70
|
}, [divRef, showPreview]);
|
|
71
|
-
(0, react_use_1.useKey)((e) =>
|
|
71
|
+
(0, react_use_1.useKey)((e) => enableSubmitInPreview &&
|
|
72
|
+
showPreview &&
|
|
73
|
+
isWrapperFocused(divRef) &&
|
|
74
|
+
isSubmitKeyDown(e), () => {
|
|
75
|
+
editor.emit('submit', null);
|
|
76
|
+
if (hidePreviewAfterSubmit) {
|
|
77
|
+
onShowPreviewChange(false);
|
|
78
|
+
}
|
|
79
|
+
}, { event: 'keydown' }, [hidePreviewAfterSubmit, enableSubmitInPreview, showPreview, showPreview]);
|
|
72
80
|
const settings = (0, react_1.useMemo)(() => (react_1.default.createElement(Settings, { mode: editorMode, onModeChange: onModeChange, toolbarVisibility: editor.toolbarVisible && !showPreview, onToolbarVisibilityChange: onToolbarVisibilityChange, onSplitModeChange: onSplitModeChange, splitModeEnabled: editor.splitModeEnabled, splitMode: editor.splitMode, stickyToolbar: stickyToolbar, onShowPreviewChange: onShowPreviewChange, showPreview: showPreview, renderPreviewButton: canRenderPreview })), [
|
|
73
81
|
canRenderPreview,
|
|
74
82
|
stickyToolbar,
|
|
@@ -7,6 +7,10 @@ export declare const ignoreIfCursorInsideMathInline: Command;
|
|
|
7
7
|
*/
|
|
8
8
|
export declare const removeEmptyMathInlineIfCursorIsAtBeginning: Command;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Handle cursor movement to the right at the boundary of a MathInline block
|
|
11
11
|
*/
|
|
12
|
-
export declare const
|
|
12
|
+
export declare const moveCursorRightOfMathInline: Command;
|
|
13
|
+
/**
|
|
14
|
+
* Handle cursor movement to the left at the boundary of a MathInline block
|
|
15
|
+
*/
|
|
16
|
+
export declare const moveCursorLeftOfMathInline: Command;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.moveCursorLeftOfMathInline = exports.moveCursorRightOfMathInline = exports.removeEmptyMathInlineIfCursorIsAtBeginning = exports.ignoreIfCursorInsideMathInline = void 0;
|
|
4
4
|
const prosemirror_state_1 = require("prosemirror-state");
|
|
5
5
|
const selection_1 = require("../../../utils/selection");
|
|
6
6
|
const const_1 = require("./const");
|
|
@@ -30,15 +30,41 @@ const removeEmptyMathInlineIfCursorIsAtBeginning = ({ tr, schema }, dispatch) =>
|
|
|
30
30
|
};
|
|
31
31
|
exports.removeEmptyMathInlineIfCursorIsAtBeginning = removeEmptyMathInlineIfCursorIsAtBeginning;
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* Handle cursor movement to the right at the boundary of a MathInline block
|
|
34
34
|
*/
|
|
35
|
-
const
|
|
35
|
+
const moveCursorRightOfMathInline = ({ tr, schema }, dispatch) => {
|
|
36
36
|
var _a;
|
|
37
37
|
const $cursor = (0, selection_1.get$Cursor)(tr.selection);
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
if ($cursor) {
|
|
39
|
+
const mathType = (0, const_1.mathIType)(schema);
|
|
40
|
+
const isOnBeforeOfMathInline = ((_a = $cursor.nodeAfter) === null || _a === void 0 ? void 0 : _a.type) === mathType;
|
|
41
|
+
const isOnEndOfMathInline = $cursor.parentOffset === $cursor.parent.content.size &&
|
|
42
|
+
$cursor.parent.type === mathType;
|
|
43
|
+
if (isOnBeforeOfMathInline || isOnEndOfMathInline) {
|
|
44
|
+
const newPos = $cursor.pos + 1;
|
|
45
|
+
dispatch === null || dispatch === void 0 ? void 0 : dispatch(tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, newPos)));
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
};
|
|
51
|
+
exports.moveCursorRightOfMathInline = moveCursorRightOfMathInline;
|
|
52
|
+
/**
|
|
53
|
+
* Handle cursor movement to the left at the boundary of a MathInline block
|
|
54
|
+
*/
|
|
55
|
+
const moveCursorLeftOfMathInline = ({ tr, schema }, dispatch) => {
|
|
56
|
+
var _a;
|
|
57
|
+
const $cursor = (0, selection_1.get$Cursor)(tr.selection);
|
|
58
|
+
if ($cursor) {
|
|
59
|
+
const mathType = (0, const_1.mathIType)(schema);
|
|
60
|
+
const isOnAfterOfMathInline = ((_a = $cursor.nodeBefore) === null || _a === void 0 ? void 0 : _a.type) === mathType;
|
|
61
|
+
const isOnStartOfMathInline = $cursor.parentOffset === 0 && $cursor.parent.type === mathType;
|
|
62
|
+
if (isOnAfterOfMathInline || isOnStartOfMathInline) {
|
|
63
|
+
const newPos = $cursor.pos - 1;
|
|
64
|
+
dispatch === null || dispatch === void 0 ? void 0 : dispatch(tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, newPos)));
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
41
67
|
}
|
|
42
68
|
return false;
|
|
43
69
|
};
|
|
44
|
-
exports.
|
|
70
|
+
exports.moveCursorLeftOfMathInline = moveCursorLeftOfMathInline;
|
|
@@ -24,7 +24,7 @@ const Math = (builder, opts) => {
|
|
|
24
24
|
builder.use(MathSpecs_1.MathSpecs);
|
|
25
25
|
builder.addKeymap(() => ({
|
|
26
26
|
Enter: commands_1.ignoreIfCursorInsideMathInline,
|
|
27
|
-
Backspace: (0, prosemirror_commands_1.chainCommands)(commands_1.
|
|
27
|
+
Backspace: (0, prosemirror_commands_1.chainCommands)(commands_1.removeEmptyMathInlineIfCursorIsAtBeginning, commands_1.moveCursorLeftOfMathInline),
|
|
28
28
|
}));
|
|
29
29
|
builder
|
|
30
30
|
.addPlugin(() => (0, view_and_edit_1.mathViewAndEditPlugin)(Object.assign(Object.assign({}, opts), { reactRenderer: builder.context.get('reactrenderer') })))
|
|
@@ -8,7 +8,6 @@ const selection_1 = require("../../../utils/selection");
|
|
|
8
8
|
const commands_1 = require("./commands");
|
|
9
9
|
const const_1 = require("./const");
|
|
10
10
|
const hint_1 = require("./hint");
|
|
11
|
-
// eslint-disable-line import/order
|
|
12
11
|
const MATH_ACTIVE_DECO = 'math_active_decoration';
|
|
13
12
|
class MathNodeView {
|
|
14
13
|
constructor(node, opts) {
|
|
@@ -162,13 +161,14 @@ class MathBlockNodeView extends MathNodeView {
|
|
|
162
161
|
exports.MathBlockNodeView = MathBlockNodeView;
|
|
163
162
|
const mathViewAndEditPlugin = (options) => new prosemirror_state_1.Plugin({
|
|
164
163
|
props: {
|
|
164
|
+
handleKeyDown: (0, prosemirror_keymap_1.keydownHandler)({
|
|
165
|
+
ArrowRight: commands_1.moveCursorRightOfMathInline,
|
|
166
|
+
ArrowLeft: commands_1.moveCursorLeftOfMathInline,
|
|
167
|
+
}),
|
|
165
168
|
nodeViews: {
|
|
166
169
|
[const_1.MathNode.Block]: (node) => new MathBlockNodeView(node, options),
|
|
167
170
|
[const_1.MathNode.Inline]: (node) => new MathInlineNodeView(node, options),
|
|
168
171
|
},
|
|
169
|
-
handleKeyDown: (0, prosemirror_keymap_1.keydownHandler)({
|
|
170
|
-
ArrowLeft: commands_1.moveCursorToEndOfMathInline,
|
|
171
|
-
}),
|
|
172
172
|
decorations: (state) => {
|
|
173
173
|
const { selection } = state;
|
|
174
174
|
if ((0, selection_1.isTextSelection)(selection)) {
|
|
@@ -10,12 +10,12 @@ const getSchemaSpecs = (opts, placeholder) => {
|
|
|
10
10
|
var _a, _b, _c, _d;
|
|
11
11
|
return ({
|
|
12
12
|
[const_1.CutNode.Cut]: {
|
|
13
|
-
attrs: { class: { default: 'yfm-cut' } },
|
|
13
|
+
attrs: { class: { default: 'yfm-cut' }, open: { default: null } },
|
|
14
14
|
content: `${const_1.CutNode.CutTitle} ${const_1.CutNode.CutContent}`,
|
|
15
15
|
group: 'block yfm-cut',
|
|
16
|
-
parseDOM: [{ tag: '
|
|
16
|
+
parseDOM: [{ tag: '.yfm-cut' }],
|
|
17
17
|
toDOM(node) {
|
|
18
|
-
return ['
|
|
18
|
+
return ['details', node.attrs, 0];
|
|
19
19
|
},
|
|
20
20
|
selectable: true,
|
|
21
21
|
allowSelection: true,
|
|
@@ -26,9 +26,9 @@ const getSchemaSpecs = (opts, placeholder) => {
|
|
|
26
26
|
attrs: { class: { default: 'yfm-cut-title' } },
|
|
27
27
|
content: 'inline*',
|
|
28
28
|
group: 'block yfm-cut',
|
|
29
|
-
parseDOM: [{ tag: '
|
|
29
|
+
parseDOM: [{ tag: '.yfm-cut-title' }],
|
|
30
30
|
toDOM(node) {
|
|
31
|
-
return ['
|
|
31
|
+
return ['summary', node.attrs, 0];
|
|
32
32
|
},
|
|
33
33
|
placeholder: {
|
|
34
34
|
content: (_b = (_a = placeholder === null || placeholder === void 0 ? void 0 : placeholder[const_1.CutNode.CutTitle]) !== null && _a !== void 0 ? _a : opts === null || opts === void 0 ? void 0 : opts.yfmCutTitlePlaceholder) !== null && _b !== void 0 ? _b : DEFAULT_PLACEHOLDERS.Title,
|
|
@@ -43,7 +43,7 @@ const getSchemaSpecs = (opts, placeholder) => {
|
|
|
43
43
|
attrs: { class: { default: 'yfm-cut-content' } },
|
|
44
44
|
content: '(block | paragraph)+',
|
|
45
45
|
group: 'block yfm-cut',
|
|
46
|
-
parseDOM: [{ tag: '
|
|
46
|
+
parseDOM: [{ tag: '.yfm-cut-content' }],
|
|
47
47
|
toDOM(node) {
|
|
48
48
|
return ['div', node.attrs, 0];
|
|
49
49
|
},
|
|
@@ -5,7 +5,7 @@ const prosemirror_state_1 = require("prosemirror-state");
|
|
|
5
5
|
const prosemirror_utils_1 = require("prosemirror-utils");
|
|
6
6
|
const const_1 = require("../const");
|
|
7
7
|
const createYfmCutNode = (schema) => (content) => {
|
|
8
|
-
return (0, const_1.cutType)(schema).create({ class: 'yfm-cut open' }, [
|
|
8
|
+
return (0, const_1.cutType)(schema).create({ class: 'yfm-cut open', open: true }, [
|
|
9
9
|
(0, const_1.cutTitleType)(schema).create(null),
|
|
10
10
|
(0, const_1.cutContentType)(schema).create(null, content),
|
|
11
11
|
]);
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
.ProseMirror.yfm .yfm-cut {
|
|
2
2
|
border: 1px dashed transparent;
|
|
3
3
|
border-radius: var(--g-border-radius-s);
|
|
4
|
+
/* TODO: Remove this after updating @diplodoc/transform to version 4.19.0 or higher */
|
|
5
|
+
/* This ensures backward compatibility with earlier versions of cut-extension */
|
|
4
6
|
}
|
|
5
7
|
.ProseMirror.yfm .yfm-cut:hover {
|
|
6
8
|
border-color: var(--g-color-line-generic);
|
|
7
9
|
}
|
|
8
10
|
.ProseMirror.yfm .yfm-cut.yfm-cut-active {
|
|
9
11
|
border-color: var(--g-color-line-generic);
|
|
12
|
+
}
|
|
13
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title:focus {
|
|
14
|
+
outline: 0;
|
|
15
|
+
}
|
|
16
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title {
|
|
17
|
+
list-style: none;
|
|
18
|
+
}
|
|
19
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title::-webkit-details-marker,
|
|
20
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title::marker {
|
|
21
|
+
display: none;
|
|
10
22
|
}
|
|
@@ -4,7 +4,7 @@ exports.YfmCutTitleNodeView = void 0;
|
|
|
4
4
|
class YfmCutTitleNodeView {
|
|
5
5
|
constructor(node) {
|
|
6
6
|
this.node = node;
|
|
7
|
-
this.dom = document.createElement('
|
|
7
|
+
this.dom = document.createElement('summary');
|
|
8
8
|
this.dom.classList.add('yfm-cut-title');
|
|
9
9
|
this.dom.replaceChildren((this.contentDOM = document.createElement('div')));
|
|
10
10
|
this.contentDOM.classList.add('g-md-yfm-cut-title-inner');
|
|
@@ -12,6 +12,7 @@ class YfmCutTitleNodeView {
|
|
|
12
12
|
// ignore clicking on the title content
|
|
13
13
|
// you can open/close yfm-cut by clicking on the arrow icon
|
|
14
14
|
e.stopPropagation();
|
|
15
|
+
e.preventDefault();
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
18
|
update(node) {
|
|
@@ -42,6 +42,7 @@ function openParentYfmCuts($pos, domAtPos) {
|
|
|
42
42
|
if ($pos.node(depth - 1).type === (0, const_1.cutType)(schema)) {
|
|
43
43
|
const { node: cutDomNode } = domAtPos($pos.start(depth - 1), 0);
|
|
44
44
|
cutDomNode.classList.add('open');
|
|
45
|
+
cutDomNode.setAttribute('open', 'true');
|
|
45
46
|
depth--;
|
|
46
47
|
}
|
|
47
48
|
}
|
|
@@ -89,9 +90,10 @@ class CutAutoOpenOnDragOver {
|
|
|
89
90
|
this._timeout = setTimeout(this._openCut.bind(this), CutAutoOpenOnDragOver.OPEN_TIMEOUT);
|
|
90
91
|
}
|
|
91
92
|
_openCut() {
|
|
92
|
-
var _a;
|
|
93
|
+
var _a, _b;
|
|
93
94
|
if (this._editorView.dragging) {
|
|
94
95
|
(_a = this._cutElem) === null || _a === void 0 ? void 0 : _a.classList.add('open');
|
|
96
|
+
(_b = this._cutElem) === null || _b === void 0 ? void 0 : _b.setAttribute('open', 'true');
|
|
95
97
|
}
|
|
96
98
|
this._clear();
|
|
97
99
|
}
|
package/build/cjs/version.js
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VERSION = void 0;
|
|
4
4
|
/** During build process, the current version will be injected here */
|
|
5
|
-
exports.VERSION = typeof '13.
|
|
5
|
+
exports.VERSION = typeof '13.24.0' !== 'undefined' ? '13.24.0' : 'unknown';
|
|
@@ -17,6 +17,8 @@ export declare type MarkdownEditorViewProps = ClassNameProps & {
|
|
|
17
17
|
settingsVisible?: boolean;
|
|
18
18
|
toaster: ToasterPublicMethods;
|
|
19
19
|
stickyToolbar: boolean;
|
|
20
|
+
enableSubmitInPreview?: boolean;
|
|
21
|
+
hidePreviewAfterSubmit?: boolean;
|
|
20
22
|
};
|
|
21
23
|
export declare const MarkdownEditorView: React.ForwardRefExoticComponent<ClassNameProps & {
|
|
22
24
|
editor?: Editor | undefined;
|
|
@@ -29,4 +31,6 @@ export declare const MarkdownEditorView: React.ForwardRefExoticComponent<ClassNa
|
|
|
29
31
|
settingsVisible?: boolean | undefined;
|
|
30
32
|
toaster: ToasterPublicMethods;
|
|
31
33
|
stickyToolbar: boolean;
|
|
34
|
+
enableSubmitInPreview?: boolean | undefined;
|
|
35
|
+
hidePreviewAfterSubmit?: boolean | undefined;
|
|
32
36
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -30,7 +30,7 @@ export const MarkdownEditorView = React.forwardRef((props, ref) => {
|
|
|
30
30
|
const editor = ((_a = props.editor) !== null && _a !== void 0 ? _a : context);
|
|
31
31
|
if (!editor)
|
|
32
32
|
throw new Error('[MarkdownEditorView]: an instance of the editor must be passed through the props or context');
|
|
33
|
-
const { autofocus, className, settingsVisible = true, markupToolbarConfig = mToolbarConfigByPreset[editor.preset], wysiwygToolbarConfig = wToolbarConfigByPreset[editor.preset], markupHiddenActionsConfig = mHiddenDataByPreset[editor.preset], wysiwygHiddenActionsConfig = wHiddenDataByPreset[editor.preset], toaster, stickyToolbar, } = props;
|
|
33
|
+
const { autofocus, className, settingsVisible = true, markupToolbarConfig = mToolbarConfigByPreset[editor.preset], wysiwygToolbarConfig = wToolbarConfigByPreset[editor.preset], markupHiddenActionsConfig = mHiddenDataByPreset[editor.preset], wysiwygHiddenActionsConfig = wHiddenDataByPreset[editor.preset], toaster, stickyToolbar, enableSubmitInPreview = true, hidePreviewAfterSubmit = false, } = props;
|
|
34
34
|
const rerender = useUpdate();
|
|
35
35
|
React.useLayoutEffect(() => {
|
|
36
36
|
editor.on('rerender', rerender);
|
|
@@ -65,7 +65,15 @@ export const MarkdownEditorView = React.forwardRef((props, ref) => {
|
|
|
65
65
|
divRef.current.focus();
|
|
66
66
|
}
|
|
67
67
|
}, [divRef, showPreview]);
|
|
68
|
-
useKey((e) =>
|
|
68
|
+
useKey((e) => enableSubmitInPreview &&
|
|
69
|
+
showPreview &&
|
|
70
|
+
isWrapperFocused(divRef) &&
|
|
71
|
+
isSubmitKeyDown(e), () => {
|
|
72
|
+
editor.emit('submit', null);
|
|
73
|
+
if (hidePreviewAfterSubmit) {
|
|
74
|
+
onShowPreviewChange(false);
|
|
75
|
+
}
|
|
76
|
+
}, { event: 'keydown' }, [hidePreviewAfterSubmit, enableSubmitInPreview, showPreview, showPreview]);
|
|
69
77
|
const settings = useMemo(() => (React.createElement(Settings, { mode: editorMode, onModeChange: onModeChange, toolbarVisibility: editor.toolbarVisible && !showPreview, onToolbarVisibilityChange: onToolbarVisibilityChange, onSplitModeChange: onSplitModeChange, splitModeEnabled: editor.splitModeEnabled, splitMode: editor.splitMode, stickyToolbar: stickyToolbar, onShowPreviewChange: onShowPreviewChange, showPreview: showPreview, renderPreviewButton: canRenderPreview })), [
|
|
70
78
|
canRenderPreview,
|
|
71
79
|
stickyToolbar,
|
|
@@ -7,6 +7,10 @@ export declare const ignoreIfCursorInsideMathInline: Command;
|
|
|
7
7
|
*/
|
|
8
8
|
export declare const removeEmptyMathInlineIfCursorIsAtBeginning: Command;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Handle cursor movement to the right at the boundary of a MathInline block
|
|
11
11
|
*/
|
|
12
|
-
export declare const
|
|
12
|
+
export declare const moveCursorRightOfMathInline: Command;
|
|
13
|
+
/**
|
|
14
|
+
* Handle cursor movement to the left at the boundary of a MathInline block
|
|
15
|
+
*/
|
|
16
|
+
export declare const moveCursorLeftOfMathInline: Command;
|
|
@@ -25,14 +25,39 @@ export const removeEmptyMathInlineIfCursorIsAtBeginning = ({ tr, schema }, dispa
|
|
|
25
25
|
return false;
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Handle cursor movement to the right at the boundary of a MathInline block
|
|
29
29
|
*/
|
|
30
|
-
export const
|
|
30
|
+
export const moveCursorRightOfMathInline = ({ tr, schema }, dispatch) => {
|
|
31
31
|
var _a;
|
|
32
32
|
const $cursor = get$Cursor(tr.selection);
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
if ($cursor) {
|
|
34
|
+
const mathType = mathIType(schema);
|
|
35
|
+
const isOnBeforeOfMathInline = ((_a = $cursor.nodeAfter) === null || _a === void 0 ? void 0 : _a.type) === mathType;
|
|
36
|
+
const isOnEndOfMathInline = $cursor.parentOffset === $cursor.parent.content.size &&
|
|
37
|
+
$cursor.parent.type === mathType;
|
|
38
|
+
if (isOnBeforeOfMathInline || isOnEndOfMathInline) {
|
|
39
|
+
const newPos = $cursor.pos + 1;
|
|
40
|
+
dispatch === null || dispatch === void 0 ? void 0 : dispatch(tr.setSelection(TextSelection.create(tr.doc, newPos)));
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Handle cursor movement to the left at the boundary of a MathInline block
|
|
48
|
+
*/
|
|
49
|
+
export const moveCursorLeftOfMathInline = ({ tr, schema }, dispatch) => {
|
|
50
|
+
var _a;
|
|
51
|
+
const $cursor = get$Cursor(tr.selection);
|
|
52
|
+
if ($cursor) {
|
|
53
|
+
const mathType = mathIType(schema);
|
|
54
|
+
const isOnAfterOfMathInline = ((_a = $cursor.nodeBefore) === null || _a === void 0 ? void 0 : _a.type) === mathType;
|
|
55
|
+
const isOnStartOfMathInline = $cursor.parentOffset === 0 && $cursor.parent.type === mathType;
|
|
56
|
+
if (isOnAfterOfMathInline || isOnStartOfMathInline) {
|
|
57
|
+
const newPos = $cursor.pos - 1;
|
|
58
|
+
dispatch === null || dispatch === void 0 ? void 0 : dispatch(tr.setSelection(TextSelection.create(tr.doc, newPos)));
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
36
61
|
}
|
|
37
62
|
return false;
|
|
38
63
|
};
|
|
@@ -4,7 +4,7 @@ import { hasParentNodeOfType } from 'prosemirror-utils';
|
|
|
4
4
|
import { inlineNodeInputRule, textblockTypeInputRule } from '../../../utils/inputrules';
|
|
5
5
|
import { isTextSelection } from '../../../utils/selection';
|
|
6
6
|
import { MathSpecs } from './MathSpecs';
|
|
7
|
-
import { ignoreIfCursorInsideMathInline,
|
|
7
|
+
import { ignoreIfCursorInsideMathInline, moveCursorLeftOfMathInline, removeEmptyMathInlineIfCursorIsAtBeginning, } from './commands';
|
|
8
8
|
import { mathBType, mathIType } from './const';
|
|
9
9
|
import { mathViewAndEditPlugin } from './view-and-edit';
|
|
10
10
|
import './index.css';
|
|
@@ -17,7 +17,7 @@ export const Math = (builder, opts) => {
|
|
|
17
17
|
builder.use(MathSpecs);
|
|
18
18
|
builder.addKeymap(() => ({
|
|
19
19
|
Enter: ignoreIfCursorInsideMathInline,
|
|
20
|
-
Backspace: chainCommands(
|
|
20
|
+
Backspace: chainCommands(removeEmptyMathInlineIfCursorIsAtBeginning, moveCursorLeftOfMathInline),
|
|
21
21
|
}));
|
|
22
22
|
builder
|
|
23
23
|
.addPlugin(() => mathViewAndEditPlugin(Object.assign(Object.assign({}, opts), { reactRenderer: builder.context.get('reactrenderer') })))
|
|
@@ -2,10 +2,10 @@ import { keydownHandler } from 'prosemirror-keymap';
|
|
|
2
2
|
import { Plugin } from 'prosemirror-state';
|
|
3
3
|
import { Decoration, DecorationSet } from 'prosemirror-view';
|
|
4
4
|
import { isTextSelection } from '../../../utils/selection';
|
|
5
|
-
import {
|
|
5
|
+
import { moveCursorLeftOfMathInline, moveCursorRightOfMathInline } from './commands';
|
|
6
6
|
import { CLASSNAMES, MathNode } from './const';
|
|
7
7
|
import { b, renderMathHint } from './hint';
|
|
8
|
-
import './view-and-edit.css';
|
|
8
|
+
import './view-and-edit.css';
|
|
9
9
|
const MATH_ACTIVE_DECO = 'math_active_decoration';
|
|
10
10
|
export class MathNodeView {
|
|
11
11
|
constructor(node, opts) {
|
|
@@ -156,13 +156,14 @@ export class MathBlockNodeView extends MathNodeView {
|
|
|
156
156
|
}
|
|
157
157
|
export const mathViewAndEditPlugin = (options) => new Plugin({
|
|
158
158
|
props: {
|
|
159
|
+
handleKeyDown: keydownHandler({
|
|
160
|
+
ArrowRight: moveCursorRightOfMathInline,
|
|
161
|
+
ArrowLeft: moveCursorLeftOfMathInline,
|
|
162
|
+
}),
|
|
159
163
|
nodeViews: {
|
|
160
164
|
[MathNode.Block]: (node) => new MathBlockNodeView(node, options),
|
|
161
165
|
[MathNode.Inline]: (node) => new MathInlineNodeView(node, options),
|
|
162
166
|
},
|
|
163
|
-
handleKeyDown: keydownHandler({
|
|
164
|
-
ArrowLeft: moveCursorToEndOfMathInline,
|
|
165
|
-
}),
|
|
166
167
|
decorations: (state) => {
|
|
167
168
|
const { selection } = state;
|
|
168
169
|
if (isTextSelection(selection)) {
|
|
@@ -7,12 +7,12 @@ export const getSchemaSpecs = (opts, placeholder) => {
|
|
|
7
7
|
var _a, _b, _c, _d;
|
|
8
8
|
return ({
|
|
9
9
|
[CutNode.Cut]: {
|
|
10
|
-
attrs: { class: { default: 'yfm-cut' } },
|
|
10
|
+
attrs: { class: { default: 'yfm-cut' }, open: { default: null } },
|
|
11
11
|
content: `${CutNode.CutTitle} ${CutNode.CutContent}`,
|
|
12
12
|
group: 'block yfm-cut',
|
|
13
|
-
parseDOM: [{ tag: '
|
|
13
|
+
parseDOM: [{ tag: '.yfm-cut' }],
|
|
14
14
|
toDOM(node) {
|
|
15
|
-
return ['
|
|
15
|
+
return ['details', node.attrs, 0];
|
|
16
16
|
},
|
|
17
17
|
selectable: true,
|
|
18
18
|
allowSelection: true,
|
|
@@ -23,9 +23,9 @@ export const getSchemaSpecs = (opts, placeholder) => {
|
|
|
23
23
|
attrs: { class: { default: 'yfm-cut-title' } },
|
|
24
24
|
content: 'inline*',
|
|
25
25
|
group: 'block yfm-cut',
|
|
26
|
-
parseDOM: [{ tag: '
|
|
26
|
+
parseDOM: [{ tag: '.yfm-cut-title' }],
|
|
27
27
|
toDOM(node) {
|
|
28
|
-
return ['
|
|
28
|
+
return ['summary', node.attrs, 0];
|
|
29
29
|
},
|
|
30
30
|
placeholder: {
|
|
31
31
|
content: (_b = (_a = placeholder === null || placeholder === void 0 ? void 0 : placeholder[CutNode.CutTitle]) !== null && _a !== void 0 ? _a : opts === null || opts === void 0 ? void 0 : opts.yfmCutTitlePlaceholder) !== null && _b !== void 0 ? _b : DEFAULT_PLACEHOLDERS.Title,
|
|
@@ -40,7 +40,7 @@ export const getSchemaSpecs = (opts, placeholder) => {
|
|
|
40
40
|
attrs: { class: { default: 'yfm-cut-content' } },
|
|
41
41
|
content: '(block | paragraph)+',
|
|
42
42
|
group: 'block yfm-cut',
|
|
43
|
-
parseDOM: [{ tag: '
|
|
43
|
+
parseDOM: [{ tag: '.yfm-cut-content' }],
|
|
44
44
|
toDOM(node) {
|
|
45
45
|
return ['div', node.attrs, 0];
|
|
46
46
|
},
|
|
@@ -2,7 +2,7 @@ import { TextSelection } from 'prosemirror-state';
|
|
|
2
2
|
import { findParentNodeClosestToPos } from 'prosemirror-utils';
|
|
3
3
|
import { cutContentType, cutTitleType, cutType } from '../const';
|
|
4
4
|
const createYfmCutNode = (schema) => (content) => {
|
|
5
|
-
return cutType(schema).create({ class: 'yfm-cut open' }, [
|
|
5
|
+
return cutType(schema).create({ class: 'yfm-cut open', open: true }, [
|
|
6
6
|
cutTitleType(schema).create(null),
|
|
7
7
|
cutContentType(schema).create(null, content),
|
|
8
8
|
]);
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
.ProseMirror.yfm .yfm-cut {
|
|
2
2
|
border: 1px dashed transparent;
|
|
3
3
|
border-radius: var(--g-border-radius-s);
|
|
4
|
+
/* TODO: Remove this after updating @diplodoc/transform to version 4.19.0 or higher */
|
|
5
|
+
/* This ensures backward compatibility with earlier versions of cut-extension */
|
|
4
6
|
}
|
|
5
7
|
.ProseMirror.yfm .yfm-cut:hover {
|
|
6
8
|
border-color: var(--g-color-line-generic);
|
|
7
9
|
}
|
|
8
10
|
.ProseMirror.yfm .yfm-cut.yfm-cut-active {
|
|
9
11
|
border-color: var(--g-color-line-generic);
|
|
12
|
+
}
|
|
13
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title:focus {
|
|
14
|
+
outline: 0;
|
|
15
|
+
}
|
|
16
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title {
|
|
17
|
+
list-style: none;
|
|
18
|
+
}
|
|
19
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title::-webkit-details-marker,
|
|
20
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title::marker {
|
|
21
|
+
display: none;
|
|
10
22
|
}
|
|
@@ -2,7 +2,7 @@ import './yfm-cut-title.css';
|
|
|
2
2
|
export class YfmCutTitleNodeView {
|
|
3
3
|
constructor(node) {
|
|
4
4
|
this.node = node;
|
|
5
|
-
this.dom = document.createElement('
|
|
5
|
+
this.dom = document.createElement('summary');
|
|
6
6
|
this.dom.classList.add('yfm-cut-title');
|
|
7
7
|
this.dom.replaceChildren((this.contentDOM = document.createElement('div')));
|
|
8
8
|
this.contentDOM.classList.add('g-md-yfm-cut-title-inner');
|
|
@@ -10,6 +10,7 @@ export class YfmCutTitleNodeView {
|
|
|
10
10
|
// ignore clicking on the title content
|
|
11
11
|
// you can open/close yfm-cut by clicking on the arrow icon
|
|
12
12
|
e.stopPropagation();
|
|
13
|
+
e.preventDefault();
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
16
|
update(node) {
|
|
@@ -38,6 +38,7 @@ function openParentYfmCuts($pos, domAtPos) {
|
|
|
38
38
|
if ($pos.node(depth - 1).type === cutType(schema)) {
|
|
39
39
|
const { node: cutDomNode } = domAtPos($pos.start(depth - 1), 0);
|
|
40
40
|
cutDomNode.classList.add('open');
|
|
41
|
+
cutDomNode.setAttribute('open', 'true');
|
|
41
42
|
depth--;
|
|
42
43
|
}
|
|
43
44
|
}
|
|
@@ -85,9 +86,10 @@ class CutAutoOpenOnDragOver {
|
|
|
85
86
|
this._timeout = setTimeout(this._openCut.bind(this), CutAutoOpenOnDragOver.OPEN_TIMEOUT);
|
|
86
87
|
}
|
|
87
88
|
_openCut() {
|
|
88
|
-
var _a;
|
|
89
|
+
var _a, _b;
|
|
89
90
|
if (this._editorView.dragging) {
|
|
90
91
|
(_a = this._cutElem) === null || _a === void 0 ? void 0 : _a.classList.add('open');
|
|
92
|
+
(_b = this._cutElem) === null || _b === void 0 ? void 0 : _b.setAttribute('open', 'true');
|
|
91
93
|
}
|
|
92
94
|
this._clear();
|
|
93
95
|
}
|
package/build/esm/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** During build process, the current version will be injected here */
|
|
2
|
-
export const VERSION = typeof '13.
|
|
2
|
+
export const VERSION = typeof '13.24.0' !== 'undefined' ? '13.24.0' : 'unknown';
|
package/build/styles.css
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
.g-md-editor-component {
|
|
2
2
|
display: flex;
|
|
3
3
|
height: 100%;
|
|
4
|
+
outline: none;
|
|
4
5
|
}
|
|
5
6
|
.g-md-editor-component_split_vertical {
|
|
6
7
|
display: grid;
|
|
@@ -1047,6 +1048,8 @@ body :has(.g-md-resizable_resizing) {
|
|
|
1047
1048
|
.ProseMirror.yfm .yfm-cut {
|
|
1048
1049
|
border: 1px dashed transparent;
|
|
1049
1050
|
border-radius: var(--g-border-radius-s);
|
|
1051
|
+
/* TODO: Remove this after updating @diplodoc/transform to version 4.19.0 or higher */
|
|
1052
|
+
/* This ensures backward compatibility with earlier versions of cut-extension */
|
|
1050
1053
|
}
|
|
1051
1054
|
.ProseMirror.yfm .yfm-cut:hover {
|
|
1052
1055
|
border-color: var(--g-color-line-generic);
|
|
@@ -1054,6 +1057,16 @@ body :has(.g-md-resizable_resizing) {
|
|
|
1054
1057
|
.ProseMirror.yfm .yfm-cut.yfm-cut-active {
|
|
1055
1058
|
border-color: var(--g-color-line-generic);
|
|
1056
1059
|
}
|
|
1060
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title:focus {
|
|
1061
|
+
outline: 0;
|
|
1062
|
+
}
|
|
1063
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title {
|
|
1064
|
+
list-style: none;
|
|
1065
|
+
}
|
|
1066
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title::-webkit-details-marker,
|
|
1067
|
+
.ProseMirror.yfm .yfm-cut .yfm-cut-title::marker {
|
|
1068
|
+
display: none;
|
|
1069
|
+
}
|
|
1057
1070
|
.yfm-editor .yfm-file {
|
|
1058
1071
|
pointer-events: none;
|
|
1059
1072
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/markdown-editor",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.24.0",
|
|
4
4
|
"description": "Markdown wysiwyg and markup editor",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
"@diplodoc/html-extension": "2.3.2",
|
|
205
205
|
"@diplodoc/latex-extension": "1.0.3",
|
|
206
206
|
"@diplodoc/mermaid-extension": "1.2.1",
|
|
207
|
-
"@diplodoc/transform": "4.
|
|
207
|
+
"@diplodoc/transform": "4.26.0",
|
|
208
208
|
"@gravity-ui/components": "3.0.0",
|
|
209
209
|
"@gravity-ui/eslint-config": "3.1.1",
|
|
210
210
|
"@gravity-ui/prettier-config": "1.1.0",
|
|
@@ -279,7 +279,7 @@
|
|
|
279
279
|
"@diplodoc/html-extension": "2.3.2",
|
|
280
280
|
"@diplodoc/latex-extension": "^1.0.3",
|
|
281
281
|
"@diplodoc/mermaid-extension": "^1.0.0",
|
|
282
|
-
"@diplodoc/transform": ">=4.5.0
|
|
282
|
+
"@diplodoc/transform": ">=4.5.0 <=4.26.0",
|
|
283
283
|
"@gravity-ui/components": "^3.0.0",
|
|
284
284
|
"@gravity-ui/uikit": "^6.11.0",
|
|
285
285
|
"highlight.js": "^11.8.0",
|