docs: publish open-source guides and MIT license

This commit is contained in:
eezd committed 2026-10-26 22:03:45 +08:00
1 parent 1f01140b1d
commit b1faab339e
10 files changed
+530 -86

No files matched your search

+7 -2
View File
@@ -1,6 +1,11 @@
# 本地交接文件与设计文档不入库
# 本地交接文件与历史设计文档不入库;公开文档单独放行
CONTEXT.md
docs/
docs/*
!docs/guide.md
!docs/deployment.md
!docs/development.md
!docs/api.md
!docs/images/
# 前端
node_modules/
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 eezd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+57 -84
View File
@@ -1,103 +1,76 @@
# RawMark
<div align="center">
<img src="web/public/icon.svg" width="80" height="80" alt="RawMark logo" />
<h1>RawMark</h1>
<p><strong>A space of your own. A place to write.</strong></p>
<p>A self-hosted Markdown workspace for your personal notes. Your files, your server, ready in your browser.</p>
<p><strong>English</strong> · <a href="README.zh-CN.md">简体中文</a></p>
<p>
<a href="#quick-start">Quick start</a> ·
<a href="docs/guide.md">User guide</a> ·
<a href="docs/deployment.md">Deployment</a> ·
<a href="https://github.com/eezd/RawMark/issues">Report an issue</a>
</p>
</div>
纯 Markdown 笔记网页编辑器:所见即所得(类 Obsidian Live Preview)、文件即真源、Docker 部署、浏览器访问。
<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/images/workspace-dark.png" />
<img src="docs/images/workspace-light.png" alt="RawMark workspace with a file tree on the left, Markdown live preview and tabs in the center, and a document outline on the right" width="1440" />
</picture>
## 部署
<p align="center"><sub>Actual workspace with sample notes · <a href="docs/images/workspace-light.png">Light mode</a> · <a href="docs/images/workspace-dark.png">Dark mode</a></sub></p>
本机部署沿用 `/srv/AlphaPulse/deploy` 的目录约定,端口按 `/docker/main/.env` 的个人项目范围(21000–21999)分配为 `RAWMARK_PORT=21000`:
## Made for your notes
RawMark is for people who want to keep their notes on their own server. Organize knowledge, track projects, and collect ideas, then pick up where you left off in a browser on your computer, tablet, or phone.
Notes are ordinary `.md` files, with images stored in an `assets/` folder alongside them. Access your files directly or export them whenever you like, and open them with the Markdown tools you already use.
- **Focus on writing.** Switch between Markdown live preview and source mode, with support for tables, task lists, math, Mermaid diagrams, and syntax highlighting.
- **Keep things organized.** Folders, tags, full-text search, and document outlines, with drag-and-drop moves, bulk actions, and custom file icons.
- **Continue where you left off.** Multiple tabs and pinned notes survive refreshes and browser restarts. Changes save automatically, and external file edits sync to the page.
- **Keep images with your notes.** Paste, upload, or import images in bulk. View references, rename, move, replace, and clean up unreferenced images in the image manager.
- **Make it feel familiar.** Light and dark modes, separate interface, text, and code fonts, font imports, customizable shortcuts, themes, and CSS snippets.
- **Take your data with you.** Import Markdown or ZIP archives and export notes with attachments. Use the recycle bin, full-instance backups, settings migration, API automation, and frontend plugins.
RawMark is built for **single-user, self-hosted use**. It currently does not offer collaboration or public sharing.
## Quick start
With Git and Docker installed, build and run locally:
```sh
cd deploy
install -d -m 750 -o 65532 -g 65532 data
docker compose --env-file /docker/main/.env up -d --build --wait
```
持久化数据位于 `deploy/data/`,与 `.dev-data/` 独立。首次打开网页时直接设置登录密码。
升级已有实例移除分享时,先备份数据与旧镜像、停止旧服务,再对 `rawmark.db` 执行一次 `scripts/remove-sharing.sql`,然后启动新版本。脚本删除分享表、专用密钥及分享快捷键;不会删除笔记或图片。旧分享页面和接口返回 404。回滚必须配套恢复数据库和旧镜像,不能只恢复旧程序。
升级到 Typora 默认快捷键时,先停止服务并备份数据与旧镜像,再对 `rawmark.db` 执行一次 `scripts/reset-shortcuts.sql`。该脚本按本次需求清空已有快捷键覆盖,其他设置保留;程序启动不会再次重置快捷键。
宿主机 Nginx 配置为 `deploy/nginx/raw.134333.xyz.conf`,复用现有通配证书及 WebSocket 升级映射;安装到 `/etc/nginx/conf.d/134333.xyz/` 后,先执行 `nginx -t` 再重载。
域名 `raw.134333.xyz` 在 DNSPod 设置 CNAME 指向 `cdn.134333.xyz`(与 AlphaPulse 一致);还需在 Cloudflare for SaaS 的 `unino.top` 区域添加该自定义域名,并等待域名与托管证书均为 `active`。仅设置 CNAME 或旧区域中的 A 记录不足以完成 CDN 接入。访问地址为 `https://raw.134333.xyz`。修改端口时需同步端口登记和 Nginx 上游。
其他服务器也可直接构建并运行:
```sh
mkdir -p ~/rawmark-data
git clone https://github.com/eezd/RawMark.git
cd RawMark
docker build -t rawmark .
docker run -d --name rawmark \
--user "$(id -u):$(id -g)" \
-p 8080:8080 \
-v ~/rawmark-data:/data \
--restart unless-stopped \
docker run -d --name rawmark --restart unless-stopped \
-p 127.0.0.1:21000:8080 \
-v rawmark-data:/data \
rawmark
```
- 首次打开直接设置登录密码,之后凭密码与图片验证码登录;请在将新实例开放给他人访问前完成初始化。
- 笔记以普通 `.md` 文件保存在 `数据目录/vault/`,粘贴、上传和导入的图片统一存放在笔记同级的 `assets/`,链接使用 `./assets/文件名`,同目录相同内容去重。笔记跨目录移动时图片跟随,仍被其他笔记引用的原图保留;删除单篇笔记不会删除共享图片。旧 `笔记名.assets/` 仍可读取、移动与恢复;外部修改会实时同步到网页。
- 知识工具:标准 Markdown 链接构成图谱,支持正文 `#标签` 与 YAML `tags`。笔记或文件夹在应用内改名、移动时维护入链和相对出链;公式和代码示例不参与关系提取。
- 外观:浅色玻璃工作台与深色模式,默认字体为 Maple Mono Normal NL NF CN v7.9(界面、正文与代码),字体资源随应用本地提供,文字在所需字体加载完成后显示,加载失败会提示刷新;代码块使用 highlight.js,固定采用官网的 Atom One Dark 配色,与页面明暗模式独立;界面、正文与代码字体可分别选择,各字体下拉均支持导入 TTF/OTF/WOFF/WOFF2(单个不超过30 MB)及删除;Maple为不可删除的默认字体,删除正在使用的字体会恢复Maple,导入字体保存在服务器数据目录的fonts/并跨设备共用。界面字号默认 14px,可输入 14–20px 并单独重置,与编辑器及阅读字号独立;排版、玻璃透明度、选中文本工具栏均可在设置中调整并即时保存。
- 选区格式:电脑与触屏选中文字后提供外观、加粗、斜体、下划线、删除线、高亮和链接。外观可设置配色、字体、局部字号与效果;下划线及外观以受限的标准 HTML 行内标签保存在 Markdown 中,源码与导出保留标签,其他软件的显示取决于其 HTML 支持。清除样式只重置局部外观;底部不再显示格式栏。
- 图片管理:侧栏默认隐藏 `assets` 和 `笔记名.assets`;右键文件夹选择「图片管理」,查看当前目录及直属附件目录的图片,支持检索、排序、网格/列表、批量上传、引用查看及预览、重命名、移动、替换。可切换整个知识库;清理孤立图片须确认候选,服务端再次核对全库引用后移入回收站,可恢复。上传至所选目录的 `assets/`,相同内容自动去重。根目录可在侧栏空白处右键或通过命令面板打开。图片改名/移动会更新笔记中的本地引用;替换保留路径,选择相同扩展名的图片(最大 50 MB),旧图片不进回收站。
- `--user` 让容器以宿主机用户身份读写数据目录;不指定时容器以 UID 65532 运行,需要该用户对目录有写权限。
- 请通过 HTTPS 反向代理(Caddy、Nginx 等)访问,并转发 WebSocket(浏览器使用 `/api/v1/resources/<ticket>/events/`,脚本可使用 Bearer 连接 `/api/v1/events`)。
- 多选与导出:Ctrl/Cmd 点击切换选择,Shift 点击选择可见范围;右键批量删除、移动或导出 Markdown。单篇无附件直接下载 `.md`,其他情况下载包含 Markdown 与本地附件的 ZIP;重名目标不会被覆盖,批量操作会汇报单项失败。
- 设置:桌面使用居中窗口,手机使用分类与内容两级布局;支持搜索设置并定位、常用排版项单独重置,自动保存状态与失败提示可见。外观与编辑器分别管理,安装入口位于「关于」。
- 回收站与存储:回收站支持清空全部;默认按原删除时间保留 30 天,0 表示永不自动删除,服务启动及每小时执行清理,修改期限同样影响已有条目。设置「存储空间」进入即统计数据目录、外置笔记库及内置可选字体(不含默认 Maple),支持刷新和字体明细;不跟随内部符号链接,附件与回收站包含在笔记库总量中。
- 快捷键:支持按命令名称、ID 或组合键搜索,添加、逐条移除和单项/全部重置,并拒绝冲突绑定。默认跟随 [Typora](https://support.typora.io/Shortcut-Keys/) 的 Windows/Linux 或 macOS 组合,无对应项和插件默认留空;浏览器保留键可自行重新绑定。Ctrl/Cmd+1~6 设置标题,同级再次触发恢复正文;字号可直接输入,编辑器字号随有效输入即时生效。
- 备份与维护:设置「存储空间」提供完整实例、普通 Markdown 笔记库、设置与资源三种迁移入口。完整实例含数据库、登录信息、回收站与资源,恢复会替换当前业务数据并要求重新登录;设置包含偏好、插件数据及字体/主题/插件,保留包外资源,同 ID 资源替换。两者应用前均在数据目录 `backups/` 保存恢复包;不包含运维环境配置、派生索引或临时文件。普通笔记导出保留目录与原文,即使仓库与应用目录重合或嵌套也不包含应用数据库、资源与暂存文件;缺失附件记录于 `.rawmark-export/missing-assets.json`,导回时忽略该报告并导入新文件夹。
- 维护边界:备份恢复只接受本程序的版本化 ZIP,顺序分块上传,每块 8 MiB,压缩上限 2 GiB、展开上限 8 GiB/100000 项;完整恢复前需停止外部程序直接改写仓库。维护期间暂时暂停 API 操作,实例恢复在关闭数据库和后台任务后执行,中断时回退操作前备份。优化/重建仅作用于派生索引;临时清理不删除用户文件、活动上传或恢复备份。重置偏好保留插件存储、账户、资源和本机标签页。日志保存于 `logs/`,三份、每份至多 10 MiB,可导出日志及版本运行摘要,不补录历史日志。
Open **http://localhost:21000**, set your password on first use, and create your first note. Data lives in the Docker volume `rawmark-data` and persists when you recreate the container with the same volume.
- 文件目录操作:右键「文件目录」标题或目录空白处,可搜索、打开标签索引、新建笔记、新建目录、导入文档及管理图片;也可点击标题打开菜单。文件夹右键操作以所选文件夹为目标。
- 导入:文件目录或文件夹右键菜单选择「导入」,支持多选 UTF-8 `.md` 文件或单个 ZIP(总上传上限 100 MB)。ZIP 新建同名文件夹并保留笔记层级,本地图片归入各笔记同级 `assets/`;全部改链后移除已迁移且无引用的重复原图,其他附件和未使用图片保留。同名不同内容不覆盖,缺失的本地链接会提示,外部图片不会自动下载。
- 自动化:在设置「账户与安全 → API 令牌」中创建只读或读写令牌,以 `Authorization: Bearer <令牌>` 调用 REST API,接口说明见 `/api/v1/openapi.json`。
These commands listen on localhost only. For a remote server, complete the initial setup before configuring HTTPS access. See the [deployment guide](docs/deployment.md) for Docker Compose, existing note folders, backups, and upgrades.
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `RAWMARK_DATA` | `/data` | 数据目录(数据库、可重建的搜索索引 `index.db`、默认笔记仓库) |
| `RAWMARK_VAULT` | `$RAWMARK_DATA/vault` | 笔记仓库目录,可指向已有的笔记文件夹 |
| `RAWMARK_ADDR` | `:8080` | 监听地址 |
## Documentation
文件树默认使用 📂 / 📄,可点击图标或右键“修改图标”,选择表情或内置线性图标。自定义属性存于仓库的 `.rawmark/tree-icons.json`,随应用内移动、重命名及回收站恢复保留,不改动或导出到 Markdown 正文;外部文件操作不保证跟随。
Detailed guides are currently available in Simplified Chinese.
## 开发
| What you want to do | Start here |
| --- | --- |
| Write, organize notes, manage images, and customize the workspace | [User guide](docs/guide.md) |
| Deploy, configure storage, back up, and upgrade | [Deployment and maintenance](docs/deployment.md) |
| Develop locally, understand the project structure, and run checks | [Development guide](docs/development.md) |
| Write scripts, authenticate, and call the API | [API and authentication](docs/api.md) |
需要 Go 1.27+、Node 24+ 与 pnpm 12.11.2(可通过 Corepack 启用)。开发时不必构建前端或 Docker 镜像,一键启动:
## Help and contributing
```sh
scripts/dev.sh # 后端 go run -tags dev + 前端 Vite 热更新,Ctrl+C 同时退出
scripts/dev.sh --host # 前端监听所有网卡,手机访问 http://<电脑 IP>:5173
```
Bug reports and suggestions are welcome in [Issues](https://github.com/eezd/RawMark/issues). Include your version, deployment method, browser, and steps to reproduce. Remove passwords, tokens, and private note content from logs and screenshots.
浏览器打开 http://localhost:5173 ,首次使用直接设置登录密码。端口与数据目录可用 `API_PORT`、`WEB_PORT`、`RAWMARK_DATA` 覆盖,详见 `scripts/dev.sh --help`。
开发模式从源码统计可选字体,日志导出的版本标为 `dev`,不读取已有 `web/dist`;生产模式使用前端构建清单与页面构建版本。
Before contributing, read [AGENTS.md](AGENTS.md) and the [development guide](docs/development.md), both currently in Simplified Chinese. RawMark prioritizes simplicity and clarity; please discuss substantial features or architectural changes in an issue first.
检查:
## Acknowledgments and license
```sh
pnpm -C web install --frozen-lockfile
pnpm -C web lint:check
pnpm -C web typecheck
pnpm -C web test
pnpm -C web build
go vet -tags dev ./...
go test ./internal/...
go test -tags dev ./web
```
Built with projects including [CodeMirror](https://codemirror.net/), [Vue](https://vuejs.org/), [Element Plus](https://element-plus.org/), [highlight.js](https://highlightjs.org/), and [Maple Mono](https://github.com/subframe7536/maple-font). The frontend structure draws on [vue3-starter](https://github.com/eezd/vue3-starter), whose [MIT license](web/LICENSE) is retained. [Maple Mono](web/src/common/appearance/fonts/maple/LICENSE.txt) and other third-party assets retain their respective licenses.
字体资源已入库,普通构建无需下载或转换。重新生成时,在独立 Python 环境安装 `fonttools[woff]`,下载 [v7.9 指定字体包](https://github.com/subframe7536/maple-font/releases/download/v7.9/MapleMonoNormalNL-NF-CN.zip),运行 `python3 scripts/prepare-maple-font.py /path/to/MapleMonoNormalNL-NF-CN.zip`;生成 WOFF2 与 `maple-font.css`,保留上游许可。
## 前端结构与接口升级
前端以 [vue3-starter](https://github.com/eezd/vue3-starter/tree/fd41d62ce3f1c8338a478e0be3e2f31b53b7ea5e) 为结构基线,保留 RawMark 的编辑器、主题与布局;模板许可在 `web/LICENSE`。`web/src/pages/workspace/` 管理笔记、目录、编辑器与图片,`pages/settings/` 管理设置及维护,`pages/login/` 管理初始化与验证码登录;页面私有组件、类型和组合函数跟随模块。全部资源 API 统一位于 `common/apis/<resource>/index.ts` 与 `type.ts`,API 函数直接调用 `request<ResponseData>({ url, method, data, params })` 并返回完整 `{ code, data, message }`,调用方读取 `.data`;原文及下载用 `returnResponse: true` 保留 Axios 响应和响应头,204 为 void,事件连接也归资源 API。实际共享的外观、Markdown、插件 SDK 位于 `common/`;请求、路由、共享状态分别由 `http/`、`router/`、`pinia/` 管理。唯一前端构建入口为 `web/`,使用 pnpm 锁文件。此次 API 目录与普通页面调整复用已部署的统一后端协议,不新增数据库迁移。
本次协议升级需前后端一起发布,旧页面与旧 Cookie 会话不能继续使用,需要重新登录。升级前备份数据库和旧镜像;启动新程序时沿用现有 SQLite 初始化流程新增 `resource_tickets` 表及过期索引,保留笔记、设置、密码和 API 令牌。生产迁移与部署须另行授权,不手动运行历史清理 SQL。回滚使用配套数据库和旧镜像;新前端不能连接旧后端。
登录流程先 `POST /api/v1/auth/captcha`,取得 `{captchaId,imageDataUrl,expiresAt}`;刷新传 `replaceId` 使旧挑战失效。再提交 `POST /api/v1/auth/login` 的 `{password,captchaId,captchaCode}`,后端校验六位数字,挑战绑定来源、五分钟过期且一次性消费(密码或验证码失败也会消费)。保留登录防暴力破解与签发限流。首次 `POST /auth/setup` 直接设置密码,不需要已有登录挑战。
登录/初始化返回 `{token,expiresAt}`。浏览器将 `rms_` 会话 Token 保存于 localStorage `rawmark.token`,所有受保护请求带 `Authorization: Bearer <token>`;服务端只存哈希、固定三十天有效,不滑动续期。`GET /auth/me` 返回真实权限及到期时间,`POST /auth/logout` 服务端撤销会话后返回 204;注销失败保留本地身份并明确报错。401 清除当前身份及动态路由,403 保留身份;旧请求或排队写入不能覆盖或注销新会话。localStorage 属于同源脚本可读的凭据,管理员安装的前端插件仍为全权限插件,不能承诺隔离。
普通 JSON 响应统一为 `{code,data,message}`,code=0 成功,message 表示成功或明确失败原因;错误保留 400/401/403/404/409/412/429/500/503 等 HTTP 状态。维护接口中,无效输入或备份内容返回 400,维护占用或磁盘空间不足返回 503,文件系统/数据库内部故障返回 500。通用错误码为 HTTP 状态乘 100,40001 验证码错误/已使用、40002 验证码过期、40003 当前密码错误、40101 密码错误、41200 版本冲突;冲突版本位于 `data.rev`。文件原文、下载、WebSocket、204 和 OpenAPI 文档不包装。旧 JSON 客户端必须更新解包方式,不提供双格式兼容。
`rm_` API 令牌无需重新创建,read/write 权限不变;令牌不能管理账户、令牌、维护或资源票据。只读令牌仍可 POST 导出。第三方脚本只需保留 Bearer 请求头并按新 JSON 协议解包,文件/导出原始字节不变;WebSocket 客户端可继续以 Bearer 请求头连接 `/api/v1/events`。
浏览器原生图片、字体、插件相对模块导入及 WebSocket 无法统一设置认证头,使用 `POST /auth/tickets` 签发的受限资源 URL。图片/字体票据不超过父会话期限,插件另绑定 ID 和版本;每次读取都核对父会话,注销后立即不可读。事件握手票据一分钟有效、只能使用一次,已连接事件在发送与心跳时检查父凭据。主 Token 不放在 URL,不使用 Cookie 兜底;私有响应 no-store、Referrer-Policy=no-referrer,PWA 仅缓存静态外壳。部署代理也须避免记录票据 URL,仓库 Nginx 配置已提供脱敏日志格式;CDN/其他代理需按同样规则配置。
RawMark is open source under the [MIT License](LICENSE). Third-party code and fonts retain their own license and copyright notices.
+74
View File
@@ -0,0 +1,74 @@
<div align="center">
<img src="web/public/icon.svg" width="80" height="80" alt="RawMark 标志" />
<h1>RawMark</h1>
<p><strong>在自己的空间,安心写作。</strong></p>
<p>自托管的个人 Markdown 笔记工作台。文件属于你,打开浏览器就能继续写。</p>
<p><a href="README.md">English</a> · <strong>简体中文</strong></p>
<p>
<a href="#快速开始">快速开始</a> ·
<a href="docs/guide.md">使用指南</a> ·
<a href="docs/deployment.md">部署文档</a> ·
<a href="https://github.com/eezd/RawMark/issues">反馈问题</a>
</p>
</div>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/images/workspace-dark.png" />
<img src="docs/images/workspace-light.png" alt="RawMark 主界面:左侧文件目录,中间 Markdown 即时预览编辑器和标签页,右侧文章大纲" width="1440" />
</picture>
<p align="center"><sub>真实工作区,使用示例笔记 · <a href="docs/images/workspace-light.png">浅色界面</a> · <a href="docs/images/workspace-dark.png">深色界面</a></sub></p>
## 为记录而设计
RawMark 适合想把笔记保存在自己服务器上的个人用户:整理知识、记录项目、收集灵感,在电脑、平板或手机的浏览器中继续写作。
笔记就是普通的 `.md` 文件,图片放在笔记旁的 `assets/` 文件夹。你可以直接访问文件,也可以随时导出,用熟悉的 Markdown 工具打开。
- **专注写作**:Markdown 即时预览与源码模式切换,支持表格、任务列表、数学公式、Mermaid 和代码高亮。
- **有条理地整理**:文件夹、标签、全文搜索与文章大纲;拖动移动、批量操作、自定义文件图标,让笔记各归其位。
- **延续工作状态**:多标签页与固定标签,刷新或重启后恢复;自动保存,外部文件修改同步到页面。
- **让图片跟着笔记走**:粘贴、上传与批量导入图片;图片管理支持引用查看、重命名、移动、替换及孤立图片清理。
- **按自己的习惯调整**:浅色与深色模式,独立的界面、正文及代码字体,可导入字体、自定义快捷键、主题和 CSS 片段。
- **数据可带走**:导入 Markdown 或 ZIP,导出笔记与附件;回收站、完整实例备份与设置迁移,支持 API 自动化及前端插件扩展。
RawMark 面向**单用户、自托管**场景。目前不提供多人协作或公开分享。
## 快速开始
需要 Git 和 Docker。在本地构建镜像并启动:
```sh
git clone https://github.com/eezd/RawMark.git
cd RawMark
docker build -t rawmark .
docker run -d --name rawmark --restart unless-stopped \
-p 127.0.0.1:21000:8080 \
-v rawmark-data:/data \
rawmark
```
打开 **http://localhost:21000**,首次访问设置登录密码,即可创建第一篇笔记。数据保存在 Docker 卷 `rawmark-data` 中,重建容器不会丢失。
以上命令仅监听本机。部署到服务器时,请先完成初始化,再配置 HTTPS 访问;Docker Compose、已有笔记目录接入、备份与升级见[部署文档](docs/deployment.md)。
## 文档
| 想做什么 | 从这里开始 |
| --- | --- |
| 写作、整理笔记、管理图片与个性化设置 | [使用指南](docs/guide.md) |
| 部署、配置存储、备份和升级 | [部署与维护](docs/deployment.md) |
| 本地开发、了解目录职责和运行检查 | [开发指南](docs/development.md) |
| 编写脚本、接入认证和调用接口 | [API 与认证](docs/api.md) |
## 参与项目
欢迎通过 [Issues](https://github.com/eezd/RawMark/issues) 报告问题或提出建议。报告问题时,请附上版本、部署方式、浏览器和复现步骤;日志与截图中请移除密码、令牌及私人笔记内容。
提交改动前请阅读 [AGENTS.md](AGENTS.md) 和[开发指南](docs/development.md)。RawMark 优先保持简单、清晰,较大的功能或架构调整建议先通过 Issue 讨论。
## 致谢与许可
感谢 [CodeMirror](https://codemirror.net/)、[Vue](https://vuejs.org/)、[Element Plus](https://element-plus.org/)、[highlight.js](https://highlightjs.org/) 和 [Maple Mono](https://github.com/subframe7536/maple-font) 等项目。前端结构参考 [vue3-starter](https://github.com/eezd/vue3-starter),其 [MIT 许可](web/LICENSE) 保留;[Maple 字体许可](web/src/common/appearance/fonts/maple/LICENSE.txt)及其他第三方许可遵循各自文件。
RawMark 采用 [MIT License](LICENSE) 开源;第三方代码与字体保留各自的许可和版权声明。
+86
View File
@@ -0,0 +1,86 @@
# API 与认证
[返回项目首页](../README.zh-CN.md) · [开发指南](development.md)
API 基础路径为 `/api/v1`。完整端点、请求字段、权限和响应以 [OpenAPI 源文件](../internal/api/openapi.json)为准,运行中的实例在 `GET /api/v1/openapi.json` 提供同一文档。测试 `TestOpenAPICoversRoutes` 核对路由覆盖。
## 脚本接入
在「设置 → 账户与安全 → API 令牌」创建只读或读写令牌。受保护 API 只接受 `Authorization: Bearer <token>`,不接受 Cookie,也不要将主令牌放进 URL。
以下只读示例从环境变量读取凭据:
```sh
# 先在本机环境中设置 RAWMARK_URL 和 RAWMARK_TOKEN,不要提交真实值。
curl --fail-with-body \
-H "Authorization: Bearer $RAWMARK_TOKEN" \
"$RAWMARK_URL/api/v1/tree"
```
`rm_` API 令牌在服务端只存哈希,保留 read/write 权限。只读令牌可读取笔记、搜索和执行只读 POST 导出,不能写入;API 令牌不能管理账户、令牌、维护或资源票据,不能为自身扩权。管理操作需要浏览器登录会话。
## JSON 与 HTTP 语义
普通 JSON 成功响应:
```json
{
"code": 0,
"data": { "ok": true },
"message": "成功"
}
```
`code = 0` 表示成功,非零表示失败;失败时 `message` 是可展示的原因。保留真实 HTTP 状态,不把错误全部转为 200。通用错误码为 HTTP 状态乘 100,特定业务码如下:
| HTTP | code | 含义 |
| --- | --- | --- |
| 400 | 40001 | 验证码错误、无效或已使用 |
| 400 | 40002 | 验证码过期 |
| 400 | 40003 | 修改密码时当前密码错误,不清理身份 |
| 401 | 40101 | 登录密码错误 |
| 412 | 41200 | 文件版本冲突,当前版本在 `data.rev` |
401 表示需要重新认证;403 表示当前身份没有权限,不能据此注销用户。维护输入或备份内容无效返回 400,占用或空间不足返回 503,文件系统/数据库内部故障返回 500。
**文件原文、下载、WebSocket、204 及 OpenAPI 文档不包 JSON 外壳**。`GET /files/{path}` 返回 Markdown 原文和 `ETag`;`PUT /files/{path}` 接收原文,成功返回包含 `rev` 的 JSON。用 `If-Match: "rev"` 防止覆盖新版本,或 `If-None-Match: *` 要求目标不存在;都不带会直接覆盖,不适合需要冲突保护的写入。
## 浏览器登录
实例没有用户名、注册或角色系统。尚未初始化时,`POST /auth/setup` 使用 `{ password }` 设置密码并返回会话;已经初始化的实例不能再次初始化。
正常登录流程:
1. `POST /auth/captcha` 获取 `{ captchaId, imageDataUrl, expiresAt }`。
2. 展示图片,用户填写密码与六位数字验证码。
3. `POST /auth/login` 提交 `{ password, captchaId, captchaCode }`。
4. 成功返回 `{ token, expiresAt }`,再通过 `GET /auth/me` 恢复真实身份与权限。
以上字段均位于普通响应的 `data` 中。刷新验证码时传 `{ replaceId }` 使旧挑战失效。挑战绑定来源,五分钟过期;每次登录提交一次性消费,即使密码或验证码错误也不能重用,失败必须刷新。签发与登录均保留限流。
`rms_` 浏览器会话 Token 保存在 localStorage 的 `rawmark.token`,固定三十天有效、不滑动续期,服务端仅存哈希。退出调用 `POST /auth/logout`,服务端撤销成功返回 204 后才清理本地身份;请求失败时保留身份并提示错误,不能仅删除本地 Token 宣称注销完成。
localStorage 可被同源脚本读取;有完整前端权限的插件必须视为可信代码,不能承诺凭据隔离。
## 原生资源与事件
原生图片、字体、插件模块与浏览器 WebSocket 不能统一设置认证头,通过 `POST /auth/tickets` 获取受限资源 URL;主 Token 不进入 URL。票据服务端只保存哈希,每次读取检查父会话,父会话退出后即失效。
- 图片/字体票据不超过父会话有效期。
- 插件票据额外绑定插件 ID 和版本,支持相对模块导入。
- 事件握手票据一分钟有效、仅消费一次;已连接事件仍会检查父凭据。
- 脚本 WebSocket 客户端可以通过 Bearer 请求头继续连接 `/api/v1/events`。
私有响应使用 `Cache-Control: no-store` 与 `Referrer-Policy: no-referrer`,API 和私有资源不进入 PWA 静态缓存。代理日志也需脱敏,见[部署文档](deployment.md#https-与反向代理)。
## 前端请求责任
请求处理、认证与路由守卫分别位于 `http/`、`pinia/` 和 `router/`。匿名跳登录并保留合法站内回跳,拒绝外部地址与循环跳转。401 清理当前身份、权限与动态路由,403 保留身份。
每次替换或退出会话更新代号、取消旧请求。用户信息、路由安装、异步响应与排队写入均须检查所属会话;旧结果按 Axios 取消语义拒绝,不能覆盖或注销新身份,也不提示取消错误。
同一错误只由一个责任层提示。请求默认负责展示,已有行内状态、保存重试或批量汇总的 API 使用 `errorOwner: 'caller'`;失败依然 reject,不以空列表或默认值伪装成功。
## 旧客户端迁移
统一协议需要前后端同时更新,不保留 Cookie/Bearer 或两种 JSON 格式兜底。旧 `rm_` API 令牌无需重建,但调用方要改为读取 `{ code, data, message }` 中的 `data`;文件及导出字节语义不变。旧浏览器页面需重新登录,不能连接新旧混用的后端。
+119
View File
@@ -0,0 +1,119 @@
# 部署与维护
[返回项目首页](../README.zh-CN.md) · [使用指南](guide.md) · [开发指南](development.md)
RawMark 将前端嵌入 Go 服务,运行时使用 SQLite 与文件系统,不需要额外数据库服务。目前从源码构建 Docker 镜像;以下命令不依赖预先发布的镜像仓库。
## Docker 快速启动
安装 Git、Docker 后:
```sh
git clone https://github.com/eezd/RawMark.git
cd RawMark
docker build -t rawmark .
docker run -d --name rawmark --restart unless-stopped \
-p 127.0.0.1:21000:8080 \
-v rawmark-data:/data \
rawmark
```
访问 http://localhost:21000 完成首次密码设置。命名卷 `rawmark-data` 保存应用数据,重新创建容器时应继续挂载同一个卷,不要删除它。服务器上的本机端口可通过 SSH 隧道访问,再完成初始化:
```sh
ssh -L 21000:127.0.0.1:21000 user@your-server
```
容器默认以 UID/GID `65532:65532` 运行,Docker 新建命名卷会继承镜像数据目录的权限。
## Docker Compose
仓库提供 [deploy/docker-compose.yml](../deploy/docker-compose.yml),使用宿主机的 `deploy/data/` 持久化。Linux 上首次部署可执行:
```sh
mkdir -p deploy/data
sudo chown 65532:65532 deploy/data
docker compose -f deploy/docker-compose.yml up -d --build --wait
```
该配置默认发布到所有网卡的 **21000** 端口。对公网开放前完成初始化并设置访问边界;使用反向代理时,可将 Compose 端口绑定改为 `127.0.0.1:${RAWMARK_PORT:-21000}:8080`。自定义端口可使用 `RAWMARK_PORT=21001 docker compose -f deploy/docker-compose.yml up -d --build --wait`。
不要把快速开始中的容器与 Compose 实例同时指向同一份数据库或笔记库;切换部署方式前先停止旧实例、备份并确认数据位置。
## 存储与配置
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `RAWMARK_DATA` | `/data` | 应用数据库、索引、资源与默认笔记库所在目录 |
| `RAWMARK_VAULT` | `$RAWMARK_DATA/vault` | Markdown 笔记库,可以单独挂载已有目录 |
| `RAWMARK_ADDR` | `:8080` | 容器或二进制内部的监听地址 |
主要数据:
| 路径 | 内容 |
| --- | --- |
| `vault/` | Markdown 文件、附件与笔记库元数据;设定外置笔记库时位于对应目录 |
| `rawmark.db` | 密码、会话、API 令牌、设置等应用状态 |
| `index.db` | 可重建的搜索索引 |
| `fonts/`、`themes/`、`plugins/` | 用户导入的字体、主题和插件 |
| `backups/` | 导入或恢复操作前生成的回退备份 |
| `logs/` | 运行日志 |
要接入已有文件夹,可额外挂载它并设置 `RAWMARK_VAULT`:
```sh
docker run -d --name rawmark --restart unless-stopped \
--user "$(id -u):$(id -g)" \
-p 127.0.0.1:21000:8080 \
-v "$HOME/rawmark-data:/data" \
-v "$HOME/notes:/vault" \
-e RAWMARK_VAULT=/vault \
rawmark
```
先创建 `$HOME/rawmark-data` 和 `$HOME/notes`,确保所选用户可写。此例以宿主机当前用户运行,适合管理自己的已有目录;不设置 `--user` 时须给容器默认用户写权限。RawMark 会修改笔记和链接,首次接入前请备份已有目录。
## HTTPS 与反向代理
远程访问使用 HTTPS。代理到 RawMark 时需要转发 Host、协议与来源地址,并启用 WebSocket 升级和长连接;浏览器事件连接使用 `/api/v1/resources/<ticket>/events/`。代理上传限制也应满足实际导入需求。
[仓库 Nginx 配置](../deploy/nginx/raw.134333.xyz.conf)包含 WebSocket 和票据日志脱敏示例,但其中域名、证书 include、反爬 include、端口及日志路径属于原部署环境,**需要按自己的服务器调整,不能原样安装**。`$connection_upgrade` 的 map 也需要在 Nginx 的 `http` 上下文定义。
资源票据是凭据:代理、CDN 和访问日志不得记录明文票据、查询参数或携带凭据的 Referer;应用的 `no-store` 不能代替代理日志脱敏。Nginx 错误日志也可能包含原始请求路径,仓库示例对票据资源路径关闭错误日志,保留脱敏访问日志及应用错误日志。
若使用 CDN,需独立完成自定义域名与 TLS 证书配置,并确认 API、私有资源和 WebSocket 不被错误缓存;仅配置 DNS 不代表 HTTPS 接入已完成。
## 备份与恢复
在「设置 → 存储空间」选择所需导出类型:
| 类型 | 适合用途 | 恢复行为 |
| --- | --- | --- |
| 普通 Markdown 笔记库 | 迁移到其他笔记工具 | 导入到新文件夹,不替换实例 |
| 设置与资源 | 迁移偏好、插件数据、字体/主题/插件 | 合并资源,同 ID 替换,包外资源保留 |
| 完整实例 | 迁移或恢复 RawMark | 替换业务数据,包含登录信息、回收站和资源,完成后重新登录 |
设置导入与完整恢复只接受本程序的版本化 ZIP,应用前会在 `backups/` 保留回退包。上传顺序分块,每块 8 MiB,压缩包上限 2 GiB,展开上限 8 GiB、100000 项。不包含运维环境配置、派生索引或临时文件。
完整恢复前停止其他程序直接改写笔记库。维护时暂时暂停 API 操作,关闭数据库和后台任务后恢复,中断时回退操作前备份。导出的完整包包含账户和笔记等敏感数据,应妥善保管,不提交到仓库或附在公开 Issue 中。
独立于应用备份,升级前建议停止服务后备份完整数据目录、外置笔记库、部署配置与旧镜像。SQLite 运行时可能有 WAL 文件,不要只复制正在写入的 `rawmark.db` 来冒充一致备份。
## 升级与回退
1. 确认目标版本的行为和数据兼容性,保留当前镜像及部署配置。
2. 停止旧服务,备份应用数据与外置笔记库。
3. 更新源码并重新构建,使用同一份挂载启动新实例;不要并行运行新旧服务。
4. 核对容器健康、登录、笔记与附件。回退时使用配套的旧镜像与数据备份。
Bearer 认证升级需要前后端一起发布。旧 Cookie 页面不能继续使用,需重新登录;启动程序会沿现有 SQLite 初始化流程创建资源票据表和索引,笔记、密码、设置与已有 API 令牌保留。第三方客户端的 JSON 解包方式须遵循[当前协议](api.md)。
`scripts/remove-sharing.sql` 和 `scripts/reset-shortcuts.sql` 是历史版本的一次性迁移:前者移除旧分享数据,后者清空旧快捷键覆盖。**新部署无需运行,已执行过的实例不要重跑**;只有确认来自对应旧版本且需要该迁移时,才在停服并备份后单独执行。
## 日常维护与排查
- 容器自带健康检查,也可访问 `GET /api/v1/health`;健康不代表所有业务流程已验证。
- 设置内的优化/重建仅处理派生索引;清理临时文件不删除用户文件、活动上传或恢复备份。
- 重置设置保留账户、资源、插件存储和本机标签页。
- 日志位于 `logs/`,轮转保留三份,每份至多 10 MiB;可在设置中导出日志及版本摘要。该功能不补录历史日志。
- 更新后界面异常先核对前后端是否来自同一构建,再查看浏览器网络请求和应用日志;插件与外观恢复入口见[使用指南](guide.md#插件与界面恢复)。
+99
View File
@@ -0,0 +1,99 @@
# 开发指南
[返回项目首页](../README.zh-CN.md) · [API 与认证](api.md) · [项目约束](../AGENTS.md)
## 工具链
- Go 1.27.2 或更高版本,具体要求见 [go.mod](../go.mod)。
- Node.js 24+、pnpm **12.11.2**;前端依赖以 [pnpm-lock.yaml](../web/pnpm-lock.yaml) 为准。
- Docker 仅在验证容器构建或部署时需要,本地开发不强制使用。
前端采用 Vue 3、TypeScript、Vite、Router、Pinia、Element Plus、Axios、SCSS 与 UnoCSS;编辑器使用 CodeMirror 6。服务端使用 Go 标准库 HTTP、SQLite 与文件系统;Markdown 文件是真源,搜索索引可以重建。
## 启动本地开发
```sh
corepack enable
corepack prepare [email protected] --activate
scripts/dev.sh
```
脚本使用锁文件安装前端依赖,同时启动 Go 开发服务和 Vite 热更新。打开 http://localhost:5173,首次访问初始化密码;Ctrl+C 同时退出。
```sh
scripts/dev.sh --host # 允许局域网设备访问前端
scripts/dev.sh --help
```
`RAWMARK_DATA` 默认指向仓库的 `.dev-data/`,`API_PORT` 默认 8080,`WEB_PORT` 默认 5173。可通过环境变量覆盖,例如 `API_PORT=18080 WEB_PORT=15173 scripts/dev.sh`。不要将开发服务指向生产数据;初始化、恢复、导入和删除测试只使用合成数据。
开发模式从源码统计可选字体,日志版本显示为 `dev`,不读取旧 `web/dist`。生产模式使用嵌入的前端构建、字体清单和构建版本。
## 目录职责
```text
cmd/rawmark/ 服务入口
internal/
api/ HTTP 路由、授权、协议及 OpenAPI
auth/ 密码、会话与 API 凭据
store/ 应用 SQLite
vault/ 真源笔记、附件与文件操作
search/ 可重建的派生索引
web/
src/
pages/login/ 初始化与验证码登录
pages/workspace/ 笔记、目录、编辑器与图片管理
pages/settings/ 设置、账户与维护
common/apis/ 全部资源 API
common/components/ 跨模块公共组件
common/ 共享外观、Markdown、插件 SDK 与工具
http/ Axios、认证头、统一响应与错误
router/ 路由与守卫
pinia/ 实例及共享认证、权限、设置状态
types/auto/ 自动生成的导入声明
deploy/ 容器与代理配置
scripts/ 开发、资源生成及历史迁移脚本
```
页面私有组件、类型、状态、组合函数和资源跟随 `pages/<module>/`,确实跨模块复用的能力才进入 `common`;公共代码不得依赖页面私有实现。模块内优先相对导入,跨职责用 `@`(`web/src`)与 `@@`(`web/src/common`)。
全部资源接口位于 `common/apis/<resource>/index.ts` 和 `type.ts`。函数直接调用 `request<ResponseData>({ url, method, data, params })`,返回完整 `{ code, data, message }`,调用方显式读取 `.data`。原文/下载设置 `returnResponse: true` 保留 Axios 响应与响应头,204 返回 void,事件连接也归资源 API。不增加页面私有请求入口或多格式 fallback。
公共组件放在 `common/components/<PascalCaseName>/index.vue`。SFC 使用 Composition API 与 TypeScript,其他文件使用 kebab-case。自动声明应修改生成配置后重新构建,不手工编辑。更完整的执行约束以根 [AGENTS.md](../AGENTS.md) 为准,不另维护一套规范。
## 验证
```sh
pnpm -C web install --frozen-lockfile
pnpm -C web lint:check
pnpm -C web typecheck
pnpm -C web test
pnpm -C web build
go vet -tags dev ./...
go test ./internal/...
go test -tags dev ./web
```
前端使用 Vitest,测试随模块存放;Go 使用标准 `testing`。生产构建需先生成 `web/dist`,Go 再将其嵌入二进制。`-tags dev` 保留无需嵌入产物的开发和对应测试边界。
按改动风险补充 Go race、Docker 构建及真实浏览器验收。认证与请求变更应覆盖验证码成功/失败/过期、401 与 403、服务端注销以及旧会话响应隔离;编辑器与文件操作应核对原文保存、版本冲突、附件及移动/导入/导出。不用空数据或模拟成功掩盖失败。
## 主题、字体与插件
内置默认、白色与黑色主题,保留独立明暗模式和 CSS 片段。自定义主题位于数据目录 `themes/<id>/`,包含 `manifest.json` 与 `theme.css`;清单包含 `id`、`name`、`version`,ID 与目录一致,不能覆盖保留的 `default`、`white`、`black`。在外观设置刷新列表后选择。
默认字体资源已入库,常规构建无需下载或转换。重新生成时,在独立 Python 环境安装 `fonttools[woff]`,下载 [Maple v7.9 指定字体包](https://github.com/subframe7536/maple-font/releases/download/v7.9/MapleMonoNormalNL-NF-CN.zip),执行:
```sh
python3 scripts/prepare-maple-font.py /path/to/MapleMonoNormalNL-NF-CN.zip
```
脚本生成 WOFF2 和 `maple-font.css`,保留上游许可。代码块使用 highlight.js 的固定 Atom One Dark,不能在更新主题时顺带恢复旧高亮实现或配色。
插件 SDK 类型见 [common/plugin-api/index.d.ts](../web/src/common/plugin-api/index.d.ts),加载与生命周期实现位于 `common/plugins/`。插件仅在前端运行,安装者必须信任其代码;命名空间、停用及资源版本管理不等于权限沙箱。编辑器扩展故障时保留正文并停用当前页相关扩展。
## 提交改动
先阅读 [AGENTS.md](../AGENTS.md),聚焦实际需求,保留必要契约,不机械照搬模板示例。前端目录以 [vue3-starter 固定基线](https://github.com/eezd/vue3-starter/tree/fd41d62ce3f1c8338a478e0be3e2f31b53b7ea5e) 为参考,RawMark 的编辑器、主题和专用交互按业务保留。
提交前运行适用检查,说明实际验证与未验证范围。Commit 使用清晰英文,按功能拆分;不要提交真实笔记、账户数据、密钥或本地交接文件。
+67
View File
@@ -0,0 +1,67 @@
# 使用指南
[返回项目首页](../README.zh-CN.md) · [部署与维护](deployment.md) · [API 与认证](api.md)
RawMark 是单用户笔记工作台,笔记保存在服务器上。多个浏览器可以访问同一个实例;它不是多人协作系统,目前没有公开分享功能。
## 开始写作
首次访问设置密码,之后通过密码和图片验证码登录。在侧栏「文件目录」标题或空白处右键,可以搜索、新建笔记、新建目录、导入文档、打开标签索引或管理图片;点击标题同样可以打开菜单,便于触屏使用。
编辑器默认使用即时预览,点击右上角图标切换源码模式、打开大纲或进入专注写作。支持标准 Markdown、表格、任务列表、代码块、数学公式、Mermaid、脚注和 YAML 元数据。
正文修改自动保存,保存失败或版本冲突会明确提示。外部程序修改笔记时会同步到页面;出现冲突时请核对内容,不要直接覆盖仍需保留的版本。
选中文字后可使用外观、加粗、斜体、下划线、删除线、高亮与链接。局部外观和下划线以受限的标准 HTML 标签存入 Markdown,源码和导出会保留;其他阅读器是否呈现这些样式取决于其 HTML 支持。
## 整理笔记
- **文件与文件夹**:右键重命名、移动、删除或导出。拖到文件夹行会移入该文件夹,拖到笔记行会移入该笔记所在目录。
- **多选**:Ctrl/Cmd 点击切换选择,Shift 点击选择可见范围,再通过右键菜单批量操作。部分操作失败会逐项报告。
- **标签页**:支持固定和关闭其他标签;固定标签不会被「关闭其他标签页」关闭。打开的标签及固定状态在当前浏览器保存,刷新或重启后恢复。
- **图标**:文件夹默认 📂、文件默认 📄,点击图标或右键「修改图标」选择表情或内置图标。
- **标签和搜索**:正文 `#标签`、YAML `tags` 可用于归类;全文搜索用于查找笔记。文章标题生成右侧大纲。
应用内重命名和移动会维护笔记中的本地链接与图片引用。直接在文件系统中操作时,不保证链接、图标等元数据跟随;这些操作优先在 RawMark 内完成。
## 导入与导出
在目录或文件夹菜单选择「导入」,支持多个 UTF-8 `.md` 文件或单个 ZIP,总上传上限为 100 MiB。
ZIP 会导入到同名新文件夹,保留笔记层级。本地图片归入各笔记同级的 `assets/`,并改写引用;同名不同内容不会覆盖。缺失的本地链接会提示,远程图片不会自动下载。可以用思源笔记等工具导出的 Markdown ZIP 迁入,具体排版仍取决于其 Markdown 内容。
导出时,单篇无附件笔记直接下载 `.md`;其他情况下载保留层级、原文与本地附件的 ZIP,不下载远程资源。选中项存在缺失附件时会报错,便于先修复再导出。
整个笔记库的普通 Markdown 导出在「设置 → 存储空间」,缺失附件记录于导出包的 `.rawmark-export/missing-assets.json`。这个报告不会在重新导入时成为笔记。
## 图片管理
粘贴、上传和导入的图片默认保存在笔记同级的 `assets/`,同目录相同内容去重,正文使用相对路径。侧栏隐藏附件目录,右键文件夹选择「图片管理」即可查看,也可切换整个知识库。
图片管理提供检索、排序、网格/列表、批量上传、预览、引用查看、重命名、移动和替换。重命名或移动会更新笔记引用;替换保留路径,要求相同扩展名、最大 50 MiB,旧图片不会进入回收站。
笔记跨目录移动时图片跟随,仍被其他笔记引用的原图保留。**删除单篇笔记不会顺便删除共享图片**。清理孤立图片会先展示候选,再核对全库引用,将符合条件的图片移入回收站。旧版 `笔记名.assets/` 附件目录仍可读取、移动与恢复。
## 外观、字体与快捷键
在「设置 → 外观」切换明暗模式、主题,调整界面字体和字号、玻璃透明度或 CSS 片段;正文与代码字体、正文宽度、行高等位于编辑器设置。设置保存在服务器,多个设备共享;标签页等本机状态单独保存。
默认字体为 Maple Mono Normal NL NF CN v7.9,不可删除。界面、正文和代码可分别选择字体,各字体选择器支持导入 TTF、OTF、WOFF、WOFF2(单个不超过 30 MiB)及删除导入字体。页面等待所需字体加载后显示,失败会提示刷新。代码块固定使用 highlight.js 的 Atom One Dark,与页面明暗模式独立。
快捷键默认参考 Typora 的 Windows/Linux 或 macOS 组合,无对应项及插件命令默认留空。可以搜索、添加、逐条删除、单项或全部重置,冲突绑定会被拒绝。Ctrl/Cmd+1~6 设置对应标题,再次触发同级标题恢复正文;浏览器保留键可自行改绑。
手机设置采用分类和内容两级布局。应用安装入口位于「设置 → 关于」;PWA 缓存静态外壳,**不代表支持离线编辑与离线同步**。
## 回收站与存储空间
删除的内容进入回收站,支持恢复和清空全部。默认保留 30 天,设置为 0 则不自动删除;修改期限同样影响已有条目,清理在启动时及每小时执行。
「存储空间」自动展示数据目录、外置笔记库和可选字体占用;字体统计不含默认 Maple,附件与回收站计入笔记库。这里还可导出/导入完整实例、笔记和设置,优化/重建索引、清理临时文件、重置设置及导出日志。
完整实例恢复会替换当前业务数据并要求重新登录;替换前请先备份,具体范围、限制与恢复注意事项见[部署与维护](deployment.md#备份与恢复)。
## 插件与界面恢复
插件由实例管理者安装,属于有完整前端权限的扩展,请只安装可信来源;不提供沙箱隔离保证。开发入口见[开发指南](development.md#主题字体与插件)。
插件导致界面异常时,可在地址后加 `?disable-plugins` 暂停插件并进入管理。主题或 CSS 片段导致界面不可用时,可加 `?reset-appearance` 临时停用自定义外观,再进入设置恢复默认。这些入口不自动删除笔记或丢弃编辑内容。
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB