@uiw/react-md-editor 4.1.6 → 4.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 +1 -1
- package/dist/mdeditor.css +5 -0
- package/dist/mdeditor.js +2378 -1029
- package/dist/mdeditor.min.css +1 -1
- package/dist/mdeditor.min.js +1 -1
- package/esm/Editor.factory.js +70 -17
- package/esm/components/TextArea/Markdown.common.d.ts +3 -5
- package/esm/components/TextArea/Markdown.common.js +2 -56
- package/esm/components/TextArea/Markdown.d.ts +3 -5
- package/esm/components/TextArea/Markdown.factory.d.ts +6 -0
- package/esm/components/TextArea/Markdown.factory.js +138 -0
- package/esm/components/TextArea/Markdown.js +2 -63
- package/esm/components/TextArea/index.css +5 -0
- package/esm/components/TextArea/index.less +5 -0
- package/esm/components/TextArea/splitBlocks.d.ts +13 -0
- package/esm/components/TextArea/splitBlocks.js +111 -0
- package/esm/package.json +1 -0
- package/lib/Editor.factory.js +78 -18
- package/lib/components/TextArea/Markdown.common.d.ts +3 -5
- package/lib/components/TextArea/Markdown.common.js +3 -60
- package/lib/components/TextArea/Markdown.d.ts +3 -5
- package/lib/components/TextArea/Markdown.factory.d.ts +6 -0
- package/lib/components/TextArea/Markdown.factory.js +148 -0
- package/lib/components/TextArea/Markdown.js +3 -67
- package/lib/components/TextArea/index.less +5 -0
- package/lib/components/TextArea/splitBlocks.d.ts +13 -0
- package/lib/components/TextArea/splitBlocks.js +117 -0
- package/markdown-editor.css +5 -0
- package/package.json +18 -12
- package/src/Editor.factory.tsx +64 -12
- package/src/components/TextArea/Markdown.common.tsx +3 -46
- package/src/components/TextArea/Markdown.factory.tsx +132 -0
- package/src/components/TextArea/Markdown.tsx +3 -55
- package/src/components/TextArea/index.less +5 -0
- package/src/components/TextArea/splitBlocks.ts +114 -0
package/lib/Editor.factory.js
CHANGED
|
@@ -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 = ["
|
|
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,7 +109,7 @@ 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 ?
|
|
112
|
+
previewOptions = _ref$previewOptions === void 0 ? DEFAULT_PREVIEW_OPTIONS : _ref$previewOptions,
|
|
59
113
|
textareaProps = _ref.textareaProps,
|
|
60
114
|
id = _ref.id,
|
|
61
115
|
name = _ref.name,
|
|
@@ -88,14 +142,14 @@ function createMDEditor(options) {
|
|
|
88
142
|
toolbarBottom = _ref$toolbarBottom === void 0 ? false : _ref$toolbarBottom,
|
|
89
143
|
components = _ref.components,
|
|
90
144
|
renderTextarea = _ref.renderTextarea,
|
|
91
|
-
other = (0, _objectWithoutProperties2["default"])(_ref,
|
|
145
|
+
other = (0, _objectWithoutProperties2["default"])(_ref, _excluded2);
|
|
92
146
|
var cmds = commands.map(function (item) {
|
|
93
147
|
return commandsFilter ? commandsFilter(item, false) : item;
|
|
94
148
|
}).filter(Boolean);
|
|
95
149
|
var extraCmds = extraCommands.map(function (item) {
|
|
96
150
|
return commandsFilter ? commandsFilter(item, true) : item;
|
|
97
151
|
}).filter(Boolean);
|
|
98
|
-
var
|
|
152
|
+
var _useReducer3 = (0, _react.useReducer)(_Context.reducer, {
|
|
99
153
|
markdown: propsValue,
|
|
100
154
|
preview: previewType,
|
|
101
155
|
components: components,
|
|
@@ -111,9 +165,9 @@ function createMDEditor(options) {
|
|
|
111
165
|
fullscreen: fullscreen,
|
|
112
166
|
barPopup: {}
|
|
113
167
|
}),
|
|
114
|
-
|
|
115
|
-
state =
|
|
116
|
-
dispatch =
|
|
168
|
+
_useReducer4 = (0, _slicedToArray2["default"])(_useReducer3, 2),
|
|
169
|
+
state = _useReducer4[0],
|
|
170
|
+
dispatch = _useReducer4[1];
|
|
117
171
|
var container = (0, _react.useRef)(null);
|
|
118
172
|
var previewRef = (0, _react.useRef)(null);
|
|
119
173
|
var enableScrollRef = (0, _react.useRef)(enableScroll);
|
|
@@ -225,12 +279,15 @@ function createMDEditor(options) {
|
|
|
225
279
|
initScroll.current = true;
|
|
226
280
|
}
|
|
227
281
|
if (textareaDom && previewDom) {
|
|
228
|
-
var
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
282
|
+
var inputRange = Math.max(0, textareaDom.scrollHeight - textareaDom.offsetHeight);
|
|
283
|
+
var previewRange = Math.max(0, previewDom.scrollHeight - previewDom.offsetHeight);
|
|
284
|
+
if (inputRange > 0 && previewRange > 0) {
|
|
285
|
+
if (e.target === textareaDom && active.current === 'text') {
|
|
286
|
+
previewDom.scrollTop = textareaDom.scrollTop / inputRange * previewRange;
|
|
287
|
+
}
|
|
288
|
+
if (e.target === previewDom && active.current === 'preview') {
|
|
289
|
+
textareaDom.scrollTop = previewDom.scrollTop / previewRange * inputRange;
|
|
290
|
+
}
|
|
234
291
|
}
|
|
235
292
|
var scrollTop = 0;
|
|
236
293
|
if (active.current === 'text') {
|
|
@@ -247,16 +304,19 @@ function createMDEditor(options) {
|
|
|
247
304
|
var handlePreviewScroll = function handlePreviewScroll(e) {
|
|
248
305
|
return handleScroll(e, 'preview');
|
|
249
306
|
};
|
|
307
|
+
var previewRenderMs = (0, _react.useRef)(0);
|
|
308
|
+
var previewMarkdown = useDeferredValue(usePreviewSource(state.markdown || '', previewRenderMs));
|
|
250
309
|
var mdPreview = (0, _react.useMemo)(function () {
|
|
251
310
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
252
311
|
ref: previewRef,
|
|
253
312
|
className: previewClassName,
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
313
|
+
onScroll: handlePreviewScroll,
|
|
314
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(TimedPreview, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, previewOptions), {}, {
|
|
315
|
+
renderMsRef: previewRenderMs,
|
|
316
|
+
source: previewMarkdown
|
|
257
317
|
}))
|
|
258
318
|
});
|
|
259
|
-
}, [previewClassName, previewOptions,
|
|
319
|
+
}, [previewClassName, previewOptions, previewMarkdown]);
|
|
260
320
|
var preview = (components === null || components === void 0 ? void 0 : components.preview) && (components === null || components === void 0 ? void 0 : components.preview(state.markdown || '', state, dispatch));
|
|
261
321
|
if (preview && /*#__PURE__*/_react["default"].isValidElement(preview)) {
|
|
262
322
|
mdPreview = /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
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"] =
|
|
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
|
|
14
|
-
var
|
|
15
|
-
var _templateObject;
|
|
16
|
-
function html2Escape(sHtml) {
|
|
17
|
-
return sHtml.replace(/[<&"]/g, function (c) {
|
|
18
|
-
return {
|
|
19
|
-
'<': '<',
|
|
20
|
-
'>': '>',
|
|
21
|
-
'&': '&',
|
|
22
|
-
'"': '"'
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
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
|
+
'<': '<',
|
|
21
|
+
'>': '>',
|
|
22
|
+
'&': '&',
|
|
23
|
+
'"': '"'
|
|
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
|
+
}
|
|
@@ -1,75 +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"] =
|
|
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 _rehypePrismPlus = _interopRequireDefault(require("rehype-prism-plus"));
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
var _templateObject;
|
|
16
|
-
function html2Escape(sHtml) {
|
|
17
|
-
return sHtml
|
|
18
|
-
// .replace(/```(\w+)?([\s\S]*?)(\s.+)?```/g, (str: string) => {
|
|
19
|
-
// return str.replace(
|
|
20
|
-
// /[<&"]/g,
|
|
21
|
-
// (c: string) => (({ '<': '<', '>': '>', '&': '&', '"': '"' } as Record<string, string>)[c]),
|
|
22
|
-
// );
|
|
23
|
-
// })
|
|
24
|
-
.replace(/[<&"]/g, function (c) {
|
|
25
|
-
return {
|
|
26
|
-
'<': '<',
|
|
27
|
-
'>': '>',
|
|
28
|
-
'&': '&',
|
|
29
|
-
'"': '"'
|
|
30
|
-
}[c];
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
function Markdown(props) {
|
|
34
|
-
var prefixCls = props.prefixCls;
|
|
35
|
-
var _useContext = (0, _react.useContext)(_Context.EditorContext),
|
|
36
|
-
_useContext$markdown = _useContext.markdown,
|
|
37
|
-
markdown = _useContext$markdown === void 0 ? '' : _useContext$markdown,
|
|
38
|
-
highlightEnable = _useContext.highlightEnable,
|
|
39
|
-
dispatch = _useContext.dispatch;
|
|
40
|
-
var preRef = /*#__PURE__*/_react["default"].createRef();
|
|
41
|
-
(0, _react.useEffect)(function () {
|
|
42
|
-
if (preRef.current && dispatch) {
|
|
43
|
-
dispatch({
|
|
44
|
-
textareaPre: preRef.current
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
|
-
}, []);
|
|
49
|
-
if (!markdown) {
|
|
50
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)("pre", {
|
|
51
|
-
ref: preRef,
|
|
52
|
-
className: "".concat(prefixCls, "-text-pre wmde-markdown-color")
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
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>");
|
|
56
|
-
if (highlightEnable) {
|
|
57
|
-
try {
|
|
58
|
-
mdStr = (0, _rehype.rehype)().data('settings', {
|
|
59
|
-
fragment: true
|
|
60
|
-
})
|
|
61
|
-
// https://github.com/uiwjs/react-md-editor/issues/593
|
|
62
|
-
// @ts-ignore
|
|
63
|
-
.use(_rehypePrismPlus["default"], {
|
|
64
|
-
ignoreMissing: true
|
|
65
|
-
}).processSync(mdStr).toString();
|
|
66
|
-
} catch (error) {}
|
|
67
|
-
}
|
|
68
|
-
return /*#__PURE__*/_react["default"].createElement('div', {
|
|
69
|
-
className: 'wmde-markdown-color',
|
|
70
|
-
dangerouslySetInnerHTML: {
|
|
71
|
-
__html: mdStr || ''
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
}
|
|
9
|
+
var _Markdown = require("./Markdown.factory");
|
|
10
|
+
var _default = exports["default"] = (0, _Markdown.createMarkdown)(_rehypePrismPlus["default"]);
|
|
75
11
|
module.exports = exports.default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits markdown into blocks that Prism's markdown grammar highlights the same way
|
|
3
|
+
* on their own as it does in the full document, so unchanged blocks can be cached.
|
|
4
|
+
* Joining the returned blocks always yields the original string.
|
|
5
|
+
*
|
|
6
|
+
* A block ends where a run of blank lines starts, so each block keeps its leading blank
|
|
7
|
+
* lines (indented code needs them). No split happens inside a ``` fence, front matter or
|
|
8
|
+
* multiline markup or link references, or right before a `---` line, which Prism
|
|
9
|
+
* would read as front matter. Whitespace-only lines stay in their block because
|
|
10
|
+
* Prism's inline emphasis can span them.
|
|
11
|
+
* Fences follow Prism's rule, not CommonMark's, so the split matches what Prism sees.
|
|
12
|
+
*/
|
|
13
|
+
export declare function splitBlocks(markdown: string): string[];
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.splitBlocks = splitBlocks;
|
|
7
|
+
var FENCE_OPEN = /^```/;
|
|
8
|
+
var FENCE_CLOSE = /^```\r?\n?$/;
|
|
9
|
+
var BLANK_LINE = /^[ \t]*\r?\n?$/;
|
|
10
|
+
var FRONT_MATTER_FENCE = /^---\r?\n?$/;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Splits markdown into blocks that Prism's markdown grammar highlights the same way
|
|
14
|
+
* on their own as it does in the full document, so unchanged blocks can be cached.
|
|
15
|
+
* Joining the returned blocks always yields the original string.
|
|
16
|
+
*
|
|
17
|
+
* A block ends where a run of blank lines starts, so each block keeps its leading blank
|
|
18
|
+
* lines (indented code needs them). No split happens inside a ``` fence, front matter or
|
|
19
|
+
* multiline markup or link references, or right before a `---` line, which Prism
|
|
20
|
+
* would read as front matter. Whitespace-only lines stay in their block because
|
|
21
|
+
* Prism's inline emphasis can span them.
|
|
22
|
+
* Fences follow Prism's rule, not CommonMark's, so the split matches what Prism sees.
|
|
23
|
+
*/
|
|
24
|
+
function splitBlocks(markdown) {
|
|
25
|
+
var lines = markdown.match(/[^\n]*\n|[^\n]+$/g) || [];
|
|
26
|
+
var blocks = [];
|
|
27
|
+
var current = '';
|
|
28
|
+
var pendingSplit = -1;
|
|
29
|
+
var inFence = false;
|
|
30
|
+
var inFrontMatter = /^(?:\s*[\r\n])?---(?:\r?\n|$)/.test(markdown);
|
|
31
|
+
var frontMatterStarted = false;
|
|
32
|
+
var syntax = {
|
|
33
|
+
end: '',
|
|
34
|
+
quote: '',
|
|
35
|
+
brackets: 0,
|
|
36
|
+
subset: 0
|
|
37
|
+
};
|
|
38
|
+
var previousIsBlank = true;
|
|
39
|
+
lines.forEach(function (line) {
|
|
40
|
+
var isBlank = BLANK_LINE.test(line);
|
|
41
|
+
var canSplit = !inFence && !inFrontMatter && !syntax.end && !syntax.brackets;
|
|
42
|
+
if (/^\r?\n$/.test(line) && !previousIsBlank && canSplit) {
|
|
43
|
+
pendingSplit = current.length;
|
|
44
|
+
}
|
|
45
|
+
if (!isBlank && pendingSplit > 0) {
|
|
46
|
+
if (!FRONT_MATTER_FENCE.test(line)) {
|
|
47
|
+
blocks.push(current.slice(0, pendingSplit));
|
|
48
|
+
current = current.slice(pendingSplit);
|
|
49
|
+
}
|
|
50
|
+
pendingSplit = -1;
|
|
51
|
+
}
|
|
52
|
+
current += line;
|
|
53
|
+
previousIsBlank = isBlank;
|
|
54
|
+
if (inFrontMatter) {
|
|
55
|
+
if (FRONT_MATTER_FENCE.test(line)) {
|
|
56
|
+
inFrontMatter = !frontMatterStarted;
|
|
57
|
+
frontMatterStarted = true;
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (inFence) {
|
|
62
|
+
inFence = !FENCE_CLOSE.test(line);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (!syntax.end && FENCE_OPEN.test(line)) {
|
|
66
|
+
inFence = true;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
updateSyntax(line, syntax);
|
|
70
|
+
});
|
|
71
|
+
if (current) {
|
|
72
|
+
blocks.push(current);
|
|
73
|
+
}
|
|
74
|
+
return blocks;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Keep potential multiline Prism tokens together. Unclosed syntax conservatively
|
|
78
|
+
// keeps the rest of the document in one block until the user closes it.
|
|
79
|
+
function updateSyntax(line, state) {
|
|
80
|
+
var reference = false;
|
|
81
|
+
for (var i = 0; i < line.length; i++) {
|
|
82
|
+
var _char = line[i];
|
|
83
|
+
if (state.end && state.end !== '>') {
|
|
84
|
+
var end = line.indexOf(state.end, i);
|
|
85
|
+
if (end === -1) return;
|
|
86
|
+
i = end + state.end.length - 1;
|
|
87
|
+
state.end = '';
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (state.end === '>') {
|
|
91
|
+
if (state.quote) {
|
|
92
|
+
if (_char === state.quote) state.quote = '';
|
|
93
|
+
} else if (_char === '"' || _char === "'") {
|
|
94
|
+
state.quote = _char;
|
|
95
|
+
} else if (_char === '[') {
|
|
96
|
+
state.subset++;
|
|
97
|
+
} else if (_char === ']' && state.subset) {
|
|
98
|
+
state.subset--;
|
|
99
|
+
} else if (_char === '>' && !state.subset) {
|
|
100
|
+
state.end = '';
|
|
101
|
+
}
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (_char === '\\') {
|
|
105
|
+
i++;
|
|
106
|
+
} else if (_char === '<' && /[a-z!?/]/i.test(line[i + 1] || '')) {
|
|
107
|
+
state.end = line.startsWith('<!--', i) ? '-->' : line.startsWith('<![CDATA[', i) ? ']]>' : line.startsWith('<?', i) ? '?>' : '>';
|
|
108
|
+
} else if (_char === '[') {
|
|
109
|
+
state.brackets++;
|
|
110
|
+
} else if (_char === ']') {
|
|
111
|
+
state.brackets = Math.max(0, state.brackets - 1);
|
|
112
|
+
reference = line[i + 1] === ':';
|
|
113
|
+
} else if (reference && (_char === '"' || _char === "'" || _char === '(')) {
|
|
114
|
+
state.end = _char === '(' ? ')' : _char;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
package/markdown-editor.css
CHANGED
|
@@ -131,6 +131,11 @@
|
|
|
131
131
|
.w-md-editor-text-pre .token.bold {
|
|
132
132
|
font-weight: unset !important;
|
|
133
133
|
}
|
|
134
|
+
.w-md-editor-text-pre .token.list,
|
|
135
|
+
.w-md-editor-text-pre .token.table {
|
|
136
|
+
display: inline;
|
|
137
|
+
font-size: inherit;
|
|
138
|
+
}
|
|
134
139
|
.w-md-editor-text-pre .token.title {
|
|
135
140
|
line-height: unset !important;
|
|
136
141
|
font-size: unset !important;
|