mirror of
https://github.com/panatgithub/AnkiHeadingSync.git
synced 2026-07-22 06:51:43 +00:00
删除已失效的 legacy sync use case、syncRegistry 持久化与旧 card pipeline,运行入口保持 ManualSyncService 主链。 Remove the obsolete legacy sync use cases, syncRegistry persistence, and old card pipeline while keeping the runtime on ManualSyncService.
5.9 KiB
5.9 KiB
模块 2:将 Anki noteId 回写到标题块末尾,使用短标记 <!-- AHS:123 -->
归档说明(2026-04-21):本文描述的是已移除的 legacy syncRegistry 主链方案。 当前保留的生产同步链路是
ManualSyncService所在的 manual-sync 体系。
Summary
- 新增卡片同步成功后,把返回的
Anki noteId写回对应标题块的块尾,格式固定为<!-- AHS:<noteId> -->。 - 以后该标题块再次同步时,优先按这个
noteId更新原卡,不再依赖标题 + 行号 + 路径。 - 标记放在块尾而不是标题下方,用来明确卡片边界。
- 老卡不迁移,只对以后新增的卡生效;老卡继续走当前
cardKey逻辑。 - 如果块尾
noteId在 Anki 中不存在,自动重建新卡并替换为新的noteId。 - 如果同一标题块从
basic切到cloze或反过来,直接报错并要求用户重建。
Key Changes
1. 标记语法与块尾规则
- 唯一支持的标记格式:
<!-- AHS:<正整数> -->
- 标记位置固定:
- 当前标题块最后一个非空内容行之后
- 下一个同级或更高层级标题之前
- 写回规则固定:
- 有正文时:写在正文末尾
- 无正文时:写在标题下一行
- 标记本身视为块尾终止标记
- 读取规则固定:
- 只识别当前标题块块尾的最后一个合法
AHS标记 - 标记不进入
bodyMarkdown - 同一标题块多个合法
AHS标记时报错 - 非法
AHS格式时报错,不静默忽略
- 只识别当前标题块块尾的最后一个合法
2. 提取与渲染
CardDraft增加embeddedNoteId?: numberSourceLocation增加块尾定位信息,至少包括:blockEndLinecontentEndLinemarkerLine?: number
CardExtractionService负责:- 识别块尾
<!-- AHS:... --> - 从正文中剔除该标记
- 将
embeddedNoteId放入CardDraft
- 识别块尾
CardRenderingService不处理身份标记,继续只处理标题和正文渲染
3. 同步身份与本地状态
- 同步身份模式固定为三种:
embedded-note-idlegacy-card-keypending-note-id-write
SyncRecord增加:identityMode: "embedded-note-id" | "legacy-card-key" | "pending-note-id-write"legacyCardKey?: stringnoteId: numberfilePathsourceHashlastSyncedAtorphan
SyncRegistry必须支持:findByNoteId(noteId)get(cardKey)保留兼容
- 新卡首次成功写回
AHS标记后,记录保存为embedded-note-id - 老卡无标记时,继续保存为
legacy-card-key - 建卡成功但标记写回失败时,保存为
pending-note-id-write并保留legacyCardKey
4. 规划逻辑
- 匹配优先级固定:
- 有
embeddedNoteId时,按noteId - 无
embeddedNoteId时,按当前legacy cardKey
- 有
- 对
embeddedNoteId卡片:- registry 有同
noteId记录:按sourceHash判断是否更新 - registry 无记录:仍视为已有卡,可直接更新
- registry 有同
- orphan 判定拆成两套:
embedded-note-id按本轮看到的noteIdlegacy-card-key按本轮看到的cardKey
- 老卡不自动补写
AHS,只保留当前行为
5. 执行逻辑
AnkiGateway增加:getNoteSummaries(noteIds: number[]): Promise<Array<{ noteId: number; modelName: string }>>
- 执行前先校验所有
embeddedNoteId:- note 存在且模型一致:
updateNote - note 不存在:自动重建
- note 存在但模型不一致:报错并停止该卡同步
- note 存在且模型一致:
- 自动重建流程固定:
addNote- 用新的
noteId替换块尾旧AHS标记 - registry 更新为新的
embedded-note-id
- 新卡首次同步流程固定:
- 无
AHS标记,先addNote - 把返回的
noteId写到块尾 - registry 保存为
embedded-note-id
- 无
6. Markdown 写回
VaultGateway增加:replaceMarkdownFile(path: string, expectedContent: string, nextContent: string): Promise<void>
- 写回采用 optimistic concurrency:
- 文件内容仍等于扫描时内容才允许写回
- 块尾写回算法固定:
- 定位当前标题块结束边界
- 移除旧
AHS标记(若存在) - 将新标记写到块内最后一个非空内容行之后
- 不允许落到下一个标题之后
- 若
addNote成功但写回失败:- 不删除新建 note
- registry 记为
pending-note-id-write - 以后只要还能按 legacy key 命中,就继续尝试补写
AHS
- 补写成功后,记录转为
embedded-note-id
Public Interfaces / Types
CardDraft.embeddedNoteId?: numberSourceLocation.contentEndLine: numberSourceLocation.markerLine?: numberSyncRecord.identityModeSyncRecord.legacyCardKey?: stringVaultGateway.replaceMarkdownFile(...)AnkiGateway.getNoteSummaries(...)HeadingSyncMarkernoteId: numberraw: stringlineIndex: number
Test Plan
- 块尾
<!-- AHS:123 -->能被正确识别 AHS标记不会进入bodyMarkdown- 同一标题块多个
AHS标记时报错 - 非法
AHS格式时报错 - 新卡创建后,
AHS被写到块尾 - 空正文标题块时,
AHS写在标题下一行 - 带
AHS的卡在改标题、改正文、块内移动、文件移动后仍更新原 note - registry 丢失时,带
AHS的卡仍能按noteId更新 noteId在 Anki 不存在时会自动重建,并替换块尾AHSbasic/cloze类型切换时报错- 老卡无
AHS时继续走 legacycardKey addNote成功但写回失败时,生成pending-note-id-write- 下次命中后可补写
AHS并转正 - orphan 检测对
embedded-note-id和legacy-card-key都正确
Assumptions
- 第一版只支持块尾短标记
<!-- AHS:<noteId> --> - 不兼容旧的
ID:行、长注释格式、frontmatter、block ID - 老卡不迁移;只有以后新增的卡获得稳定
noteId身份 basic与cloze的跨类型切换第一版不自动处理- 允许插件改写 Markdown 文件,在标题块末尾插入或替换
AHS标记