This is an automated email from the ASF dual-hosted git repository.

robin0716 pushed a commit to branch feat/1.7.2/ui
in repository https://gitbox.apache.org/repos/asf/answer.git

commit 3d43700556306965f7816e6cdb031327c16193a6
Author: robin <[email protected]>
AuthorDate: Tue Dec 16 14:50:29 2025 +0800

    refactor(editor): streamline editor component structure and enhance command 
methods
    
    - Removed unnecessary conditional rendering in the MDEditor component for 
the PluginRender.
    - Simplified the MarkdownEditor component's useEffect hooks for better 
clarity.
    - Refactored command methods to utilize self-referencing for improved 
maintainability.
---
 ui/src/components/Editor/MarkdownEditor.tsx        |  9 +---
 ui/src/components/Editor/index.tsx                 | 50 +++++++++++-----------
 .../components/Editor/utils/codemirror/commands.ts | 43 ++++++++++---------
 3 files changed, 48 insertions(+), 54 deletions(-)

diff --git a/ui/src/components/Editor/MarkdownEditor.tsx 
b/ui/src/components/Editor/MarkdownEditor.tsx
index 10145a22..fe5d8bb4 100644
--- a/ui/src/components/Editor/MarkdownEditor.tsx
+++ b/ui/src/components/Editor/MarkdownEditor.tsx
@@ -55,30 +55,25 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
     autoFocus,
   });
 
-  // 初始化内容(只在编辑器创建时执行)
   useEffect(() => {
     if (!editor) {
       return;
     }
 
-    // 初始化编辑器内容
     editor.setValue(value || '');
     lastSyncedValueRef.current = value || '';
     onEditorReady?.(editor);
-  }, [editor]); // 只在编辑器创建时执行
+  }, [editor]);
 
-  // 当外部 value 变化时更新(但不是用户输入导致的)
   useEffect(() => {
     if (!editor) {
       return;
     }
 
-    // 如果 value 和 lastSyncedValueRef 相同,说明是用户输入导致的更新,跳过
     if (value === lastSyncedValueRef.current) {
       return;
     }
 
-    // 外部 value 真正变化,更新编辑器
     const currentValue = editor.getValue();
     if (currentValue !== value) {
       editor.setValue(value || '');
@@ -86,11 +81,9 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
     }
   }, [editor, value]);
 
-  // 清理:组件卸载时销毁编辑器
   useEffect(() => {
     return () => {
       if (editor) {
-        // CodeMirror EditorView 有 destroy 方法
         const view = editor as unknown as EditorView;
         if (view.destroy) {
           view.destroy();
diff --git a/ui/src/components/Editor/index.tsx 
b/ui/src/components/Editor/index.tsx
index a914d912..94bd5836 100644
--- a/ui/src/components/Editor/index.tsx
+++ b/ui/src/components/Editor/index.tsx
@@ -123,32 +123,30 @@ const MDEditor: ForwardRefRenderFunction<EditorRef, 
Props> = (
       <div className={classNames('md-editor-wrap rounded', className)}>
         <div className="toolbar-wrap px-3 d-flex align-items-center flex-wrap">
           <EditorContext.Provider value={currentEditor}>
-            {currentEditor && (
-              <PluginRender
-                type={PluginType.Editor}
-                className="d-flex align-items-center flex-wrap"
-                editor={currentEditor}
-                previewElement={previewRef.current?.element}>
-                <Heading />
-                <Bold />
-                <Italice />
-                <div className="toolbar-divider" />
-                <Code />
-                <LinkItem />
-                <BlockQuote />
-                <Image />
-                <File />
-                <Table />
-                <div className="toolbar-divider" />
-                <OL />
-                <UL />
-                <Indent />
-                <Outdent />
-                <Hr />
-                <div className="toolbar-divider" />
-                <Help />
-              </PluginRender>
-            )}
+            <PluginRender
+              type={PluginType.Editor}
+              className="d-flex align-items-center flex-wrap"
+              editor={currentEditor}
+              previewElement={previewRef.current?.element}>
+              <Heading />
+              <Bold />
+              <Italice />
+              <div className="toolbar-divider" />
+              <Code />
+              <LinkItem />
+              <BlockQuote />
+              <Image />
+              <File />
+              <Table />
+              <div className="toolbar-divider" />
+              <OL />
+              <UL />
+              <Indent />
+              <Outdent />
+              <Hr />
+              <div className="toolbar-divider" />
+              <Help />
+            </PluginRender>
           </EditorContext.Provider>
 
           <div className="btn-group ms-auto" role="group">
diff --git a/ui/src/components/Editor/utils/codemirror/commands.ts 
b/ui/src/components/Editor/utils/codemirror/commands.ts
index 59ab064e..152bc632 100644
--- a/ui/src/components/Editor/utils/codemirror/commands.ts
+++ b/ui/src/components/Editor/utils/codemirror/commands.ts
@@ -33,7 +33,8 @@ import { Editor, Level } from '../../types';
  * @returns Object containing all command methods
  */
 export function createCommandMethods(editor: Editor) {
-  return {
+  // Create methods object that allows self-reference
+  const methods = {
     wrapText: (before: string, after = before, defaultText) => {
       const range = editor.state.selection.ranges[0];
       const selectedText = editor.state.sliceDoc(range.from, range.to);
@@ -79,39 +80,39 @@ export function createCommandMethods(editor: Editor) {
     },
 
     insertBold: (text?: string) => {
-      editor.wrapText('**', '**', text || 'bold text');
+      methods.wrapText('**', '**', text || 'bold text');
     },
 
     insertItalic: (text?: string) => {
-      editor.wrapText('*', '*', text || 'italic text');
+      methods.wrapText('*', '*', text || 'italic text');
     },
 
     insertCode: (text?: string) => {
-      editor.wrapText('`', '`', text || 'code');
+      methods.wrapText('`', '`', text || 'code');
     },
 
     insertStrikethrough: (text?: string) => {
-      editor.wrapText('~~', '~~', text || 'strikethrough text');
+      methods.wrapText('~~', '~~', text || 'strikethrough text');
     },
 
     insertHeading: (level: Level, text?: string) => {
       const headingText = '#'.repeat(level);
-      editor.wrapText(`${headingText} `, '', text || 'heading');
+      methods.wrapText(`${headingText} `, '', text || 'heading');
     },
 
     insertBlockquote: (text?: string) => {
-      editor.wrapText('> ', '', text || 'quote');
+      methods.wrapText('> ', '', text || 'quote');
     },
 
     insertCodeBlock: (language?: string, code?: string) => {
       const lang = language || '';
       const codeText = code || '';
       const block = `\`\`\`${lang}\n${codeText}\n\`\`\``;
-      editor.appendBlock(block);
+      methods.appendBlock(block);
     },
 
     insertHorizontalRule: () => {
-      editor.appendBlock('---');
+      methods.appendBlock('---');
     },
 
     insertOrderedList: () => {
@@ -121,7 +122,7 @@ export function createCommandMethods(editor: Editor) {
       if (/^\d+\.\s/.test(lineText)) {
         return;
       }
-      editor.replaceLines((lineItem) => {
+      methods.replaceLines((lineItem) => {
         if (lineItem.trim() === '') {
           return lineItem;
         }
@@ -136,7 +137,7 @@ export function createCommandMethods(editor: Editor) {
       if (/^[-*+]\s/.test(lineText)) {
         return;
       }
-      editor.replaceLines((lineItem) => {
+      methods.replaceLines((lineItem) => {
         if (lineItem.trim() === '') {
           return lineItem;
         }
@@ -149,11 +150,11 @@ export function createCommandMethods(editor: Editor) {
       const line = editor.state.doc.line(cursor.line);
       const lineText = line.text.trim();
       if (/^\d+\.\s/.test(lineText)) {
-        editor.replaceLines((lineItem) => {
+        methods.replaceLines((lineItem) => {
           return lineItem.replace(/^\d+\.\s/, '');
         });
       } else {
-        editor.insertOrderedList();
+        methods.insertOrderedList();
       }
     },
 
@@ -162,22 +163,22 @@ export function createCommandMethods(editor: Editor) {
       const line = editor.state.doc.line(cursor.line);
       const lineText = line.text.trim();
       if (/^[-*+]\s/.test(lineText)) {
-        editor.replaceLines((lineItem) => {
+        methods.replaceLines((lineItem) => {
           return lineItem.replace(/^[-*+]\s/, '');
         });
       } else {
-        editor.insertUnorderedList();
+        methods.insertUnorderedList();
       }
     },
 
     insertLink: (url: string, text?: string) => {
       const linkText = text || url;
-      editor.wrapText('[', `](${url})`, linkText);
+      methods.wrapText('[', `](${url})`, linkText);
     },
 
     insertImage: (url: string, alt?: string) => {
       const altText = alt || '';
-      editor.wrapText('![', `](${url})`, altText);
+      methods.wrapText('![', `](${url})`, altText);
     },
 
     insertTable: (rows = 3, cols = 3) => {
@@ -192,11 +193,11 @@ export function createCommandMethods(editor: Editor) {
           table.push(`| ${'---'.repeat(cols).split('').join(' | ')} |`);
         }
       }
-      editor.appendBlock(table.join('\n'));
+      methods.appendBlock(table.join('\n'));
     },
 
     indent: () => {
-      editor.replaceLines((line) => {
+      methods.replaceLines((line) => {
         if (line.trim() === '') {
           return line;
         }
@@ -205,7 +206,7 @@ export function createCommandMethods(editor: Editor) {
     },
 
     outdent: () => {
-      editor.replaceLines((line) => {
+      methods.replaceLines((line) => {
         if (line.trim() === '') {
           return line;
         }
@@ -261,4 +262,6 @@ export function createCommandMethods(editor: Editor) {
       return /^[-*+]\s/.test(lineText);
     },
   };
+
+  return methods;
 }

Reply via email to