@uiw/react-md-editor 4.1.5 → 4.1.7

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 (56) hide show
  1. package/README.md +16 -1
  2. package/dist/mdeditor.css +5 -0
  3. package/dist/mdeditor.js +2382 -1031
  4. package/dist/mdeditor.min.css +1 -1
  5. package/dist/mdeditor.min.js +1 -1
  6. package/esm/Editor.factory.js +85 -11
  7. package/esm/Types.d.ts +6 -0
  8. package/esm/commands/index.cn.d.ts +2 -1
  9. package/esm/commands/index.cn.js +2 -2
  10. package/esm/commands/index.d.ts +2 -2
  11. package/esm/commands/index.js +2 -2
  12. package/esm/commands/list.d.ts +1 -1
  13. package/esm/commands/list.js +9 -3
  14. package/esm/components/TextArea/Markdown.common.d.ts +3 -5
  15. package/esm/components/TextArea/Markdown.common.js +2 -56
  16. package/esm/components/TextArea/Markdown.d.ts +3 -5
  17. package/esm/components/TextArea/Markdown.factory.d.ts +6 -0
  18. package/esm/components/TextArea/Markdown.factory.js +138 -0
  19. package/esm/components/TextArea/Markdown.js +2 -63
  20. package/esm/components/TextArea/factory.js +6 -2
  21. package/esm/components/TextArea/index.css +5 -0
  22. package/esm/components/TextArea/index.less +5 -0
  23. package/esm/components/TextArea/splitBlocks.d.ts +13 -0
  24. package/esm/components/TextArea/splitBlocks.js +111 -0
  25. package/esm/package.json +1 -0
  26. package/lib/Editor.factory.js +93 -12
  27. package/lib/Types.d.ts +6 -0
  28. package/lib/commands/index.cn.d.ts +2 -1
  29. package/lib/commands/index.cn.js +8 -1
  30. package/lib/commands/index.d.ts +2 -2
  31. package/lib/commands/index.js +6 -0
  32. package/lib/commands/list.d.ts +1 -1
  33. package/lib/commands/list.js +5 -1
  34. package/lib/components/TextArea/Markdown.common.d.ts +3 -5
  35. package/lib/components/TextArea/Markdown.common.js +3 -60
  36. package/lib/components/TextArea/Markdown.d.ts +3 -5
  37. package/lib/components/TextArea/Markdown.factory.d.ts +6 -0
  38. package/lib/components/TextArea/Markdown.factory.js +148 -0
  39. package/lib/components/TextArea/Markdown.js +3 -67
  40. package/lib/components/TextArea/factory.js +6 -2
  41. package/lib/components/TextArea/index.less +5 -0
  42. package/lib/components/TextArea/splitBlocks.d.ts +13 -0
  43. package/lib/components/TextArea/splitBlocks.js +117 -0
  44. package/markdown-editor.css +5 -0
  45. package/package.json +18 -12
  46. package/src/Editor.factory.tsx +83 -4
  47. package/src/Types.ts +6 -0
  48. package/src/commands/index.cn.ts +2 -0
  49. package/src/commands/index.ts +2 -1
  50. package/src/commands/list.tsx +11 -2
  51. package/src/components/TextArea/Markdown.common.tsx +3 -46
  52. package/src/components/TextArea/Markdown.factory.tsx +132 -0
  53. package/src/components/TextArea/Markdown.tsx +3 -55
  54. package/src/components/TextArea/factory.tsx +7 -4
  55. package/src/components/TextArea/index.less +5 -0
  56. package/src/components/TextArea/splitBlocks.ts +114 -0
@@ -0,0 +1,111 @@
1
+ var FENCE_OPEN = /^```/;
2
+ var FENCE_CLOSE = /^```\r?\n?$/;
3
+ var BLANK_LINE = /^[ \t]*\r?\n?$/;
4
+ var FRONT_MATTER_FENCE = /^---\r?\n?$/;
5
+
6
+ /**
7
+ * Splits markdown into blocks that Prism's markdown grammar highlights the same way
8
+ * on their own as it does in the full document, so unchanged blocks can be cached.
9
+ * Joining the returned blocks always yields the original string.
10
+ *
11
+ * A block ends where a run of blank lines starts, so each block keeps its leading blank
12
+ * lines (indented code needs them). No split happens inside a ``` fence, front matter or
13
+ * multiline markup or link references, or right before a `---` line, which Prism
14
+ * would read as front matter. Whitespace-only lines stay in their block because
15
+ * Prism's inline emphasis can span them.
16
+ * Fences follow Prism's rule, not CommonMark's, so the split matches what Prism sees.
17
+ */
18
+ export function splitBlocks(markdown) {
19
+ var lines = markdown.match(/[^\n]*\n|[^\n]+$/g) || [];
20
+ var blocks = [];
21
+ var current = '';
22
+ var pendingSplit = -1;
23
+ var inFence = false;
24
+ var inFrontMatter = /^(?:\s*[\r\n])?---(?:\r?\n|$)/.test(markdown);
25
+ var frontMatterStarted = false;
26
+ var syntax = {
27
+ end: '',
28
+ quote: '',
29
+ brackets: 0,
30
+ subset: 0
31
+ };
32
+ var previousIsBlank = true;
33
+ lines.forEach(line => {
34
+ var isBlank = BLANK_LINE.test(line);
35
+ var canSplit = !inFence && !inFrontMatter && !syntax.end && !syntax.brackets;
36
+ if (/^\r?\n$/.test(line) && !previousIsBlank && canSplit) {
37
+ pendingSplit = current.length;
38
+ }
39
+ if (!isBlank && pendingSplit > 0) {
40
+ if (!FRONT_MATTER_FENCE.test(line)) {
41
+ blocks.push(current.slice(0, pendingSplit));
42
+ current = current.slice(pendingSplit);
43
+ }
44
+ pendingSplit = -1;
45
+ }
46
+ current += line;
47
+ previousIsBlank = isBlank;
48
+ if (inFrontMatter) {
49
+ if (FRONT_MATTER_FENCE.test(line)) {
50
+ inFrontMatter = !frontMatterStarted;
51
+ frontMatterStarted = true;
52
+ }
53
+ return;
54
+ }
55
+ if (inFence) {
56
+ inFence = !FENCE_CLOSE.test(line);
57
+ return;
58
+ }
59
+ if (!syntax.end && FENCE_OPEN.test(line)) {
60
+ inFence = true;
61
+ return;
62
+ }
63
+ updateSyntax(line, syntax);
64
+ });
65
+ if (current) {
66
+ blocks.push(current);
67
+ }
68
+ return blocks;
69
+ }
70
+
71
+ // Keep potential multiline Prism tokens together. Unclosed syntax conservatively
72
+ // keeps the rest of the document in one block until the user closes it.
73
+ function updateSyntax(line, state) {
74
+ var reference = false;
75
+ for (var i = 0; i < line.length; i++) {
76
+ var char = line[i];
77
+ if (state.end && state.end !== '>') {
78
+ var end = line.indexOf(state.end, i);
79
+ if (end === -1) return;
80
+ i = end + state.end.length - 1;
81
+ state.end = '';
82
+ continue;
83
+ }
84
+ if (state.end === '>') {
85
+ if (state.quote) {
86
+ if (char === state.quote) state.quote = '';
87
+ } else if (char === '"' || char === "'") {
88
+ state.quote = char;
89
+ } else if (char === '[') {
90
+ state.subset++;
91
+ } else if (char === ']' && state.subset) {
92
+ state.subset--;
93
+ } else if (char === '>' && !state.subset) {
94
+ state.end = '';
95
+ }
96
+ continue;
97
+ }
98
+ if (char === '\\') {
99
+ i++;
100
+ } else if (char === '<' && /[a-z!?/]/i.test(line[i + 1] || '')) {
101
+ state.end = line.startsWith('<!--', i) ? '-->' : line.startsWith('<![CDATA[', i) ? ']]>' : line.startsWith('<?', i) ? '?>' : '>';
102
+ } else if (char === '[') {
103
+ state.brackets++;
104
+ } else if (char === ']') {
105
+ state.brackets = Math.max(0, state.brackets - 1);
106
+ reference = line[i + 1] === ':';
107
+ } else if (reference && (char === '"' || char === "'" || char === '(')) {
108
+ state.end = char === '(' ? ')' : char;
109
+ }
110
+ }
111
+ }
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -7,15 +7,16 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.createMDEditor = createMDEditor;
9
9
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
10
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
10
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
11
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
12
12
  var _react = _interopRequireWildcard(require("react"));
13
13
  var _Toolbar = require("./components/Toolbar/");
14
14
  var _DragBar = _interopRequireDefault(require("./components/DragBar/"));
15
15
  var _commands = require("./commands/");
16
16
  var _Context = require("./Context");
17
17
  var _jsxRuntime = require("react/jsx-runtime");
18
- var _excluded = ["prefixCls", "className", "value", "commands", "commandsFilter", "direction", "extraCommands", "height", "enableScroll", "visibleDragbar", "highlightEnable", "preview", "fullscreen", "overflow", "previewOptions", "textareaProps", "maxHeight", "minHeight", "autoFocus", "autoFocusEnd", "tabSize", "defaultTabEnable", "onChange", "onStatistics", "onHeightChange", "hideToolbar", "toolbarBottom", "components", "renderTextarea"];
18
+ var _excluded = ["renderMsRef"],
19
+ _excluded2 = ["prefixCls", "className", "value", "commands", "commandsFilter", "direction", "extraCommands", "height", "enableScroll", "visibleDragbar", "highlightEnable", "preview", "fullscreen", "overflow", "previewOptions", "textareaProps", "id", "name", "required", "disabled", "readOnly", "placeholder", "aria-label", "aria-labelledby", "aria-describedby", "aria-invalid", "aria-required", "aria-errormessage", "maxHeight", "minHeight", "autoFocus", "autoFocusEnd", "tabSize", "defaultTabEnable", "onChange", "onStatistics", "onHeightChange", "hideToolbar", "toolbarBottom", "components", "renderTextarea"];
19
20
  function setGroupPopFalse() {
20
21
  var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
21
22
  Object.keys(data).forEach(function (keyname) {
@@ -23,11 +24,64 @@ function setGroupPopFalse() {
23
24
  });
24
25
  return data;
25
26
  }
27
+ var DEFAULT_PREVIEW_OPTIONS = {};
28
+
29
+ /**
30
+ * Lets the preview render after the textarea on React 18+, so typing in a large
31
+ * document stays responsive. Older React versions render it right away, as before.
32
+ */
33
+ var useDeferredValue = _react["default"].useDeferredValue || function (value) {
34
+ return value;
35
+ };
36
+ var useIsomorphicLayoutEffect = typeof window === 'undefined' ? _react.useEffect : _react.useLayoutEffect;
37
+ var SLOW_PREVIEW_MS = 50;
38
+ var MAX_PREVIEW_DELAY_MS = 500;
39
+
40
+ /**
41
+ * Keeps the preview in step with every keystroke while it renders fast. Once a preview
42
+ * render takes longer than SLOW_PREVIEW_MS, it waits for a pause in typing as long as
43
+ * that render (at most MAX_PREVIEW_DELAY_MS) before updating.
44
+ * https://github.com/uiwjs/react-md-editor/issues/620
45
+ */
46
+ function usePreviewSource(markdown, previewRenderMs) {
47
+ var _useReducer = (0, _react.useReducer)(function (count) {
48
+ return count + 1;
49
+ }, 0),
50
+ _useReducer2 = (0, _slicedToArray2["default"])(_useReducer, 2),
51
+ rerender = _useReducer2[1];
52
+ var shownRef = (0, _react.useRef)(markdown);
53
+ if (previewRenderMs.current < SLOW_PREVIEW_MS) {
54
+ shownRef.current = markdown;
55
+ }
56
+ (0, _react.useEffect)(function () {
57
+ if (shownRef.current === markdown) {
58
+ return;
59
+ }
60
+ var delay = Math.min(previewRenderMs.current, MAX_PREVIEW_DELAY_MS);
61
+ var timer = setTimeout(function () {
62
+ shownRef.current = markdown;
63
+ rerender();
64
+ }, delay);
65
+ return function () {
66
+ return clearTimeout(timer);
67
+ };
68
+ }, [markdown, previewRenderMs]);
69
+ return shownRef.current;
70
+ }
26
71
  function createMDEditor(options) {
27
72
  var MarkdownPreview = options.MarkdownPreview,
28
73
  TextArea = options.TextArea;
29
74
  var PreviewComponent = MarkdownPreview;
30
75
  var TextAreaComponent = TextArea;
76
+ function TimedPreview(props) {
77
+ var renderMsRef = props.renderMsRef,
78
+ previewProps = (0, _objectWithoutProperties2["default"])(props, _excluded);
79
+ var renderStart = performance.now();
80
+ useIsomorphicLayoutEffect(function () {
81
+ renderMsRef.current = performance.now() - renderStart;
82
+ });
83
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(PreviewComponent, (0, _objectSpread2["default"])({}, previewProps));
84
+ }
31
85
  var InternalMDEditor = /*#__PURE__*/_react["default"].forwardRef(function (props, ref) {
32
86
  var _ref = props || {},
33
87
  _ref$prefixCls = _ref.prefixCls,
@@ -55,8 +109,20 @@ function createMDEditor(options) {
55
109
  _ref$overflow = _ref.overflow,
56
110
  overflow = _ref$overflow === void 0 ? true : _ref$overflow,
57
111
  _ref$previewOptions = _ref.previewOptions,
58
- previewOptions = _ref$previewOptions === void 0 ? {} : _ref$previewOptions,
112
+ previewOptions = _ref$previewOptions === void 0 ? DEFAULT_PREVIEW_OPTIONS : _ref$previewOptions,
59
113
  textareaProps = _ref.textareaProps,
114
+ id = _ref.id,
115
+ name = _ref.name,
116
+ required = _ref.required,
117
+ disabled = _ref.disabled,
118
+ readOnly = _ref.readOnly,
119
+ placeholder = _ref.placeholder,
120
+ ariaLabel = _ref['aria-label'],
121
+ ariaLabelledBy = _ref['aria-labelledby'],
122
+ ariaDescribedBy = _ref['aria-describedby'],
123
+ ariaInvalid = _ref['aria-invalid'],
124
+ ariaRequired = _ref['aria-required'],
125
+ ariaErrorMessage = _ref['aria-errormessage'],
60
126
  _ref$maxHeight = _ref.maxHeight,
61
127
  maxHeight = _ref$maxHeight === void 0 ? 1200 : _ref$maxHeight,
62
128
  _ref$minHeight = _ref.minHeight,
@@ -76,14 +142,14 @@ function createMDEditor(options) {
76
142
  toolbarBottom = _ref$toolbarBottom === void 0 ? false : _ref$toolbarBottom,
77
143
  components = _ref.components,
78
144
  renderTextarea = _ref.renderTextarea,
79
- other = (0, _objectWithoutProperties2["default"])(_ref, _excluded);
145
+ other = (0, _objectWithoutProperties2["default"])(_ref, _excluded2);
80
146
  var cmds = commands.map(function (item) {
81
147
  return commandsFilter ? commandsFilter(item, false) : item;
82
148
  }).filter(Boolean);
83
149
  var extraCmds = extraCommands.map(function (item) {
84
150
  return commandsFilter ? commandsFilter(item, true) : item;
85
151
  }).filter(Boolean);
86
- var _useReducer = (0, _react.useReducer)(_Context.reducer, {
152
+ var _useReducer3 = (0, _react.useReducer)(_Context.reducer, {
87
153
  markdown: propsValue,
88
154
  preview: previewType,
89
155
  components: components,
@@ -99,9 +165,9 @@ function createMDEditor(options) {
99
165
  fullscreen: fullscreen,
100
166
  barPopup: {}
101
167
  }),
102
- _useReducer2 = (0, _slicedToArray2["default"])(_useReducer, 2),
103
- state = _useReducer2[0],
104
- dispatch = _useReducer2[1];
168
+ _useReducer4 = (0, _slicedToArray2["default"])(_useReducer3, 2),
169
+ state = _useReducer4[0],
170
+ dispatch = _useReducer4[1];
105
171
  var container = (0, _react.useRef)(null);
106
172
  var previewRef = (0, _react.useRef)(null);
107
173
  var enableScrollRef = (0, _react.useRef)(enableScroll);
@@ -235,16 +301,19 @@ function createMDEditor(options) {
235
301
  var handlePreviewScroll = function handlePreviewScroll(e) {
236
302
  return handleScroll(e, 'preview');
237
303
  };
304
+ var previewRenderMs = (0, _react.useRef)(0);
305
+ var previewMarkdown = useDeferredValue(usePreviewSource(state.markdown || '', previewRenderMs));
238
306
  var mdPreview = (0, _react.useMemo)(function () {
239
307
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
240
308
  ref: previewRef,
241
309
  className: previewClassName,
242
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(PreviewComponent, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, previewOptions), {}, {
310
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(TimedPreview, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, previewOptions), {}, {
311
+ renderMsRef: previewRenderMs,
243
312
  onScroll: handlePreviewScroll,
244
- source: state.markdown || ''
313
+ source: previewMarkdown
245
314
  }))
246
315
  });
247
- }, [previewClassName, previewOptions, state.markdown]);
316
+ }, [previewClassName, previewOptions, previewMarkdown]);
248
317
  var preview = (components === null || components === void 0 ? void 0 : components.preview) && (components === null || components === void 0 ? void 0 : components.preview(state.markdown || '', state, dispatch));
249
318
  if (preview && /*#__PURE__*/_react["default"].isValidElement(preview)) {
250
319
  mdPreview = /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
@@ -302,7 +371,19 @@ function createMDEditor(options) {
302
371
  children: [/(edit|live)/.test(state.preview || '') && /*#__PURE__*/(0, _jsxRuntime.jsx)(TextAreaComponent, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({
303
372
  className: "".concat(prefixCls, "-input"),
304
373
  prefixCls: prefixCls,
305
- autoFocus: autoFocus
374
+ autoFocus: autoFocus,
375
+ id: id,
376
+ name: name,
377
+ required: required,
378
+ disabled: disabled,
379
+ readOnly: readOnly,
380
+ placeholder: placeholder,
381
+ "aria-label": ariaLabel,
382
+ "aria-labelledby": ariaLabelledBy,
383
+ "aria-describedby": ariaDescribedBy,
384
+ "aria-invalid": ariaInvalid,
385
+ "aria-required": ariaRequired,
386
+ "aria-errormessage": ariaErrorMessage
306
387
  }, textareaProps), {}, {
307
388
  onChange: changeHandle,
308
389
  renderTextarea: (components === null || components === void 0 ? void 0 : components.textarea) || renderTextarea,
package/lib/Types.d.ts CHANGED
@@ -18,6 +18,12 @@ export interface MDEditorProps extends Omit<React.HTMLAttributes<HTMLDivElement>
18
18
  * The Markdown value.
19
19
  */
20
20
  value?: string;
21
+ /** Native textarea form attributes. */
22
+ name?: React.TextareaHTMLAttributes<HTMLTextAreaElement>['name'];
23
+ required?: React.TextareaHTMLAttributes<HTMLTextAreaElement>['required'];
24
+ disabled?: React.TextareaHTMLAttributes<HTMLTextAreaElement>['disabled'];
25
+ readOnly?: React.TextareaHTMLAttributes<HTMLTextAreaElement>['readOnly'];
26
+ placeholder?: React.TextareaHTMLAttributes<HTMLTextAreaElement>['placeholder'];
21
27
  /**
22
28
  * Event handler for the `onChange` event.
23
29
  */
@@ -1,6 +1,7 @@
1
1
  import { type ICommand } from './';
2
2
  import { divider } from './divider';
3
3
  import { group } from './group';
4
+ import { makeList } from './list';
4
5
  declare let bold: ICommand;
5
6
  declare let code: ICommand;
6
7
  declare let codeBlock: ICommand;
@@ -30,4 +31,4 @@ declare let table: ICommand;
30
31
  declare let help: ICommand;
31
32
  export declare const getCommands: () => ICommand[];
32
33
  export declare const getExtraCommands: () => ICommand[];
33
- export { title, title1, title2, title3, title4, title5, title6, bold, codeBlock, comment, italic, strikethrough, hr, group, divider, link, quote, code, image, unorderedListCommand, orderedListCommand, checkedListCommand, table, issue, help, codeEdit, codeLive, codePreview, fullscreen, };
34
+ export { title, title1, title2, title3, title4, title5, title6, bold, codeBlock, comment, italic, strikethrough, hr, group, divider, link, quote, code, image, unorderedListCommand, orderedListCommand, checkedListCommand, makeList, table, issue, help, codeEdit, codeLive, codePreview, fullscreen, };
@@ -18,7 +18,14 @@ Object.defineProperty(exports, "group", {
18
18
  return _group.group;
19
19
  }
20
20
  });
21
- exports.unorderedListCommand = exports.title6 = exports.title5 = exports.title4 = exports.title3 = exports.title2 = exports.title1 = exports.title = exports.table = exports.strikethrough = exports.quote = exports.orderedListCommand = exports.link = exports.italic = exports.issue = exports.image = exports.hr = exports.help = void 0;
21
+ exports.link = exports.italic = exports.issue = exports.image = exports.hr = exports.help = void 0;
22
+ Object.defineProperty(exports, "makeList", {
23
+ enumerable: true,
24
+ get: function get() {
25
+ return _list.makeList;
26
+ }
27
+ });
28
+ exports.unorderedListCommand = exports.title6 = exports.title5 = exports.title4 = exports.title3 = exports.title2 = exports.title1 = exports.title = exports.table = exports.strikethrough = exports.quote = exports.orderedListCommand = void 0;
22
29
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
23
30
  var _divider = require("./divider");
24
31
  var _group = require("./group");
@@ -10,7 +10,7 @@ import { hr } from './hr';
10
10
  import { image } from './image';
11
11
  import { italic } from './italic';
12
12
  import { link } from './link';
13
- import { checkedListCommand, orderedListCommand, unorderedListCommand } from './list';
13
+ import { checkedListCommand, makeList, orderedListCommand, unorderedListCommand } from './list';
14
14
  import { codeEdit, codeLive, codePreview } from './preview';
15
15
  import { quote } from './quote';
16
16
  import { strikethrough } from './strikeThrough';
@@ -93,4 +93,4 @@ declare class TextAreaCommandOrchestrator implements CommandOrchestrator {
93
93
  getState(): false | TextState;
94
94
  executeCommand(command: ICommand<string>, dispatch?: React.Dispatch<ContextStore>, state?: ExecuteCommandState, shortcuts?: string[]): void;
95
95
  }
96
- export { title, title1, title2, title3, title4, title5, title6, heading, heading1, heading2, heading3, heading4, heading5, heading6, bold, codeBlock, comment, italic, strikethrough, hr, group, divider, link, quote, code, image, unorderedListCommand, orderedListCommand, checkedListCommand, table, issue, help, codeEdit, codeLive, codePreview, fullscreen, getCommands, getExtraCommands, getStateFromTextArea, TextAreaCommandOrchestrator, TextAreaTextApi, };
96
+ export { title, title1, title2, title3, title4, title5, title6, heading, heading1, heading2, heading3, heading4, heading5, heading6, bold, codeBlock, comment, italic, strikethrough, hr, group, divider, link, quote, code, image, unorderedListCommand, orderedListCommand, checkedListCommand, makeList, table, issue, help, codeEdit, codeLive, codePreview, fullscreen, getCommands, getExtraCommands, getStateFromTextArea, TextAreaCommandOrchestrator, TextAreaTextApi, };
@@ -151,6 +151,12 @@ Object.defineProperty(exports, "link", {
151
151
  return _link.link;
152
152
  }
153
153
  });
154
+ Object.defineProperty(exports, "makeList", {
155
+ enumerable: true,
156
+ get: function get() {
157
+ return _list.makeList;
158
+ }
159
+ });
154
160
  Object.defineProperty(exports, "orderedListCommand", {
155
161
  enumerable: true,
156
162
  get: function get() {
@@ -1,6 +1,6 @@
1
1
  import { type ICommand, type ExecuteState, TextAreaTextApi } from './';
2
2
  import { AlterLineFunction } from '../utils/markdownUtils';
3
- export declare const makeList: (state: ExecuteState, api: TextAreaTextApi, insertBefore: string | AlterLineFunction) => void;
3
+ export declare const makeList: (state: ExecuteState, api: TextAreaTextApi, insertBefore: string | AlterLineFunction, selectionStrategy?: "word" | "line") => void;
4
4
  export declare const unorderedListCommand: ICommand;
5
5
  export declare const orderedListCommand: ICommand;
6
6
  export declare const checkedListCommand: ICommand;
@@ -9,7 +9,11 @@ var _react = _interopRequireDefault(require("react"));
9
9
  var _markdownUtils = require("../utils/markdownUtils");
10
10
  var _jsxRuntime = require("react/jsx-runtime");
11
11
  var makeList = exports.makeList = function makeList(state, api, insertBefore) {
12
- var newSelectionRange = (0, _markdownUtils.selectWord)({
12
+ var selectionStrategy = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'word';
13
+ var newSelectionRange = selectionStrategy === 'line' ? (0, _markdownUtils.selectLine)({
14
+ text: state.text,
15
+ selection: state.selection
16
+ }) : (0, _markdownUtils.selectWord)({
13
17
  text: state.text,
14
18
  selection: state.selection,
15
19
  prefix: state.command.prefix
@@ -1,5 +1,3 @@
1
- import React from 'react';
2
- import { type IProps } from '../../Types';
3
- export interface MarkdownProps extends IProps, React.HTMLAttributes<HTMLPreElement> {
4
- }
5
- export default function Markdown(props: MarkdownProps): import("react/jsx-runtime").JSX.Element;
1
+ export type { MarkdownProps } from './Markdown.factory';
2
+ declare const _default: (props: import("./Markdown.factory").MarkdownProps) => import("react/jsx-runtime").JSX.Element;
3
+ export default _default;
@@ -1,68 +1,11 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
4
- var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard")["default"];
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
- exports["default"] = Markdown;
9
- var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
10
- var _react = _interopRequireWildcard(require("react"));
11
- var _rehype = require("rehype");
7
+ exports["default"] = void 0;
12
8
  var _common = _interopRequireDefault(require("rehype-prism-plus/common"));
13
- var _Context = require("../../Context");
14
- var _jsxRuntime = require("react/jsx-runtime");
15
- var _templateObject;
16
- function html2Escape(sHtml) {
17
- return sHtml.replace(/[<&"]/g, function (c) {
18
- return {
19
- '<': '&lt;',
20
- '>': '&gt;',
21
- '&': '&amp;',
22
- '"': '&quot;'
23
- }[c];
24
- });
25
- }
26
- function Markdown(props) {
27
- var prefixCls = props.prefixCls;
28
- var _useContext = (0, _react.useContext)(_Context.EditorContext),
29
- _useContext$markdown = _useContext.markdown,
30
- markdown = _useContext$markdown === void 0 ? '' : _useContext$markdown,
31
- highlightEnable = _useContext.highlightEnable,
32
- dispatch = _useContext.dispatch;
33
- var preRef = /*#__PURE__*/_react["default"].createRef();
34
- (0, _react.useEffect)(function () {
35
- if (preRef.current && dispatch) {
36
- dispatch({
37
- textareaPre: preRef.current
38
- });
39
- }
40
- // eslint-disable-next-line react-hooks/exhaustive-deps
41
- }, []);
42
- if (!markdown) {
43
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("pre", {
44
- ref: preRef,
45
- className: "".concat(prefixCls, "-text-pre wmde-markdown-color")
46
- });
47
- }
48
- var mdStr = "<pre class=\"language-markdown ".concat(prefixCls, "-text-pre wmde-markdown-color\"><code class=\"language-markdown\">").concat(html2Escape(String.raw(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2["default"])(["", ""])), markdown)), "\n</code></pre>");
49
- if (highlightEnable) {
50
- try {
51
- mdStr = (0, _rehype.rehype)().data('settings', {
52
- fragment: true
53
- })
54
- // https://github.com/uiwjs/react-md-editor/issues/593
55
- // @ts-ignore
56
- .use(_common["default"], {
57
- ignoreMissing: true
58
- }).processSync(mdStr).toString();
59
- } catch (error) {}
60
- }
61
- return /*#__PURE__*/_react["default"].createElement('div', {
62
- className: 'wmde-markdown-color',
63
- dangerouslySetInnerHTML: {
64
- __html: mdStr || ''
65
- }
66
- });
67
- }
9
+ var _Markdown = require("./Markdown.factory");
10
+ var _default = exports["default"] = (0, _Markdown.createMarkdown)(_common["default"]);
68
11
  module.exports = exports.default;
@@ -1,5 +1,3 @@
1
- import React from 'react';
2
- import { type IProps } from '../../Types';
3
- export interface MarkdownProps extends IProps, React.HTMLAttributes<HTMLPreElement> {
4
- }
5
- export default function Markdown(props: MarkdownProps): import("react/jsx-runtime").JSX.Element;
1
+ export type { MarkdownProps } from './Markdown.factory';
2
+ declare const _default: (props: import("./Markdown.factory").MarkdownProps) => import("react/jsx-runtime").JSX.Element;
3
+ export default _default;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import type rehypePrismPlus from 'rehype-prism-plus';
3
+ import { type IProps } from '../../Types';
4
+ export interface MarkdownProps extends IProps, React.HTMLAttributes<HTMLPreElement> {
5
+ }
6
+ export declare function createMarkdown(rehypePrism: typeof rehypePrismPlus): (props: MarkdownProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard")["default"];
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.createMarkdown = createMarkdown;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ var _rehype = require("rehype");
10
+ var _Context = require("../../Context");
11
+ var _splitBlocks = require("./splitBlocks");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ /**
14
+ * Prism's markdown grammar takes quadratic time on long lines, so a single base64 image
15
+ * line can block the editor for minutes. Blocks with such a line are shown uncoloured.
16
+ */var MAX_HIGHLIGHT_LINE_LENGTH = 1000;
17
+ function html2Escape(sHtml) {
18
+ return sHtml.replace(/[<&"]/g, function (c) {
19
+ return {
20
+ '<': '&lt;',
21
+ '>': '&gt;',
22
+ '&': '&amp;',
23
+ '"': '&quot;'
24
+ }[c];
25
+ });
26
+ }
27
+ function hasLongLine(text) {
28
+ var lineStart = 0;
29
+ while (lineStart <= text.length) {
30
+ var lineEnd = text.indexOf('\n', lineStart);
31
+ var end = lineEnd === -1 ? text.length : lineEnd;
32
+ if (end - lineStart > MAX_HIGHLIGHT_LINE_LENGTH) {
33
+ return true;
34
+ }
35
+ lineStart = end + 1;
36
+ }
37
+ return false;
38
+ }
39
+ function getCodeInnerHtml(html) {
40
+ var codeStart = html.indexOf('<code');
41
+ var contentStart = html.indexOf('>', codeStart) + 1;
42
+ var contentEnd = html.lastIndexOf('</code>');
43
+ return html.slice(contentStart, contentEnd);
44
+ }
45
+ var MarkdownBlock = /*#__PURE__*/_react["default"].memo(function MarkdownBlock(props) {
46
+ return /*#__PURE__*/_react["default"].createElement('span', {
47
+ dangerouslySetInnerHTML: {
48
+ __html: props.html
49
+ }
50
+ });
51
+ });
52
+ function createMarkdown(rehypePrism) {
53
+ var processor = (0, _rehype.rehype)().data('settings', {
54
+ fragment: true
55
+ })
56
+ // https://github.com/uiwjs/react-md-editor/issues/593
57
+ // @ts-ignore
58
+ .use(rehypePrism, {
59
+ ignoreMissing: true
60
+ });
61
+ function highlightBlock(block) {
62
+ var escaped = html2Escape(block);
63
+ if (hasLongLine(block)) {
64
+ return escaped;
65
+ }
66
+ try {
67
+ var html = processor.processSync("<pre><code class=\"language-markdown\">".concat(escaped, "</code></pre>")).toString();
68
+ return getCodeInnerHtml(html);
69
+ } catch (error) {
70
+ return escaped;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Highlighting runs per block, and blocks whose text did not change reuse their cached
76
+ * HTML and DOM, so typing in a large document only re-highlights the edited block.
77
+ * https://github.com/uiwjs/react-md-editor/issues/620
78
+ */
79
+ return function Markdown(props) {
80
+ var prefixCls = props.prefixCls;
81
+ var _useContext = (0, _react.useContext)(_Context.EditorContext),
82
+ _useContext$markdown = _useContext.markdown,
83
+ markdown = _useContext$markdown === void 0 ? '' : _useContext$markdown,
84
+ highlightEnable = _useContext.highlightEnable,
85
+ dispatch = _useContext.dispatch;
86
+ var preRef = (0, _react.useRef)(null);
87
+ var cacheRef = (0, _react.useRef)(new Map());
88
+ var nextIdRef = (0, _react.useRef)(0);
89
+ (0, _react.useEffect)(function () {
90
+ if (preRef.current && dispatch) {
91
+ dispatch({
92
+ textareaPre: preRef.current
93
+ });
94
+ }
95
+ // eslint-disable-next-line react-hooks/exhaustive-deps
96
+ }, []);
97
+ var blocks = (0, _react.useMemo)(function () {
98
+ if (!highlightEnable) {
99
+ cacheRef.current = new Map();
100
+ return [];
101
+ }
102
+ var cache = new Map();
103
+ var occurrences = new Map();
104
+ var result = (0, _splitBlocks.splitBlocks)(markdown).map(function (block) {
105
+ var highlighted = cacheRef.current.get(block) || cache.get(block);
106
+ if (!highlighted) {
107
+ highlighted = {
108
+ id: nextIdRef.current++,
109
+ html: highlightBlock(block)
110
+ };
111
+ }
112
+ cache.set(block, highlighted);
113
+ var occurrence = occurrences.get(block) || 0;
114
+ occurrences.set(block, occurrence + 1);
115
+ return {
116
+ key: "".concat(highlighted.id, "-").concat(occurrence),
117
+ html: highlighted.html
118
+ };
119
+ });
120
+ cacheRef.current = cache;
121
+ return result;
122
+ }, [markdown, highlightEnable]);
123
+ if (!markdown) {
124
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("pre", {
125
+ ref: preRef,
126
+ className: "".concat(prefixCls, "-text-pre wmde-markdown-color")
127
+ });
128
+ }
129
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
130
+ className: "wmde-markdown-color",
131
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("pre", {
132
+ ref: preRef,
133
+ className: "language-markdown ".concat(prefixCls, "-text-pre wmde-markdown-color"),
134
+ children: highlightEnable ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("code", {
135
+ className: "language-markdown code-highlight",
136
+ children: [blocks.map(function (block) {
137
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(MarkdownBlock, {
138
+ html: block.html
139
+ }, block.key);
140
+ }), '\n']
141
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("code", {
142
+ className: "language-markdown",
143
+ children: "".concat(markdown, "\n")
144
+ })
145
+ })
146
+ });
147
+ };
148
+ }