@gravity-ui/markdown-editor 13.21.4 → 13.23.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 (30) hide show
  1. package/README.md +7 -7
  2. package/build/cjs/bundle/MarkdownEditorView.d.ts +1 -2
  3. package/build/cjs/bundle/MarkdownEditorView.js +22 -12
  4. package/build/cjs/bundle/config/index.d.ts +1 -0
  5. package/build/cjs/bundle/config/index.js +1 -0
  6. package/build/cjs/extensions/markdown/Lists/ListsSpecs/const.d.ts +11 -2
  7. package/build/cjs/extensions/markdown/Lists/ListsSpecs/const.js +12 -3
  8. package/build/cjs/extensions/markdown/Lists/ListsSpecs/parser.js +2 -0
  9. package/build/cjs/extensions/markdown/Lists/ListsSpecs/schema.js +14 -3
  10. package/build/cjs/extensions/markdown/Lists/ListsSpecs/serializer.js +16 -3
  11. package/build/cjs/extensions/yfm/YfmHtmlBlock/YfmHtmlBlockSpecs/index.d.ts +1 -1
  12. package/build/cjs/extensions/yfm/YfmHtmlBlock/index.d.ts +1 -1
  13. package/build/cjs/i18n/menubar/index.d.ts +1 -1
  14. package/build/cjs/version.js +1 -1
  15. package/build/cjs/view/hocs/withYfmHtml/types.d.ts +1 -1
  16. package/build/esm/bundle/MarkdownEditorView.d.ts +1 -2
  17. package/build/esm/bundle/MarkdownEditorView.js +17 -7
  18. package/build/esm/bundle/config/index.d.ts +1 -0
  19. package/build/esm/bundle/config/index.js +1 -0
  20. package/build/esm/extensions/markdown/Lists/ListsSpecs/const.d.ts +11 -2
  21. package/build/esm/extensions/markdown/Lists/ListsSpecs/const.js +11 -2
  22. package/build/esm/extensions/markdown/Lists/ListsSpecs/parser.js +2 -0
  23. package/build/esm/extensions/markdown/Lists/ListsSpecs/schema.js +15 -4
  24. package/build/esm/extensions/markdown/Lists/ListsSpecs/serializer.js +17 -4
  25. package/build/esm/extensions/yfm/YfmHtmlBlock/YfmHtmlBlockSpecs/index.d.ts +1 -1
  26. package/build/esm/extensions/yfm/YfmHtmlBlock/index.d.ts +1 -1
  27. package/build/esm/i18n/menubar/index.d.ts +1 -1
  28. package/build/esm/version.js +1 -1
  29. package/build/esm/view/hocs/withYfmHtml/types.d.ts +1 -1
  30. package/package.json +3 -3
package/README.md CHANGED
@@ -52,13 +52,13 @@ function Editor({onSubmit}) {
52
52
  }
53
53
  ```
54
54
  Read more:
55
- - [How to connect the editor in the Create React App](docs/how-to-add-editor-with-create-react-app.md)
56
- - [How to add preview for markup mode](docs/how-to-add-preview.md)
57
- - [How to add HTML extension](docs/how-to-connect-html-extension.md)
58
- - [How to add Latex extension](docs/how-to-connect-latex-extension.md)
59
- - [How to add Mermaid extension](docs/how-to-connect-mermaid-extension.md)
60
- - [How to write extension](docs/how-to-create-extension.md)
61
- - [How to add GPT extension](docs/how-to-connect-gpt-extensions.md)
55
+ - [How to connect the editor in the Create React App](https://github.com/gravity-ui/markdown-editor/blob/main/docs/how-to-add-editor-with-create-react-app.md)
56
+ - [How to add preview for markup mode](https://github.com/gravity-ui/markdown-editor/blob/main/docs/how-to-add-preview.md)
57
+ - [How to add HTML extension](https://github.com/gravity-ui/markdown-editor/blob/main/docs/how-to-connect-html-extension.md)
58
+ - [How to add Latex extension](https://github.com/gravity-ui/markdown-editor/blob/main/docs/how-to-connect-latex-extension.md)
59
+ - [How to add Mermaid extension](https://github.com/gravity-ui/markdown-editor/blob/main/docs/how-to-connect-mermaid-extension.md)
60
+ - [How to write extension](https://github.com/gravity-ui/markdown-editor/blob/main/docs/how-to-create-extension.md)
61
+ - [How to add GPT extension](https://github.com/gravity-ui/markdown-editor/blob/main/docs/how-to-connect-gpt-extensions.md)
62
62
 
63
63
 
64
64
  ### i18n
@@ -2,8 +2,7 @@ import React from 'react';
2
2
  import type { ToasterPublicMethods } from '@gravity-ui/uikit';
3
3
  import { ClassNameProps } from '../classname';
4
4
  import type { Editor } from './Editor';
5
- import { MToolbarData, MToolbarItemData } from './config/markup';
6
- import { WToolbarData, WToolbarItemData } from './config/wysiwyg';
5
+ import { MToolbarData, MToolbarItemData, WToolbarData, WToolbarItemData } from './config';
7
6
  export declare const cnEditorComponent: import("@bem-react/classname").ClassNameFormatter;
8
7
  export declare type MarkdownEditorViewProps = ClassNameProps & {
9
8
  editor?: Editor;
@@ -8,16 +8,13 @@ const react_use_1 = require("react-use");
8
8
  const classname_1 = require("../classname");
9
9
  const bundle_1 = require("../i18n/bundle");
10
10
  const logger_1 = require("../logger");
11
- const hooks_1 = require("../react-utils/hooks");
12
- const toaster_1 = require("../react-utils/toaster");
13
- const useSticky_1 = require("../react-utils/useSticky");
14
- const platform_1 = require("../utils/platform");
11
+ const react_utils_1 = require("../react-utils");
12
+ const utils_1 = require("../utils");
15
13
  const HorizontalDrag_1 = require("./HorizontalDrag");
16
14
  const MarkupEditorView_1 = require("./MarkupEditorView");
17
15
  const SplitModeView_1 = require("./SplitModeView");
18
16
  const WysiwygEditorView_1 = require("./WysiwygEditorView");
19
- const markup_1 = require("./config/markup");
20
- const wysiwyg_1 = require("./config/wysiwyg");
17
+ const config_1 = require("./config");
21
18
  const context_1 = require("./context");
22
19
  const settings_1 = require("./settings");
23
20
  const sticky_1 = require("./sticky");
@@ -31,12 +28,12 @@ exports.MarkdownEditorView = react_1.default.forwardRef((props, ref) => {
31
28
  (0, react_1.useEffect)(() => {
32
29
  setIsMounted(true);
33
30
  }, []);
34
- const [showPreview, , unsetShowPreview, toggleShowPreview] = (0, hooks_1.useBooleanState)(false);
31
+ const [showPreview, , unsetShowPreview, toggleShowPreview] = (0, react_utils_1.useBooleanState)(false);
35
32
  const context = (0, context_1.useMarkdownEditorContext)();
36
33
  const editor = ((_a = props.editor) !== null && _a !== void 0 ? _a : context);
37
34
  if (!editor)
38
35
  throw new Error('[MarkdownEditorView]: an instance of the editor must be passed through the props or context');
39
- const { autofocus, className, settingsVisible = true, markupToolbarConfig = markup_1.mToolbarConfigByPreset[editor.preset], wysiwygToolbarConfig = wysiwyg_1.wToolbarConfigByPreset[editor.preset], markupHiddenActionsConfig = markup_1.mHiddenDataByPreset[editor.preset], wysiwygHiddenActionsConfig = wysiwyg_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, } = props;
40
37
  const rerender = (0, react_use_1.useUpdate)();
41
38
  react_1.default.useLayoutEffect(() => {
42
39
  editor.on('rerender', rerender);
@@ -66,6 +63,12 @@ exports.MarkdownEditorView = react_1.default.forwardRef((props, ref) => {
66
63
  (0, react_use_1.useKey)((e) => canRenderPreview && isPreviewKeyDown(e), () => onShowPreviewChange(!showPreview), { event: 'keydown' }, [showPreview, editorMode, onShowPreviewChange, canRenderPreview]);
67
64
  const editorWrapperRef = (0, react_1.useRef)(null);
68
65
  const splitModeViewWrapperRef = (0, react_1.useRef)(null);
66
+ (0, react_1.useEffect)(() => {
67
+ if (showPreview) {
68
+ divRef.current.focus();
69
+ }
70
+ }, [divRef, showPreview]);
71
+ (0, react_use_1.useKey)((e) => showPreview && isWrapperFocused(divRef) && isSubmitKeyDown(e), () => editor.emit('submit', null), { event: 'keydown' }, [showPreview]);
69
72
  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 })), [
70
73
  canRenderPreview,
71
74
  stickyToolbar,
@@ -98,11 +101,11 @@ exports.MarkdownEditorView = react_1.default.forwardRef((props, ref) => {
98
101
  });
99
102
  return null;
100
103
  } },
101
- react_1.default.createElement(toaster_1.ToasterContext.Provider, { value: toaster },
104
+ react_1.default.createElement(react_utils_1.ToasterContext.Provider, { value: toaster },
102
105
  react_1.default.createElement("div", { ref: divRef, className: b({
103
106
  settings: settingsVisible,
104
107
  split: markupSplitMode && editor.splitMode,
105
- }, [className]) },
108
+ }, [className]), role: "button", tabIndex: 0 },
106
109
  react_1.default.createElement("div", { className: b('editor-wrapper'), ref: editorWrapperRef }, showPreview ? (react_1.default.createElement(react_1.default.Fragment, null,
107
110
  react_1.default.createElement("div", { className: b('preview-wrapper') }, (_b = editor.renderPreview) === null || _b === void 0 ? void 0 : _b.call(editor, {
108
111
  getValue: editor.getValue,
@@ -120,7 +123,7 @@ exports.MarkdownEditorView.displayName = 'MarkdownEditorView';
120
123
  const MarkupSearchAnchor = ({ mode }) => (react_1.default.createElement(react_1.default.Fragment, null, mode === 'markup' && react_1.default.createElement("div", { className: "g-md-search-anchor" })));
121
124
  function Settings(props) {
122
125
  const wrapperRef = (0, react_1.useRef)(null);
123
- const isSticky = (0, useSticky_1.useSticky)(wrapperRef) && props.toolbarVisibility && props.stickyToolbar;
126
+ const isSticky = (0, react_utils_1.useSticky)(wrapperRef) && props.toolbarVisibility && props.stickyToolbar;
124
127
  return (react_1.default.createElement("div", { className: b('settings-wrapper') },
125
128
  react_1.default.createElement("div", { ref: wrapperRef, className: sticky_1.stickyCn.settings({
126
129
  withToolbar: props.toolbarVisibility,
@@ -130,6 +133,13 @@ function Settings(props) {
130
133
  react_1.default.createElement(MarkupSearchAnchor, Object.assign({}, props)))));
131
134
  }
132
135
  function isPreviewKeyDown(e) {
133
- const modKey = (0, platform_1.isMac)() ? e.metaKey : e.ctrlKey;
136
+ const modKey = (0, utils_1.isMac)() ? e.metaKey : e.ctrlKey;
134
137
  return modKey && e.shiftKey && e.code === 'KeyP';
135
138
  }
139
+ function isWrapperFocused(divRef) {
140
+ return document.activeElement === divRef.current;
141
+ }
142
+ function isSubmitKeyDown(e) {
143
+ const modKey = (0, utils_1.isMac)() ? e.metaKey : e.ctrlKey;
144
+ return modKey && e.code === 'Enter';
145
+ }
@@ -1 +1,2 @@
1
1
  export * from './wysiwyg';
2
+ export * from './markup';
@@ -2,3 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./wysiwyg"), exports);
5
+ tslib_1.__exportStar(require("./markup"), exports);
@@ -5,10 +5,19 @@ export declare enum ListNode {
5
5
  }
6
6
  export declare enum ListsAttr {
7
7
  Tight = "tight",
8
- /** used in bullet list only */
8
+ /** @deprecated Use `ListsAttr.Markup` instead */
9
9
  Bullet = "bullet",
10
10
  /** used in ordered list only */
11
11
  Order = "order",
12
- /** used in list item only */
13
12
  Markup = "markup"
14
13
  }
14
+ export declare const Markup: {
15
+ bullet: {
16
+ values: string[];
17
+ default: string;
18
+ };
19
+ ordered: {
20
+ values: string[];
21
+ default: string;
22
+ };
23
+ };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ListsAttr = exports.ListNode = void 0;
3
+ exports.Markup = exports.ListsAttr = exports.ListNode = void 0;
4
4
  var ListNode;
5
5
  (function (ListNode) {
6
6
  ListNode["ListItem"] = "list_item";
@@ -10,10 +10,19 @@ var ListNode;
10
10
  var ListsAttr;
11
11
  (function (ListsAttr) {
12
12
  ListsAttr["Tight"] = "tight";
13
- /** used in bullet list only */
13
+ /** @deprecated Use `ListsAttr.Markup` instead */
14
14
  ListsAttr["Bullet"] = "bullet";
15
15
  /** used in ordered list only */
16
16
  ListsAttr["Order"] = "order";
17
- /** used in list item only */
18
17
  ListsAttr["Markup"] = "markup";
19
18
  })(ListsAttr = exports.ListsAttr || (exports.ListsAttr = {}));
19
+ exports.Markup = {
20
+ bullet: {
21
+ values: ['-', '+', '*'],
22
+ default: '*',
23
+ },
24
+ ordered: {
25
+ values: ['.', ')'],
26
+ default: '.',
27
+ },
28
+ };
@@ -14,6 +14,7 @@ exports.parserTokens = {
14
14
  getAttrs: (token, tokens, i) => ({
15
15
  [const_1.ListsAttr.Tight]: listIsTight(tokens, i),
16
16
  [const_1.ListsAttr.Bullet]: token.markup,
17
+ [const_1.ListsAttr.Markup]: token.markup,
17
18
  }),
18
19
  },
19
20
  [const_1.ListNode.OrderedList]: {
@@ -22,6 +23,7 @@ exports.parserTokens = {
22
23
  getAttrs: (token, tokens, i) => ({
23
24
  [const_1.ListsAttr.Order]: Number(token.attrGet('start')) || 1,
24
25
  [const_1.ListsAttr.Tight]: listIsTight(tokens, i),
26
+ [const_1.ListsAttr.Markup]: token.markup,
25
27
  }),
26
28
  },
27
29
  };
@@ -4,7 +4,10 @@ exports.schemaSpecs = void 0;
4
4
  const const_1 = require("./const");
5
5
  exports.schemaSpecs = {
6
6
  [const_1.ListNode.ListItem]: {
7
- attrs: { [const_1.ListsAttr.Tight]: { default: false }, [const_1.ListsAttr.Markup]: { default: null } },
7
+ attrs: {
8
+ [const_1.ListsAttr.Tight]: { default: false },
9
+ [const_1.ListsAttr.Markup]: { default: null },
10
+ },
8
11
  content: '(paragraph|block)+',
9
12
  defining: true,
10
13
  parseDOM: [{ tag: 'li' }],
@@ -19,7 +22,11 @@ exports.schemaSpecs = {
19
22
  [const_1.ListNode.BulletList]: {
20
23
  content: `${const_1.ListNode.ListItem}+`,
21
24
  group: 'block',
22
- attrs: { [const_1.ListsAttr.Tight]: { default: false }, [const_1.ListsAttr.Bullet]: { default: '*' } },
25
+ attrs: {
26
+ [const_1.ListsAttr.Tight]: { default: false },
27
+ [const_1.ListsAttr.Bullet]: { default: const_1.Markup.bullet.default },
28
+ [const_1.ListsAttr.Markup]: { default: const_1.Markup.bullet.default },
29
+ },
23
30
  parseDOM: [
24
31
  {
25
32
  tag: 'ul',
@@ -36,7 +43,11 @@ exports.schemaSpecs = {
36
43
  complex: 'root',
37
44
  },
38
45
  [const_1.ListNode.OrderedList]: {
39
- attrs: { [const_1.ListsAttr.Order]: { default: 1 }, [const_1.ListsAttr.Tight]: { default: false } },
46
+ attrs: {
47
+ [const_1.ListsAttr.Order]: { default: 1 },
48
+ [const_1.ListsAttr.Tight]: { default: false },
49
+ [const_1.ListsAttr.Markup]: { default: const_1.Markup.ordered.default },
50
+ },
40
51
  content: `${const_1.ListNode.ListItem}+`,
41
52
  group: 'block',
42
53
  parseDOM: [
@@ -7,15 +7,28 @@ exports.serializerTokens = {
7
7
  state.renderContent(node);
8
8
  },
9
9
  [const_1.ListNode.BulletList]: (state, node) => {
10
- state.renderList(node, ' ', (_i, li) => (li.attrs[const_1.ListsAttr.Markup] || node.attrs[const_1.ListsAttr.Bullet] || '*') + ' ');
10
+ state.renderList(node, ' ', (_i, li) => {
11
+ const markup = getMarkup({ item: li, list: node, type: 'bullet' });
12
+ return markup + ' ';
13
+ });
11
14
  },
12
15
  [const_1.ListNode.OrderedList]: (state, node) => {
13
16
  const start = node.attrs[const_1.ListsAttr.Order] || 1;
14
17
  const maxW = String(start + node.childCount - 1).length;
15
18
  const space = state.repeat(' ', maxW + 2);
16
- state.renderList(node, space, (i) => {
19
+ state.renderList(node, space, (i, li) => {
17
20
  const nStr = String(start + i);
18
- return state.repeat(' ', maxW - nStr.length) + nStr + '. ';
21
+ const markup = getMarkup({ item: li, list: node, type: 'ordered' });
22
+ return state.repeat(' ', maxW - nStr.length) + nStr + markup + ' ';
19
23
  });
20
24
  },
21
25
  };
26
+ function getMarkup({ item, list, type, }) {
27
+ const defs = const_1.Markup[type];
28
+ let value = item.attrs[const_1.ListsAttr.Markup];
29
+ if (!defs.values.includes(value))
30
+ value = list.attrs[const_1.ListsAttr.Markup];
31
+ if (!defs.values.includes(value))
32
+ value = defs.default;
33
+ return value;
34
+ }
@@ -1,4 +1,4 @@
1
- import { PluginOptions } from '@diplodoc/html-extension/plugin/transform';
1
+ import { PluginOptions } from '@diplodoc/html-extension/plugin';
2
2
  import type { ExtensionNodeSpec } from '../../../../core';
3
3
  export { yfmHtmlBlockNodeName } from './const';
4
4
  export interface YfmHtmlBlockSpecsOptions extends Omit<PluginOptions, 'runtimeJsPath' | 'containerClasses' | 'bundle' | 'embeddingMode'> {
@@ -1,4 +1,4 @@
1
- import { PluginOptions } from '@diplodoc/html-extension/plugin/transform';
1
+ import { PluginOptions } from '@diplodoc/html-extension/plugin';
2
2
  import type { IHTMLIFrameElementConfig } from '@diplodoc/html-extension/runtime';
3
3
  import { Action, ExtensionAuto } from '../../../core';
4
4
  import { YfmHtmlBlockAction } from './YfmHtmlBlockSpecs/const';
@@ -1,4 +1,4 @@
1
- export declare const i18n: <G extends "bold" | "code" | "link" | "italic" | "strike" | "underline" | "mark" | "quote" | "colorify" | "mono" | "text" | "html" | "cut" | "table" | "image" | "code_inline" | "heading" | "note" | "file" | "codeblock" | "checkbox" | "emoji" | "list" | "tabs" | "math" | "heading1" | "heading2" | "heading3" | "heading4" | "heading5" | "heading6" | "gpt" | "undo" | "redo" | "math_inline" | "math_block" | "colorify__color_blue" | "colorify__color_default" | "colorify__color_gray" | "colorify__color_green" | "colorify__color_orange" | "colorify__color_red" | "colorify__color_violet" | "colorify__color_yellow" | "colorify__group_text" | "folding-heading" | "folding-heading_hint" | "hrule" | "list__action_lift" | "list__action_sink" | "list_action_disabled" | "mermaid" | "more_action" | "olist" | "ulist", S extends string>(key: G | (string extends S ? S : never), params?: {
1
+ export declare const i18n: <G extends "bold" | "code" | "link" | "italic" | "strike" | "underline" | "mark" | "quote" | "colorify" | "mono" | "text" | "html" | "cut" | "table" | "image" | "code_inline" | "list" | "heading" | "note" | "file" | "codeblock" | "checkbox" | "emoji" | "tabs" | "math" | "heading1" | "heading2" | "heading3" | "heading4" | "heading5" | "heading6" | "gpt" | "undo" | "redo" | "math_inline" | "math_block" | "colorify__color_blue" | "colorify__color_default" | "colorify__color_gray" | "colorify__color_green" | "colorify__color_orange" | "colorify__color_red" | "colorify__color_violet" | "colorify__color_yellow" | "colorify__group_text" | "folding-heading" | "folding-heading_hint" | "hrule" | "list__action_lift" | "list__action_sink" | "list_action_disabled" | "mermaid" | "more_action" | "olist" | "ulist", S extends string>(key: G | (string extends S ? S : never), params?: {
2
2
  [key: string]: any;
3
3
  } | undefined) => S extends G ? {
4
4
  bold: string;
@@ -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.21.4' !== 'undefined' ? '13.21.4' : 'unknown';
5
+ exports.VERSION = typeof '13.23.0' !== 'undefined' ? '13.23.0' : 'unknown';
@@ -1,3 +1,3 @@
1
- import type { PluginOptions } from '@diplodoc/html-extension/plugin/transform';
1
+ import type { PluginOptions } from '@diplodoc/html-extension/plugin';
2
2
  export type { TransformMeta } from '../../types';
3
3
  export declare type PluginRuntime = PluginOptions['runtimeJsPath'];
@@ -2,8 +2,7 @@ import React from 'react';
2
2
  import type { ToasterPublicMethods } from '@gravity-ui/uikit';
3
3
  import { ClassNameProps } from '../classname';
4
4
  import type { Editor } from './Editor';
5
- import { MToolbarData, MToolbarItemData } from './config/markup';
6
- import { WToolbarData, WToolbarItemData } from './config/wysiwyg';
5
+ import { MToolbarData, MToolbarItemData, WToolbarData, WToolbarItemData } from './config';
7
6
  import '../styles/styles.css';
8
7
  import './MarkdownEditorView.css';
9
8
  export declare const cnEditorComponent: import("@bem-react/classname").ClassNameFormatter;
@@ -4,16 +4,13 @@ import { useEnsuredForwardedRef, useKey, useUpdate } from 'react-use';
4
4
  import { cn } from '../classname';
5
5
  import { i18n } from '../i18n/bundle';
6
6
  import { logger } from '../logger';
7
- import { useBooleanState } from '../react-utils/hooks';
8
- import { ToasterContext } from '../react-utils/toaster';
9
- import { useSticky } from '../react-utils/useSticky';
10
- import { isMac } from '../utils/platform';
7
+ import { ToasterContext, useBooleanState, useSticky } from '../react-utils';
8
+ import { isMac } from '../utils';
11
9
  import { HorizontalDrag } from './HorizontalDrag';
12
10
  import { MarkupEditorView } from './MarkupEditorView';
13
11
  import { SplitModeView } from './SplitModeView';
14
12
  import { WysiwygEditorView } from './WysiwygEditorView';
15
- import { mHiddenDataByPreset, mToolbarConfigByPreset, } from './config/markup';
16
- import { wHiddenDataByPreset, wToolbarConfigByPreset, } from './config/wysiwyg';
13
+ import { mHiddenDataByPreset, mToolbarConfigByPreset, wHiddenDataByPreset, wToolbarConfigByPreset, } from './config';
17
14
  import { useMarkdownEditorContext } from './context';
18
15
  import { EditorSettings } from './settings';
19
16
  import { stickyCn } from './sticky';
@@ -63,6 +60,12 @@ export const MarkdownEditorView = React.forwardRef((props, ref) => {
63
60
  useKey((e) => canRenderPreview && isPreviewKeyDown(e), () => onShowPreviewChange(!showPreview), { event: 'keydown' }, [showPreview, editorMode, onShowPreviewChange, canRenderPreview]);
64
61
  const editorWrapperRef = useRef(null);
65
62
  const splitModeViewWrapperRef = useRef(null);
63
+ useEffect(() => {
64
+ if (showPreview) {
65
+ divRef.current.focus();
66
+ }
67
+ }, [divRef, showPreview]);
68
+ useKey((e) => showPreview && isWrapperFocused(divRef) && isSubmitKeyDown(e), () => editor.emit('submit', null), { event: 'keydown' }, [showPreview]);
66
69
  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 })), [
67
70
  canRenderPreview,
68
71
  stickyToolbar,
@@ -99,7 +102,7 @@ export const MarkdownEditorView = React.forwardRef((props, ref) => {
99
102
  React.createElement("div", { ref: divRef, className: b({
100
103
  settings: settingsVisible,
101
104
  split: markupSplitMode && editor.splitMode,
102
- }, [className]) },
105
+ }, [className]), role: "button", tabIndex: 0 },
103
106
  React.createElement("div", { className: b('editor-wrapper'), ref: editorWrapperRef }, showPreview ? (React.createElement(React.Fragment, null,
104
107
  React.createElement("div", { className: b('preview-wrapper') }, (_b = editor.renderPreview) === null || _b === void 0 ? void 0 : _b.call(editor, {
105
108
  getValue: editor.getValue,
@@ -130,3 +133,10 @@ function isPreviewKeyDown(e) {
130
133
  const modKey = isMac() ? e.metaKey : e.ctrlKey;
131
134
  return modKey && e.shiftKey && e.code === 'KeyP';
132
135
  }
136
+ function isWrapperFocused(divRef) {
137
+ return document.activeElement === divRef.current;
138
+ }
139
+ function isSubmitKeyDown(e) {
140
+ const modKey = isMac() ? e.metaKey : e.ctrlKey;
141
+ return modKey && e.code === 'Enter';
142
+ }
@@ -1 +1,2 @@
1
1
  export * from './wysiwyg';
2
+ export * from './markup';
@@ -1 +1,2 @@
1
1
  export * from './wysiwyg';
2
+ export * from './markup';
@@ -5,10 +5,19 @@ export declare enum ListNode {
5
5
  }
6
6
  export declare enum ListsAttr {
7
7
  Tight = "tight",
8
- /** used in bullet list only */
8
+ /** @deprecated Use `ListsAttr.Markup` instead */
9
9
  Bullet = "bullet",
10
10
  /** used in ordered list only */
11
11
  Order = "order",
12
- /** used in list item only */
13
12
  Markup = "markup"
14
13
  }
14
+ export declare const Markup: {
15
+ bullet: {
16
+ values: string[];
17
+ default: string;
18
+ };
19
+ ordered: {
20
+ values: string[];
21
+ default: string;
22
+ };
23
+ };
@@ -7,10 +7,19 @@ export var ListNode;
7
7
  export var ListsAttr;
8
8
  (function (ListsAttr) {
9
9
  ListsAttr["Tight"] = "tight";
10
- /** used in bullet list only */
10
+ /** @deprecated Use `ListsAttr.Markup` instead */
11
11
  ListsAttr["Bullet"] = "bullet";
12
12
  /** used in ordered list only */
13
13
  ListsAttr["Order"] = "order";
14
- /** used in list item only */
15
14
  ListsAttr["Markup"] = "markup";
16
15
  })(ListsAttr || (ListsAttr = {}));
16
+ export const Markup = {
17
+ bullet: {
18
+ values: ['-', '+', '*'],
19
+ default: '*',
20
+ },
21
+ ordered: {
22
+ values: ['.', ')'],
23
+ default: '.',
24
+ },
25
+ };
@@ -11,6 +11,7 @@ export const parserTokens = {
11
11
  getAttrs: (token, tokens, i) => ({
12
12
  [ListsAttr.Tight]: listIsTight(tokens, i),
13
13
  [ListsAttr.Bullet]: token.markup,
14
+ [ListsAttr.Markup]: token.markup,
14
15
  }),
15
16
  },
16
17
  [ListNode.OrderedList]: {
@@ -19,6 +20,7 @@ export const parserTokens = {
19
20
  getAttrs: (token, tokens, i) => ({
20
21
  [ListsAttr.Order]: Number(token.attrGet('start')) || 1,
21
22
  [ListsAttr.Tight]: listIsTight(tokens, i),
23
+ [ListsAttr.Markup]: token.markup,
22
24
  }),
23
25
  },
24
26
  };
@@ -1,7 +1,10 @@
1
- import { ListNode, ListsAttr } from './const';
1
+ import { ListNode, ListsAttr, Markup } from './const';
2
2
  export const schemaSpecs = {
3
3
  [ListNode.ListItem]: {
4
- attrs: { [ListsAttr.Tight]: { default: false }, [ListsAttr.Markup]: { default: null } },
4
+ attrs: {
5
+ [ListsAttr.Tight]: { default: false },
6
+ [ListsAttr.Markup]: { default: null },
7
+ },
5
8
  content: '(paragraph|block)+',
6
9
  defining: true,
7
10
  parseDOM: [{ tag: 'li' }],
@@ -16,7 +19,11 @@ export const schemaSpecs = {
16
19
  [ListNode.BulletList]: {
17
20
  content: `${ListNode.ListItem}+`,
18
21
  group: 'block',
19
- attrs: { [ListsAttr.Tight]: { default: false }, [ListsAttr.Bullet]: { default: '*' } },
22
+ attrs: {
23
+ [ListsAttr.Tight]: { default: false },
24
+ [ListsAttr.Bullet]: { default: Markup.bullet.default },
25
+ [ListsAttr.Markup]: { default: Markup.bullet.default },
26
+ },
20
27
  parseDOM: [
21
28
  {
22
29
  tag: 'ul',
@@ -33,7 +40,11 @@ export const schemaSpecs = {
33
40
  complex: 'root',
34
41
  },
35
42
  [ListNode.OrderedList]: {
36
- attrs: { [ListsAttr.Order]: { default: 1 }, [ListsAttr.Tight]: { default: false } },
43
+ attrs: {
44
+ [ListsAttr.Order]: { default: 1 },
45
+ [ListsAttr.Tight]: { default: false },
46
+ [ListsAttr.Markup]: { default: Markup.ordered.default },
47
+ },
37
48
  content: `${ListNode.ListItem}+`,
38
49
  group: 'block',
39
50
  parseDOM: [
@@ -1,18 +1,31 @@
1
- import { ListNode, ListsAttr } from './const';
1
+ import { ListNode, ListsAttr, Markup } from './const';
2
2
  export const serializerTokens = {
3
3
  [ListNode.ListItem]: (state, node) => {
4
4
  state.renderContent(node);
5
5
  },
6
6
  [ListNode.BulletList]: (state, node) => {
7
- state.renderList(node, ' ', (_i, li) => (li.attrs[ListsAttr.Markup] || node.attrs[ListsAttr.Bullet] || '*') + ' ');
7
+ state.renderList(node, ' ', (_i, li) => {
8
+ const markup = getMarkup({ item: li, list: node, type: 'bullet' });
9
+ return markup + ' ';
10
+ });
8
11
  },
9
12
  [ListNode.OrderedList]: (state, node) => {
10
13
  const start = node.attrs[ListsAttr.Order] || 1;
11
14
  const maxW = String(start + node.childCount - 1).length;
12
15
  const space = state.repeat(' ', maxW + 2);
13
- state.renderList(node, space, (i) => {
16
+ state.renderList(node, space, (i, li) => {
14
17
  const nStr = String(start + i);
15
- return state.repeat(' ', maxW - nStr.length) + nStr + '. ';
18
+ const markup = getMarkup({ item: li, list: node, type: 'ordered' });
19
+ return state.repeat(' ', maxW - nStr.length) + nStr + markup + ' ';
16
20
  });
17
21
  },
18
22
  };
23
+ function getMarkup({ item, list, type, }) {
24
+ const defs = Markup[type];
25
+ let value = item.attrs[ListsAttr.Markup];
26
+ if (!defs.values.includes(value))
27
+ value = list.attrs[ListsAttr.Markup];
28
+ if (!defs.values.includes(value))
29
+ value = defs.default;
30
+ return value;
31
+ }
@@ -1,4 +1,4 @@
1
- import { PluginOptions } from '@diplodoc/html-extension/plugin/transform';
1
+ import { PluginOptions } from '@diplodoc/html-extension/plugin';
2
2
  import type { ExtensionNodeSpec } from '../../../../core';
3
3
  export { yfmHtmlBlockNodeName } from './const';
4
4
  export interface YfmHtmlBlockSpecsOptions extends Omit<PluginOptions, 'runtimeJsPath' | 'containerClasses' | 'bundle' | 'embeddingMode'> {
@@ -1,4 +1,4 @@
1
- import { PluginOptions } from '@diplodoc/html-extension/plugin/transform';
1
+ import { PluginOptions } from '@diplodoc/html-extension/plugin';
2
2
  import type { IHTMLIFrameElementConfig } from '@diplodoc/html-extension/runtime';
3
3
  import { Action, ExtensionAuto } from '../../../core';
4
4
  import { YfmHtmlBlockAction } from './YfmHtmlBlockSpecs/const';
@@ -1,4 +1,4 @@
1
- export declare const i18n: <G extends "bold" | "code" | "link" | "italic" | "strike" | "underline" | "mark" | "quote" | "colorify" | "mono" | "text" | "html" | "cut" | "table" | "image" | "code_inline" | "heading" | "note" | "file" | "codeblock" | "checkbox" | "emoji" | "list" | "tabs" | "math" | "heading1" | "heading2" | "heading3" | "heading4" | "heading5" | "heading6" | "gpt" | "undo" | "redo" | "math_inline" | "math_block" | "colorify__color_blue" | "colorify__color_default" | "colorify__color_gray" | "colorify__color_green" | "colorify__color_orange" | "colorify__color_red" | "colorify__color_violet" | "colorify__color_yellow" | "colorify__group_text" | "folding-heading" | "folding-heading_hint" | "hrule" | "list__action_lift" | "list__action_sink" | "list_action_disabled" | "mermaid" | "more_action" | "olist" | "ulist", S extends string>(key: G | (string extends S ? S : never), params?: {
1
+ export declare const i18n: <G extends "bold" | "code" | "link" | "italic" | "strike" | "underline" | "mark" | "quote" | "colorify" | "mono" | "text" | "html" | "cut" | "table" | "image" | "code_inline" | "list" | "heading" | "note" | "file" | "codeblock" | "checkbox" | "emoji" | "tabs" | "math" | "heading1" | "heading2" | "heading3" | "heading4" | "heading5" | "heading6" | "gpt" | "undo" | "redo" | "math_inline" | "math_block" | "colorify__color_blue" | "colorify__color_default" | "colorify__color_gray" | "colorify__color_green" | "colorify__color_orange" | "colorify__color_red" | "colorify__color_violet" | "colorify__color_yellow" | "colorify__group_text" | "folding-heading" | "folding-heading_hint" | "hrule" | "list__action_lift" | "list__action_sink" | "list_action_disabled" | "mermaid" | "more_action" | "olist" | "ulist", S extends string>(key: G | (string extends S ? S : never), params?: {
2
2
  [key: string]: any;
3
3
  } | undefined) => S extends G ? {
4
4
  bold: string;
@@ -1,2 +1,2 @@
1
1
  /** During build process, the current version will be injected here */
2
- export const VERSION = typeof '13.21.4' !== 'undefined' ? '13.21.4' : 'unknown';
2
+ export const VERSION = typeof '13.23.0' !== 'undefined' ? '13.23.0' : 'unknown';
@@ -1,3 +1,3 @@
1
- import type { PluginOptions } from '@diplodoc/html-extension/plugin/transform';
1
+ import type { PluginOptions } from '@diplodoc/html-extension/plugin';
2
2
  export type { TransformMeta } from '../../types';
3
3
  export declare type PluginRuntime = PluginOptions['runtimeJsPath'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/markdown-editor",
3
- "version": "13.21.4",
3
+ "version": "13.23.0",
4
4
  "description": "Markdown wysiwyg and markup editor",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -201,7 +201,7 @@
201
201
  },
202
202
  "devDependencies": {
203
203
  "@diplodoc/folding-headings-extension": "0.1.0",
204
- "@diplodoc/html-extension": "2.1.0",
204
+ "@diplodoc/html-extension": "2.3.2",
205
205
  "@diplodoc/latex-extension": "1.0.3",
206
206
  "@diplodoc/mermaid-extension": "1.2.1",
207
207
  "@diplodoc/transform": "4.22.0",
@@ -276,7 +276,7 @@
276
276
  },
277
277
  "peerDependencies": {
278
278
  "@diplodoc/folding-headings-extension": "^0.1.0",
279
- "@diplodoc/html-extension": "2.1.0",
279
+ "@diplodoc/html-extension": "2.3.2",
280
280
  "@diplodoc/latex-extension": "^1.0.3",
281
281
  "@diplodoc/mermaid-extension": "^1.0.0",
282
282
  "@diplodoc/transform": ">=4.5.0 <4.19.0",