Skip to content
chenfeitechPublic

About

markdown gui tools

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

43 Commits

Folders and files

Repository files navigation

xink

基于 GPUI 的本地优先 Markdown 笔记桌面应用,目标是提供 Obsidian 的基础能力: 目录管理、Markdown 编辑、实时预览,以及 JSON / YAML / TOML 数据文件的编辑与格式化预览。

核心原则:笔记就是磁盘上普通的 .md 文件——不需要账号,不上传云端,不转换格式, 不引入数据库。索引、缓存、配置都是可随时重建的派生数据。


功能总览

1. 库与目录管理

功能 说明
打开文件夹作为库 Cmd+O 选择任意文件夹;库根就是普通目录,可被 Obsidian 直接打开
多库管理 独立「库管理」窗口:新增、切换、改名、重新定位(路径失效时重选目录且 id 不变)、删除(仅移除记录,绝不删磁盘);每个库带状态徽标(当前库 / 失效 / 重复 / 嵌套)
目录树浏览 递归扫描,目录在前、同层按名称排序,库根默认展开
文件类型图标 目录 / Markdown / 图片 / 代码 / 数据文件 / 压缩包 / 表格 / 其他
默认可见范围 可编辑文本(.md、.json、.yaml、.yml、.toml)+ 图片;开启"显示全部"后其他类型也进树
始终忽略 .git、node_modules、target、.DS_Store、*.md.tmp 以及(未开"显示全部"时的)点开头隐藏项
新建 新建笔记(自动补 .md、重名报错)、新建目录
重命名 / 删除 / 移动 工具栏按钮、右键菜单、F2;禁止删除库根与库外路径
树内拖拽移动 拖拽带文件名浮层、悬停高亮落点;禁止移入自身或子目录、同名自动改名不覆盖;跨设备走"复制 + 大小校验 + 删源",大小不一致保留源文件并报错
外部导入 从访达拖入文件/目录即复制进库;也支持复制模式/移动模式的批量导入
粘贴 访达复制的文件导入,或截图直接写成 pasted-<时间戳>.<ext>
右键菜单 重命名、删除、在此新建笔记/文件夹、移动到…、复制相对路径、复制为 Markdown 链接、插入到当前笔记、粘贴到此目录
自动刷新 notify 递归监听库目录;仅"新建/删除"才重扫整棵树,"内容修改"不触发重扫

2. 笔记编辑

功能 说明
源码模式编辑 基于代码编辑控件(行号可开关),Rope 存储,不逐字符拷贝全文
格式工具栏 13 个按钮:加粗、斜体、删除线、标题、无序列表、有序列表、任务列表、引用、代码块、链接、图片、表格、分割线。有选区则包裹,无选区则插入占位并把光标放中间
自动保存 停止输入 300ms(可在 200–60000ms 间配置)后防抖写入;每次输入覆盖上一个任务,旧任务自动取消
立即保存 Cmd+S 绕过防抖立刻写盘
原子写盘 同目录写 .tmp 再 rename,崩溃绝不产生半截文件;失败清理临时文件
脏标记 未保存时标签标题显示 ●
外部修改处理 磁盘文件被外部改动:无未保存修改则自动重载;有未保存修改则保留你的内容并提示,绝不静默覆盖
多标签 同一文件只会有一个标签(重复打开只激活已有标签);标签按打开顺序排列,每个标签独立关闭按钮
最后一个标签 关闭最后一个标签不清空编辑区,而是置为空白占位页,保证下次打开有落点
会话恢复 重启后恢复上次的标签顺序与活动标签(按当前库过滤,失效路径自动剔除)
缩进配置 Tab / 空格、缩进宽度 1–16,改设置立即生效

3. 预览

功能 说明
Markdown 渲染 标题、粗斜体、删除线、列表、任务列表、引用、表格、代码块、分隔线、链接、图片
图片预览模式 点击笔记里的图片或目录树中的图片文件,在同一个预览面板显示(不新开窗口);切换/编辑笔记时自动退出
本地图片内联 相对路径 / 绝对路径 / file:// 本地图自动转 base64 data URL;带缓存(按路径 + mtime + 大小),单图上限 5MB
图片显示方式 适应宽度(20–100% 可调)或隐藏(退化为纯文本链接)
代码块高亮 syntect 默认语法全集,按语言名或扩展名查找,找不到回退纯文本;结果带缓存(256 条上限)
高亮主题 可从 syntect 全部主题中选择;默认「跟随主题」,随明暗自动切换深浅
滚动同步 编辑区与预览双向同步,逐帧轮询,带回显吸收防死循环;可在设置里关闭;图片模式不参与
版面密度 紧凑 / 适中 / 宽松三档(影响留白、段间距、标题缩放、正文最大宽度),也可单独设最大宽度
链接点击 应用内打开(尝试作为笔记打开)或交给系统浏览器,可配置
防御性预处理 连续分隔线之间自动补空行,规避底层 Markdown 解析器 panic 导致应用退出

4. 数据文件编辑(JSON / YAML / TOML)

功能 说明
可打开的类型 .json、.yaml、.yml、.toml
编辑区语法高亮 按语言高亮(json / yaml / toml)
预览显示格式化结果 预览区展示 pretty-print 之后的内容,并带代码块高亮
格式校验 实时校验;非法内容给出行 / 列 + 原因,编辑区打波浪线标记,预览顶部也有红字提示
错误不阻断保存 校验错误不会阻止你保存(xink 是编辑器,不是 IDE)
缩进宽度 JSON 缩进 1–8 空格可配置
大文件保护 超过体积上限(默认 1MB,可配置,0 表示不限制)就跳过格式化、直接显示原文
格式化只进预览 程序绝不改写你的文件。YAML 往返会丢失注释,所以格式化结果只用于预览,写盘永远是你输入的原文

5. 界面与外观

功能 说明
三栏布局 左文件树 / 中编辑 / 右预览,基于可拖拽、可停靠的 DockArea;默认左 260px、右 420px
布局持久化 布局写入 layout.json(带版本号),结构变更时自动重建默认布局
主题 跟随系统 / 浅色 / 深色;跟随系统时随系统外观变化实时切换
字体与图标 目录树、编辑区、预览区各自可设字体族 / 字号 / 行高 / 字重;目录树图标大小 12–48px

6. 设置

独立设置窗口(单例),三个分类八个分组,改动即时生效并落盘:

分类 分组 主要设置项
基本 外观 主题、界面语言
基本 目录树 图标大小、字体、是否显示全部文件
编辑器 编辑行为 自动保存开关与延迟、缩进、行号、拼写检查
编辑器 字体与排版 字体族 / 字号 / 行高 / 字重、配色
编辑器 数据文件 JSON 缩进宽度、格式化体积上限
预览 渲染 代码高亮主题、图片显示方式与宽度、链接打开方式
预览 排版 字体、版面密度、正文最大宽度
预览 同步 编辑区与预览滚动同步

附加能力:设置项搜索(输入即过滤、回车跳首个命中)、单项重置为默认、配置导入 / 导出 / 恢复全部默认; 对已配置但尚未生效的项会标注「⚠ 暂未生效」。

已知尚未生效的配置项:界面语言(文案未本地化)、拼写检查(引擎未接入)、 编辑区配色(跟随主题,未独立适配)。

7. 持久化与容错

应用状态统一放在应用数据目录(由 dirs::data_dir() 决定):

平台 路径
macOS ~/Library/Application Support/xink/
Linux ~/.local/share/xink/
Windows %APPDATA%\xink\
├── config.json        # 用户配置(基本 / 编辑器 / 预览)
├── layout.json        # Dock 布局(面板位置与大小)
├── open_notes.json    # 已打开的标签(顺序 + 当前活动标签)
├── vaults.json        # 多库注册表与当前选择
├── vault.json         # 旧版单库记录(仅作迁移来源)
└── xink.pid           # 单实例锁
  • 笔记正文不在这里,始终是库目录里普通的 .md 文件;这里都是可重建的派生状态。
  • 删除整个目录只会丢失偏好与界面状态,不会丢失任何笔记。
  • 文件缺失或 JSON 损坏一律回落默认值继续启动,不会崩在启动阶段。
  • 旧版本配置文件缺字段自动补齐;已移除的旧枚举值有兜底,不会导致整个配置解析失败。

8. 其他

  • 单实例保护:PID 文件 + 进程探测,重复启动直接退出(避免多个渲染窗口与监听线程)。
  • 外部变更监听:notify 递归监听 + 无界通道,区分"创建 / 删除 / 修改"三类事件。

快捷键

快捷键 作用
Cmd+O 打开文件夹作为库
Cmd+N 新建笔记
Cmd+S 立即保存当前笔记
Ctrl+W 关闭当前笔记标签
F2 重命名(焦点在文件树时生效)
Cmd+, 打开设置

「新建文件夹」「删除」目前只能通过文件树工具栏按钮或右键菜单触发,未绑定键位。


尚未实现

以下功能目前没有实现,避免误以为可用:

功能 状态
双链 [[笔记名]] 未实现
反向链接面板 未实现
标签 #tag 未实现
全文搜索(跨笔记) 未实现(设置窗口内的"搜索设置项"不算)
大纲 / TOC 面板 未实现
命令面板(Cmd+P) 未实现
视频播放 已尝试并放弃:Spike 阶段解码 / 渲染 / 音频 / 音画同步全部验证通过,但接进应用后画面始终出不来,代码与依赖已清理。完整复盘在 docs/video-playback-design.md(该文件位于 spike/video-playback 分支,未合入 main)

构建与运行

前置条件

macOS(GPUI 使用 Metal):安装 Xcode 命令行工具即可。

xcode-select --install

已验证:仅装 Command Line Tools 也能编译并正常运行(Metal 渲染正常)。 若要做打包签名,还需要 iconutil / sips / hdiutil(由命令行工具提供)以及 pkgbuild。

常用命令

cargo run                 # 运行
cargo test                # 运行全部测试(含 core 与 ui 的单元测试)
cargo clippy --all-targets
cargo fmt

首次编译会拉取并构建 blade-graphics / tree-sitter / resvg 等重依赖,耗时较长,属正常现象。


打包(macOS)

打包由 scripts/build_macos.sh 完成:编译 → 生成 .icns 图标 → 组装 .app → 签名 → 打包 .dmg / .pkg。

./scripts/build_macos.sh               # 编译 release,产出 .app + .dmg(最常用)
./scripts/build_macos.sh --pkg         # 额外产出 .pkg 安装器
./scripts/build_macos.sh --no-dmg      # 只产出 .app
./scripts/build_macos.sh --skip-build  # 跳过编译,用已有 target 产物重新打包
./scripts/build_macos.sh -h            # 查看用法

产物统一输出到 build/(版本号取自 Cargo.toml,无需另外维护):

产物 说明
build/xink.app 应用 Bundle
build/xink-<version>.dmg 拖拽安装盘(默认产出)
build/xink-<version>.pkg 安装器(加 --pkg)

可用环境变量覆盖默认值:

PROFILE=debug ./scripts/build_macos.sh --skip-build    # 用 debug 产物试跑打包流程
ICON_SRC=resources/other.png ./scripts/build_macos.sh  # 指定其它图标源
VERSION=0.2.0 ./scripts/build_macos.sh                 # 覆盖版本号
变量 默认值
APP_NAME xink
BUNDLE_ID com.helight.xink
VERSION 取自 Cargo.toml
ICON_SRC resources/AppIcon.png
PROFILE release
MIN_MACOS 11.0
BUILD_DIR ./build

注意事项:

  • 图标由 sips 生成多尺寸 iconset 再转 .icns。
  • 脚本会校验图标资源确实内嵌进二进制(在产物里检索 SVG),未内嵌则直接失败—— 否则打出的包在本机正常、拷到别的机器就图标全丢。
  • 签名默认是 ad-hoc(codesign --sign -),仅保证本地可运行; 分发前需用 Developer ID 重新签名(脚本结束时会打印对应命令)。

项目结构

src/
├── main.rs        启动入口:单实例检查、快捷键绑定、面板重建工厂
├── app.rs         全局状态 AppState、DockArea 布局、主题、配置更新入口
├── actions.rs     快捷键动作定义
├── core/          领域层(纯业务,不含 UI,可独立测试)
│   ├── vault.rs      库扫描、增删改移、多库注册表
│   ├── note.rs       笔记加载/保存、原子写盘、外部修改检测
│   ├── markdown.rs   预览预处理(图片内联、防御性 sanitize)
│   ├── datafile.rs   JSON / YAML / TOML 解析、格式化、校验
│   ├── media.rs      文件类型判定(唯一判据来源)
│   ├── highlight.rs  代码块语法高亮(syntect)
│   ├── config.rs     配置项定义、区间校正、持久化
│   ├── watcher.rs    外部变更监听
│   ├── session.rs    标签去重与恢复规则
│   └── fs.rs         文件复制/移动/删除/导入
├── ui/            视图层
│   ├── file_tree.rs     文件树面板
│   ├── editor.rs        编辑面板
│   ├── preview.rs       预览面板
│   ├── settings.rs      设置窗口
│   ├── tabs.rs          标签注册与"打开笔记"唯一入口
│   └── vault_manager.rs 库管理窗口
└── state/         持久化
    ├── workspace.rs      配置 / 布局 / 标签 / 库列表的读写
    └── single_instance.rs 单实例锁

测试代码放在仓库根的 tests/,目录结构镜像 src/(如 src/core/datafile.rs 的测试在 tests/core/datafile.rs,由源文件末尾的 #[path] 挂载)。详见 docs/TESTS.md。

分层铁律:ui → core 单向依赖,core/ 不得出现任何 UI 组件类型或布局样式。


文档索引

文档 内容
docs/REQUIREMENTS.md 需求规格(R1–R13)
docs/DESIGN.md 技术设计
docs/TESTS.md 测试代码的组织方式与命令
docs/json-yaml-editing-requirements.md 数据文件编辑需求(R13)
docs/json-yaml-editing-design.md 数据文件编辑设计
docs/multi-vault-design.md 多库机制设计
docs/preview-layout-design.md 预览版面设计
.codebuddy/rules/ 开发铁律(开工前必读,含会导致编译失败的硬约束)

开发约定

项目级 AI 开发规则与技能位于 .codebuddy/:

.codebuddy/rules/    开发铁律(技术栈、分层架构、编码规范、领域规则、先设计后开发)
.codebuddy/skills/   开发技能(GPUI 桌面开发、本应用开发 SOP)

开工前请先阅读 .codebuddy/rules/,其中有会导致编译失败或架构腐化的硬约束。


许可

MIT(见 Cargo.toml 的 license 字段)。

About

markdown gui tools

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages