@gravity-ui/markdown-editor 13.1.2 → 13.2.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/README.md +2 -2
- package/build/cjs/extensions/behavior/SelectionContext/tooltip.d.ts +5 -3
- package/build/cjs/extensions/behavior/SelectionContext/tooltip.js +10 -1
- package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.d.ts +1 -0
- package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js +1 -0
- package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js +8 -2
- package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js +1 -0
- package/build/cjs/extensions/yfm/YfmHeading/commands.js +8 -6
- package/build/cjs/markup/codemirror/gravity.js +24 -0
- package/build/cjs/version.js +1 -1
- package/build/esm/extensions/behavior/SelectionContext/tooltip.d.ts +5 -3
- package/build/esm/extensions/behavior/SelectionContext/tooltip.js +11 -2
- package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.d.ts +1 -0
- package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js +1 -0
- package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js +8 -2
- package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js +1 -0
- package/build/esm/extensions/yfm/YfmHeading/commands.js +8 -6
- package/build/esm/markup/codemirror/gravity.js +24 -0
- package/build/esm/version.js +1 -1
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @gravity-ui/markdown-editor · [](https://www.npmjs.com/package/@gravity-ui/markdown-editor) [](https://github.com/gravity-ui/markdown-editor/actions/workflows/ci.yml?query=branch:main) [](https://github.com/gravity-ui/markdown-editor/actions/workflows/release.yml?query=branch:main) [](https://preview.gravity-ui.com/md-editor/)
|
|
2
2
|
|
|
3
|
-
## Markdown wysiwyg and markup editor
|
|
3
|
+
## Markdown wysiwyg and markup editor
|
|
4
4
|
|
|
5
5
|
MarkdownEditor is a powerful tool for working with Markdown, which combines WYSIWYG and Markup modes. This means that you can create and edit content in a convenient visual mode, as well as have full control over the markup.
|
|
6
6
|
|
|
@@ -69,5 +69,5 @@ Don't forget to call `configure()` from [UIKit](https://github.com/gravity-ui/ui
|
|
|
69
69
|
To start the dev storybook
|
|
70
70
|
|
|
71
71
|
```shell
|
|
72
|
-
npm
|
|
72
|
+
npm start
|
|
73
73
|
```
|
|
@@ -2,10 +2,12 @@ import { PopupProps } from '@gravity-ui/uikit';
|
|
|
2
2
|
import { EditorState } from 'prosemirror-state';
|
|
3
3
|
import { EditorView } from 'prosemirror-view';
|
|
4
4
|
import { ActionStorage } from '../../../core';
|
|
5
|
-
import { ToolbarGroupItemData } from '../../../toolbar';
|
|
6
|
-
export declare type ContextGroupItemData = ToolbarGroupItemData<ActionStorage> & {
|
|
5
|
+
import { ToolbarButtonPopupData, ToolbarGroupItemData, ToolbarSingleItemData } from '../../../toolbar';
|
|
6
|
+
export declare type ContextGroupItemData = (ToolbarGroupItemData<ActionStorage> & {
|
|
7
7
|
condition?: (state: EditorState) => void;
|
|
8
|
-
}
|
|
8
|
+
}) | ((ToolbarSingleItemData<ActionStorage> | ToolbarButtonPopupData<ActionStorage>) & {
|
|
9
|
+
condition?: 'enabled';
|
|
10
|
+
});
|
|
9
11
|
export declare type ContextGroupData = ContextGroupItemData[];
|
|
10
12
|
export declare type ContextConfig = ContextGroupData[];
|
|
11
13
|
export declare class TooltipView {
|
|
@@ -54,7 +54,16 @@ class TooltipView {
|
|
|
54
54
|
getFilteredConfig() {
|
|
55
55
|
return this.baseProps.show
|
|
56
56
|
? this.menuConfig
|
|
57
|
-
.map((groupData) => groupData.filter((
|
|
57
|
+
.map((groupData) => groupData.filter((item) => {
|
|
58
|
+
const { condition } = item;
|
|
59
|
+
if (condition === 'enabled') {
|
|
60
|
+
return item.isEnable(this.actions);
|
|
61
|
+
}
|
|
62
|
+
if ((0, lodash_1.isFunction)(condition)) {
|
|
63
|
+
return condition(this.view.state);
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}))
|
|
58
67
|
.filter((groupData) => Boolean(groupData.length))
|
|
59
68
|
: [];
|
|
60
69
|
}
|
|
@@ -16,6 +16,7 @@ const YfmHeadingSpecs = (builder, opts) => {
|
|
|
16
16
|
[const_1.YfmHeadingAttr.Id]: { default: '' },
|
|
17
17
|
[const_1.YfmHeadingAttr.Level]: { default: 1 },
|
|
18
18
|
[const_1.YfmHeadingAttr.DataLine]: { default: null },
|
|
19
|
+
[const_1.YfmHeadingAttr.Folding]: { default: false },
|
|
19
20
|
},
|
|
20
21
|
content: '(text | inline)*',
|
|
21
22
|
group: 'block',
|
|
@@ -32,11 +33,13 @@ const YfmHeadingSpecs = (builder, opts) => {
|
|
|
32
33
|
toDOM(node) {
|
|
33
34
|
const id = node.attrs[const_1.YfmHeadingAttr.Id];
|
|
34
35
|
const lineNumber = node.attrs[const_1.YfmHeadingAttr.DataLine];
|
|
36
|
+
const folding = node.attrs[const_1.YfmHeadingAttr.Folding];
|
|
35
37
|
return [
|
|
36
38
|
'h' + node.attrs[const_1.YfmHeadingAttr.Level],
|
|
37
39
|
{
|
|
38
40
|
id: id || null,
|
|
39
41
|
[const_1.YfmHeadingAttr.DataLine]: lineNumber,
|
|
42
|
+
[`data-${const_1.YfmHeadingAttr.Folding}`]: folding ? '' : null,
|
|
40
43
|
},
|
|
41
44
|
0,
|
|
42
45
|
// [
|
|
@@ -61,6 +64,7 @@ const YfmHeadingSpecs = (builder, opts) => {
|
|
|
61
64
|
name: const_1.headingNodeName,
|
|
62
65
|
type: 'block',
|
|
63
66
|
getAttrs: (token) => {
|
|
67
|
+
var _a;
|
|
64
68
|
if (token.type.endsWith('_close'))
|
|
65
69
|
return {};
|
|
66
70
|
const attrs = Object.fromEntries(token.attrs || []);
|
|
@@ -70,12 +74,14 @@ const YfmHeadingSpecs = (builder, opts) => {
|
|
|
70
74
|
// attrs[YfmHeadingAttr.Id] = slugify(tokens[index + 1].content);
|
|
71
75
|
// }
|
|
72
76
|
// attrs have id only if it explicitly specified manually
|
|
73
|
-
return Object.assign({ [const_1.YfmHeadingAttr.Level]: Number(token.tag.slice(1)) }, attrs);
|
|
77
|
+
return Object.assign({ [const_1.YfmHeadingAttr.Level]: Number(token.tag.slice(1)), [const_1.YfmHeadingAttr.Folding]: (_a = token.meta) === null || _a === void 0 ? void 0 : _a.folding }, attrs);
|
|
74
78
|
},
|
|
75
79
|
},
|
|
76
80
|
},
|
|
77
81
|
toMd: (state, node) => {
|
|
78
|
-
|
|
82
|
+
const folding = node.attrs[const_1.YfmHeadingAttr.Folding];
|
|
83
|
+
const level = node.attrs[const_1.YfmHeadingAttr.Level];
|
|
84
|
+
state.write(state.repeat('#', level) + (folding ? '+' : '') + ' ');
|
|
79
85
|
state.renderInline(node);
|
|
80
86
|
const anchor = node.attrs[const_1.YfmHeadingAttr.Id];
|
|
81
87
|
if (anchor /*&& anchor !== node.firstChild?.textContent*/) {
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "headingRule", { enumerable: true, get: function
|
|
|
10
10
|
const getNodeAttrs = (level) => (node) => ({
|
|
11
11
|
[const_1.YfmHeadingAttr.Level]: level,
|
|
12
12
|
[const_1.YfmHeadingAttr.Id]: node.getAttribute('id') || '',
|
|
13
|
+
[const_1.YfmHeadingAttr.Folding]: node.hasAttribute(`data-${const_1.YfmHeadingAttr.Folding}`),
|
|
13
14
|
});
|
|
14
15
|
exports.getNodeAttrs = getNodeAttrs;
|
|
15
16
|
// export const slugify = (str: string) =>
|
|
@@ -9,15 +9,17 @@ const const_1 = require("./const");
|
|
|
9
9
|
var commands_1 = require("../../markdown/Heading/commands");
|
|
10
10
|
Object.defineProperty(exports, "resetHeading", { enumerable: true, get: function () { return commands_1.resetHeading; } });
|
|
11
11
|
const toHeading = (level) => (state, dispatch, view) => {
|
|
12
|
+
const attrs = {};
|
|
12
13
|
const parentHeading = (0, prosemirror_utils_1.findParentNodeOfType)((0, utils_1.hType)(state.schema))(state.selection);
|
|
13
|
-
if (parentHeading
|
|
14
|
-
|
|
14
|
+
if (parentHeading) {
|
|
15
|
+
if (parentHeading.node.attrs[const_1.headingLevelAttr] === level) {
|
|
16
|
+
return (0, base_1.toParagraph)(state, dispatch, view);
|
|
17
|
+
}
|
|
18
|
+
Object.assign(attrs, parentHeading.node.attrs);
|
|
15
19
|
}
|
|
16
20
|
// const text = state.selection.$head.parent.textContent;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
[const_1.YfmHeadingAttr.Level]: level,
|
|
20
|
-
};
|
|
21
|
+
// attrs[YfmHeadingAttr.Id] = slugify(text);
|
|
22
|
+
attrs[const_1.YfmHeadingAttr.Level] = level;
|
|
21
23
|
return (0, prosemirror_commands_1.setBlockType)((0, utils_1.hType)(state.schema), attrs)(state, dispatch);
|
|
22
24
|
};
|
|
23
25
|
exports.toHeading = toHeading;
|
|
@@ -33,4 +33,28 @@ exports.gravityTheme = view_1.EditorView.baseTheme({
|
|
|
33
33
|
'&.cm-focused .cm-selectionBackground, &.cm-focused ::selection': {
|
|
34
34
|
background: 'var(--g-color-base-misc-medium)',
|
|
35
35
|
},
|
|
36
|
+
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
37
|
+
padding: '4px 0',
|
|
38
|
+
lineHeight: '24px',
|
|
39
|
+
color: 'var(--g-color-text-primary)',
|
|
40
|
+
fontFamily: 'var(--g-font-family-monospace)',
|
|
41
|
+
fontSize: 'var(--g-text-body-1-font-size)',
|
|
42
|
+
backgroundColor: 'var(--g-color-base-float)',
|
|
43
|
+
border: '1px solid var(--g-color-line-generic-solid)',
|
|
44
|
+
borderRadius: '4px',
|
|
45
|
+
'& > ul': {
|
|
46
|
+
'& > completion-section': {
|
|
47
|
+
color: 'var(--g-color-text-hint)',
|
|
48
|
+
fontWeight: 'var(--g-text-accent-font-weight)',
|
|
49
|
+
borderBottom: '1px solid var(--g-color-line-generic)',
|
|
50
|
+
},
|
|
51
|
+
'& > li:hover': {
|
|
52
|
+
backgroundColor: 'var(--g-color-base-simple-hover)',
|
|
53
|
+
},
|
|
54
|
+
'& > li[aria-selected]': {
|
|
55
|
+
backgroundColor: 'var(--g-color-base-selection)',
|
|
56
|
+
color: 'revert',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
36
60
|
});
|
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.2.0' !== 'undefined' ? '13.2.0' : 'unknown';
|
|
@@ -2,10 +2,12 @@ import { PopupProps } from '@gravity-ui/uikit';
|
|
|
2
2
|
import { EditorState } from 'prosemirror-state';
|
|
3
3
|
import { EditorView } from 'prosemirror-view';
|
|
4
4
|
import { ActionStorage } from '../../../core';
|
|
5
|
-
import { ToolbarGroupItemData } from '../../../toolbar';
|
|
6
|
-
export declare type ContextGroupItemData = ToolbarGroupItemData<ActionStorage> & {
|
|
5
|
+
import { ToolbarButtonPopupData, ToolbarGroupItemData, ToolbarSingleItemData } from '../../../toolbar';
|
|
6
|
+
export declare type ContextGroupItemData = (ToolbarGroupItemData<ActionStorage> & {
|
|
7
7
|
condition?: (state: EditorState) => void;
|
|
8
|
-
}
|
|
8
|
+
}) | ((ToolbarSingleItemData<ActionStorage> | ToolbarButtonPopupData<ActionStorage>) & {
|
|
9
|
+
condition?: 'enabled';
|
|
10
|
+
});
|
|
9
11
|
export declare type ContextGroupData = ContextGroupItemData[];
|
|
10
12
|
export declare type ContextConfig = ContextGroupData[];
|
|
11
13
|
export declare class TooltipView {
|
|
@@ -5,7 +5,7 @@ import { Popup } from '@gravity-ui/uikit';
|
|
|
5
5
|
import { isFunction } from '../../../lodash';
|
|
6
6
|
import { logger } from '../../../logger';
|
|
7
7
|
import { ErrorLoggerBoundary } from '../../../react-utils/ErrorBoundary';
|
|
8
|
-
import { Toolbar } from '../../../toolbar';
|
|
8
|
+
import { Toolbar, } from '../../../toolbar';
|
|
9
9
|
import { getReactRendererFromState } from '../ReactRenderer';
|
|
10
10
|
const SelectionTooltip = (_a) => {
|
|
11
11
|
var { show, poppupProps } = _a, toolbarProps = __rest(_a, ["show", "poppupProps"]);
|
|
@@ -51,7 +51,16 @@ export class TooltipView {
|
|
|
51
51
|
getFilteredConfig() {
|
|
52
52
|
return this.baseProps.show
|
|
53
53
|
? this.menuConfig
|
|
54
|
-
.map((groupData) => groupData.filter((
|
|
54
|
+
.map((groupData) => groupData.filter((item) => {
|
|
55
|
+
const { condition } = item;
|
|
56
|
+
if (condition === 'enabled') {
|
|
57
|
+
return item.isEnable(this.actions);
|
|
58
|
+
}
|
|
59
|
+
if (isFunction(condition)) {
|
|
60
|
+
return condition(this.view.state);
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}))
|
|
55
64
|
.filter((groupData) => Boolean(groupData.length))
|
|
56
65
|
: [];
|
|
57
66
|
}
|
|
@@ -12,6 +12,7 @@ export const YfmHeadingSpecs = (builder, opts) => {
|
|
|
12
12
|
[YfmHeadingAttr.Id]: { default: '' },
|
|
13
13
|
[YfmHeadingAttr.Level]: { default: 1 },
|
|
14
14
|
[YfmHeadingAttr.DataLine]: { default: null },
|
|
15
|
+
[YfmHeadingAttr.Folding]: { default: false },
|
|
15
16
|
},
|
|
16
17
|
content: '(text | inline)*',
|
|
17
18
|
group: 'block',
|
|
@@ -28,11 +29,13 @@ export const YfmHeadingSpecs = (builder, opts) => {
|
|
|
28
29
|
toDOM(node) {
|
|
29
30
|
const id = node.attrs[YfmHeadingAttr.Id];
|
|
30
31
|
const lineNumber = node.attrs[YfmHeadingAttr.DataLine];
|
|
32
|
+
const folding = node.attrs[YfmHeadingAttr.Folding];
|
|
31
33
|
return [
|
|
32
34
|
'h' + node.attrs[YfmHeadingAttr.Level],
|
|
33
35
|
{
|
|
34
36
|
id: id || null,
|
|
35
37
|
[YfmHeadingAttr.DataLine]: lineNumber,
|
|
38
|
+
[`data-${YfmHeadingAttr.Folding}`]: folding ? '' : null,
|
|
36
39
|
},
|
|
37
40
|
0,
|
|
38
41
|
// [
|
|
@@ -57,6 +60,7 @@ export const YfmHeadingSpecs = (builder, opts) => {
|
|
|
57
60
|
name: headingNodeName,
|
|
58
61
|
type: 'block',
|
|
59
62
|
getAttrs: (token) => {
|
|
63
|
+
var _a;
|
|
60
64
|
if (token.type.endsWith('_close'))
|
|
61
65
|
return {};
|
|
62
66
|
const attrs = Object.fromEntries(token.attrs || []);
|
|
@@ -66,12 +70,14 @@ export const YfmHeadingSpecs = (builder, opts) => {
|
|
|
66
70
|
// attrs[YfmHeadingAttr.Id] = slugify(tokens[index + 1].content);
|
|
67
71
|
// }
|
|
68
72
|
// attrs have id only if it explicitly specified manually
|
|
69
|
-
return Object.assign({ [YfmHeadingAttr.Level]: Number(token.tag.slice(1)) }, attrs);
|
|
73
|
+
return Object.assign({ [YfmHeadingAttr.Level]: Number(token.tag.slice(1)), [YfmHeadingAttr.Folding]: (_a = token.meta) === null || _a === void 0 ? void 0 : _a.folding }, attrs);
|
|
70
74
|
},
|
|
71
75
|
},
|
|
72
76
|
},
|
|
73
77
|
toMd: (state, node) => {
|
|
74
|
-
|
|
78
|
+
const folding = node.attrs[YfmHeadingAttr.Folding];
|
|
79
|
+
const level = node.attrs[YfmHeadingAttr.Level];
|
|
80
|
+
state.write(state.repeat('#', level) + (folding ? '+' : '') + ' ');
|
|
75
81
|
state.renderInline(node);
|
|
76
82
|
const anchor = node.attrs[YfmHeadingAttr.Id];
|
|
77
83
|
if (anchor /*&& anchor !== node.firstChild?.textContent*/) {
|
|
@@ -4,6 +4,7 @@ export { hType, hasParentHeading, headingRule } from '../../../markdown/Heading/
|
|
|
4
4
|
export const getNodeAttrs = (level) => (node) => ({
|
|
5
5
|
[YfmHeadingAttr.Level]: level,
|
|
6
6
|
[YfmHeadingAttr.Id]: node.getAttribute('id') || '',
|
|
7
|
+
[YfmHeadingAttr.Folding]: node.hasAttribute(`data-${YfmHeadingAttr.Folding}`),
|
|
7
8
|
});
|
|
8
9
|
// export const slugify = (str: string) =>
|
|
9
10
|
// // same config as in yfm-transform
|
|
@@ -5,14 +5,16 @@ import { hType } from './YfmHeadingSpecs/utils';
|
|
|
5
5
|
import { YfmHeadingAttr, headingLevelAttr } from './const';
|
|
6
6
|
export { resetHeading } from '../../markdown/Heading/commands';
|
|
7
7
|
export const toHeading = (level) => (state, dispatch, view) => {
|
|
8
|
+
const attrs = {};
|
|
8
9
|
const parentHeading = findParentNodeOfType(hType(state.schema))(state.selection);
|
|
9
|
-
if (parentHeading
|
|
10
|
-
|
|
10
|
+
if (parentHeading) {
|
|
11
|
+
if (parentHeading.node.attrs[headingLevelAttr] === level) {
|
|
12
|
+
return toParagraph(state, dispatch, view);
|
|
13
|
+
}
|
|
14
|
+
Object.assign(attrs, parentHeading.node.attrs);
|
|
11
15
|
}
|
|
12
16
|
// const text = state.selection.$head.parent.textContent;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
[YfmHeadingAttr.Level]: level,
|
|
16
|
-
};
|
|
17
|
+
// attrs[YfmHeadingAttr.Id] = slugify(text);
|
|
18
|
+
attrs[YfmHeadingAttr.Level] = level;
|
|
17
19
|
return setBlockType(hType(state.schema), attrs)(state, dispatch);
|
|
18
20
|
};
|
|
@@ -30,4 +30,28 @@ export const gravityTheme = EditorView.baseTheme({
|
|
|
30
30
|
'&.cm-focused .cm-selectionBackground, &.cm-focused ::selection': {
|
|
31
31
|
background: 'var(--g-color-base-misc-medium)',
|
|
32
32
|
},
|
|
33
|
+
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
34
|
+
padding: '4px 0',
|
|
35
|
+
lineHeight: '24px',
|
|
36
|
+
color: 'var(--g-color-text-primary)',
|
|
37
|
+
fontFamily: 'var(--g-font-family-monospace)',
|
|
38
|
+
fontSize: 'var(--g-text-body-1-font-size)',
|
|
39
|
+
backgroundColor: 'var(--g-color-base-float)',
|
|
40
|
+
border: '1px solid var(--g-color-line-generic-solid)',
|
|
41
|
+
borderRadius: '4px',
|
|
42
|
+
'& > ul': {
|
|
43
|
+
'& > completion-section': {
|
|
44
|
+
color: 'var(--g-color-text-hint)',
|
|
45
|
+
fontWeight: 'var(--g-text-accent-font-weight)',
|
|
46
|
+
borderBottom: '1px solid var(--g-color-line-generic)',
|
|
47
|
+
},
|
|
48
|
+
'& > li:hover': {
|
|
49
|
+
backgroundColor: 'var(--g-color-base-simple-hover)',
|
|
50
|
+
},
|
|
51
|
+
'& > li[aria-selected]': {
|
|
52
|
+
backgroundColor: 'var(--g-color-base-selection)',
|
|
53
|
+
color: 'revert',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
33
57
|
});
|
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.2.0' !== 'undefined' ? '13.2.0' : 'unknown';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/markdown-editor",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.2.0",
|
|
4
4
|
"description": "Markdown wysiwyg and markup editor",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
18
|
"start": "npm run storybook:start",
|
|
19
|
-
"dev": "npm run storybook:start",
|
|
20
19
|
"clean": "gulp clean",
|
|
21
20
|
"build": "gulp",
|
|
22
21
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|