覆盖普通卡、Cloze、语义 QA 与 QA Group 12,新增回链名称与放置位置设置、渲染位置控制、QA Group 模板漂移更新与 renderConfigHash 失效。 Cover normal cards, cloze, semantic QA, and QA Group 12 with configurable backlink label and placement, placement-aware rendering, QA Group template drift updates, and renderConfigHash invalidation.
4.7 KiB
Obsidian Backlink Config Gap Report
Scope
本报告基于当前仓库真实代码审查,聚焦这五条链路与计划差距:
- settings 默认值、校验、持久化与旧 data.json 兼容
- 普通 QA / Cloze / 语义 QA 的回链渲染入口
- Cloze title/body 合并影响面
- QA Group 12 模板生成与 model drift 更新链路
- renderConfigHash 对已同步卡片的失效机制
Confirmed Gaps
1. 普通卡回链仍硬编码在 ManualCardRenderer
src/domain/manual-sync/services/ManualCardRenderer.ts 当前只在一个分支里决定回链行为:
addObsidianBacklink = true时始终向renderedFields.body末尾追加<p><a ...>Open in Obsidian</a></p>- 没有 label 配置入口
- 没有 placement 配置入口
这意味着普通 QA、Cloze、语义 QA 目前共享同一个“答案末尾 + 固定文案”硬编码。
2. Cloze 兼容点不在 renderer,而在现有字段映射合并逻辑
当前仓库结构里,Cloze 仍然由 renderer 先产出 title / body,再由 note field mapping 把它们合并进主字段。
因此实现时不需要改 Cloze 的字段结构;只要保证 question-last-line 改的是 title,answer-first-line / answer-last-line 改的是 body,现有 title<br><br>body 合并形状就会自然继承新位置。
3. QA Group 12 也仍然硬编码默认回链
src/application/services/QaGroupModelDefinition.ts 当前在模板生成里写死:
- back 模板固定把
<a class="anki-heading-sync-backlink" href="{{Src}}">Open in Obsidian</a>放在答案容器后 buildQaGroupModelDefinition()没有接收 settings 或其他配置参数
src/application/services/QaGroupModelService.ts 的 ensureModel() 也始终调用无参 buildQaGroupModelDefinition(),所以模板漂移更新机制存在,但暂时无法感知用户配置。
4. QA Group note 字段链路已经独立,不需要改字段结构
src/application/services/QaGroupSyncService.ts 当前行为已符合计划的结构约束:
Src仍由buildGroupBacklink()生成并写入 note fieldsbuildQaGroupNoteFields()仍固定写Stem / GroupId / Src / S01..S12- 没有通过普通 note field mapping 去映射 QA Group 字段
因此本轮不需要新增字段,也不需要改变 Src 含义,只需让 model template 生成使用当前 settings。
5. settings 持久化只做默认值合并,没有空 label 归一
src/infrastructure/persistence/DataJsonPluginConfigRepository.ts 当前对 settings 的处理是:
- load 时直接用
DEFAULT_SETTINGS合并旧 snapshot - save 时直接校验后原样写回
这能处理“缺字段”,但不能处理:
- 旧 / 异常 data.json 中
obsidianBacklinkLabel为空字符串或全空格 - UI 保存时把全空格文案写进 settings
计划要求的空 label 归一,需要引入一个显式 normalize 层。
6. renderConfigHash 目前还不感知新配置
src/application/services/RenderConfigService.ts 当前 hash 只包含:
- note model / mapping
addObsidianBacklinkconvertHighlightsToClozekeepPureTagLinesInCardBody
如果只修改 label 或 placement,当前 diff planner 不会把已同步卡片判定为需要更新。
7. settings UI 与 i18n 尚未暴露新配置
src/presentation/settings/PluginSettingTab.ts 当前只在 sync options 区域渲染了 addObsidianBacklink toggle,没有:
- label 文本输入
- placement 下拉
中英文消息文件里也尚未存在这两组设置文案与 placement 校验错误文案。
8. 现有测试覆盖还缺四个关键面
当前仓库已有:
PluginSettings.test.tsPluginSettingTab.test.tsManualCardRenderer.test.tsQaGroupModelService.test.tsQaGroupSyncService.test.ts
但还缺或不足:
- settings 归一化与 placement 校验
- label / placement 改变引起的 renderConfigHash 变化
- 普通卡三种 placement 的断言
- QA Group 模板三种 placement 与 drift 更新断言
Repository-Compatible Fix Direction
最安全的仓库兼容方案是:
- 在 settings 层新增集中 normalize 函数,供 load/save/UI 共用。
- 把普通卡回链渲染收口成共享 helper,并在
ManualCardRenderer内按 placement 分流到title或body。 - 让
buildQaGroupModelDefinition()接收 label/placement,并让QaGroupModelService.ensureModel()按 settings 生成模板。 - 把 label/placement 纳入
RenderConfigServicehash。 - 只扩展现有测试锚点,不改 note 字段结构、不改
Src语义、不做无关重构。
Out Of Scope
本轮不扩张到:
- 新增 note 字段
- 改写 QA Group field contract
- 修改 Cloze 合并结构
- 新增独立的 QA Group settings 面板
- 调整现有 Obsidian backlink 开关语义