mirror of
https://github.com/panatgithub/AnkiHeadingSync.git
synced 2026-07-22 06:51:43 +00:00
5.7 KiB
5.7 KiB
模块 2:将 Anki noteId 回写到标题块末尾,使用短标记 <!-- AHS:123 -->
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标记