@uiw/react-md-editor 4.1.0 → 4.1.2
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 +58 -35
- package/dist/mdeditor.css +1 -1
- package/dist/mdeditor.js +1758 -1869
- package/dist/mdeditor.min.js +1 -1
- package/dist/mdeditor.min.js.LICENSE.txt +1 -1
- package/esm/Editor.factory.js +66 -51
- package/esm/commands/list.js +3 -4
- package/esm/commands/title.js +5 -6
- package/esm/components/DragBar/index.js +3 -4
- package/esm/components/TextArea/Markdown.common.js +6 -8
- package/esm/components/TextArea/Markdown.js +6 -8
- package/esm/components/TextArea/Textarea.js +13 -17
- package/esm/components/TextArea/factory.js +12 -15
- package/esm/components/Toolbar/Child.js +8 -9
- package/esm/components/Toolbar/index.js +22 -28
- package/esm/utils/markdownUtils.js +39 -18
- package/lib/utils/markdownUtils.js +26 -1
- package/package.json +1 -1
- package/src/utils/markdownUtils.ts +37 -5
package/esm/Editor.factory.js
CHANGED
|
@@ -17,64 +17,79 @@ function setGroupPopFalse(data) {
|
|
|
17
17
|
return data;
|
|
18
18
|
}
|
|
19
19
|
export function createMDEditor(options) {
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
TextArea
|
|
23
|
-
} = options;
|
|
20
|
+
var MarkdownPreview = options.MarkdownPreview,
|
|
21
|
+
TextArea = options.TextArea;
|
|
24
22
|
var PreviewComponent = MarkdownPreview;
|
|
25
23
|
var TextAreaComponent = TextArea;
|
|
26
24
|
var InternalMDEditor = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
27
25
|
var _ref = props || {},
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
26
|
+
_ref$prefixCls = _ref.prefixCls,
|
|
27
|
+
prefixCls = _ref$prefixCls === void 0 ? 'w-md-editor' : _ref$prefixCls,
|
|
28
|
+
className = _ref.className,
|
|
29
|
+
propsValue = _ref.value,
|
|
30
|
+
_ref$commands = _ref.commands,
|
|
31
|
+
commands = _ref$commands === void 0 ? getCommands() : _ref$commands,
|
|
32
|
+
commandsFilter = _ref.commandsFilter,
|
|
33
|
+
direction = _ref.direction,
|
|
34
|
+
_ref$extraCommands = _ref.extraCommands,
|
|
35
|
+
extraCommands = _ref$extraCommands === void 0 ? getExtraCommands() : _ref$extraCommands,
|
|
36
|
+
_ref$height = _ref.height,
|
|
37
|
+
height = _ref$height === void 0 ? 200 : _ref$height,
|
|
38
|
+
_ref$enableScroll = _ref.enableScroll,
|
|
39
|
+
enableScroll = _ref$enableScroll === void 0 ? true : _ref$enableScroll,
|
|
40
|
+
_ref$visibleDragbar = _ref.visibleDragbar,
|
|
41
|
+
visibleDragbar = _ref$visibleDragbar === void 0 ? typeof props.visiableDragbar === 'boolean' ? props.visiableDragbar : true : _ref$visibleDragbar,
|
|
42
|
+
_ref$highlightEnable = _ref.highlightEnable,
|
|
43
|
+
highlightEnable = _ref$highlightEnable === void 0 ? true : _ref$highlightEnable,
|
|
44
|
+
_ref$preview = _ref.preview,
|
|
45
|
+
previewType = _ref$preview === void 0 ? 'live' : _ref$preview,
|
|
46
|
+
_ref$fullscreen = _ref.fullscreen,
|
|
47
|
+
fullscreen = _ref$fullscreen === void 0 ? false : _ref$fullscreen,
|
|
48
|
+
_ref$overflow = _ref.overflow,
|
|
49
|
+
overflow = _ref$overflow === void 0 ? true : _ref$overflow,
|
|
50
|
+
_ref$previewOptions = _ref.previewOptions,
|
|
51
|
+
previewOptions = _ref$previewOptions === void 0 ? {} : _ref$previewOptions,
|
|
52
|
+
textareaProps = _ref.textareaProps,
|
|
53
|
+
_ref$maxHeight = _ref.maxHeight,
|
|
54
|
+
maxHeight = _ref$maxHeight === void 0 ? 1200 : _ref$maxHeight,
|
|
55
|
+
_ref$minHeight = _ref.minHeight,
|
|
56
|
+
minHeight = _ref$minHeight === void 0 ? 100 : _ref$minHeight,
|
|
57
|
+
autoFocus = _ref.autoFocus,
|
|
58
|
+
_ref$autoFocusEnd = _ref.autoFocusEnd,
|
|
59
|
+
autoFocusEnd = _ref$autoFocusEnd === void 0 ? false : _ref$autoFocusEnd,
|
|
60
|
+
_ref$tabSize = _ref.tabSize,
|
|
61
|
+
tabSize = _ref$tabSize === void 0 ? 2 : _ref$tabSize,
|
|
62
|
+
_ref$defaultTabEnable = _ref.defaultTabEnable,
|
|
63
|
+
defaultTabEnable = _ref$defaultTabEnable === void 0 ? false : _ref$defaultTabEnable,
|
|
64
|
+
onChange = _ref.onChange,
|
|
65
|
+
onStatistics = _ref.onStatistics,
|
|
66
|
+
onHeightChange = _ref.onHeightChange,
|
|
67
|
+
hideToolbar = _ref.hideToolbar,
|
|
68
|
+
_ref$toolbarBottom = _ref.toolbarBottom,
|
|
69
|
+
toolbarBottom = _ref$toolbarBottom === void 0 ? false : _ref$toolbarBottom,
|
|
70
|
+
components = _ref.components,
|
|
71
|
+
renderTextarea = _ref.renderTextarea,
|
|
59
72
|
other = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
60
73
|
var cmds = commands.map(item => commandsFilter ? commandsFilter(item, false) : item).filter(Boolean);
|
|
61
74
|
var extraCmds = extraCommands.map(item => commandsFilter ? commandsFilter(item, true) : item).filter(Boolean);
|
|
62
|
-
var
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
var _useReducer = useReducer(reducer, {
|
|
76
|
+
markdown: propsValue,
|
|
77
|
+
preview: previewType,
|
|
78
|
+
components,
|
|
79
|
+
height,
|
|
80
|
+
minHeight,
|
|
81
|
+
highlightEnable,
|
|
82
|
+
tabSize,
|
|
83
|
+
defaultTabEnable,
|
|
84
|
+
scrollTop: 0,
|
|
85
|
+
scrollTopPreview: 0,
|
|
86
|
+
commands: cmds,
|
|
87
|
+
extraCommands: extraCmds,
|
|
88
|
+
fullscreen,
|
|
89
|
+
barPopup: {}
|
|
90
|
+
}),
|
|
91
|
+
state = _useReducer[0],
|
|
92
|
+
dispatch = _useReducer[1];
|
|
78
93
|
var container = useRef(null);
|
|
79
94
|
var previewRef = useRef(null);
|
|
80
95
|
var enableScrollRef = useRef(enableScroll);
|
package/esm/commands/list.js
CHANGED
|
@@ -12,10 +12,9 @@ export var makeList = (state, api, insertBefore) => {
|
|
|
12
12
|
var breaksBefore = Array(breaksBeforeCount + 1).join('\n');
|
|
13
13
|
var breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
14
14
|
var breaksAfter = Array(breaksAfterCount + 1).join('\n');
|
|
15
|
-
var
|
|
16
|
-
modifiedText,
|
|
17
|
-
insertionLength
|
|
18
|
-
} = insertBeforeEachLine(state1.selectedText, insertBefore);
|
|
15
|
+
var _insertBeforeEachLine = insertBeforeEachLine(state1.selectedText, insertBefore),
|
|
16
|
+
modifiedText = _insertBeforeEachLine.modifiedText,
|
|
17
|
+
insertionLength = _insertBeforeEachLine.insertionLength;
|
|
19
18
|
if (insertionLength < 0) {
|
|
20
19
|
// Remove
|
|
21
20
|
var selectionStart = state1.selection.start;
|
package/esm/commands/title.js
CHANGED
|
@@ -4,12 +4,11 @@ import { heading1 } from "./title1.js";
|
|
|
4
4
|
import { selectLine, executeCommand } from "../utils/markdownUtils.js";
|
|
5
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
6
|
export function headingExecute(_ref) {
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
suffix = prefix
|
|
12
|
-
} = _ref;
|
|
7
|
+
var state = _ref.state,
|
|
8
|
+
api = _ref.api,
|
|
9
|
+
prefix = _ref.prefix,
|
|
10
|
+
_ref$suffix = _ref.suffix,
|
|
11
|
+
suffix = _ref$suffix === void 0 ? prefix : _ref$suffix;
|
|
13
12
|
var newSelectionRange = selectLine({
|
|
14
13
|
text: state.text,
|
|
15
14
|
selection: state.selection
|
|
@@ -2,10 +2,9 @@ import React, { useEffect, useMemo, useRef } from 'react';
|
|
|
2
2
|
import "./index.css";
|
|
3
3
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
4
|
var DragBar = props => {
|
|
5
|
-
var {
|
|
6
|
-
prefixCls,
|
|
7
|
-
onChange
|
|
8
|
-
} = props || {};
|
|
5
|
+
var _ref = props || {},
|
|
6
|
+
prefixCls = _ref.prefixCls,
|
|
7
|
+
onChange = _ref.onChange;
|
|
9
8
|
var $dom = useRef(null);
|
|
10
9
|
var dragRef = useRef();
|
|
11
10
|
var heightRef = useRef(props.height);
|
|
@@ -14,14 +14,12 @@ function html2Escape(sHtml) {
|
|
|
14
14
|
})[c]);
|
|
15
15
|
}
|
|
16
16
|
export default function Markdown(props) {
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
dispatch
|
|
24
|
-
} = useContext(EditorContext);
|
|
17
|
+
var prefixCls = props.prefixCls;
|
|
18
|
+
var _useContext = useContext(EditorContext),
|
|
19
|
+
_useContext$markdown = _useContext.markdown,
|
|
20
|
+
markdown = _useContext$markdown === void 0 ? '' : _useContext$markdown,
|
|
21
|
+
highlightEnable = _useContext.highlightEnable,
|
|
22
|
+
dispatch = _useContext.dispatch;
|
|
25
23
|
var preRef = /*#__PURE__*/React.createRef();
|
|
26
24
|
useEffect(() => {
|
|
27
25
|
if (preRef.current && dispatch) {
|
|
@@ -21,14 +21,12 @@ function html2Escape(sHtml) {
|
|
|
21
21
|
})[c]);
|
|
22
22
|
}
|
|
23
23
|
export default function Markdown(props) {
|
|
24
|
-
var
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
dispatch
|
|
31
|
-
} = useContext(EditorContext);
|
|
24
|
+
var prefixCls = props.prefixCls;
|
|
25
|
+
var _useContext = useContext(EditorContext),
|
|
26
|
+
_useContext$markdown = _useContext.markdown,
|
|
27
|
+
markdown = _useContext$markdown === void 0 ? '' : _useContext$markdown,
|
|
28
|
+
highlightEnable = _useContext.highlightEnable,
|
|
29
|
+
dispatch = _useContext.dispatch;
|
|
32
30
|
var preRef = /*#__PURE__*/React.createRef();
|
|
33
31
|
useEffect(() => {
|
|
34
32
|
if (preRef.current && dispatch) {
|
|
@@ -10,25 +10,21 @@ import shortcuts from "./shortcuts.js";
|
|
|
10
10
|
import "./index.css";
|
|
11
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
12
|
export default function Textarea(props) {
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
onChange: _onChange
|
|
16
|
-
} = props,
|
|
13
|
+
var prefixCls = props.prefixCls,
|
|
14
|
+
_onChange = props.onChange,
|
|
17
15
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
18
16
|
var _useContext = useContext(EditorContext),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
dispatch
|
|
31
|
-
} = _useContext,
|
|
17
|
+
markdown = _useContext.markdown,
|
|
18
|
+
commands = _useContext.commands,
|
|
19
|
+
fullscreen = _useContext.fullscreen,
|
|
20
|
+
preview = _useContext.preview,
|
|
21
|
+
highlightEnable = _useContext.highlightEnable,
|
|
22
|
+
extraCommands = _useContext.extraCommands,
|
|
23
|
+
tabSize = _useContext.tabSize,
|
|
24
|
+
defaultTabEnable = _useContext.defaultTabEnable,
|
|
25
|
+
autoFocusEnd = _useContext.autoFocusEnd,
|
|
26
|
+
textareaWarp = _useContext.textareaWarp,
|
|
27
|
+
dispatch = _useContext.dispatch,
|
|
32
28
|
otherStore = _objectWithoutPropertiesLoose(_useContext, _excluded2);
|
|
33
29
|
var textRef = React.useRef(null);
|
|
34
30
|
var executeRef = React.useRef();
|
|
@@ -14,22 +14,19 @@ export function createTextArea(options) {
|
|
|
14
14
|
var useMinHeight = (_options$useMinHeight = options == null ? void 0 : options.useMinHeight) != null ? _options$useMinHeight : false;
|
|
15
15
|
return function TextArea(props) {
|
|
16
16
|
var _ref = props || {},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
renderTextarea
|
|
22
|
-
} = _ref,
|
|
17
|
+
prefixCls = _ref.prefixCls,
|
|
18
|
+
className = _ref.className,
|
|
19
|
+
onScroll = _ref.onScroll,
|
|
20
|
+
renderTextarea = _ref.renderTextarea,
|
|
23
21
|
otherProps = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
24
|
-
var
|
|
25
|
-
markdown,
|
|
26
|
-
scrollTop,
|
|
27
|
-
commands,
|
|
28
|
-
minHeight,
|
|
29
|
-
highlightEnable,
|
|
30
|
-
extraCommands,
|
|
31
|
-
dispatch
|
|
32
|
-
} = useContext(EditorContext);
|
|
22
|
+
var _useContext = useContext(EditorContext),
|
|
23
|
+
markdown = _useContext.markdown,
|
|
24
|
+
scrollTop = _useContext.scrollTop,
|
|
25
|
+
commands = _useContext.commands,
|
|
26
|
+
minHeight = _useContext.minHeight,
|
|
27
|
+
highlightEnable = _useContext.highlightEnable,
|
|
28
|
+
extraCommands = _useContext.extraCommands,
|
|
29
|
+
dispatch = _useContext.dispatch;
|
|
33
30
|
var textRef = React.useRef(null);
|
|
34
31
|
var executeRef = React.useRef();
|
|
35
32
|
var warp = /*#__PURE__*/React.createRef();
|
|
@@ -5,15 +5,14 @@ import Toolbar from "./index.js";
|
|
|
5
5
|
import { EditorContext } from "../../Context.js";
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
export default function Child(props) {
|
|
8
|
-
var {
|
|
9
|
-
prefixCls,
|
|
10
|
-
groupName,
|
|
11
|
-
commands,
|
|
12
|
-
children
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
barPopup = {}
|
|
16
|
-
} = useContext(EditorContext);
|
|
8
|
+
var _ref = props || {},
|
|
9
|
+
prefixCls = _ref.prefixCls,
|
|
10
|
+
groupName = _ref.groupName,
|
|
11
|
+
commands = _ref.commands,
|
|
12
|
+
children = _ref.children;
|
|
13
|
+
var _useContext = useContext(EditorContext),
|
|
14
|
+
_useContext$barPopup = _useContext.barPopup,
|
|
15
|
+
barPopup = _useContext$barPopup === void 0 ? {} : _useContext$barPopup;
|
|
17
16
|
return useMemo(() => /*#__PURE__*/_jsx("div", {
|
|
18
17
|
className: prefixCls + "-toolbar-child " + (groupName && barPopup[groupName] ? 'active' : ''),
|
|
19
18
|
onClick: e => e.stopPropagation(),
|
|
@@ -5,18 +5,16 @@ import Child from "./Child.js";
|
|
|
5
5
|
import "./index.css";
|
|
6
6
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
7
|
export function ToolbarItems(props) {
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
dispatch
|
|
19
|
-
} = useContext(EditorContext);
|
|
8
|
+
var prefixCls = props.prefixCls,
|
|
9
|
+
overflow = props.overflow;
|
|
10
|
+
var _useContext = useContext(EditorContext),
|
|
11
|
+
fullscreen = _useContext.fullscreen,
|
|
12
|
+
preview = _useContext.preview,
|
|
13
|
+
_useContext$barPopup = _useContext.barPopup,
|
|
14
|
+
barPopup = _useContext$barPopup === void 0 ? {} : _useContext$barPopup,
|
|
15
|
+
components = _useContext.components,
|
|
16
|
+
commandOrchestrator = _useContext.commandOrchestrator,
|
|
17
|
+
dispatch = _useContext.dispatch;
|
|
20
18
|
var originalOverflow = useRef('');
|
|
21
19
|
function handleClick(command, name) {
|
|
22
20
|
if (!dispatch) return;
|
|
@@ -110,15 +108,13 @@ export default function Toolbar(props) {
|
|
|
110
108
|
if (props === void 0) {
|
|
111
109
|
props = {};
|
|
112
110
|
}
|
|
113
|
-
var
|
|
114
|
-
prefixCls,
|
|
115
|
-
isChild,
|
|
116
|
-
className
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
extraCommands
|
|
121
|
-
} = useContext(EditorContext);
|
|
111
|
+
var _props = props,
|
|
112
|
+
prefixCls = _props.prefixCls,
|
|
113
|
+
isChild = _props.isChild,
|
|
114
|
+
className = _props.className;
|
|
115
|
+
var _useContext2 = useContext(EditorContext),
|
|
116
|
+
commands = _useContext2.commands,
|
|
117
|
+
extraCommands = _useContext2.extraCommands;
|
|
122
118
|
return /*#__PURE__*/_jsxs("div", {
|
|
123
119
|
className: prefixCls + "-toolbar " + className,
|
|
124
120
|
children: [/*#__PURE__*/_jsx(ToolbarItems, _extends({}, props, {
|
|
@@ -129,13 +125,11 @@ export default function Toolbar(props) {
|
|
|
129
125
|
});
|
|
130
126
|
}
|
|
131
127
|
export function ToolbarVisibility(props) {
|
|
132
|
-
var
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
prefixCls
|
|
138
|
-
} = props;
|
|
128
|
+
var hideToolbar = props.hideToolbar,
|
|
129
|
+
toolbarBottom = props.toolbarBottom,
|
|
130
|
+
placement = props.placement,
|
|
131
|
+
overflow = props.overflow,
|
|
132
|
+
prefixCls = props.prefixCls;
|
|
139
133
|
if (hideToolbar || placement === 'bottom' && !toolbarBottom || placement === 'top' && toolbarBottom) {
|
|
140
134
|
return null;
|
|
141
135
|
}
|
|
@@ -1,10 +1,31 @@
|
|
|
1
|
+
// `*` is a prefix of `**`, so `**text**` is bold-only and `***text***` is bold+italic.
|
|
2
|
+
function isItalicInsideBoldOnly(text, start, end) {
|
|
3
|
+
var insideBold = start >= 2 && end + 2 <= text.length && text.slice(start - 2, start) === '**' && text.slice(end, end + 2) === '**';
|
|
4
|
+
if (!insideBold) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
var insideBoldItalic = start >= 3 && end + 3 <= text.length && text.slice(start - 3, start) === '***' && text.slice(end, end + 3) === '***';
|
|
8
|
+
return !insideBoldItalic;
|
|
9
|
+
}
|
|
10
|
+
function isAlreadyWrapped(selectedText, prefix, suffix) {
|
|
11
|
+
if (selectedText.length < prefix.length + suffix.length || !selectedText.startsWith(prefix) || !selectedText.endsWith(suffix)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
if (prefix === '*' && suffix === '*') {
|
|
15
|
+
var isBold = selectedText.startsWith('**') && selectedText.endsWith('**');
|
|
16
|
+
var isBoldItalic = selectedText.startsWith('***') && selectedText.endsWith('***');
|
|
17
|
+
if (isBold && !isBoldItalic) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
1
23
|
export function selectWord(_ref) {
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
suffix = prefix
|
|
7
|
-
} = _ref;
|
|
24
|
+
var text = _ref.text,
|
|
25
|
+
selection = _ref.selection,
|
|
26
|
+
prefix = _ref.prefix,
|
|
27
|
+
_ref$suffix = _ref.suffix,
|
|
28
|
+
suffix = _ref$suffix === void 0 ? prefix : _ref$suffix;
|
|
8
29
|
var result = selection;
|
|
9
30
|
if (text && text.length && selection.start === selection.end) {
|
|
10
31
|
result = getSurroundingWord(text, selection.start);
|
|
@@ -12,6 +33,9 @@ export function selectWord(_ref) {
|
|
|
12
33
|
if (result.start >= prefix.length && result.end <= text.length - suffix.length) {
|
|
13
34
|
var selectedTextContext = text.slice(result.start - prefix.length, result.end + suffix.length);
|
|
14
35
|
if (selectedTextContext.startsWith(prefix) && selectedTextContext.endsWith(suffix)) {
|
|
36
|
+
if (prefix === '*' && suffix === '*' && isItalicInsideBoldOnly(text, result.start, result.end)) {
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
15
39
|
return {
|
|
16
40
|
start: result.start - prefix.length,
|
|
17
41
|
end: result.end + suffix.length
|
|
@@ -21,10 +45,8 @@ export function selectWord(_ref) {
|
|
|
21
45
|
return result;
|
|
22
46
|
}
|
|
23
47
|
export function selectLine(_ref2) {
|
|
24
|
-
var
|
|
25
|
-
|
|
26
|
-
selection
|
|
27
|
-
} = _ref2;
|
|
48
|
+
var text = _ref2.text,
|
|
49
|
+
selection = _ref2.selection;
|
|
28
50
|
var start = text.slice(0, selection.start).lastIndexOf('\n') + 1;
|
|
29
51
|
var end = text.slice(selection.end).indexOf('\n') + selection.end;
|
|
30
52
|
if (end === selection.end - 1) {
|
|
@@ -133,14 +155,13 @@ export function getSurroundingWord(text, position) {
|
|
|
133
155
|
};
|
|
134
156
|
}
|
|
135
157
|
export function executeCommand(_ref3) {
|
|
136
|
-
var
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
suffix = prefix
|
|
142
|
-
|
|
143
|
-
if (selectedText.length >= prefix.length + suffix.length && selectedText.startsWith(prefix) && selectedText.endsWith(suffix)) {
|
|
158
|
+
var api = _ref3.api,
|
|
159
|
+
selectedText = _ref3.selectedText,
|
|
160
|
+
selection = _ref3.selection,
|
|
161
|
+
prefix = _ref3.prefix,
|
|
162
|
+
_ref3$suffix = _ref3.suffix,
|
|
163
|
+
suffix = _ref3$suffix === void 0 ? prefix : _ref3$suffix;
|
|
164
|
+
if (isAlreadyWrapped(selectedText, prefix, suffix)) {
|
|
144
165
|
api.replaceSelection(selectedText.slice(prefix.length, suffix.length ? -suffix.length : undefined));
|
|
145
166
|
api.setSelectionRange({
|
|
146
167
|
start: selection.start - prefix.length,
|
|
@@ -10,6 +10,28 @@ exports.getSurroundingWord = getSurroundingWord;
|
|
|
10
10
|
exports.insertBeforeEachLine = insertBeforeEachLine;
|
|
11
11
|
exports.selectLine = selectLine;
|
|
12
12
|
exports.selectWord = selectWord;
|
|
13
|
+
// `*` is a prefix of `**`, so `**text**` is bold-only and `***text***` is bold+italic.
|
|
14
|
+
function isItalicInsideBoldOnly(text, start, end) {
|
|
15
|
+
var insideBold = start >= 2 && end + 2 <= text.length && text.slice(start - 2, start) === '**' && text.slice(end, end + 2) === '**';
|
|
16
|
+
if (!insideBold) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
var insideBoldItalic = start >= 3 && end + 3 <= text.length && text.slice(start - 3, start) === '***' && text.slice(end, end + 3) === '***';
|
|
20
|
+
return !insideBoldItalic;
|
|
21
|
+
}
|
|
22
|
+
function isAlreadyWrapped(selectedText, prefix, suffix) {
|
|
23
|
+
if (selectedText.length < prefix.length + suffix.length || !selectedText.startsWith(prefix) || !selectedText.endsWith(suffix)) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
if (prefix === '*' && suffix === '*') {
|
|
27
|
+
var isBold = selectedText.startsWith('**') && selectedText.endsWith('**');
|
|
28
|
+
var isBoldItalic = selectedText.startsWith('***') && selectedText.endsWith('***');
|
|
29
|
+
if (isBold && !isBoldItalic) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
13
35
|
function selectWord(_ref) {
|
|
14
36
|
var text = _ref.text,
|
|
15
37
|
selection = _ref.selection,
|
|
@@ -23,6 +45,9 @@ function selectWord(_ref) {
|
|
|
23
45
|
if (result.start >= prefix.length && result.end <= text.length - suffix.length) {
|
|
24
46
|
var selectedTextContext = text.slice(result.start - prefix.length, result.end + suffix.length);
|
|
25
47
|
if (selectedTextContext.startsWith(prefix) && selectedTextContext.endsWith(suffix)) {
|
|
48
|
+
if (prefix === '*' && suffix === '*' && isItalicInsideBoldOnly(text, result.start, result.end)) {
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
26
51
|
return {
|
|
27
52
|
start: result.start - prefix.length,
|
|
28
53
|
end: result.end + suffix.length
|
|
@@ -148,7 +173,7 @@ function executeCommand(_ref3) {
|
|
|
148
173
|
prefix = _ref3.prefix,
|
|
149
174
|
_ref3$suffix = _ref3.suffix,
|
|
150
175
|
suffix = _ref3$suffix === void 0 ? prefix : _ref3$suffix;
|
|
151
|
-
if (selectedText
|
|
176
|
+
if (isAlreadyWrapped(selectedText, prefix, suffix)) {
|
|
152
177
|
api.replaceSelection(selectedText.slice(prefix.length, suffix.length ? -suffix.length : undefined));
|
|
153
178
|
api.setSelectionRange({
|
|
154
179
|
start: selection.start - prefix.length,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uiw/react-md-editor",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.2",
|
|
4
4
|
"description": "A markdown editor with preview, implemented with React.js and TypeScript.",
|
|
5
5
|
"homepage": "https://uiwjs.github.io/react-md-editor/",
|
|
6
6
|
"funding": "https://jaywcjlove.github.io/#/sponsor",
|
|
@@ -5,6 +5,39 @@ export interface TextSection {
|
|
|
5
5
|
selection: TextRange;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
// `*` is a prefix of `**`, so `**text**` is bold-only and `***text***` is bold+italic.
|
|
9
|
+
function isItalicInsideBoldOnly(text: string, start: number, end: number): boolean {
|
|
10
|
+
const insideBold =
|
|
11
|
+
start >= 2 && end + 2 <= text.length && text.slice(start - 2, start) === '**' && text.slice(end, end + 2) === '**';
|
|
12
|
+
if (!insideBold) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const insideBoldItalic =
|
|
16
|
+
start >= 3 &&
|
|
17
|
+
end + 3 <= text.length &&
|
|
18
|
+
text.slice(start - 3, start) === '***' &&
|
|
19
|
+
text.slice(end, end + 3) === '***';
|
|
20
|
+
return !insideBoldItalic;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isAlreadyWrapped(selectedText: string, prefix: string, suffix: string): boolean {
|
|
24
|
+
if (
|
|
25
|
+
selectedText.length < prefix.length + suffix.length ||
|
|
26
|
+
!selectedText.startsWith(prefix) ||
|
|
27
|
+
!selectedText.endsWith(suffix)
|
|
28
|
+
) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if (prefix === '*' && suffix === '*') {
|
|
32
|
+
const isBold = selectedText.startsWith('**') && selectedText.endsWith('**');
|
|
33
|
+
const isBoldItalic = selectedText.startsWith('***') && selectedText.endsWith('***');
|
|
34
|
+
if (isBold && !isBoldItalic) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
|
|
8
41
|
export function selectWord({
|
|
9
42
|
text,
|
|
10
43
|
selection,
|
|
@@ -23,6 +56,9 @@ export function selectWord({
|
|
|
23
56
|
if (result.start >= prefix.length && result.end <= text.length - suffix.length) {
|
|
24
57
|
const selectedTextContext = text.slice(result.start - prefix.length, result.end + suffix.length);
|
|
25
58
|
if (selectedTextContext.startsWith(prefix) && selectedTextContext.endsWith(suffix)) {
|
|
59
|
+
if (prefix === '*' && suffix === '*' && isItalicInsideBoldOnly(text, result.start, result.end)) {
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
26
62
|
return { start: result.start - prefix.length, end: result.end + suffix.length };
|
|
27
63
|
}
|
|
28
64
|
}
|
|
@@ -139,11 +175,7 @@ export function executeCommand({
|
|
|
139
175
|
prefix: string;
|
|
140
176
|
suffix?: string;
|
|
141
177
|
}) {
|
|
142
|
-
if (
|
|
143
|
-
selectedText.length >= prefix.length + suffix.length &&
|
|
144
|
-
selectedText.startsWith(prefix) &&
|
|
145
|
-
selectedText.endsWith(suffix)
|
|
146
|
-
) {
|
|
178
|
+
if (isAlreadyWrapped(selectedText, prefix, suffix)) {
|
|
147
179
|
api.replaceSelection(selectedText.slice(prefix.length, suffix.length ? -suffix.length : undefined));
|
|
148
180
|
api.setSelectionRange({ start: selection.start - prefix.length, end: selection.end - prefix.length });
|
|
149
181
|
} else {
|