Skip to content

Commit cd385ea

Browse files
committed
添加tagInputProps支持,优化Markdown输入字段和编辑器组件
1 parent 6e4d20b commit cd385ea

File tree

7 files changed

+68
-41
lines changed

7 files changed

+68
-41
lines changed

src/MarkdownEditor/BaseMarkdownEditor.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { BaseEditor, createEditor, Editor, Selection } from 'slate';
1515
import { HistoryEditor, withHistory } from 'slate-history';
1616
import { CommentList } from './editor/components/CommentList';
1717
import { MEditor } from './editor/Editor';
18+
import { TagPopupProps } from './editor/elements/code/TagPopup';
1819
import { parserMdToSchema } from './editor/parser/parserMdToSchema';
1920
import { withMarkdown } from './editor/plugins';
2021
import { withErrorReporting } from './editor/plugins/catchError';
@@ -296,6 +297,10 @@ export type MarkdownEditorProps = {
296297
enable: boolean;
297298
placeholder?: string;
298299
};
300+
301+
tagInputProps?: {
302+
enable: boolean;
303+
} & TagPopupProps;
299304
};
300305

301306
// 组合器函数

src/MarkdownEditor/demos/preview.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ export default () => {
318318
width={'100vw'}
319319
height={'100vh'}
320320
reportMode
321-
tag={{
321+
tagInputProps={{
322+
enable: true,
322323
items: [
323324
{
324325
label: '腾讯',

src/MarkdownEditor/editor/Editor.tsx

+21-23
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import { insertParsedHtmlNodes } from './plugins/insertParsedHtmlNodes';
2525
import { parseMarkdownToNodesAndInsert } from './plugins/parseMarkdownToNodesAndInsert';
2626

2727
import { useDebounceFn } from '@ant-design/pro-components';
28+
import { useRefFunction } from '../../hooks/useRefFunction';
2829
import { PluginContext } from '../plugin';
29-
import { TagPopupProps } from './elements/code/TagPopup';
3030
import { useHighlight } from './plugins/useHighlight';
3131
import { useKeyboard } from './plugins/useKeyboard';
3232
import { useOnchange } from './plugins/useOnchange';
@@ -58,7 +58,6 @@ export type MEditorProps = {
5858
comment?: MarkdownEditorProps['comment'];
5959
prefixCls?: string;
6060
reportMode?: MarkdownEditorProps['reportMode'];
61-
tag?: TagPopupProps;
6261
placeholder?: string;
6362
} & MarkdownEditorProps;
6463

@@ -79,19 +78,13 @@ const genTableMinSize = (
7978
};
8079

8180
export const MEditor = observer(
82-
({
83-
eleItemRender,
84-
reportMode,
85-
tag,
86-
instance,
87-
...editorProps
88-
}: MEditorProps) => {
81+
({ eleItemRender, reportMode, instance, ...editorProps }: MEditorProps) => {
8982
const { store, markdownEditorRef, markdownContainerRef, readonly } =
9083
useEditorStore();
9184
const changedMark = useRef(false);
9285
const value = useRef<any[]>([EditorUtils.p]);
9386
const nodeRef = useRef<MarkdownEditorInstance>();
94-
const { prefixCls = '$' } = tag || {};
87+
const { prefixCls = '$' } = editorProps.tagInputProps || {};
9588

9689
const onKeyDown = useKeyboard(
9790
store,
@@ -106,19 +99,23 @@ export const MEditor = observer(
10699
const high = useHighlight(store);
107100
const first = useRef(true);
108101

109-
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
110-
if (tag && event?.key === prefixCls) {
111-
Transforms.insertNodes(markdownEditorRef.current, {
112-
type: 'code',
113-
code: true,
114-
tag: {
115-
...tag,
116-
},
117-
text: '',
118-
});
119-
}
120-
onKeyDown(event);
121-
};
102+
const handleKeyDown = useRefFunction(
103+
(event: React.KeyboardEvent<HTMLDivElement>) => {
104+
if (editorProps.tagInputProps?.enable && event?.key === prefixCls) {
105+
event.preventDefault();
106+
event.stopPropagation();
107+
Transforms.insertNodes(markdownEditorRef.current, [
108+
{
109+
code: true,
110+
tag: true,
111+
text: '$',
112+
},
113+
]);
114+
return;
115+
}
116+
onKeyDown(event);
117+
},
118+
);
122119

123120
/**
124121
* 初始化编辑器
@@ -587,6 +584,7 @@ export const MEditor = observer(
587584
comment={editorProps?.comment}
588585
children={props.children}
589586
hashId={hashId}
587+
tagInputProps={editorProps.tagInputProps}
590588
/>
591589
);
592590
};

src/MarkdownEditor/editor/elements/code/TagPopup/index.tsx

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Dropdown, MenuProps } from 'antd';
22
import React, { ReactNode } from 'react';
33

4-
type TagPopupProps = {
4+
export type TagPopupProps = {
55
children?: React.ReactNode;
66
onSelect?: (value: string) => void;
77
items?: Array<{
@@ -18,7 +18,7 @@ type TagPopupProps = {
1818
className?: string;
1919
};
2020

21-
const TagPopup = (
21+
export const TagPopup = (
2222
props: TagPopupProps & {
2323
text: {
2424
text: string;
@@ -43,7 +43,7 @@ const TagPopup = (
4343
return {
4444
...item,
4545
onClick: () => {
46-
onSelect && onSelect(`${key}` || '');
46+
onSelect?.(`${key}` || '');
4747
setOpen(false);
4848
},
4949
};
@@ -92,5 +92,3 @@ const TagPopup = (
9292
</Dropdown>
9393
);
9494
};
95-
96-
export { TagPopup, TagPopupProps };

src/MarkdownEditor/editor/elements/index.tsx

+12-11
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export const MLeaf = (
145145
hashId: string;
146146
comment: MarkdownEditorProps['comment'];
147147
fncProps: MarkdownEditorProps['fncProps'];
148+
tagInputProps: MarkdownEditorProps['tagInputProps'];
148149
},
149150
) => {
150151
const { markdownEditorRef, readonly } = useEditorStore();
@@ -155,34 +156,34 @@ export const MLeaf = (
155156
let className = props.hashId + ' ';
156157
let children = <>{props.children}</>;
157158
if (leaf.code) {
158-
const { tag, text } = (props?.leaf || {}) as any;
159-
const { prefixCls = '$' } = tag || {};
160-
if (tag && leaf.text?.startsWith(prefixCls)) {
159+
const { text, tag } = (props?.leaf || {}) as any;
160+
const { enable } = props.tagInputProps || {};
161+
if (enable && tag) {
161162
children = (
162163
<TagPopup
163164
{...(props?.leaf as any)?.tag}
164165
text={text}
165166
onSelect={(v) => {
166167
const path = ReactEditor.findPath(
167168
markdownEditorRef.current,
168-
props.text
169+
props.text,
169170
);
170-
171+
171172
const start = {
172173
path,
173-
offset: 1
174+
offset: 1,
174175
};
175-
176+
176177
const end = {
177178
path,
178-
offset: leaf.text?.length || 0
179+
offset: leaf.text?.length || 0,
179180
};
180-
181+
181182
Transforms.select(markdownEditorRef.current, {
182183
anchor: start,
183-
focus: end
184+
focus: end,
184185
});
185-
186+
186187
Transforms.delete(markdownEditorRef.current);
187188
markdownEditorRef.current.insertText(v);
188189
}}

src/MarkdownEditor/editor/plugins/withMarkdown.ts

+7
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,13 @@ export const withMarkdown = (editor: Editor) => {
213213
}
214214
if (operation.type === 'insert_text') {
215215
const parentNode = Node.get(editor, Path.parent(operation.path));
216+
const currentNode = Node.get(editor, operation.path);
217+
if (currentNode?.code && operation.text === ' ') {
218+
// 如果当前节点是代码块,且输入的是空格,则插入一个空格到 code 节点外
219+
Transforms.insertNodes(editor, [{ text: ' ' }]);
220+
return;
221+
}
222+
216223
if (parentNode.type === 'card-after') {
217224
if (
218225
Node.get(editor, Path.parent(Path.parent(operation.path))).type ===

src/MarkdownInputField/MarkdownInputField.tsx

+18-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import classNames from 'classnames';
33
import { useMergedState } from 'rc-util';
44
import React, { useContext, useEffect } from 'react';
55
import { useRefFunction } from '../hooks/useRefFunction';
6-
import { BaseMarkdownEditor, MarkdownEditorInstance } from '../MarkdownEditor';
6+
import {
7+
BaseMarkdownEditor,
8+
MarkdownEditorInstance,
9+
MarkdownEditorProps,
10+
} from '../MarkdownEditor';
711
import { SendButton } from './SendButton';
812
import { useStyle } from './style';
913

@@ -81,6 +85,8 @@ export type MarkdownInputFieldProps = {
8185
* @example onSend={async (text) => await submitMessage(text)}
8286
*/
8387
onSend?: (value: string) => Promise<void>;
88+
89+
tagInputProps?: MarkdownEditorProps['tagInputProps'];
8490
};
8591

8692
/**
@@ -188,6 +194,17 @@ export const MarkdownInputField: React.FC<MarkdownInputFieldProps> = (
188194
enable: true,
189195
placeholder: props.placeholder,
190196
}}
197+
tagInputProps={
198+
props.tagInputProps || {
199+
enable: true,
200+
items: [
201+
{
202+
key: 'Bold',
203+
label: 'Bold',
204+
},
205+
],
206+
}
207+
}
191208
initValue={props.value}
192209
onChange={(value) => {
193210
setValue(value);

0 commit comments

Comments
 (0)