如果你对这个项目感兴趣,或者想参与贡献的,可以看 issue 认领需求,如果想加入交流群可以添加我微信 yunmz777
拉你进群。
技术选型
框架
技术 | 用途 | 官网链接 |
---|---|---|
Next.js | React 全栈框架,支持 SSR、App Router 等特性 | nextjs.org |
React 19 | UI 框架,构建组件化用户界面 | react.dev |
TypeScript | 静态类型系统,提升开发可靠性 | www.typescriptlang.org |
富文本编辑器体系(Tiptap)
技术 | 用途 | 官网链接 |
---|---|---|
Tiptap | 基于 ProseMirror 的无头富文本编辑器框架 | tiptap.dev |
Tiptap Pro 扩展 | 表格、占位符、数学公式、拖拽、节点 ID、Emoji 等增强功能 | Pro 扩展说明 |
Yjs | 数据同步框架,实现多人协同编辑 | yjs.dev |
@hocuspocus | 基于 Yjs 的 WebSocket 协同服务端 | hocuspocus.dev |
⚙️ 工程化工具链
技术 | 用途 | 官网链接 |
---|---|---|
ESLint | 代码质量与规范检查工具 | eslint.org |
Prettier | 代码自动格式化 | prettier.io |
Husky | Git 提交钩子,配合 Lint 检查 | typicode.github.io/husky |
Commitizen + cz-git | 规范化 Git 提交信息 | commitizen-tools.github.io/commitizen/ |
Vitest | 单元测试框架,Vite 原生支持 | vitest.dev |
Playwright | 端对端浏览器测试 | playwright.dev |
样式
技术 | 用途 | 官网链接 |
---|---|---|
shadcn/ui | 基于 Radix UI 封装的现代 React 组件库,支持主题切换、无锁样式、自定义 Tailwind 风格 | ui.shadcn.com |
Tailwind CSS | 原子化 CSS 样式库,与 shadcn 深度集成 | tailwindcss.com |
Radix UI | 无样式的可访问性基础组件,shadcn 的核心依赖 | www.radix-ui.com |
tailwindcss-animate | Tailwind 的动画插件,配合 @keyframes 使用 |
github.com/jamiebuilds... |
其他精选依赖
技术 | 用途 | 官网链接 |
---|---|---|
Zustand | 轻量级状态管理库,支持持久化、异步逻辑 | zustand.pmnd.rs |
Framer Motion | 高性能动画库,适用于组件过渡、交互反馈等 | www.framer.com/motion |
Lucide | 现代图标库,支持 React 组件直接引入 | lucide.dev |
Date-fns | 常用日期处理函数库,API 简洁,体积小 | date-fns.org |
目录结构
txt
src/
├── app/ # Next.js 应用目录,包含页面路由、布局配置等
├── components/ # 可复用的 UI 组件库
├── extensions/ # Tiptap 编辑器的自定义扩展功能
├── hooks/ # 自定义 React Hooks
├── services/ # 业务逻辑服务层(如 API 调用、请求封装等)
├── stores/ # 状态管理(如使用 Zustand、Jotai 等)
├── styles/ # 全局样式和样式模块
├── types/ # 全局 TypeScript 类型定义
├── utils/ # 工具函数、辅助方法
├── worker/ # Web Worker 实现,用于异步或性能密集型任务
└── middleware.ts # Next.js 中间件,用于请求拦截、认证控制等
其中 styles 里面包含了大量的 tiptap 的 css 样式,这些 CSS 文件用于为 Tiptap 提供完整的富文本样式支持。由于 Tiptap 是无头组件,所有样式(如段落、代码块、表格、列表、协同编辑等)都需自行定义。每个 CSS 文件针对一个功能模块进行样式分离,便于维护与扩展。这种拆分方式能保持样式结构清晰、职责明确。

每个不同的文件都代表不同的插件的样式,例如 code.css
代表代码块 <pre><code>
的样式定义,包括背景色、字体、行号样式,适配 CodeBlock 插件(如支持语法高亮的效果)。
对于 components 又分为两个不同的分类,src 目录下的是全局公共组件或者业务性质可共用的,在 app 目录下的是每个页面或者一个 layout 路由组下的业务组件,为了避免渲染成路由,可用 _components
命名的方式命名。
核心模块
Service 封装和调用
service 目录下的 request.ts 为全局的 fetch 封装:
这段代码封装了一个基于 fetch
的请求工具类,支持统一拦截、超时控制、错误处理与自动重试等高级功能。同时,它提供了 get/post/put/delete/patch
等方法,返回统一格式的响应结果,便于在项目中稳定复用。
对于不同模块的,可以再 service 目录下再新建一个新的目录作为特定模块的封装,例如我有一个 user 模块,index.ts 作为函数的封装,type.ts 作为接口的出参和入参的类型。
具体调用时可以不用添加
try...catch
语法捕捉,可以在具体调用时传入不同的错误结果不同的处理,由统一的 fetch 实例来处理。
tiptap 扩展
借助 tiptap 的强大的扩展功能,我们可以在原来的基础上扩展任务我们想要的功能,甚至你可以在 tiptap 上扩展一个页面。
如果要创建一个扩展,一般遵循以下原则:
ts
import { Node, NodeViewRendererProps } from "@tiptap/core";
// - Node: 创建扩展的核心 API
// - NodeViewRendererProps: 自定义组件的 props 类型(含 editor、node 等)
import {
NodeViewWrapper, // 将 React 组件包装为 NodeView
ReactNodeViewRenderer, // 用于包裹 React 节点,Tiptap 会识别它作为 NodeView 的容器
useEditorState, // 用于订阅 editor 的状态(如目录、选中状态等)
} from "@tiptap/react";
// 👉 你的自定义组件(实际渲染逻辑)
import MyReactComponent from "./MyReactComponent";
// 👉 正式定义扩展
export const MyNode = Node.create({
name: "myNode", // 节点名称,必须唯一
group: "block", // 节点分组,可选 block / inline / list
atom: true, // 原子节点,不可编辑内部内容
draggable: true, // 是否允许拖拽移动
inline: false, // 是否是 inline 类型,默认为 block
// HTML -> Node 映射(反序列化)
parseHTML() {
return [
{
tag: 'div[data-type="my-node"]',
},
];
},
// Node -> HTML 映射(序列化)
renderHTML({ HTMLAttributes }) {
return ["div", { ...HTMLAttributes, "data-type": "my-node" }, ""]; // SSR 输出结构
},
// 客户端渲染视图(NodeView)------ 仅在浏览器中执行
addNodeView() {
if (typeof window !== "undefined") {
return ReactNodeViewRenderer(MyReactComponent);
}
return null; // SSR 时跳过 NodeView
},
// 自定义命令:插入该节点
addCommands() {
return {
insertMyNode:
() =>
({ commands }) => {
return commands.insertContent({
type: this.name,
});
},
};
},
});
创建完成之后可以在这里添加并导出:
这两个文件都要。
协同

贡献指南
1. Fork 仓库
首先,fork 仓库到你的 GitHub 账户中。这会创建一个你自己的仓库副本。
2. 克隆仓库
在你的本地机器上克隆你刚刚 fork 的仓库:
bash
git clone https://github.com/你的用户名/项目名.git
cd 项目名
3. 添加上游远程仓库
为了保持你的仓库与原始仓库同步,请添加上游远程仓库:
bash
git remote add upstream https://github.com/xun082/DocFlow.git
4. 创建新分支
在开始工作之前,请确保你创建了一个新的分支:
bash
git checkout -b feat/你的分支名
其中 feat/
是表示"功能开发分支"的前缀,后者为你具体的功能点描述,例如:
bash
feat/login-page # 开发登录页面功能
feat/user-permission # 实现用户权限控制
feat/invite-code-refactor # 重构邀请码功能模块
对于不同的功能有不同的前缀:
前缀 | 说明 |
---|---|
feature/ |
新功能开发 |
fix/ |
缺陷修复 |
hotfix/ |
线上紧急修复 |
refactor/ |
重构代码,不涉及功能变更 |
test/ |
添加或修改测试相关内容 |
chore/ |
构建、依赖等杂项维护 |
docs/ |
文档更新 |
开发流程
在开启之前,请确保你的 NodeJs 版本大于或者等于 20,PNPM 版本大于或者等于 9
1. 安装依赖
在你开始开发之前,请安装所有的依赖:
bash
pnpm install
2. 运行项目
为了确保你在一个正常运行的环境下进行开发,启动项目:
bash
pnpm dev
3. 提交更改
在提交你的更改之前,请确保你进行了适当的代码格式化和 lint:
bash
pnpm lint
pnpm format
然后提交你的更改:
bash
git add .
pnpm commit
5. 同步你的分支
在你准备好提交你的更改之前,请确保你的分支是最新的:
bash
git fetch upstream
git rebase upstream/main
6. 推送分支
将你的分支推送到你自己的仓库:
bash
git push origin feature/你的分支名
7. 创建 Pull Request
在 GitHub 上,导航到你 fork 的仓库,点击 "Compare & pull request" 按钮。请确保你详细描述了你所做的更改。
代码审查
所有的 Pull Request 都会被审查。请注意以下几点:
- 你的代码是否清晰且易于理解。
- 你是否遵循了项目的代码风格和规范。
- 你是否添加了适当的测试。
- 你的更改是否与现有的代码兼容。
常见问题
如何报告 Bug?
如果你发现了 Bug,请在 GitHub 上创建一个 Issue,并尽可能详细地描述 Bug 及其复现步骤。
如何请求新功能?
如果你有新功能的建议,请在 GitHub 上创建一个 Issue,详细描述你的建议及其潜在的用途。