mirror of
https://github.com/panatgithub/AnkiHeadingSync.git
synced 2026-07-22 06:51:43 +00:00
7.9 KiB
7.9 KiB
模块 5:Deck 模式选择与文件级 / 文件夹级 Deck 解析
Summary
本模块的目标是把 deck 相关功能做成“用户可选择、可理解、可插入模板”的产品形态,而不是隐式启用多套 deck 策略。
用户看到的 deck 体系固定为三层:
- 始终存在
defaultDeck,作为兜底方案 - 可选开启“文件级自定义牌组”
- 可选开启一种高级文件夹映射模式
最终优先级固定为:
文件级显式 deck > 文件夹映射 deck > defaultDeck
本轮按最新确认的决策执行:
- 旧卡 deck 行为:执行命令时按最新代码规则执行
- YAML key:与用户输入的识别名一致,默认值为
TARGET DECK - 默认模板:
obsidian::filename - 模板变量:只支持裸变量
filename
需求描述
1. 默认模式:只使用 defaultDeck
- 插件始终有
defaultDeck - 在其它 deck 功能都未开启时,所有卡都进入
defaultDeck - 这是最简单的兜底方案
2. 基本选项:开启文件级自定义牌组
开启后,设置页提供以下配置:
牌组识别名- 默认值:
TARGET DECK - 同时作用于 YAML key 和正文标记
- 默认值:
默认牌组模板- 默认值:
obsidian::filename
- 默认值:
插入位置- 单选:
YAML或正文
- 单选:
开启后插件具备两种能力:
- 解析已有文件级 deck 声明
- 提供“向当前文件插入 deck 模板”的操作
3. 高级选项:开启文件夹映射
高级选项是互斥单选,固定三态:
关闭文件夹级映射文件夹及文件名级映射
语义固定为:
关闭- 不启用文件夹映射
文件夹级映射- 例:
数学/第一章/第一节.md->数学::第一章
- 例:
文件夹及文件名级映射- 例:
数学/第一章/第一节.md->数学::第一章::第一节
- 例:
设置页必须显示这两种模式的说明和示例。
Key Changes
配置与设置页
新增或调整 PluginSettings:
defaultDeck: stringfileDeckEnabled: booleanfileDeckMarker: string- 默认
TARGET DECK
- 默认
fileDeckTemplate: string- 默认
obsidian::filename
- 默认
fileDeckInsertLocation: "yaml" | "body"folderDeckMode: "off" | "folder" | "folder-and-file"
defaultDeck 继续必填。
设置页固定展示四块内容:
Default Deck- 保留现有输入框
- 继续作为必填兜底 deck
文件级自定义牌组- 开关
- 识别名输入框
- 默认牌组模板输入框
- 插入位置单选
- “向当前文件插入 deck 模板”的操作入口
高级:文件夹映射- 单选:关闭 / 文件夹级映射 / 文件夹及文件名级映射
- 带说明文案和示例
最终优先级说明- 明文显示:文件级 > 文件夹映射 > 默认 deck
文件级 deck 解析规则
文件级显式 deck 支持两类来源:
- YAML
- 正文
两类来源统一使用用户设置的 fileDeckMarker 作为识别名。默认情况下:
- YAML key:
TARGET DECK - 正文标记:
TARGET DECK
正文支持两种语法:
TARGET DECK
数学::第一章
TARGET DECK: 数学::第一章
YAML 在默认情况下写作:
TARGET DECK: 数学::第一章
规则固定为:
- YAML key 与正文 marker 使用同一个用户配置值
- 正文只取第一个合法声明
- fenced code block 内的正文 deck 声明必须忽略
- YAML 与正文同时存在且不同:
- 继续同步
- 以 YAML 为准
- 产出结构化 warning
模板插入规则
新增“向当前文件插入 deck 模板”的操作。
模板规则固定:
- 默认模板:
obsidian::filename - 第一版只支持一个变量:
filename filename展开为当前文件名,不含.md
插入行为固定:
- 当插入位置是
yaml- 在 frontmatter 中写入
<fileDeckMarker>: <展开后的模板值> - 若没有 frontmatter,则创建 frontmatter
- 在 frontmatter 中写入
- 当插入位置是
body- 在正文靠前位置插入单行声明
- 格式:
<fileDeckMarker>: <展开后的模板值>
本轮不支持更多模板 DSL,不支持 [[filename]]。
文件夹映射规则
文件夹映射只在 folderDeckMode !== "off" 时参与解析。
folder- 仅使用父文件夹路径
folder-and-file- 使用父文件夹路径 + 当前文件名
规范化规则固定:
/转成::- trim 首尾空格
- 去掉空层级
- 结果为空则视为无效
- 文件夹名或文件名中若包含
::,产出 warning,并放弃该映射结果 - 放弃后回退到
defaultDeck
最终解析规则
最终顺序固定:
- 文件级显式 deck
- 文件夹映射 deck
defaultDeck
附加规则:
- 文件级 deck 关闭时:
- 不解析 YAML
- 不解析正文
- 只走文件夹映射或默认 deck
- 文件夹映射关闭时:
- 只走文件级或默认 deck
同步语义
本轮按最新决策执行:普通同步会让旧卡按最新 deck 规则重梳理并迁移。
这意味着:
toCreate- 使用最终
resolvedDeck - 若 deck 不存在,先
ensureDecks - 再
addNotes
- 使用最终
toUpdate- 只更新字段
toChangeDeck- 当已有 note 的 resolved deck 变化时,普通同步通过
changeDecks迁移
- 当已有 note 的 resolved deck 变化时,普通同步通过
- 普通同步会在 deck 规则变化时重新评估未改动文件
rebuildIndex仍只刷新索引与 marker,不负责 Anki deck 迁移
当前主链路接入点
本轮必须基于当前 manual-sync 主链路,不落到旧的 legacy 链路:
CardIndexingService- 提取文件级 deck 原始线索
RenderConfigService或新增的DeckResolutionService- 解析最终
resolvedDeck
- 解析最终
DiffPlannerService
- 产出字段更新与 deck 迁移两类计划
ManualSyncService- 汇总 warnings
AnkiBatchExecutor
- 新卡使用
resolvedDeck,旧卡在需要时执行changeDecks
Warning 结构
新增结构化 warning:
deck_conflict_yaml_bodydeck_multiple_body_declarationsdeck_invalid_folder_segmentdeck_fallback_default
结果对象中必须包含:
warnings: DeckResolutionWarning[]
UI 层可以额外展示 notice,但 warning 不能只存在于 notice。
Test Plan
设置与模板
- 默认加载时:
fileDeckEnabled = falsefileDeckMarker = "TARGET DECK"fileDeckTemplate = "obsidian::filename"fileDeckInsertLocation = "body"folderDeckMode = "off"
- 设置页能正确保存和回显上述字段
- 模板插入时:
- YAML 模式能写入
<marker>: <deck> - 正文模式能写入
<marker>: <deck> filename正确展开
- YAML 模式能写入
文件级 deck 解析
- 只存在 YAML 时正确解析
- 只存在正文单行语法时正确解析
- 只存在正文双行语法时正确解析
- marker 改名后,YAML 和正文都按新 marker 识别
- fenced code block 内正文声明被忽略
- 多个正文声明时只取第一个并 warning
- YAML 与正文冲突时取 YAML 并 warning
文件夹映射
folder模式下:数学/第一章/第一节.md->数学::第一章
folder-and-file模式下:数学/第一章/第一节.md->数学::第一章::第一节
- 根目录文件回退到
defaultDeck - 路径片段包含
::时 warning,并回退到 default
最终解析优先级
- 文件级 deck 覆盖文件夹映射和 default
- 无文件级时,文件夹映射覆盖 default
- 文件级关闭时,只走文件夹映射或 default
- 文件夹映射关闭时,只走文件级或 default
同步链路
- 新卡创建使用
resolvedDeck - deck 不存在时先
ensureDecks - warnings 能沿链路出现在最终 sync result
- 旧卡在普通同步中会按最新 deck 规则迁移到新的 resolved deck
Assumptions
- 本轮是 deck 配置与解析能力增强,不重构旧卡 deck 更新语义。
- YAML key 与正文 marker 使用同一个用户配置值。
- 模板语法只支持裸变量
filename。 - 文件夹映射模式互斥单选。
- 不实现 folder->deck 手工映射表,不实现多模板 DSL,不实现标题级 deck 覆盖。