From d45f7411919ac4f87f437b48c63a7b97be7030a0 Mon Sep 17 00:00:00 2001 From: tabzzz Date: Tue, 4 Feb 2025 02:31:40 +0800 Subject: [PATCH 1/5] =?UTF-8?q?refactor(mini-markdown-editor):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=BF=AB=E6=8D=B7=E9=94=AE=E6=A8=A1=E5=9D=97=EF=BC=8C?= =?UTF-8?q?=E5=88=86=E7=A6=BB=E7=BC=96=E8=BE=91=E5=99=A8=E5=86=85=E5=A4=96?= =?UTF-8?q?=E7=9A=84=E4=B8=8D=E5=90=8C=E5=BF=AB=E6=8D=B7=E6=8C=89=E9=94=AE?= =?UTF-8?q?=E5=8C=BA=E5=9F=9F=E8=AE=BE=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 初级阶段 --- .../src/EditorWrapper.tsx | 32 +-- .../src/common/hotkeys.ts | 27 ++- .../src/components/Editor/index.tsx | 13 +- .../src/plugins/markdown-hotkeys.ts | 183 ++++++++++++++++++ 4 files changed, 227 insertions(+), 28 deletions(-) create mode 100644 packages/mini-markdown-editor/src/plugins/markdown-hotkeys.ts diff --git a/packages/mini-markdown-editor/src/EditorWrapper.tsx b/packages/mini-markdown-editor/src/EditorWrapper.tsx index ccb8d58..2358b8f 100644 --- a/packages/mini-markdown-editor/src/EditorWrapper.tsx +++ b/packages/mini-markdown-editor/src/EditorWrapper.tsx @@ -8,7 +8,7 @@ import Status from "@/components/Status"; import { Row, Col, ConfigProvider as AntdConfigProvider, theme as AntdTheme } from "antd"; import { ToolbarProvider } from "@/components/providers/toolbar-provider"; import { ConfigProvider } from "@/components/providers/config-provider"; -import { HotkeysProvider } from "@/components/providers/hotkeys-provider"; +// import { HotkeysProvider } from "@/components/providers/hotkeys-provider"; import { GlobalConfig } from "./types/global-config"; import { useToolbarStore } from "./store/toolbar"; import { useInitSyncScrollStatus } from "./hooks/use-init-sync-scroll-status"; @@ -160,21 +160,21 @@ const EditorWrapper: FC = (config) => { - - - {/* 工具栏 */} - - - {/* 内容区域 */} - - - } - preview={} - /> - - - + {/* */} + + {/* 工具栏 */} + + + {/* 内容区域 */} + + + } + preview={} + /> + + + {/* */} {/* 底部状态栏 */} {config.status ? ( diff --git a/packages/mini-markdown-editor/src/common/hotkeys.ts b/packages/mini-markdown-editor/src/common/hotkeys.ts index f97f4da..fe93cf3 100644 --- a/packages/mini-markdown-editor/src/common/hotkeys.ts +++ b/packages/mini-markdown-editor/src/common/hotkeys.ts @@ -4,12 +4,12 @@ type Description = string; export class Hotkey { // Tools static readonly TITLE = { - FIRST: new Hotkey("mod+1", "heaing-1"), - SECOND: new Hotkey("mod+2", "heaing-2"), - THIRD: new Hotkey("mod+3", "heaing-3"), - FOURTH: new Hotkey("mod+4", "heaing-4"), - FIFTH: new Hotkey("mod+5", "heaing-5"), - SIXTH: new Hotkey("mod+6", "heaing-6"), + FIRST: new Hotkey("mod+1", "heading-1"), + SECOND: new Hotkey("mod+2", "heading-2"), + THIRD: new Hotkey("mod+3", "heading-3"), + FOURTH: new Hotkey("mod+4", "heading-4"), + FIFTH: new Hotkey("mod+5", "heading-5"), + SIXTH: new Hotkey("mod+6", "heading-6"), } as const; static readonly BOLD = new Hotkey("mod+b", "bold"); // **text** static readonly ITALIC = new Hotkey("mod+i", "italic"); // _text_ @@ -31,6 +31,7 @@ export class Hotkey { private constructor( public readonly command: Command, public readonly description: Description, + public readonly handle?: void | (() => void), ) { Hotkey.validateCommand(command); } @@ -43,6 +44,20 @@ export class Hotkey { return /Mac|iPod|iPhone|iPad/.test(navigator.userAgent); })(); + // 调整为 CodeMirror 支持的快捷键形式 + get codeMirrorCommand(): string { + return this.command + .split("+") + .map((key) => { + if (key === "mod") return "Mod"; + if (key === "shift") return "Shift"; + if (key === "alt") return "Alt"; + if (key === "ctrl") return "Ctrl"; + return key.charAt(0).toLowerCase() + key.slice(1); + }) + .join("-"); + } + // 键值映射表 private static readonly KEY_MAPPING = { mod: Hotkey.isMac ? "⌘" : "Ctrl", diff --git a/packages/mini-markdown-editor/src/components/Editor/index.tsx b/packages/mini-markdown-editor/src/components/Editor/index.tsx index 606d7a9..2286f24 100644 --- a/packages/mini-markdown-editor/src/components/Editor/index.tsx +++ b/packages/mini-markdown-editor/src/components/Editor/index.tsx @@ -8,9 +8,10 @@ import { history } from "@codemirror/commands"; import { useEditorContentStore } from "@/store/editor"; import { handleEditorScroll } from "@/utils/handle-scroll"; import { useEditorShortcuts } from "@/hooks/use-editor-shortcuts"; -import { HotkeysContext } from "../providers/hotkeys-provider"; +// import { HotkeysContext } from "../providers/hotkeys-provider"; import { usePersistEditorContent } from "@/hooks/use-persist-editor-content"; import { ConfigContext } from "../providers/config-provider"; +import { markdownHotkeys } from "@/plugins/markdown-hotkeys"; const ScrollWrapper = styled.div` width: 100%; @@ -114,16 +115,16 @@ const Editor: FC<{ isSyncScroll: boolean }> = ({ isSyncScroll }) => { setScrollWrapper("editor"); }; - const { createKeymapExtension } = useContext(HotkeysContext); - // 创建扩展数组 + // const { createKeymapExtension } = useContext(HotkeysContext); + // // 创建扩展数组 const extensions = useMemo( () => [ + markdownHotkeys(), markdown({ base: markdownLanguage, codeLanguages: languages }), scrollWrapper === "editor" ? eventExt : [], - createKeymapExtension!(), history(), ], - [scrollWrapper, createKeymapExtension], + [scrollWrapper], ); const { theme } = useContext(ConfigContext); @@ -143,7 +144,7 @@ const Editor: FC<{ isSyncScroll: boolean }> = ({ isSyncScroll }) => { highlightActiveLineGutter: false, searchKeymap: false, autocompletion: false, - defaultKeymap: false, + defaultKeymap: true, }} autoFocus={true} style={{ height: "100%" }} diff --git a/packages/mini-markdown-editor/src/plugins/markdown-hotkeys.ts b/packages/mini-markdown-editor/src/plugins/markdown-hotkeys.ts new file mode 100644 index 0000000..5a596ea --- /dev/null +++ b/packages/mini-markdown-editor/src/plugins/markdown-hotkeys.ts @@ -0,0 +1,183 @@ +import { Extension } from "@codemirror/state"; +import { keymap } from "@codemirror/view"; +import { Hotkey } from "@/common/hotkeys"; +import { InsertTextEvent } from "@/config/toolbar/event"; +import { ToolbarType } from "@/types/toolbar"; + +// 定义默认快捷键支持 +const KEYMAP = { + // Headings + [Hotkey.TITLE.FIRST.codeMirrorCommand]: { + run: () => { + Hotkey.TITLE.FIRST.handle?.(); + InsertTextEvent(Hotkey.TITLE.FIRST.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.TITLE.SECOND.codeMirrorCommand]: { + run: () => { + Hotkey.TITLE.SECOND.handle?.(); + InsertTextEvent(Hotkey.TITLE.SECOND.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.TITLE.THIRD.codeMirrorCommand]: { + run: () => { + Hotkey.TITLE.THIRD.handle?.(); + InsertTextEvent(Hotkey.TITLE.THIRD.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.TITLE.FOURTH.codeMirrorCommand]: { + run: () => { + Hotkey.TITLE.FOURTH.handle?.(); + InsertTextEvent(Hotkey.TITLE.FOURTH.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.TITLE.FIFTH.codeMirrorCommand]: { + run: () => { + Hotkey.TITLE.FIFTH.handle?.(); + InsertTextEvent(Hotkey.TITLE.FIFTH.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.TITLE.SIXTH.codeMirrorCommand]: { + run: () => { + Hotkey.TITLE.SIXTH.handle?.(); + InsertTextEvent(Hotkey.TITLE.SIXTH.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + + // Text + [Hotkey.BOLD.codeMirrorCommand]: { + run: () => { + Hotkey.BOLD.handle?.(); + InsertTextEvent(Hotkey.BOLD.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.ITALIC.codeMirrorCommand]: { + run: () => { + Hotkey.ITALIC.handle?.(); + InsertTextEvent(Hotkey.ITALIC.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.UNDERLINE.codeMirrorCommand]: { + run: () => { + Hotkey.UNDERLINE.handle?.(); + InsertTextEvent(Hotkey.UNDERLINE.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.DELETE.codeMirrorCommand]: { + run: () => { + Hotkey.DELETE.handle?.(); + InsertTextEvent(Hotkey.DELETE.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + + // Block elements + [Hotkey.BLOCKQUOTE.codeMirrorCommand]: { + run: () => { + Hotkey.BLOCKQUOTE.handle?.(); + InsertTextEvent(Hotkey.BLOCKQUOTE.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.UNORDERED_LIST.codeMirrorCommand]: { + run: () => { + Hotkey.UNORDERED_LIST.handle?.(); + InsertTextEvent(Hotkey.UNORDERED_LIST.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.ORDERED_LIST.codeMirrorCommand]: { + run: () => { + Hotkey.ORDERED_LIST.handle?.(); + InsertTextEvent(Hotkey.ORDERED_LIST.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + + // Code + [Hotkey.INLINE_CODE.codeMirrorCommand]: { + run: () => { + Hotkey.INLINE_CODE.handle?.(); + InsertTextEvent(Hotkey.INLINE_CODE.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.CODE_BLOCK.codeMirrorCommand]: { + run: () => { + Hotkey.CODE_BLOCK.handle?.(); + InsertTextEvent(Hotkey.CODE_BLOCK.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + + // Other elements + [Hotkey.LINK.codeMirrorCommand]: { + run: () => { + Hotkey.LINK.handle?.(); + InsertTextEvent(Hotkey.LINK.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.TABLE.codeMirrorCommand]: { + run: () => { + Hotkey.TABLE.handle?.(); + InsertTextEvent(Hotkey.TABLE.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + + // Actions + [Hotkey.FULL_SCREEN.codeMirrorCommand]: { + run: () => { + Hotkey.FULL_SCREEN.handle?.(); + InsertTextEvent(Hotkey.FULL_SCREEN.description as ToolbarType); + return true; + }, + preventDefault: true, + }, + [Hotkey.SAVE.codeMirrorCommand]: { + run: () => { + Hotkey.SAVE.handle?.(); + InsertTextEvent(Hotkey.SAVE.description as ToolbarType); + return true; + }, + preventDefault: true, + }, +}; + +export function markdownHotkeys(): Extension { + return keymap.of([ + ...Object.entries(KEYMAP).map(([key, value]) => ({ + key, + ...value, + })), + + //! 留空 暴露外部其他内部快捷键 + ]); +} -- Gitee From 70a721eef86e8c6db57a98e8f3db71e3a15f484e Mon Sep 17 00:00:00 2001 From: tabzzz Date: Tue, 4 Feb 2025 02:58:58 +0800 Subject: [PATCH 2/5] =?UTF-8?q?refactor(mini-markdown-editor):=20=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=8C=96=E5=88=92=E5=88=86=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Editor/index.tsx | 16 +++--------- .../src/extensions/codemirror/event.ts | 14 ++++++++++ .../codemirror/hotkeys.ts} | 2 +- .../src/extensions/codemirror/index.ts | 26 +++++++++++++++++++ .../src/extensions/codemirror/markdown.ts | 10 +++++++ 5 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 packages/mini-markdown-editor/src/extensions/codemirror/event.ts rename packages/mini-markdown-editor/src/{plugins/markdown-hotkeys.ts => extensions/codemirror/hotkeys.ts} (98%) create mode 100644 packages/mini-markdown-editor/src/extensions/codemirror/index.ts create mode 100644 packages/mini-markdown-editor/src/extensions/codemirror/markdown.ts diff --git a/packages/mini-markdown-editor/src/components/Editor/index.tsx b/packages/mini-markdown-editor/src/components/Editor/index.tsx index 2286f24..016c68d 100644 --- a/packages/mini-markdown-editor/src/components/Editor/index.tsx +++ b/packages/mini-markdown-editor/src/components/Editor/index.tsx @@ -1,17 +1,13 @@ import { FC, useCallback, useContext, useEffect, useMemo, useRef } from "react"; import styled from "styled-components"; import CodeMirror, { type EditorView, ViewUpdate } from "@uiw/react-codemirror"; -import { markdown, markdownLanguage } from "@codemirror/lang-markdown"; -import { languages } from "@codemirror/language-data"; import * as events from "@uiw/codemirror-extensions-events"; -import { history } from "@codemirror/commands"; import { useEditorContentStore } from "@/store/editor"; import { handleEditorScroll } from "@/utils/handle-scroll"; import { useEditorShortcuts } from "@/hooks/use-editor-shortcuts"; -// import { HotkeysContext } from "../providers/hotkeys-provider"; import { usePersistEditorContent } from "@/hooks/use-persist-editor-content"; import { ConfigContext } from "../providers/config-provider"; -import { markdownHotkeys } from "@/plugins/markdown-hotkeys"; +import { createEditorExtensions } from "@/extensions/codemirror"; const ScrollWrapper = styled.div` width: 100%; @@ -115,15 +111,9 @@ const Editor: FC<{ isSyncScroll: boolean }> = ({ isSyncScroll }) => { setScrollWrapper("editor"); }; - // const { createKeymapExtension } = useContext(HotkeysContext); - // // 创建扩展数组 + // 创建编辑器扩展 const extensions = useMemo( - () => [ - markdownHotkeys(), - markdown({ base: markdownLanguage, codeLanguages: languages }), - scrollWrapper === "editor" ? eventExt : [], - history(), - ], + () => createEditorExtensions({ scrollWrapper, eventExt }), [scrollWrapper], ); diff --git a/packages/mini-markdown-editor/src/extensions/codemirror/event.ts b/packages/mini-markdown-editor/src/extensions/codemirror/event.ts new file mode 100644 index 0000000..abe97ff --- /dev/null +++ b/packages/mini-markdown-editor/src/extensions/codemirror/event.ts @@ -0,0 +1,14 @@ +import { EditorView, ViewPlugin } from "@uiw/react-codemirror"; + +interface EventOptions { + scrollWrapper: string; + eventExt?: ViewPlugin<{ + dom?: HTMLElement; + view: EditorView; + destroy(): void; + }>; +} + +export const createEventExtension = (eventOptions: EventOptions): any => { + return eventOptions.scrollWrapper === "editor" ? eventOptions.eventExt : []; +}; diff --git a/packages/mini-markdown-editor/src/plugins/markdown-hotkeys.ts b/packages/mini-markdown-editor/src/extensions/codemirror/hotkeys.ts similarity index 98% rename from packages/mini-markdown-editor/src/plugins/markdown-hotkeys.ts rename to packages/mini-markdown-editor/src/extensions/codemirror/hotkeys.ts index 5a596ea..65f40b6 100644 --- a/packages/mini-markdown-editor/src/plugins/markdown-hotkeys.ts +++ b/packages/mini-markdown-editor/src/extensions/codemirror/hotkeys.ts @@ -171,7 +171,7 @@ const KEYMAP = { }, }; -export function markdownHotkeys(): Extension { +export function createHotkeysExtension(): Extension { return keymap.of([ ...Object.entries(KEYMAP).map(([key, value]) => ({ key, diff --git a/packages/mini-markdown-editor/src/extensions/codemirror/index.ts b/packages/mini-markdown-editor/src/extensions/codemirror/index.ts new file mode 100644 index 0000000..3679869 --- /dev/null +++ b/packages/mini-markdown-editor/src/extensions/codemirror/index.ts @@ -0,0 +1,26 @@ +import { Extension } from "@codemirror/state"; +import { EditorView, ViewPlugin } from "@uiw/react-codemirror"; +import { history } from "@codemirror/commands"; +import { createMarkdownExtension } from "./markdown"; +import { createHotkeysExtension } from "./hotkeys"; +import { createEventExtension } from "./event"; + +interface ExtensionOptions { + scrollWrapper?: string; + eventExt?: ViewPlugin<{ + dom?: HTMLElement; + view: EditorView; + destroy(): void; + }>; +} + +export const createEditorExtensions = (options: ExtensionOptions = {}): Extension[] => { + const { scrollWrapper = "editor", eventExt } = options; + + return [ + createHotkeysExtension(), + createMarkdownExtension(), + createEventExtension({ scrollWrapper, eventExt }), + history(), + ]; +}; diff --git a/packages/mini-markdown-editor/src/extensions/codemirror/markdown.ts b/packages/mini-markdown-editor/src/extensions/codemirror/markdown.ts new file mode 100644 index 0000000..b5237a8 --- /dev/null +++ b/packages/mini-markdown-editor/src/extensions/codemirror/markdown.ts @@ -0,0 +1,10 @@ +import { markdown } from "@codemirror/lang-markdown"; +import { languages } from "@codemirror/language-data"; +import { markdownLanguage } from "@codemirror/lang-markdown"; + +export const createMarkdownExtension = () => { + return markdown({ + base: markdownLanguage, + codeLanguages: languages, + }); +}; -- Gitee From 6a3a05a576302fcad6f523b872a88bd8cb2dc032 Mon Sep 17 00:00:00 2001 From: tabzzz Date: Tue, 4 Feb 2025 03:51:25 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat(mini-markdown-editor):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=B7=A5=E5=85=B7=E6=A0=8Ftooltip=E7=9A=84=E5=8F=8C?= =?UTF-8?q?=E5=B1=82=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mini-markdown-editor/src/common/help.ts | 15 +++++++++++++++ .../mini-markdown-editor/src/common/hotkeys.ts | 18 +++++++++++++++++- .../src/components/Editor/index.tsx | 4 ++-- .../src/components/Toolbar/ToolbarItem.tsx | 13 ++++++++++--- .../src/components/base/IconTooltip.tsx | 16 ++++++++++++++-- .../src/config/toolbar/base.tsx | 15 +++++++++++++++ .../mini-markdown-editor/src/types/toolbar.ts | 1 + 7 files changed, 74 insertions(+), 8 deletions(-) diff --git a/packages/mini-markdown-editor/src/common/help.ts b/packages/mini-markdown-editor/src/common/help.ts index bac993b..279988b 100644 --- a/packages/mini-markdown-editor/src/common/help.ts +++ b/packages/mini-markdown-editor/src/common/help.ts @@ -31,6 +31,21 @@ export const grammar = [ icon: Heading3, rule: "### heading", }, + // { + // title: "四级标题", + // icon: Heading4, + // rule: "#### heading", + // }, + // { + // title: "五级标题", + // icon: Heading5, + // rule: "##### heading", + // }, + // { + // title: "六级标题", + // icon: Heading6, + // rule: "###### heading", + // }, { title: "加粗", icon: Bold, diff --git a/packages/mini-markdown-editor/src/common/hotkeys.ts b/packages/mini-markdown-editor/src/common/hotkeys.ts index fe93cf3..c12983e 100644 --- a/packages/mini-markdown-editor/src/common/hotkeys.ts +++ b/packages/mini-markdown-editor/src/common/hotkeys.ts @@ -22,7 +22,9 @@ export class Hotkey { static readonly CODE_BLOCK = new Hotkey("mod+alt+c", "code"); // ```code``` static readonly LINK = new Hotkey("mod+k", "link"); // [text](url) static readonly TABLE = new Hotkey("mod+alt+t", "table"); // table - //? undo和redo在此不定义,此快捷键在文本框自带 + //! 为避免冲突,此处使用cm的history插件,不手动实现undo和redo功能 + static readonly UNDO = new Hotkey("mod+z", "undo"); // undo + static readonly REDO = new Hotkey("mod+shift+z", "redo"); // redo static readonly FULL_SCREEN = new Hotkey("mod+alt+f", "fullscreen"); // fullscreen // Actions @@ -58,6 +60,20 @@ export class Hotkey { .join("-"); } + // 实现供展示快捷键的转换 + get displayCommand(): string { + return this.command + .split("+") + .map((key) => { + if (key === "mod") return Hotkey.isMac ? "⌘" : "Ctrl"; + if (key === "shift") return "⇧"; + if (key === "alt") return Hotkey.isMac ? "⌥" : "Alt"; + if (key === "ctrl") return Hotkey.isMac ? "⌃" : "Ctrl"; + return key.charAt(0).toUpperCase() + key.slice(1); + }) + .join(" + "); + } + // 键值映射表 private static readonly KEY_MAPPING = { mod: Hotkey.isMac ? "⌘" : "Ctrl", diff --git a/packages/mini-markdown-editor/src/components/Editor/index.tsx b/packages/mini-markdown-editor/src/components/Editor/index.tsx index 016c68d..e1650ba 100644 --- a/packages/mini-markdown-editor/src/components/Editor/index.tsx +++ b/packages/mini-markdown-editor/src/components/Editor/index.tsx @@ -4,7 +4,7 @@ import CodeMirror, { type EditorView, ViewUpdate } from "@uiw/react-codemirror"; import * as events from "@uiw/codemirror-extensions-events"; import { useEditorContentStore } from "@/store/editor"; import { handleEditorScroll } from "@/utils/handle-scroll"; -import { useEditorShortcuts } from "@/hooks/use-editor-shortcuts"; +// import { useEditorShortcuts } from "@/hooks/use-editor-shortcuts"; import { usePersistEditorContent } from "@/hooks/use-persist-editor-content"; import { ConfigContext } from "../providers/config-provider"; import { createEditorExtensions } from "@/extensions/codemirror"; @@ -59,7 +59,7 @@ const Editor: FC<{ isSyncScroll: boolean }> = ({ isSyncScroll }) => { [editorViewRef], ); // 监听快捷键 - useEditorShortcuts(); + // useEditorShortcuts(); // 持久化存储内容 const { saveContent, getContent } = usePersistEditorContent(); diff --git a/packages/mini-markdown-editor/src/components/Toolbar/ToolbarItem.tsx b/packages/mini-markdown-editor/src/components/Toolbar/ToolbarItem.tsx index 3311025..e41d9ae 100644 --- a/packages/mini-markdown-editor/src/components/Toolbar/ToolbarItem.tsx +++ b/packages/mini-markdown-editor/src/components/Toolbar/ToolbarItem.tsx @@ -40,11 +40,18 @@ const ToolbarItemWrapper = styled.div` } `; -const ToolbarItemRender: FC = ({ list, title, icon, onClick, component }) => { +const ToolbarItemRender: FC = ({ + list, + title, + description, + icon, + onClick, + component, +}) => { if (list && list.length > 0) { return ( <> - + {/* {title} */} {icon &&
} @@ -57,7 +64,7 @@ const ToolbarItemRender: FC = ({ list, title, icon, onClick, co } else { return ( <> - + {/* {title} */} {icon &&
}
diff --git a/packages/mini-markdown-editor/src/components/base/IconTooltip.tsx b/packages/mini-markdown-editor/src/components/base/IconTooltip.tsx index 0387fbd..2e5c922 100644 --- a/packages/mini-markdown-editor/src/components/base/IconTooltip.tsx +++ b/packages/mini-markdown-editor/src/components/base/IconTooltip.tsx @@ -3,11 +3,23 @@ import { Tooltip } from "antd"; const IconTooltip: FC<{ content: string | React.ReactNode; + description?: string; children: React.ReactNode; onClick?: () => void; -}> = ({ content, children, onClick }) => { +}> = ({ content, description, children, onClick }) => { + const title = ( +
+
{content}
+
{description}
+
+ ); return ( - +
{children}
); diff --git a/packages/mini-markdown-editor/src/config/toolbar/base.tsx b/packages/mini-markdown-editor/src/config/toolbar/base.tsx index da24b69..bfc0649 100644 --- a/packages/mini-markdown-editor/src/config/toolbar/base.tsx +++ b/packages/mini-markdown-editor/src/config/toolbar/base.tsx @@ -20,6 +20,8 @@ import { ToolbarItem } from "@/types/toolbar"; import Upload from "@/components/Toolbar/Upload"; import FullScreen from "@/components/Toolbar/FullScreen"; import { Contents, Read, Write, Help, Output } from "@/components/Toolbar/ShowLayout"; +// 快捷键描述 +import { Hotkey } from "@/common/hotkeys"; export const toolbar: ToolbarItem[] = [ { @@ -63,24 +65,28 @@ export const toolbar: ToolbarItem[] = [ type: "bold", icon: BoldIcon, title: "加粗", + description: Hotkey.BOLD.displayCommand, onClick: () => InsertTextEvent("bold"), }, { type: "italic", icon: ItalicIcon, title: "斜体", + description: Hotkey.ITALIC.displayCommand, onClick: () => InsertTextEvent("italic"), }, { type: "underline", icon: UnderlineIcon, title: "下划线", + description: Hotkey.UNDERLINE.displayCommand, onClick: () => InsertTextEvent("underline"), }, { type: "delete", icon: DeleteIcon, title: "删除线", + description: Hotkey.DELETE.displayCommand, onClick: () => InsertTextEvent("delete"), }, { @@ -90,36 +96,42 @@ export const toolbar: ToolbarItem[] = [ type: "blockquote", icon: BlockquoteIcon, title: "引用", + description: Hotkey.BLOCKQUOTE.displayCommand, onClick: () => InsertTextEvent("blockquote"), }, { type: "ul", icon: UlIcon, title: "无序列表", + description: Hotkey.UNORDERED_LIST.displayCommand, onClick: () => InsertTextEvent("ul"), }, { type: "ol", icon: OlIcon, title: "有序列表", + description: Hotkey.ORDERED_LIST.displayCommand, onClick: () => InsertTextEvent("ol"), }, { type: "inlinecode", icon: InlineCodeIcon, title: "行内代码", + description: Hotkey.INLINE_CODE.displayCommand, onClick: () => InsertTextEvent("inlinecode"), }, { type: "code", icon: CodeIcon, title: "代码块", + description: Hotkey.CODE_BLOCK.displayCommand, onClick: () => InsertTextEvent("code"), }, { type: "link", icon: LinkIcon, title: "链接", + description: Hotkey.LINK.displayCommand, onClick: () => InsertTextEvent("link"), }, { @@ -142,6 +154,7 @@ export const toolbar: ToolbarItem[] = [ type: "table", icon: TableIcon, title: "表格", + description: Hotkey.TABLE.displayCommand, onClick: () => InsertTextEvent("table"), }, { @@ -151,12 +164,14 @@ export const toolbar: ToolbarItem[] = [ type: "undo", icon: Undo, title: "撤销", + description: Hotkey.UNDO.displayCommand, onClick: () => UndoEvent(), }, { type: "redo", icon: Redo, title: "重做", + description: Hotkey.REDO.displayCommand, onClick: () => RedoEvent(), }, { diff --git a/packages/mini-markdown-editor/src/types/toolbar.ts b/packages/mini-markdown-editor/src/types/toolbar.ts index 5295325..b8ed662 100644 --- a/packages/mini-markdown-editor/src/types/toolbar.ts +++ b/packages/mini-markdown-editor/src/types/toolbar.ts @@ -2,6 +2,7 @@ export interface ToolbarItem { type: ToolbarType; icon?: string; title?: string; + description?: string; list?: ToolbarItemListItem[]; disabled?: boolean; visible?: boolean; -- Gitee From c5def6e1ca39aa7891f4bbeb46505fa45be5e2e4 Mon Sep 17 00:00:00 2001 From: tabzzz Date: Tue, 4 Feb 2025 04:09:58 +0800 Subject: [PATCH 4/5] =?UTF-8?q?chore(mini-markdown-editor):=20=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E6=B7=BB=E5=8A=A0=E5=B8=AE=E5=8A=A9=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mini-markdown-editor/src/common/help.ts | 70 +++++++++++++++++-- .../src/common/hotkeys.ts | 64 +++++------------ .../src/config/toolbar/base.tsx | 26 +++---- 3 files changed, 93 insertions(+), 67 deletions(-) diff --git a/packages/mini-markdown-editor/src/common/help.ts b/packages/mini-markdown-editor/src/common/help.ts index 279988b..3543a8a 100644 --- a/packages/mini-markdown-editor/src/common/help.ts +++ b/packages/mini-markdown-editor/src/common/help.ts @@ -11,9 +11,14 @@ import Ol from "@/assets/images/ol.svg?raw"; import InlineCode from "@/assets/images/inlinecode.svg?raw"; import Code from "@/assets/images/code.svg?raw"; import Link from "@/assets/images/link.svg?raw"; +import TableIcon from "@/assets/images/table.svg?raw"; +import Undo from "@/assets/images/undo.svg?raw"; +import Redo from "@/assets/images/redo.svg?raw"; import Image from "@/assets/images/image.svg?raw"; import ThematicBreak from "@/assets/images/thematic-break.svg?raw"; +import { Hotkey } from "./hotkeys"; + // markdown语法规则 export const grammar = [ { @@ -108,28 +113,81 @@ export const grammar = [ }, ]; -const isMac = /Mac/.test(navigator.userAgent); - // 快捷键 export const shortcuts = [ { title: "加粗", icon: Bold, - rule: isMac ? "Cmd + B" : "Ctrl + B", + rule: Hotkey.BOLD.helpCommand, }, { title: "斜体", icon: Italic, - rule: isMac ? "Cmd + I" : "Ctrl + I", + rule: Hotkey.ITALIC.helpCommand, }, { title: "下划线", icon: Underline, - rule: isMac ? "Cmd + U" : "Ctrl + U", + rule: Hotkey.UNDERLINE.helpCommand, }, { title: "删除线", icon: Delete, - rule: isMac ? "Cmd + D" : "Ctrl + D", + rule: Hotkey.DELETE.helpCommand, + }, + { + title: "引用", + icon: Blockquote, + rule: Hotkey.BLOCKQUOTE.helpCommand, + }, + { + title: "无序列表", + icon: Ul, + rule: Hotkey.UNORDERED_LIST.helpCommand, + }, + { + title: "有序列表", + icon: Ol, + rule: Hotkey.ORDERED_LIST.helpCommand, + }, + { + title: "内联代码", + icon: InlineCode, + rule: Hotkey.INLINE_CODE.helpCommand, + }, + { + title: "代码块", + icon: Code, + rule: Hotkey.CODE_BLOCK.helpCommand, + }, + { + title: "链接", + icon: Link, + rule: Hotkey.LINK.helpCommand, + }, + { + title: "表格", + icon: TableIcon, + rule: Hotkey.TABLE.helpCommand, + }, + { + title: "撤销", + icon: Undo, + rule: Hotkey.UNDO.helpCommand, + }, + { + title: "重做", + icon: Redo, + rule: Hotkey.REDO.helpCommand, + }, + { + title: "全屏", + icon: "", + rule: Hotkey.FULL_SCREEN.helpCommand, + }, + { + title: "保存", + icon: "", + rule: Hotkey.SAVE.helpCommand, }, ]; diff --git a/packages/mini-markdown-editor/src/common/hotkeys.ts b/packages/mini-markdown-editor/src/common/hotkeys.ts index c12983e..cde6d7f 100644 --- a/packages/mini-markdown-editor/src/common/hotkeys.ts +++ b/packages/mini-markdown-editor/src/common/hotkeys.ts @@ -60,32 +60,15 @@ export class Hotkey { .join("-"); } - // 实现供展示快捷键的转换 - get displayCommand(): string { - return this.command - .split("+") - .map((key) => { - if (key === "mod") return Hotkey.isMac ? "⌘" : "Ctrl"; - if (key === "shift") return "⇧"; - if (key === "alt") return Hotkey.isMac ? "⌥" : "Alt"; - if (key === "ctrl") return Hotkey.isMac ? "⌃" : "Ctrl"; - return key.charAt(0).toUpperCase() + key.slice(1); - }) - .join(" + "); - } - // 键值映射表 private static readonly KEY_MAPPING = { mod: Hotkey.isMac ? "⌘" : "Ctrl", shift: "⇧", alt: Hotkey.isMac ? "⌥" : "Alt", ctrl: Hotkey.isMac ? "⌃" : "Ctrl", - equal: "=", - minus: "-", - plus: "+", } as const; - // 优化后的readableCommand方法 + // 供工具栏使用的可读性更好的快捷键 get readableCommand(): string { return this.command .split("+") @@ -94,37 +77,22 @@ export class Hotkey { Hotkey.KEY_MAPPING[key as keyof typeof Hotkey.KEY_MAPPING] || key.charAt(0).toUpperCase() + key.slice(1), ) - .join(" "); + .join(" + "); + } + + // 供帮助文档使用的可读性更好的快捷键 + get helpCommand(): string { + return this.command + .split("+") + .map((key) => { + if (key === "mod") return "Mod"; + if (key === "shift") return "Shift"; + if (key === "alt") return "Alt"; + if (key === "ctrl") return "Ctrl"; + return key.charAt(0).toUpperCase() + key.slice(1); + }) + .join("+"); } - // 第一版-非常朴素的写法 - // get readableCommand() { - // const isMac = process.platform === "darwin"; - // return this.command - // .replace("mod", isMac ? "⌘" : "Ctrl") - // .split("+") - // .map((value) => { - // if (value === "shift") { - // return "⇧"; - // } - // if (value === "alt") { - // return isMac ? "⌥" : "Alt"; - // } - // if (value === "ctrl") { - // return isMac ? "⌃" : "Ctrl"; - // } - // if (value === "equal") { - // return "="; - // } - // if (value === "minus") { - // return "-"; - // } - // if (value === "plus") { - // return "+"; - // } - // return value.charAt(0).toUpperCase() + value.slice(1); - // }) - // .join(" "); - // } // 添加修饰键验证机制 //! 如果后续添加单键支持要修改这里,否则不生效 diff --git a/packages/mini-markdown-editor/src/config/toolbar/base.tsx b/packages/mini-markdown-editor/src/config/toolbar/base.tsx index bfc0649..84c7cc0 100644 --- a/packages/mini-markdown-editor/src/config/toolbar/base.tsx +++ b/packages/mini-markdown-editor/src/config/toolbar/base.tsx @@ -65,28 +65,28 @@ export const toolbar: ToolbarItem[] = [ type: "bold", icon: BoldIcon, title: "加粗", - description: Hotkey.BOLD.displayCommand, + description: Hotkey.BOLD.readableCommand, onClick: () => InsertTextEvent("bold"), }, { type: "italic", icon: ItalicIcon, title: "斜体", - description: Hotkey.ITALIC.displayCommand, + description: Hotkey.ITALIC.readableCommand, onClick: () => InsertTextEvent("italic"), }, { type: "underline", icon: UnderlineIcon, title: "下划线", - description: Hotkey.UNDERLINE.displayCommand, + description: Hotkey.UNDERLINE.readableCommand, onClick: () => InsertTextEvent("underline"), }, { type: "delete", icon: DeleteIcon, title: "删除线", - description: Hotkey.DELETE.displayCommand, + description: Hotkey.DELETE.readableCommand, onClick: () => InsertTextEvent("delete"), }, { @@ -96,42 +96,42 @@ export const toolbar: ToolbarItem[] = [ type: "blockquote", icon: BlockquoteIcon, title: "引用", - description: Hotkey.BLOCKQUOTE.displayCommand, + description: Hotkey.BLOCKQUOTE.readableCommand, onClick: () => InsertTextEvent("blockquote"), }, { type: "ul", icon: UlIcon, title: "无序列表", - description: Hotkey.UNORDERED_LIST.displayCommand, + description: Hotkey.UNORDERED_LIST.readableCommand, onClick: () => InsertTextEvent("ul"), }, { type: "ol", icon: OlIcon, title: "有序列表", - description: Hotkey.ORDERED_LIST.displayCommand, + description: Hotkey.ORDERED_LIST.readableCommand, onClick: () => InsertTextEvent("ol"), }, { type: "inlinecode", icon: InlineCodeIcon, title: "行内代码", - description: Hotkey.INLINE_CODE.displayCommand, + description: Hotkey.INLINE_CODE.readableCommand, onClick: () => InsertTextEvent("inlinecode"), }, { type: "code", icon: CodeIcon, title: "代码块", - description: Hotkey.CODE_BLOCK.displayCommand, + description: Hotkey.CODE_BLOCK.readableCommand, onClick: () => InsertTextEvent("code"), }, { type: "link", icon: LinkIcon, title: "链接", - description: Hotkey.LINK.displayCommand, + description: Hotkey.LINK.readableCommand, onClick: () => InsertTextEvent("link"), }, { @@ -154,7 +154,7 @@ export const toolbar: ToolbarItem[] = [ type: "table", icon: TableIcon, title: "表格", - description: Hotkey.TABLE.displayCommand, + description: Hotkey.TABLE.readableCommand, onClick: () => InsertTextEvent("table"), }, { @@ -164,14 +164,14 @@ export const toolbar: ToolbarItem[] = [ type: "undo", icon: Undo, title: "撤销", - description: Hotkey.UNDO.displayCommand, + description: Hotkey.UNDO.readableCommand, onClick: () => UndoEvent(), }, { type: "redo", icon: Redo, title: "重做", - description: Hotkey.REDO.displayCommand, + description: Hotkey.REDO.readableCommand, onClick: () => RedoEvent(), }, { -- Gitee From f0eabe5d7c04d3ee853f81746caf51aeead7f9d7 Mon Sep 17 00:00:00 2001 From: tabzzz Date: Tue, 4 Feb 2025 04:31:27 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix(mini-markdown-editor):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8Dheading=E8=B5=B7=E6=9C=AB=E4=BD=8D=E7=BD=AE=E9=94=99?= =?UTF-8?q?=E4=B9=B1=EF=BC=8C=E8=A1=A5=E5=85=85=E5=B7=A5=E5=85=B7=E6=A0=8F?= =?UTF-8?q?tooltip=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/mini-markdown-editor/src/common/help.ts | 3 ++- .../src/components/Toolbar/FullScreen.tsx | 7 ++++++- .../src/config/toolbar/template.ts | 10 +++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/mini-markdown-editor/src/common/help.ts b/packages/mini-markdown-editor/src/common/help.ts index 3543a8a..406038c 100644 --- a/packages/mini-markdown-editor/src/common/help.ts +++ b/packages/mini-markdown-editor/src/common/help.ts @@ -16,6 +16,7 @@ import Undo from "@/assets/images/undo.svg?raw"; import Redo from "@/assets/images/redo.svg?raw"; import Image from "@/assets/images/image.svg?raw"; import ThematicBreak from "@/assets/images/thematic-break.svg?raw"; +import FullScreenIcon from "@/assets/images/fullscreen.svg?raw"; import { Hotkey } from "./hotkeys"; @@ -182,7 +183,7 @@ export const shortcuts = [ }, { title: "全屏", - icon: "", + icon: FullScreenIcon, rule: Hotkey.FULL_SCREEN.helpCommand, }, { diff --git a/packages/mini-markdown-editor/src/components/Toolbar/FullScreen.tsx b/packages/mini-markdown-editor/src/components/Toolbar/FullScreen.tsx index 3066968..ef8c666 100644 --- a/packages/mini-markdown-editor/src/components/Toolbar/FullScreen.tsx +++ b/packages/mini-markdown-editor/src/components/Toolbar/FullScreen.tsx @@ -2,6 +2,7 @@ import FullScreenIcon from "@/assets/images/fullscreen.svg?raw"; import ExitFullScreenIcon from "@/assets/images/exit-fullscreen.svg?raw"; import IconTooltip from "../base/IconTooltip"; import { useToolbarStore } from "@/store/toolbar"; +import { Hotkey } from "@/common/hotkeys"; const FullScreen = () => { const isFullScreen = useToolbarStore((state) => state.isFullScreen); @@ -9,7 +10,11 @@ const FullScreen = () => { return ( <> - setIsFullScreen(!isFullScreen)}> + setIsFullScreen(!isFullScreen)} + > {/* {"全屏"} */}