From 236c8f387e31732043d1c8cfd31cf565bf38093a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?wifi=E6=AD=AAf?= <1402772884@qq.com>
Date: Mon, 27 Jan 2025 10:14:01 +0800
Subject: [PATCH] =?UTF-8?q?feat(mini-markdown-editor):=20=E9=87=8D?=
=?UTF-8?q?=E6=9E=84=E6=B8=B2=E6=9F=93=E5=B8=83=E5=B1=80,=20=E6=94=AF?=
=?UTF-8?q?=E6=8C=81=E4=BE=A7=E8=BE=B9=E6=A0=8F=E6=B8=B2=E6=9F=93,=20?=
=?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8F=AA=E5=86=99=E3=80=81=E4=BB=85=E9=A2=84?=
=?UTF-8?q?=E8=A7=88=E6=8C=89=E9=92=AE=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/core/transform/render/link.ts | 10 +-
.../src/EditorWrapper.tsx | 92 +++++++++++++++----
.../src/components/Toolbar/ShowLayout.tsx | 40 ++++++++
.../src/components/Toolbar/ToolbarItem.tsx | 1 +
.../src/config/toolbar/base.tsx | 9 +-
.../mini-markdown-editor/src/store/toolbar.ts | 23 ++++-
6 files changed, 145 insertions(+), 30 deletions(-)
create mode 100644 packages/mini-markdown-editor/src/components/Toolbar/ShowLayout.tsx
diff --git a/packages/mini-markdown-ast-parser/src/core/transform/render/link.ts b/packages/mini-markdown-ast-parser/src/core/transform/render/link.ts
index 956165e..4a7eca6 100644
--- a/packages/mini-markdown-ast-parser/src/core/transform/render/link.ts
+++ b/packages/mini-markdown-ast-parser/src/core/transform/render/link.ts
@@ -1,7 +1,7 @@
-import { Tokens } from '@/types/tokens'
-import { astToHtml } from '..'
-import { prefix } from '@/common/constant'
+import { Tokens } from "@/types/tokens";
+import { astToHtml } from "..";
+import { prefix } from "@/common/constant";
export const renderLink = (node: Tokens) => {
- return `${astToHtml(node.children![0])}`
-}
+ return `${astToHtml(node.children![0])}`;
+};
diff --git a/packages/mini-markdown-editor/src/EditorWrapper.tsx b/packages/mini-markdown-editor/src/EditorWrapper.tsx
index 62e1d59..d009c1c 100644
--- a/packages/mini-markdown-editor/src/EditorWrapper.tsx
+++ b/packages/mini-markdown-editor/src/EditorWrapper.tsx
@@ -1,4 +1,4 @@
-import { FC, useDeferredValue } from "react";
+import { FC, Fragment, useDeferredValue } from "react";
import styled from "styled-components";
import { useEditorContentStore } from "@/store/editor";
import Toolbar from "@/components/Toolbar";
@@ -42,7 +42,10 @@ const ContentWrapper = styled.div`
`;
const StyledRow = styled(Row)`
+ width: 100%;
height: 100%;
+ display: flex;
+ justify-content: center;
.ant-col {
height: 100%;
overflow-y: auto;
@@ -62,12 +65,80 @@ const Divider = styled.div`
height: 100%;
width: 1px;
position: absolute;
- left: 50%;
top: 50%;
- transform: translate(-50%, -50%);
z-index: 1;
`;
+// 布局配置映射
+const LayoutConfig = {
+ // 只写模式
+ WRITE_ONLY: { cols: [18], components: ["editor"] },
+ // 仅预览模式
+ READ_ONLY: { cols: [18], components: ["preview"] },
+ // 读写模式
+ READ_WRITE: { cols: [12, 12], components: ["editor", "preview"] },
+ // 只写+侧边栏
+ WRITE_ONLY_SIDEBAR: { cols: [18, 6], components: ["editor", "sidebar"] },
+ // 仅预览+侧边栏
+ READ_ONLY_SIDEBAR: { cols: [18, 6], components: ["preview", "sidebar"] },
+ // 读写+侧边栏
+ READ_WRITE_SIDEBAR: { cols: [9, 9, 6], components: ["editor", "preview", "sidebar"] },
+};
+
+// 渲染不同分区
+const RenderRow: FC<{
+ editor: React.ReactNode;
+ preview: React.ReactNode;
+}> = ({ editor, preview }) => {
+ const { isOnlyWrite, isOnlyPreview, isSidebar, sidebarComponent } = useToolbarStore();
+
+ // 根据状态确定布局配置
+ const getLayoutConfig = () => {
+ // 处理只写模式
+ if (isOnlyWrite && !isOnlyPreview) {
+ return isSidebar ? LayoutConfig.WRITE_ONLY_SIDEBAR : LayoutConfig.WRITE_ONLY;
+ }
+ // 处理只读模式
+ if (!isOnlyWrite && isOnlyPreview) {
+ return isSidebar ? LayoutConfig.READ_ONLY_SIDEBAR : LayoutConfig.READ_ONLY;
+ }
+ // 处理读写模式(默认模式)
+ if (!isOnlyWrite && !isOnlyPreview) {
+ return isSidebar ? LayoutConfig.READ_WRITE_SIDEBAR : LayoutConfig.READ_WRITE;
+ }
+ // 处理异常情况(都为true的情况),默认返回只写模式
+ return isSidebar ? LayoutConfig.WRITE_ONLY_SIDEBAR : LayoutConfig.WRITE_ONLY;
+ };
+
+ const layout = getLayoutConfig();
+ const components = {
+ editor,
+ preview,
+ sidebar: sidebarComponent,
+ };
+ // 两列以上时显示分割线
+ const showDivider = layout.cols.length > 1;
+
+ return (
+ <>
+ {layout.cols.map((span, index) => {
+ const offset =
+ (layout.cols.slice(0, index + 1).reduce((acc, curr) => acc + curr, 0) /
+ layout.cols.reduce((acc, curr) => acc + curr, 0)) *
+ 100;
+ return (
+
+ {components[layout.components[index] as keyof typeof components]}
+ {showDivider && (
+
+ )}
+
+ );
+ })}
+ >
+ );
+};
+
const EditorWrapper: FC = (config) => {
const content = useEditorContentStore((state) => state.content);
const deferredContent = useDeferredValue(content);
@@ -84,21 +155,8 @@ const EditorWrapper: FC = (config) => {
{/* 内容区域 */}
-
- {/* 编辑区 */}
-
-
-
- {/* 渲染区 */}
-
-
-
- {/* 渲染区 */}
- 123
-
+ } preview={} />
- {/* 分割线 */}
-
{/* 底部状态栏 */}
diff --git a/packages/mini-markdown-editor/src/components/Toolbar/ShowLayout.tsx b/packages/mini-markdown-editor/src/components/Toolbar/ShowLayout.tsx
new file mode 100644
index 0000000..e16bcdd
--- /dev/null
+++ b/packages/mini-markdown-editor/src/components/Toolbar/ShowLayout.tsx
@@ -0,0 +1,40 @@
+import { FC } from "react";
+import styled from "styled-components";
+import IconTooltip from "../base/IconTooltip";
+import WriteIcon from "@/assets/images/write.svg?raw";
+import PreviewIcon from "@/assets/images/perview.svg?raw";
+import { useToolbarStore } from "@/store/toolbar";
+
+const Wrapper = styled.div<{ $isSelect: boolean }>`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ color: ${(props) => (props.$isSelect ? "#0366d6" : "")};
+`;
+
+export const Write: FC = () => {
+ const { isOnlyWrite, setIsOnlyWrite } = useToolbarStore();
+ return (
+ <>
+ setIsOnlyWrite()}>
+
+
+ >
+ );
+};
+
+export const Read: FC = () => {
+ const { isOnlyPreview, setIsOnlyPreview } = useToolbarStore();
+ return (
+ <>
+ setIsOnlyPreview()}>
+
+
+ >
+ );
+};
diff --git a/packages/mini-markdown-editor/src/components/Toolbar/ToolbarItem.tsx b/packages/mini-markdown-editor/src/components/Toolbar/ToolbarItem.tsx
index 59f4b93..b7736a1 100644
--- a/packages/mini-markdown-editor/src/components/Toolbar/ToolbarItem.tsx
+++ b/packages/mini-markdown-editor/src/components/Toolbar/ToolbarItem.tsx
@@ -24,6 +24,7 @@ const ToolbarItemWrapper = styled.div`
height: 16px;
display: block;
flex-shrink: 0;
+ user-select: none;
}
`;
diff --git a/packages/mini-markdown-editor/src/config/toolbar/base.tsx b/packages/mini-markdown-editor/src/config/toolbar/base.tsx
index faacec0..d02048b 100644
--- a/packages/mini-markdown-editor/src/config/toolbar/base.tsx
+++ b/packages/mini-markdown-editor/src/config/toolbar/base.tsx
@@ -14,8 +14,6 @@ import ImageIcon from "@/assets/images/image.svg";
import TableIcon from "@/assets/images/table.svg";
import Undo from "@/assets/images/undo.svg";
import Redo from "@/assets/images/redo.svg";
-import WriteIcon from "@/assets/images/write.svg";
-import PreviewIcon from "@/assets/images/perview.svg";
import ContentsIcon from "@/assets/images/contents.svg";
import HelpIcon from "@/assets/images/help.svg";
import OutputPDFIcon from "@/assets/images/output-pdf.svg";
@@ -24,6 +22,7 @@ import { ToolbarItem } from "@/types/toolbar";
// 组件
import Upload from "@/components/Toolbar/Upload";
import FullScreen from "@/components/Toolbar/FullScreen";
+import { Read, Write } from "@/components/Toolbar/ShowLayout";
export const toolbar: ToolbarItem[] = [
{
@@ -170,13 +169,11 @@ export const toolbar: ToolbarItem[] = [
},
{
type: "write",
- icon: WriteIcon,
- title: "只写",
+ component: ,
},
{
type: "preview",
- icon: PreviewIcon,
- title: "仅预览",
+ component: ,
},
{
type: "contents",
diff --git a/packages/mini-markdown-editor/src/store/toolbar.ts b/packages/mini-markdown-editor/src/store/toolbar.ts
index 88be379..178150a 100644
--- a/packages/mini-markdown-editor/src/store/toolbar.ts
+++ b/packages/mini-markdown-editor/src/store/toolbar.ts
@@ -2,15 +2,34 @@ import { create } from "zustand";
export interface ToolbarStoreType {
isFullScreen: boolean;
- setIsFullScreen: (isFullScreen: boolean) => any;
+ setIsFullScreen: (isFullScreen: boolean) => void;
+ isOnlyWrite: boolean;
+ setIsOnlyWrite: () => void;
+ isOnlyPreview: boolean;
+ setIsOnlyPreview: () => void;
+ isSidebar: boolean;
+ sidebarComponent: React.ReactNode | null;
}
-const useToolbarStore = create((set) => ({
+const useToolbarStore = create((set, get) => ({
// 全屏
isFullScreen: false,
setIsFullScreen: (isFullScreen: boolean) => set({ isFullScreen }),
// 只写
+ isOnlyWrite: false,
+ setIsOnlyWrite: () => {
+ const { isOnlyWrite } = get();
+ set({ isOnlyWrite: !isOnlyWrite, isOnlyPreview: false });
+ },
// 仅预览
+ isOnlyPreview: false,
+ setIsOnlyPreview: () => {
+ const { isOnlyPreview } = get();
+ set({ isOnlyPreview: !isOnlyPreview, isOnlyWrite: false });
+ },
+ // 侧边栏
+ isSidebar: false,
+ sidebarComponent: null,
}));
export { useToolbarStore };
--
Gitee