@uiw/react-md-editor 3.20.4 → 3.20.6

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 (189) hide show
  1. package/README.md +5 -2
  2. package/dist/mdeditor.css +13 -0
  3. package/dist/mdeditor.js +9004 -934
  4. package/dist/mdeditor.min.css +1 -1
  5. package/dist/mdeditor.min.js +1 -1
  6. package/esm/Context.d.ts +3 -3
  7. package/esm/Context.js +1 -2
  8. package/esm/Editor.d.ts +1 -1
  9. package/esm/Editor.js +9 -2
  10. package/esm/commands/bold.js +8 -7
  11. package/esm/commands/code.js +2 -3
  12. package/esm/commands/comment.js +2 -2
  13. package/esm/commands/divider.js +1 -2
  14. package/esm/commands/fullscreen.js +2 -3
  15. package/esm/commands/group.d.ts +1 -1
  16. package/esm/commands/group.js +1 -2
  17. package/esm/commands/hr.js +3 -4
  18. package/esm/commands/image.js +12 -8
  19. package/esm/commands/index.d.ts +5 -2
  20. package/esm/commands/index.js +5 -3
  21. package/esm/commands/italic.js +11 -9
  22. package/esm/commands/link.js +9 -7
  23. package/esm/commands/list.d.ts +1 -1
  24. package/esm/commands/list.js +2 -3
  25. package/esm/commands/preview.js +2 -3
  26. package/esm/commands/quote.js +2 -3
  27. package/esm/commands/strikeThrough.js +11 -9
  28. package/esm/commands/title.js +1 -2
  29. package/esm/commands/title1.js +1 -2
  30. package/esm/commands/title2.js +2 -3
  31. package/esm/commands/title3.js +2 -3
  32. package/esm/commands/title4.js +2 -3
  33. package/esm/commands/title5.js +2 -3
  34. package/esm/commands/title6.js +2 -3
  35. package/esm/components/DragBar/index.js +1 -2
  36. package/esm/components/TextArea/Markdown.js +1 -2
  37. package/esm/components/TextArea/Textarea.js +1 -2
  38. package/esm/components/TextArea/handleKeyDown.d.ts +1 -0
  39. package/esm/components/TextArea/handleKeyDown.js +1 -2
  40. package/esm/components/TextArea/index.d.ts +2 -2
  41. package/esm/components/TextArea/index.js +1 -2
  42. package/esm/components/TextArea/shortcuts.d.ts +1 -0
  43. package/esm/components/TextArea/shortcuts.js +1 -2
  44. package/esm/components/Toolbar/Child.d.ts +2 -1
  45. package/esm/components/Toolbar/Child.js +1 -2
  46. package/esm/components/Toolbar/index.d.ts +1 -0
  47. package/esm/components/Toolbar/index.js +1 -2
  48. package/esm/index.js +1 -2
  49. package/esm/react-app-env.d.ts +1 -0
  50. package/esm/utils/InsertTextAtPosition.js +1 -2
  51. package/esm/utils/markdownUtils.js +1 -2
  52. package/lib/Context.d.ts +3 -3
  53. package/lib/Context.js +1 -2
  54. package/lib/Editor.d.ts +1 -1
  55. package/lib/Editor.js +13 -2
  56. package/lib/commands/bold.js +8 -7
  57. package/lib/commands/code.js +3 -4
  58. package/lib/commands/comment.js +3 -2
  59. package/lib/commands/divider.js +1 -2
  60. package/lib/commands/fullscreen.js +3 -4
  61. package/lib/commands/group.d.ts +1 -1
  62. package/lib/commands/group.js +1 -2
  63. package/lib/commands/hr.js +4 -5
  64. package/lib/commands/image.js +13 -9
  65. package/lib/commands/index.d.ts +5 -2
  66. package/lib/commands/index.js +5 -3
  67. package/lib/commands/italic.js +12 -10
  68. package/lib/commands/link.js +10 -8
  69. package/lib/commands/list.d.ts +1 -1
  70. package/lib/commands/list.js +3 -4
  71. package/lib/commands/preview.js +3 -4
  72. package/lib/commands/quote.js +3 -4
  73. package/lib/commands/strikeThrough.js +12 -10
  74. package/lib/commands/title.js +1 -2
  75. package/lib/commands/title1.js +1 -2
  76. package/lib/commands/title2.js +3 -4
  77. package/lib/commands/title3.js +3 -4
  78. package/lib/commands/title4.js +3 -4
  79. package/lib/commands/title5.js +3 -4
  80. package/lib/commands/title6.js +3 -4
  81. package/lib/components/DragBar/index.js +1 -2
  82. package/lib/components/TextArea/Markdown.js +1 -2
  83. package/lib/components/TextArea/Textarea.js +1 -2
  84. package/lib/components/TextArea/handleKeyDown.d.ts +1 -0
  85. package/lib/components/TextArea/handleKeyDown.js +1 -2
  86. package/lib/components/TextArea/index.d.ts +2 -2
  87. package/lib/components/TextArea/index.js +1 -2
  88. package/lib/components/TextArea/shortcuts.d.ts +1 -0
  89. package/lib/components/TextArea/shortcuts.js +1 -2
  90. package/lib/components/Toolbar/Child.d.ts +2 -1
  91. package/lib/components/Toolbar/Child.js +1 -2
  92. package/lib/components/Toolbar/index.d.ts +1 -0
  93. package/lib/components/Toolbar/index.js +1 -2
  94. package/lib/index.js +1 -2
  95. package/lib/react-app-env.d.ts +1 -0
  96. package/lib/utils/InsertTextAtPosition.js +1 -2
  97. package/lib/utils/markdownUtils.js +1 -2
  98. package/package.json +1 -1
  99. package/src/Editor.tsx +4 -0
  100. package/src/__test__/commands.test.tsx +4 -4
  101. package/src/commands/bold.tsx +9 -8
  102. package/src/commands/code.tsx +1 -1
  103. package/src/commands/comment.tsx +1 -0
  104. package/src/commands/divider.tsx +1 -0
  105. package/src/commands/fullscreen.tsx +1 -1
  106. package/src/commands/hr.tsx +4 -4
  107. package/src/commands/image.tsx +13 -10
  108. package/src/commands/index.ts +5 -2
  109. package/src/commands/italic.tsx +12 -11
  110. package/src/commands/link.tsx +9 -9
  111. package/src/commands/list.tsx +1 -1
  112. package/src/commands/preview.tsx +1 -1
  113. package/src/commands/quote.tsx +1 -1
  114. package/src/commands/strikeThrough.tsx +12 -11
  115. package/src/commands/title2.tsx +1 -1
  116. package/src/commands/title3.tsx +1 -1
  117. package/src/commands/title4.tsx +1 -1
  118. package/src/commands/title5.tsx +1 -1
  119. package/src/commands/title6.tsx +1 -1
  120. package/esm/Context.js.map +0 -19
  121. package/esm/Editor.js.map +0 -116
  122. package/esm/commands/bold.js.map +0 -36
  123. package/esm/commands/code.js.map +0 -47
  124. package/esm/commands/comment.js.map +0 -35
  125. package/esm/commands/divider.js.map +0 -14
  126. package/esm/commands/fullscreen.js.map +0 -28
  127. package/esm/commands/group.js.map +0 -26
  128. package/esm/commands/hr.js.map +0 -26
  129. package/esm/commands/image.js.map +0 -36
  130. package/esm/commands/index.js.map +0 -69
  131. package/esm/commands/italic.js.map +0 -36
  132. package/esm/commands/link.js.map +0 -36
  133. package/esm/commands/list.js.map +0 -61
  134. package/esm/commands/preview.js.map +0 -31
  135. package/esm/commands/quote.js.map +0 -44
  136. package/esm/commands/strikeThrough.js.map +0 -36
  137. package/esm/commands/title.js.map +0 -16
  138. package/esm/commands/title1.js.map +0 -33
  139. package/esm/commands/title2.js.map +0 -33
  140. package/esm/commands/title3.js.map +0 -33
  141. package/esm/commands/title4.js.map +0 -33
  142. package/esm/commands/title5.js.map +0 -33
  143. package/esm/commands/title6.js.map +0 -33
  144. package/esm/components/DragBar/index.js.map +0 -41
  145. package/esm/components/TextArea/Markdown.js.map +0 -47
  146. package/esm/components/TextArea/Textarea.js.map +0 -47
  147. package/esm/components/TextArea/handleKeyDown.js.map +0 -66
  148. package/esm/components/TextArea/index.js.map +0 -57
  149. package/esm/components/TextArea/shortcuts.js.map +0 -52
  150. package/esm/components/Toolbar/Child.js.map +0 -28
  151. package/esm/components/Toolbar/index.js.map +0 -84
  152. package/esm/index.js.map +0 -15
  153. package/esm/utils/InsertTextAtPosition.js.map +0 -67
  154. package/esm/utils/markdownUtils.js.map +0 -31
  155. package/lib/Context.js.map +0 -19
  156. package/lib/Editor.js.map +0 -112
  157. package/lib/commands/bold.js.map +0 -35
  158. package/lib/commands/code.js.map +0 -46
  159. package/lib/commands/comment.js.map +0 -35
  160. package/lib/commands/divider.js.map +0 -14
  161. package/lib/commands/fullscreen.js.map +0 -27
  162. package/lib/commands/group.js.map +0 -25
  163. package/lib/commands/hr.js.map +0 -25
  164. package/lib/commands/image.js.map +0 -35
  165. package/lib/commands/index.js.map +0 -64
  166. package/lib/commands/italic.js.map +0 -35
  167. package/lib/commands/link.js.map +0 -35
  168. package/lib/commands/list.js.map +0 -60
  169. package/lib/commands/preview.js.map +0 -30
  170. package/lib/commands/quote.js.map +0 -43
  171. package/lib/commands/strikeThrough.js.map +0 -35
  172. package/lib/commands/title.js.map +0 -15
  173. package/lib/commands/title1.js.map +0 -32
  174. package/lib/commands/title2.js.map +0 -32
  175. package/lib/commands/title3.js.map +0 -32
  176. package/lib/commands/title4.js.map +0 -32
  177. package/lib/commands/title5.js.map +0 -32
  178. package/lib/commands/title6.js.map +0 -32
  179. package/lib/components/DragBar/index.js.map +0 -40
  180. package/lib/components/TextArea/Markdown.js.map +0 -47
  181. package/lib/components/TextArea/Textarea.js.map +0 -47
  182. package/lib/components/TextArea/handleKeyDown.js.map +0 -66
  183. package/lib/components/TextArea/index.js.map +0 -54
  184. package/lib/components/TextArea/shortcuts.js.map +0 -52
  185. package/lib/components/Toolbar/Child.js.map +0 -26
  186. package/lib/components/Toolbar/index.js.map +0 -82
  187. package/lib/index.js.map +0 -13
  188. package/lib/utils/InsertTextAtPosition.js.map +0 -67
  189. package/lib/utils/markdownUtils.js.map +0 -31
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard")["default"];
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.title6 = void 0;
8
- var React = _interopRequireWildcard(require("react"));
8
+ var _react = _interopRequireDefault(require("react"));
9
9
  var _InsertTextAtPosition = require("../utils/InsertTextAtPosition");
10
10
  var _jsxRuntime = require("react/jsx-runtime");
11
11
  var title6 = {
@@ -32,5 +32,4 @@ var title6 = {
32
32
  }
33
33
  }
34
34
  };
35
- exports.title6 = title6;
36
- //# sourceMappingURL=title6.js.map
35
+ exports.title6 = title6;
@@ -83,5 +83,4 @@ var DragBar = function DragBar(props) {
83
83
  };
84
84
  var _default = DragBar;
85
85
  exports["default"] = _default;
86
- module.exports = exports.default;
87
- //# sourceMappingURL=index.js.map
86
+ module.exports = exports.default;
@@ -71,5 +71,4 @@ function Markdown(props) {
71
71
  }
72
72
  });
73
73
  }
74
- module.exports = exports.default;
75
- //# sourceMappingURL=Markdown.js.map
74
+ module.exports = exports.default;
@@ -87,5 +87,4 @@ function Textarea(props) {
87
87
  }
88
88
  }));
89
89
  }
90
- module.exports = exports.default;
91
- //# sourceMappingURL=Textarea.js.map
90
+ module.exports = exports.default;
@@ -1 +1,2 @@
1
+ /// <reference types="react" />
1
2
  export default function handleKeyDown(e: KeyboardEvent | React.KeyboardEvent<HTMLTextAreaElement>, tabSize?: number, defaultTabEnable?: boolean): void;
@@ -83,5 +83,4 @@ function handleKeyDown(e) {
83
83
  return (0, _InsertTextAtPosition.insertTextAtPosition)(target, startStr);
84
84
  }
85
85
  }
86
- module.exports = exports.default;
87
- //# sourceMappingURL=handleKeyDown.js.map
86
+ module.exports = exports.default;
@@ -4,7 +4,7 @@ import { TextAreaProps } from './Textarea';
4
4
  import { IProps } from '../../Editor';
5
5
  import { TextAreaCommandOrchestrator, ICommand } from '../../commands';
6
6
  import './index.less';
7
- declare type RenderTextareaHandle = {
7
+ type RenderTextareaHandle = {
8
8
  dispatch: ContextStore['dispatch'];
9
9
  onChange?: TextAreaProps['onChange'];
10
10
  useContext?: {
@@ -19,7 +19,7 @@ export interface ITextAreaProps extends Omit<React.TextareaHTMLAttributes<HTMLTe
19
19
  onScroll?: (e: React.UIEvent<HTMLDivElement>) => void;
20
20
  renderTextarea?: (props: React.TextareaHTMLAttributes<HTMLTextAreaElement> | React.HTMLAttributes<HTMLDivElement>, opts: RenderTextareaHandle) => JSX.Element;
21
21
  }
22
- export declare type TextAreaRef = {
22
+ export type TextAreaRef = {
23
23
  text?: HTMLTextAreaElement;
24
24
  warp?: HTMLDivElement;
25
25
  };
@@ -99,5 +99,4 @@ function TextArea(props) {
99
99
  })
100
100
  });
101
101
  }
102
- module.exports = exports.default;
103
- //# sourceMappingURL=index.js.map
102
+ module.exports = exports.default;
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import { ICommand, TextAreaCommandOrchestrator } from '../../commands';
2
3
  import { ContextStore, ExecuteCommandState } from '../../Context';
3
4
  export default function shortcutsHandle(e: KeyboardEvent | React.KeyboardEvent<HTMLTextAreaElement>, commands?: ICommand[], commandOrchestrator?: TextAreaCommandOrchestrator, dispatch?: React.Dispatch<ContextStore>, state?: ExecuteCommandState): void;
@@ -66,5 +66,4 @@ function shortcutsHandle(e) {
66
66
  return;
67
67
  }
68
68
  }
69
- module.exports = exports.default;
70
- //# sourceMappingURL=shortcuts.js.map
69
+ module.exports = exports.default;
@@ -1,6 +1,7 @@
1
+ /// <reference types="react" />
1
2
  import './Child.less';
2
3
  import { IToolbarProps } from './';
3
- export declare type ChildProps = IToolbarProps & {
4
+ export type ChildProps = IToolbarProps & {
4
5
  children?: JSX.Element;
5
6
  groupName?: string;
6
7
  };
@@ -36,5 +36,4 @@ function Child(props) {
36
36
  // eslint-disable-next-line react-hooks/exhaustive-deps
37
37
  [commands, barPopup, groupName, prefixCls]);
38
38
  }
39
- module.exports = exports.default;
40
- //# sourceMappingURL=Child.js.map
39
+ module.exports = exports.default;
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import { IProps } from '../../Editor';
2
3
  import { ICommand } from '../../commands';
3
4
  import './index.less';
@@ -134,5 +134,4 @@ function Toolbar() {
134
134
  commands: extraCommands || []
135
135
  }))]
136
136
  });
137
- }
138
- //# sourceMappingURL=index.js.map
137
+ }
package/lib/index.js CHANGED
@@ -60,5 +60,4 @@ Object.keys(_Context).forEach(function (key) {
60
60
  });
61
61
  });
62
62
  var _default = _Editor["default"];
63
- exports["default"] = _default;
64
- //# sourceMappingURL=index.js.map
63
+ exports["default"] = _default;
@@ -0,0 +1 @@
1
+ /// <reference types="react-scripts" />
@@ -142,5 +142,4 @@ function insertTextAtPosition(input, text) {
142
142
  e.initEvent('input', true, false);
143
143
  input.dispatchEvent(e);
144
144
  }
145
- }
146
- //# sourceMappingURL=InsertTextAtPosition.js.map
145
+ }
@@ -112,5 +112,4 @@ function getSurroundingWord(text, position) {
112
112
  start: start,
113
113
  end: end
114
114
  };
115
- }
116
- //# sourceMappingURL=markdownUtils.js.map
115
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uiw/react-md-editor",
3
- "version": "3.20.4",
3
+ "version": "3.20.6",
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
  "author": "kenny wang <wowohoo@qq.com>",
package/src/Editor.tsx CHANGED
@@ -265,6 +265,10 @@ const InternalMDEditor = (
265
265
  () => height !== state.height && onHeightChange && onHeightChange(state.height, height, state),
266
266
  [height, onHeightChange, state],
267
267
  );
268
+ // eslint-disable-next-line react-hooks/exhaustive-deps
269
+ useMemo(() => commands !== state.commands && dispatch({ commands: cmds }), [props.commands]);
270
+ // eslint-disable-next-line react-hooks/exhaustive-deps
271
+ useMemo(() => extraCommands !== state.extraCommands && dispatch({ extraCommands: extraCmds }), [props.extraCommands]);
268
272
 
269
273
  const textareaDomRef = useRef<HTMLDivElement>();
270
274
  const active = useRef<'text' | 'preview'>('preview');
@@ -152,7 +152,7 @@ it('MDEditor commands HR', async () => {
152
152
  }),
153
153
  );
154
154
  const inputNode = screen.getByTitle('test');
155
- expect(inputNode).toHaveValue('\n\n----------\n\ntitle');
155
+ expect(inputNode).toHaveValue('\n\n-----------\n\ntitle');
156
156
  });
157
157
 
158
158
  it('MDEditor commands strikethrough text', async () => {
@@ -206,7 +206,7 @@ it('MDEditor commands link', async () => {
206
206
  }),
207
207
  );
208
208
  const inputNode = screen.getByTitle('test');
209
- expect(inputNode).toHaveValue('[title](url)');
209
+ expect(inputNode).toHaveValue('[title](URL Here)');
210
210
  });
211
211
 
212
212
  it('MDEditor commands image', async () => {
@@ -233,7 +233,7 @@ it('MDEditor commands image', async () => {
233
233
  }),
234
234
  );
235
235
  const inputNode = screen.getByTitle('test');
236
- expect(inputNode).toHaveValue('![](title)');
236
+ expect(inputNode).toHaveValue('![image](title)');
237
237
  });
238
238
 
239
239
  it("MDEditor commands image === ''", async () => {
@@ -260,7 +260,7 @@ it("MDEditor commands image === ''", async () => {
260
260
  }),
261
261
  );
262
262
  const inputNode = screen.getByTitle('test');
263
- expect(inputNode).toHaveValue('![](https://example.com/your-image.png)');
263
+ expect(inputNode).toHaveValue('![image](https://example.com/your-image.png)');
264
264
  });
265
265
 
266
266
  it('MDEditor commands Add unordered list', async () => {
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
- import { ICommand, TextState, TextAreaTextApi } from './';
2
+ import { ICommand, ExecuteState, TextAreaTextApi } from './';
3
3
  import { selectWord } from '../utils/markdownUtils';
4
4
 
5
5
  export const bold: ICommand = {
6
6
  name: 'bold',
7
7
  keyCommand: 'bold',
8
8
  shortcuts: 'ctrlcmd+b',
9
- value: '**',
9
+ value: '**{{text}}**',
10
10
  buttonProps: { 'aria-label': 'Add bold text (ctrl + b)', title: 'Add bold text (ctrl + b)' },
11
11
  icon: (
12
12
  <svg role="img" width="12" height="12" viewBox="0 0 384 512">
@@ -16,16 +16,17 @@ export const bold: ICommand = {
16
16
  />
17
17
  </svg>
18
18
  ),
19
- execute: (state: TextState, api: TextAreaTextApi) => {
19
+ execute: (state: ExecuteState, api: TextAreaTextApi) => {
20
20
  // Adjust the selection to encompass the whole word if the caret is inside one
21
21
  const newSelectionRange = selectWord({ text: state.text, selection: state.selection });
22
22
  const state1 = api.setSelectionRange(newSelectionRange);
23
23
  // Replaces the current selection with the bold mark up
24
- const state2 = api.replaceSelection(`**${state1.selectedText}**`);
24
+ const val = state.command.value || '';
25
+ api.replaceSelection(val.replace(/({{text}})/gi, state1.selectedText));
26
+
27
+ const start = state1.selection.start + val.indexOf('{{text}}');
28
+ const end = state1.selection.start + val.indexOf('{{text}}') + (state1.selection.end - state1.selection.start);
25
29
  // Adjust the selection to not contain the **
26
- api.setSelectionRange({
27
- start: state2.selection.end - 2 - state1.selectedText?.length,
28
- end: state2.selection.end - 2,
29
- });
30
+ api.setSelectionRange({ start, end });
30
31
  },
31
32
  };
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { ICommand, TextState, TextAreaTextApi } from './';
3
3
  import {
4
4
  selectWord,
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import { ICommand, TextState, TextAreaTextApi } from './';
2
3
  import { selectWord } from '../utils/markdownUtils';
3
4
 
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import { ICommand } from './';
2
3
 
3
4
  export const divider: ICommand = {
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { ICommand, TextState, TextAreaTextApi } from './';
3
3
  import { ContextStore, ExecuteCommandState } from '../Context';
4
4
 
@@ -1,5 +1,5 @@
1
- import * as React from 'react';
2
- import { ICommand, TextState, TextAreaTextApi } from './';
1
+ import React from 'react';
2
+ import { ICommand, ExecuteState, TextAreaTextApi } from './';
3
3
 
4
4
  export const hr: ICommand = {
5
5
  name: 'hr',
@@ -16,7 +16,7 @@ export const hr: ICommand = {
16
16
  />
17
17
  </svg>
18
18
  ),
19
- execute: (state: TextState, api: TextAreaTextApi) => {
20
- api.replaceSelection(`${state.selectedText}\n\n----------\n\n`);
19
+ execute: (state: ExecuteState, api: TextAreaTextApi) => {
20
+ api.replaceSelection(`${state.selectedText}\n\n${state.command.value || ''}-\n\n`);
21
21
  },
22
22
  };
@@ -1,12 +1,12 @@
1
- import * as React from 'react';
2
- import { ICommand, TextState, TextAreaTextApi } from './';
1
+ import React from 'react';
2
+ import { ICommand, ExecuteState, TextAreaTextApi } from './';
3
3
  import { selectWord } from '../utils/markdownUtils';
4
4
 
5
5
  export const image: ICommand = {
6
6
  name: 'image',
7
7
  keyCommand: 'image',
8
8
  shortcuts: 'ctrlcmd+k',
9
- value: '![image]()',
9
+ value: '![image]({{text}})',
10
10
  buttonProps: { 'aria-label': 'Add image (ctrl + k)', title: 'Add image (ctrl + k)' },
11
11
  icon: (
12
12
  <svg width="13" height="13" viewBox="0 0 20 20">
@@ -16,17 +16,20 @@ export const image: ICommand = {
16
16
  />
17
17
  </svg>
18
18
  ),
19
- execute: (state: TextState, api: TextAreaTextApi) => {
19
+ execute: (state: ExecuteState, api: TextAreaTextApi) => {
20
20
  // Select everything
21
21
  const newSelectionRange = selectWord({ text: state.text, selection: state.selection });
22
22
  const state1 = api.setSelectionRange(newSelectionRange);
23
23
  // Replaces the current selection with the image
24
24
  const imageTemplate = state1.selectedText || 'https://example.com/your-image.png';
25
- api.replaceSelection(`![](${imageTemplate})`);
26
- // Adjust the selection to not contain the **
27
- api.setSelectionRange({
28
- start: 4 + state1.selection.start,
29
- end: 4 + state1.selection.start + imageTemplate.length,
30
- });
25
+ const val = state.command.value || '';
26
+ api.replaceSelection(val.replace(/({{text}})/gi, imageTemplate));
27
+
28
+ const start = state1.selection.start + val.indexOf('{{text}}');
29
+ let end = state1.selection.start + val.indexOf('{{text}}') + (state1.selection.end - state1.selection.start);
30
+ if (!state1.selectedText) {
31
+ end = end + imageTemplate.length;
32
+ }
33
+ api.setSelectionRange({ start, end });
31
34
  },
32
35
  };
@@ -58,7 +58,7 @@ export interface ICommandBase<T> {
58
58
  index: number,
59
59
  ) => void | undefined | null | React.ReactElement;
60
60
  execute?: (
61
- state: TextState,
61
+ state: ExecuteState,
62
62
  api: TextAreaTextApi,
63
63
  dispatch?: React.Dispatch<ContextStore>,
64
64
  executeCommandState?: ExecuteCommandState,
@@ -66,6 +66,8 @@ export interface ICommandBase<T> {
66
66
  ) => void;
67
67
  }
68
68
 
69
+ export type ExecuteState = TextState & { command: ICommand };
70
+
69
71
  export type ICommand<T = string> = ICommandChildCommands<T> | ICommandChildHandle<T>;
70
72
 
71
73
  export interface TextRange {
@@ -164,7 +166,8 @@ class TextAreaCommandOrchestrator implements CommandOrchestrator {
164
166
  state?: ExecuteCommandState,
165
167
  shortcuts?: string[],
166
168
  ): void {
167
- command.execute && command.execute(getStateFromTextArea(this.textArea), this.textApi, dispatch, state, shortcuts);
169
+ command.execute &&
170
+ command.execute({ command, ...getStateFromTextArea(this.textArea) }, this.textApi, dispatch, state, shortcuts);
168
171
  }
169
172
  }
170
173
 
@@ -1,12 +1,12 @@
1
- import * as React from 'react';
2
- import { ICommand, TextState, TextAreaTextApi } from './';
1
+ import React from 'react';
2
+ import { ICommand, ExecuteState, TextAreaTextApi } from './';
3
3
  import { selectWord } from '../utils/markdownUtils';
4
4
 
5
5
  export const italic: ICommand = {
6
6
  name: 'italic',
7
7
  keyCommand: 'italic',
8
8
  shortcuts: 'ctrlcmd+i',
9
- value: '* *',
9
+ value: '*{{text}}*',
10
10
  buttonProps: { 'aria-label': 'Add italic text (ctrl + i)', title: 'Add italic text (ctrl + i)' },
11
11
  icon: (
12
12
  <svg data-name="italic" width="12" height="12" role="img" viewBox="0 0 320 512">
@@ -16,16 +16,17 @@ export const italic: ICommand = {
16
16
  />
17
17
  </svg>
18
18
  ),
19
- execute: (state: TextState, api: TextAreaTextApi) => {
19
+ execute: (state: ExecuteState, api: TextAreaTextApi) => {
20
20
  // Adjust the selection to encompass the whole word if the caret is inside one
21
21
  const newSelectionRange = selectWord({ text: state.text, selection: state.selection });
22
22
  const state1 = api.setSelectionRange(newSelectionRange);
23
- // Replaces the current selection with the italic mark up
24
- const state2 = api.replaceSelection(`*${state1.selectedText}*`);
25
- // Adjust the selection to not contain the *
26
- api.setSelectionRange({
27
- start: state2.selection.end - 1 - state1.selectedText.length,
28
- end: state2.selection.end - 1,
29
- });
23
+ // Replaces the current selection with the bold mark up
24
+ const val = state.command.value || '';
25
+ api.replaceSelection(val.replace(/({{text}})/gi, state1.selectedText));
26
+
27
+ const start = state1.selection.start + val.indexOf('{{text}}');
28
+ const end = state1.selection.start + val.indexOf('{{text}}') + (state1.selection.end - state1.selection.start);
29
+ // Adjust the selection to not contain the **
30
+ api.setSelectionRange({ start, end });
30
31
  },
31
32
  };
@@ -1,12 +1,12 @@
1
- import * as React from 'react';
2
- import { ICommand, TextState, TextAreaTextApi } from './';
1
+ import React from 'react';
2
+ import { ICommand, ExecuteState, TextAreaTextApi } from './';
3
3
  import { selectWord } from '../utils/markdownUtils';
4
4
 
5
5
  export const link: ICommand = {
6
6
  name: 'link',
7
7
  keyCommand: 'link',
8
8
  shortcuts: 'ctrlcmd+l',
9
- value: '[](url)',
9
+ value: '[{{text}}](URL Here)',
10
10
  buttonProps: { 'aria-label': 'Add a link (ctrl + l)', title: 'Add a link (ctrl + l)' },
11
11
  icon: (
12
12
  <svg data-name="italic" width="12" height="12" role="img" viewBox="0 0 520 520">
@@ -16,16 +16,16 @@ export const link: ICommand = {
16
16
  />
17
17
  </svg>
18
18
  ),
19
- execute: (state: TextState, api: TextAreaTextApi) => {
19
+ execute: (state: ExecuteState, api: TextAreaTextApi) => {
20
20
  // Adjust the selection to encompass the whole word if the caret is inside one
21
21
  const newSelectionRange = selectWord({ text: state.text, selection: state.selection });
22
22
  const state1 = api.setSelectionRange(newSelectionRange);
23
+ const val = state.command.value || '';
23
24
  // Replaces the current selection with the bold mark up
24
- const state2 = api.replaceSelection(`[${state1.selectedText}](url)`);
25
+ api.replaceSelection(val.replace(/({{text}})/gi, state1.selectedText));
26
+ const start = state1.selection.start + val.indexOf('{{text}}');
27
+ const end = state1.selection.start + val.indexOf('{{text}}') + (state1.selection.end - state1.selection.start);
25
28
  // Adjust the selection to not contain the **
26
- api.setSelectionRange({
27
- start: state2.selection.end - 6 - state1.selectedText.length,
28
- end: state2.selection.end - 6,
29
- });
29
+ api.setSelectionRange({ start, end });
30
30
  },
31
31
  };
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { ICommand, TextState, TextAreaTextApi } from './';
3
3
  import {
4
4
  selectWord,
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { ICommand, TextState, TextAreaTextApi } from './';
3
3
  import { ContextStore, ExecuteCommandState } from '../Context';
4
4
 
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { ICommand, TextState, TextAreaTextApi } from './';
3
3
  import {
4
4
  getBreaksNeededForEmptyLineBefore,
@@ -1,5 +1,5 @@
1
- import * as React from 'react';
2
- import { ICommand, TextState, TextAreaTextApi } from './';
1
+ import React from 'react';
2
+ import { ICommand, ExecuteState, TextAreaTextApi } from './';
3
3
  import { selectWord } from '../utils/markdownUtils';
4
4
 
5
5
  export const strikethrough: ICommand = {
@@ -10,7 +10,7 @@ export const strikethrough: ICommand = {
10
10
  'aria-label': 'Add strikethrough text (ctrl + shift + x)',
11
11
  title: 'Add strikethrough text (ctrl + shift + x)',
12
12
  },
13
- value: '~~',
13
+ value: '~~{{text}}~~',
14
14
  icon: (
15
15
  <svg data-name="strikethrough" width="12" height="12" role="img" viewBox="0 0 512 512">
16
16
  <path
@@ -19,16 +19,17 @@ export const strikethrough: ICommand = {
19
19
  />
20
20
  </svg>
21
21
  ),
22
- execute: (state: TextState, api: TextAreaTextApi) => {
22
+ execute: (state: ExecuteState, api: TextAreaTextApi) => {
23
23
  // Adjust the selection to encompass the whole word if the caret is inside one
24
24
  const newSelectionRange = selectWord({ text: state.text, selection: state.selection });
25
25
  const state1 = api.setSelectionRange(newSelectionRange);
26
- // Replaces the current selection with the strikethrough mark up
27
- const state2 = api.replaceSelection(`~~${state1.selectedText}~~`);
28
- // Adjust the selection to not contain the ~~
29
- api.setSelectionRange({
30
- start: state2.selection.end - 2 - state1.selectedText.length,
31
- end: state2.selection.end - 2,
32
- });
26
+ // Replaces the current selection with the bold mark up
27
+ const val = state.command.value || '';
28
+ api.replaceSelection(val.replace(/({{text}})/gi, state1.selectedText));
29
+
30
+ const start = state1.selection.start + val.indexOf('{{text}}');
31
+ const end = state1.selection.start + val.indexOf('{{text}}') + (state1.selection.end - state1.selection.start);
32
+ // Adjust the selection to not contain the **
33
+ api.setSelectionRange({ start, end });
33
34
  },
34
35
  };
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { insertAtLineStart } from '../utils/InsertTextAtPosition';
3
3
  import { ICommand, TextState, TextAreaTextApi } from './';
4
4
 
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { insertAtLineStart } from '../utils/InsertTextAtPosition';
3
3
  import { ICommand, TextState, TextAreaTextApi } from './';
4
4
 
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { insertAtLineStart } from '../utils/InsertTextAtPosition';
3
3
  import { ICommand, TextState, TextAreaTextApi } from './';
4
4
 
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { insertAtLineStart } from '../utils/InsertTextAtPosition';
3
3
  import { ICommand, TextState, TextAreaTextApi } from './';
4
4
 
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { insertAtLineStart } from '../utils/InsertTextAtPosition';
3
3
  import { ICommand, TextState, TextAreaTextApi } from './';
4
4
 
@@ -1,19 +0,0 @@
1
- {
2
- "version": 3,
3
- "names": [
4
- "React",
5
- "reducer",
6
- "state",
7
- "action",
8
- "EditorContext",
9
- "createContext",
10
- "markdown"
11
- ],
12
- "sources": [
13
- "../src/Context.tsx"
14
- ],
15
- "sourcesContent": [
16
- "import React from 'react';\nimport { ICommand, TextAreaCommandOrchestrator } from './commands';\nimport { MDEditorProps } from './Editor';\n\nexport type PreviewType = 'live' | 'edit' | 'preview';\n\nexport interface ContextStore {\n components?: MDEditorProps['components'];\n commands?: ICommand<string>[];\n extraCommands?: ICommand<string>[];\n markdown?: string;\n preview?: PreviewType;\n height?: React.CSSProperties['height'];\n fullscreen?: boolean;\n highlightEnable?: boolean;\n autoFocus?: boolean;\n textarea?: HTMLTextAreaElement;\n commandOrchestrator?: TextAreaCommandOrchestrator;\n textareaWarp?: HTMLDivElement;\n textareaPre?: HTMLPreElement;\n container?: HTMLDivElement | null;\n dispatch?: React.Dispatch<ContextStore>;\n barPopup?: Record<string, boolean>;\n scrollTop?: number;\n scrollTopPreview?: number;\n tabSize?: number;\n defaultTabEnable?: boolean;\n}\n\nexport type ExecuteCommandState = Pick<ContextStore, 'fullscreen' | 'preview' | 'highlightEnable'>;\n\nexport function reducer(state: ContextStore, action: ContextStore) {\n return { ...state, ...action };\n}\n\nexport const EditorContext = React.createContext<ContextStore>({ markdown: '' });\n"
17
- ],
18
- "mappings": ";AAAA,OAAOA,KAAK,MAAM,OAAO;AA+BzB,OAAO,SAASC,OAAO,CAACC,KAAmB,EAAEC,MAAoB,EAAE;EACjE,oBAAYD,KAAK,EAAKC,MAAM;AAC9B;AAEA,OAAO,IAAMC,aAAa,gBAAGJ,KAAK,CAACK,aAAa,CAAe;EAAEC,QAAQ,EAAE;AAAG,CAAC,CAAC"
19
- }