From 911949bedccd816c5ab2dfb6a8f5dc773a63e52b Mon Sep 17 00:00:00 2001 From: Dusk Date: Sun, 26 Apr 2026 11:47:11 +0800 Subject: [PATCH] fix(sync): make saved field mappings authoritative MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 中文: 统一已保存字段映射为同步权威来源,移除填空题对 isCloze 与命名猜测的阻断,并让多级列表问答按已保存 titleField 与 slots 同步。 English: Makes saved field mappings the sync authority, removes cloze blocking based on isCloze and name heuristics, and syncs QA Group cards with saved title and slot mappings. --- docs/field-mapping-authority-decisions.md | 69 +++++++++ docs/field-mapping-authority-gap-report.md | 138 +++++++++++++++++ main.js | 40 ++--- src/application/config/PluginSettings.test.ts | 38 +++++ src/application/config/PluginSettings.ts | 63 +++++++- .../services/NoteFieldMappingService.test.ts | 57 ++++++- .../services/NoteFieldMappingService.ts | 16 +- .../services/QaGroupSyncService.test.ts | 140 +++++++++++++++++- .../services/QaGroupSyncService.ts | 21 ++- .../anki/AnkiConnectGateway.test.ts | 25 +--- src/infrastructure/anki/AnkiConnectGateway.ts | 14 +- src/presentation/i18n/messages/en.ts | 7 +- src/presentation/i18n/messages/zh.ts | 7 +- .../settings/PluginSettingTab.test.ts | 62 +++++++- src/presentation/settings/PluginSettingTab.ts | 91 +++++++++++- 15 files changed, 699 insertions(+), 89 deletions(-) create mode 100644 docs/field-mapping-authority-decisions.md create mode 100644 docs/field-mapping-authority-gap-report.md diff --git a/docs/field-mapping-authority-decisions.md b/docs/field-mapping-authority-decisions.md new file mode 100644 index 0000000..0a75056 --- /dev/null +++ b/docs/field-mapping-authority-decisions.md @@ -0,0 +1,69 @@ +# Field Mapping Authority Decisions + +## 1. 同步权威来源 + +最终统一规则: + +1. 用户在设置里已保存的 `noteFieldMappings` 是同步权威来源 +2. 自动识别只负责“首次建议”或“草稿建议” +3. 同步期不再让字段名/模型名/模板名猜测覆盖 saved mapping + +## 2. Basic / Semantic QA + +保持现有行为: + +1. 要求 saved mapping 存在 +2. `titleField` 与 `bodyField` 都已配置 +3. 两字段必须不同 +4. 两字段仍存在于当前 Anki 字段列表中 + +## 3. Cloze + +最终行为: + +1. 不再使用 `isCloze` 作为同步阻断条件 +2. 不再依赖模型名 / 模板名 / 字段名猜 Cloze 兼容性 +3. 只要求 `cloze:` saved mapping 存在 +4. `mainField` 已配置 +5. `mainField` 仍存在于当前 Anki 字段列表 +6. 真正的模型语义不兼容,由 AnkiConnect 的 `addNote` / `updateNoteFields` / `updateNoteModel` 返回真实错误 + +## 4. QA Group + +最终行为: + +1. 同步直接使用已保存的 `qa-group:` mapping +2. saved `titleField` 和 `slots` 都是权威来源 +3. 不在同步期重新 `suggest()` slots +4. 不再要求 warnings 已确认才能同步 +5. 只校验这些确定性事实: + - mapping 存在 + - `titleField` 已配置 + - 至少有一个 slot + - slot 里的 question/answer 字段仍存在 + - 当前块的 item 数量不超过 saved slot 数量 + +## 5. 设置页 + +最终行为: + +1. 读取 Anki 字段后,仍会为缺失 mapping 的卡片类型生成建议映射 +2. Basic / Cloze 继续在刷新时保留用户已选字段,只更新 `loadedFieldNames` / `loadedAt` +3. QA Group 若已有 saved mapping,则刷新缓存时保留已保存 `titleField` / `slots` +4. QA Group 不再在缓存刷新时自动重算 slots 覆盖 saved mapping + +## 6. `getModelDetails()` + +最终行为: + +1. 继续返回字段列表 +2. 不再通过英文模型名 / 模板名 / 字段名推断 Cloze 兼容性 +3. `isCloze` 保留在 DTO 形状中,但不再承担同步阻断职责 + +## 7. 与计划的显式偏差 + +有一个实现层偏差,但不影响本次目标: + +1. 当前仓库没有 QA Group slot 级别的手动编辑 UI +2. 因此本轮不新增 slot 编辑器 +3. 通过“保存后不被同步期与缓存刷新期覆盖”来落实 saved mapping authority \ No newline at end of file diff --git a/docs/field-mapping-authority-gap-report.md b/docs/field-mapping-authority-gap-report.md new file mode 100644 index 0000000..1f5c249 --- /dev/null +++ b/docs/field-mapping-authority-gap-report.md @@ -0,0 +1,138 @@ +# Field Mapping Authority Gap Report + +## 审查范围 + +本轮先按真实仓库代码审查了以下控制点: + +1. [src/application/services/NoteFieldMappingService.ts](src/application/services/NoteFieldMappingService.ts) +2. [src/application/services/QaGroupSyncService.ts](src/application/services/QaGroupSyncService.ts) +3. [src/application/services/QaGroupFieldMappingService.ts](src/application/services/QaGroupFieldMappingService.ts) +4. [src/presentation/settings/PluginSettingTab.ts](src/presentation/settings/PluginSettingTab.ts) +5. [src/infrastructure/anki/AnkiConnectGateway.ts](src/infrastructure/anki/AnkiConnectGateway.ts) +6. [src/application/services/AnkiBatchExecutor.ts](src/application/services/AnkiBatchExecutor.ts) +7. [src/application/services/NoteFieldMappingService.test.ts](src/application/services/NoteFieldMappingService.test.ts) +8. [src/application/services/QaGroupSyncService.test.ts](src/application/services/QaGroupSyncService.test.ts) +9. [src/presentation/settings/PluginSettingTab.test.ts](src/presentation/settings/PluginSettingTab.test.ts) +10. [src/infrastructure/anki/AnkiConnectGateway.test.ts](src/infrastructure/anki/AnkiConnectGateway.test.ts) + +## 实际实现现状 + +### 1. 普通问答 / Cloze 的同步权威入口 + +[src/application/services/AnkiBatchExecutor.ts](src/application/services/AnkiBatchExecutor.ts) 会在 addNote / updateNoteFields / updateNoteModel 前统一调用 [src/application/services/NoteFieldMappingService.ts](src/application/services/NoteFieldMappingService.ts) 做字段映射。 + +当前普通问答行为已经基本符合“已保存映射优先”: + +1. 通过 `createNoteFieldMappingKey(card.type, card.noteModel)` 读取已保存映射 +2. 校验字段存在 +3. 再映射 title/body + +### 2. Cloze 目前仍被 `isCloze` 阻断 + +当前 [src/application/services/NoteFieldMappingService.ts](src/application/services/NoteFieldMappingService.ts) 里有两处同步期阻断: + +1. `validateMapping()` 中如果 `noteModelDetails.isCloze === false`,抛出 `errors.noteFieldMapping.clozeIncompatible` +2. `mapCloze()` 中再次以 `noteModelDetails.isCloze === false` 阻断 + +这意味着: + +1. 只要插件猜错模型是不是 cloze +2. 即使 `cloze:` 已保存、`mainField` 已配置、字段也仍存在 +3. 同步也会在插件侧被提前拦截 + +### 3. `getModelDetails()` 当前确实依赖英文名/模板名/字段名猜 Cloze + +[src/infrastructure/anki/AnkiConnectGateway.ts](src/infrastructure/anki/AnkiConnectGateway.ts) 的 `getModelDetails()` 当前会: + +1. 先看模型名是否包含 `cloze` +2. 再看模板名是否包含 `cloze` +3. 最后回退到字段名里是否有 `Text` + +这正是本次要移除或降级的语言/命名型猜测来源。 + +### 4. QA Group 同步当前不是用 saved mapping 做权威 + +[src/application/services/QaGroupSyncService.ts](src/application/services/QaGroupSyncService.ts) 的 `resolveQaGroupModel()` 当前会: + +1. 读取 `settings.noteFieldMappings[qa-group:]` +2. 但不直接使用保存的 `slots` +3. 每次同步都重新调用 `qaGroupFieldMappingService.suggest(...)` +4. 再用自动识别结果作为 `mapping` + +因此当前行为与计划冲突: + +1. 同步时仍由字段名模式识别决定 slots +2. 已保存 slots 可能被忽略 +3. 自定义语言或任意字段名的 saved mapping 无法作为同步权威 + +### 5. QA Group 同步当前还会被自动识别 warnings 阻断 + +`resolveQaGroupModel()` 还会调用: + +1. `qaGroupFieldMappingService.validateWarningsAccepted(mapping)` + +这意味着同步仍依赖自动识别 warnings 的确认状态,而不是只依赖确定性的“保存映射是否存在 / 是否完整 / 字段是否仍存在”。 + +### 6. 设置页当前也会覆盖已保存 QA Group 映射 + +[src/presentation/settings/PluginSettingTab.ts](src/presentation/settings/PluginSettingTab.ts) 当前在以下路径会重新生成 QA Group mapping: + +1. `seedDraftMapping()` +2. `syncQaGroupMappingFromCache()` +3. `getCurrentMappingForConfig()` 的兜底逻辑 + +这些路径目前只保留: + +1. `titleField` +2. `acceptedWarnings` + +但会重新 `suggest()` 出新的 `slots`,从而覆盖已保存映射。 + +### 7. 设置页的 QA Group 自动识别仍有价值,但角色需要下调为“建议” + +当前 QA Group 设置 UI: + +1. 只允许显式选择 `titleField` +2. `slots` 仍来自自动识别摘要 + +这说明仓库现实和计划存在一个实现层面的差异: + +1. 当前没有 slot 级别的手动编辑 UI +2. 因此本轮不能把“手动选 slots”做成新交互 +3. 但必须保证一旦 settings 里已有 saved slots,同步与缓存刷新都不能再覆盖它们 + +## 需要落地的缺口 + +### Cloze + +需要改为: + +1. 只要求 `cloze:` 保存映射存在 +2. `mainField` 已配置 +3. `mainField` 仍存在于当前字段列表 +4. 不再以 `isCloze` 阻断 + +### QA Group + +需要改为: + +1. 同步直接使用 `qa-group:` 已保存映射 +2. 不在同步期重新 `suggest()` +3. 不再以 auto-detect warnings 阻断 +4. 只校验 saved mapping 的 title/slots/字段存在性/slot 数量是否足够 + +### 设置页 + +需要改为: + +1. 读字段后仍可生成建议映射 +2. 但如果当前已有 QA Group saved mapping,则刷新缓存时只更新 `loadedFieldNames` / `loadedAt` +3. 不再用 `suggest()` 覆盖已保存 `slots` + +## 计划适配说明 + +与附带计划相比,仓库现实有一个需要明确记录的适配点: + +1. 当前设置页没有 QA Group slot 级手动编辑 UI +2. 所以本轮不会新增新的 slot 编辑交互 +3. 改为把“已保存 mapping 权威”落实在同步期与缓存刷新期,避免任何自动识别覆盖 saved slots \ No newline at end of file diff --git a/main.js b/main.js index 8bb7e2d..8fb9b80 100644 --- a/main.js +++ b/main.js @@ -1,35 +1,35 @@ /* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD */ -"use strict";var Sn=Object.defineProperty;var fo=Object.getOwnPropertyDescriptor;var go=Object.getOwnPropertyNames;var mo=Object.prototype.hasOwnProperty;var We=(e,t)=>{for(var n in t)Sn(e,n,{get:t[n],enumerable:!0})},ho=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of go(t))!mo.call(e,i)&&i!==n&&Sn(e,i,{get:()=>t[i],enumerable:!(r=fo(t,i))||r.enumerable});return e};var ko=e=>ho(Sn({},"__esModule",{value:!0}),e);var ll={};We(ll,{default:()=>dl});module.exports=ko(ll);var lo=require("obsidian");function L(e,t){return`${e}:${t}`}function Cn(e){return e?.cardType==="basic"||e?.cardType==="semantic-qa"}function Ur(e){return e?.cardType==="cloze"}function B(e){return e?.cardType==="qa-group"}var Qr=require("obsidian");function ie(){return(0,Qr.getLanguage)()==="zh"?"zh":"en"}function ae(e,t){return t.join(e==="zh"?"\u3001":", ")}var Mn={commands:{syncCurrentFileToAnki:"Sync current file to Anki",syncVaultToAnki:"Sync vault to Anki",rebuildCardIndex:"Rebuild card index",clearCurrentFileSyncedCards:"Clear synced cards in current file",cleanupEmptyDecks:"Clean up empty decks"},settings:{pluginTitle:"Anki Heading Sync",ankiConnectUrl:{name:"AnkiConnect URL",desc:"Default is http://127.0.0.1:8765",placeholder:"http://127.0.0.1:8765"},qaHeadingLevel:{name:"QA heading level",desc:"Default is H4"},clozeHeadingLevel:{name:"Cloze heading level",desc:"Default is H5"},cardAnswerCutoffMode:{name:"Card answer cutoff mode",desc:"A valid sync marker always wins. Without a valid marker, either keep the whole heading block or stop before the first 2+ consecutive blank lines.",options:{headingBlock:"heading-block: whole heading block",doubleBlankLines:"double-blank-lines: stop before the first 2+ blank lines"}},qaGroup:{title:"QA Group 12",marker:{name:"QA Group marker",desc:"When a QA heading ends with this hashtag marker, the whole heading block syncs as one ObsiAnki QA Group 12 note.",placeholder:"#anki-list"},managedNoteType:"Managed note type: {{modelName}}. QA Group sync writes Stem / GroupId / Src / S01..S12 directly. The same note type can also appear in the field mapping panels below if you want to reuse it for other routes.",managedModelContract:"Managed model contract: {{fieldCount}} fields and {{templateCount}} templates are checked automatically during sync."},semanticQa:{title:"Semantic QA",marker:{name:"Semantic QA marker",desc:"When a QA heading ends with this hashtag marker, first-level list items with indented child content become separate cards.",placeholder:"#anki-list-qa"},previewTitle:"Semantic QA preview",triggerHeadingExample:"Trigger heading example: {{heading}}",previewUnavailable:"Preview unavailable. Use a trailing hashtag marker such as #anki-list-qa.",questionPreview:"Question preview: {{question}}",answerPreview:"Answer preview: {{answer}}"},syncOptions:{addObsidianBacklink:{name:"Add Obsidian backlink",desc:"Append a backlink to the source heading into synced cards."},obsidianBacklinkLabel:{name:"Obsidian backlink label",desc:"The text shown for the backlink. Blank input falls back to Open in Obsidian.",placeholder:"Open in Obsidian"},obsidianBacklinkPlacement:{name:"Obsidian backlink placement",desc:"Choose whether the backlink is appended to the question field or placed at the start or end of the answer body.",options:{questionLastLine:"Last line of question field",answerFirstLine:"First line of answer body",answerLastLine:"Last line of answer body"}},highlightsToCloze:{name:"Highlights to Cloze",desc:"Convert ==highlight== segments into cloze deletions for cloze cards."},syncObsidianTagsToAnki:{name:"Sync Obsidian tags to Anki",desc:"Sync Obsidian-recognized tags from the current note into Anki note tags, including nested tags. On each sync, these tags overwrite the managed tags in Anki based on the current Obsidian content."},keepPureTagLinesInCardBody:{name:"Keep pure tag lines in card body",desc:'When turned off, remove every line in the card body that contains only tags, such as "#ProjectA #\u91CD\u70B9/\u6848\u4F8B". Inline tags like "This is a #tag example" and lines with ordinary text like "\u6807\u7B7E\uFF1A#\u9879\u76EEA" are kept. Extra blank lines created by removal are cleaned up automatically.'}},mapping:{title:"Note type field mappings",refresh:{name:"Refresh note types from Anki",button:"Refresh note types"},status:{idle:"Refresh note types from Anki to load the available note types.",loadedCount:"Loaded {{count}} note types from Anki.",empty:"Anki returned no note types.",failedLoadNoteTypes:"Failed to load note types from Anki.",loadedSavedMapping:"Loaded saved mapping for {{modelName}}.",selectedModel:"Selected {{modelName}}. Read fields from Anki to create or refresh its mapping.",loadedFieldsForModel:"Loaded fields for {{modelName}}. Review the suggested mapping and save it.",failedLoadFields:"Failed to load fields for {{modelName}}.",noLoadedFields:"No loaded fields for {{modelName}}. Read fields from Anki first.",savedMapping:"Saved mapping for {{modelName}}.",failedSaveMapping:"Failed to save mapping for {{modelName}}.",savedMappingReady:"Saved mapping is ready for {{title}}.",noSavedMapping:"No saved mapping for {{title}}. Read fields from Anki first."},section:{basic:{title:"QA / Basic",description:"Choose the QA note type, read its fields from Anki, then confirm the title/body mapping."},cloze:{title:"Cloze",description:"Choose the cloze note type, read its fields from Anki, then confirm the main field mapping."},semanticQa:{title:"Semantic QA",description:"Choose the semantic QA note type, read its fields from Anki, then confirm the title/body mapping for child cards."}},noteTypeLabel:"{{title}} note type",noteTypeDesc:"Loaded from Anki note types. Refresh if the latest models are not shown.",fieldsLabel:"{{title}} fields",fieldsDesc:"Load the current note type fields from Anki, then review the suggested mapping.",readFieldsButton:"Read fields from Anki",loadedFields:"Loaded fields: {{fields}}",loadedFieldsNone:"Loaded fields: none. Read fields from Anki first.",mappingLabel:"{{title}} mapping",mappingDesc:"Save the current field mapping for this specific note type.",saveMappingButton:"Save mapping",titleFieldLabel:"{{title}} title field",titleFieldDesc:"Which Anki field should receive the heading/title fragment.",bodyFieldLabel:"{{title}} body field",bodyFieldDesc:"Which Anki field should receive the body fragment.",mainField:{name:"Cloze main field",desc:"The selected field receives title +

+ body during sync."},selectFieldPlaceholder:"-- Select field --"},deck:{defaultSectionTitle:"Default deck",defaultDeck:{name:"Default deck",desc:"Lowest priority: used when neither a file-level deck nor a folder mapping matches."},fileDeckSectionTitle:"File-level custom deck",fileDeckEnabled:{name:"Enable file-level custom deck",desc:"When enabled, a shared marker can define one deck for the whole note in YAML or body."},marker:{name:"Deck marker name",desc:"YAML key and body marker share the same identifier. The default value is TARGET DECK."},template:{name:"Default deck template",desc:"Only the filename variable is supported. It expands to the current file name without .md when inserted."},insertLocation:{name:"Template insert location",desc:"Choose whether the deck template is written into YAML frontmatter or the body header area.",options:{body:"Body header",yaml:"YAML frontmatter"}},insertTemplate:{name:"Insert deck template into the current file",desc:"Write the deck declaration into the current active Markdown file using the current marker, template, and insert location.",button:"Insert deck template"},folderMappingSectionTitle:"Advanced: folder mapping",folderDeckMode:{name:"Folder mapping mode",desc:"Off / parent folders only / parent folders plus current file name.",options:{off:"Off",folder:"Folder-based mapping",folderAndFile:"Folder-and-file mapping"}},examplesTitle:"Examples:",folderExample:"Folder-based mapping example: \u6570\u5B66/\u7B2C\u4E00\u7AE0/\u7B2C\u4E00\u8282.md -> \u6570\u5B66::\u7B2C\u4E00\u7AE0",folderAndFileExample:"Folder-and-file mapping example: \u6570\u5B66/\u7B2C\u4E00\u7AE0/\u7B2C\u4E00\u8282.md -> \u6570\u5B66::\u7B2C\u4E00\u7AE0::\u7B2C\u4E00\u8282",fallbackDesc:"If neither folder-and-file mapping nor file-level custom decks are used, the default deck name is used as the Anki deck.",priorityTitle:"Final priority",priorityDesc:"Final deck priority: file-level custom deck > folder-mapped deck > default deck."},scope:{name:"Plugin run scope",summary:{all:"Process Markdown files across the whole vault",include:"Only process Markdown files in the checked folders below",exclude:"Process the whole vault, but skip Markdown files in the checked folders below"},option:{all:"All files",include:"Only in selected folders",exclude:"Exclude selected folders"},treeDescription:{include:"Only in selected folders: only process Markdown files in the checked folders below",exclude:"Exclude selected folders: process the whole vault, but skip Markdown files in the checked folders below"},loading:"Loading folders from the current vault...",empty:"There are no selectable folders in the current vault.",failedLoad:"Failed to load folders from the current vault.",expandFolder:"Expand {{name}}",collapseFolder:"Collapse {{name}}"},cards:{cardTypes:{title:"Card types and basics",desc:"Edit recognition rules directly. Changes save automatically.",advancedHint:"Advanced: keep AnkiConnect URL here without promoting it to a separate status card.",markerPlaceholder:"/",fieldsUnavailable:"-- Read fields first --",autoManagedField:"Managed automatically",autoComposedAnswer:"Auto composed",qaGroupManagedNoteType:"{{modelName}} (managed automatically)",statusLabel:"Status: ",cacheEmpty:"There are no cached Anki note templates yet. Read the Anki template config manually.",cacheSummary:"Currently using {{noteTypeCount}} cached note templates with {{configuredCount}} selected card modes configured.",cacheChanged:"Anki currently reports {{liveCount}} note templates, which differs from the {{cachedCount}} cached templates on this page. The UI is still using the cache with {{configuredCount}} selected card modes configured; read the Anki template config manually to refresh.",cacheCheckFailed:"Still using {{noteTypeCount}} cached note templates with {{configuredCount}} selected card modes configured. The background check for the latest template list failed; read the Anki template config manually if you need a refresh.",loadedSummary:"Loaded {{noteTypeCount}} note templates and configured {{configuredCount}} selected card modes.",loadedFieldsStatus:"Refreshed fields for {{count}} selected note types.",failedLoad:"Failed to load note types or fields from Anki.",failedSave:"Failed to save card type settings.",loadAnki:{button:"Read Anki note types and fields manually",loading:"Loading Anki note types and fields..."},columns:{enabled:"Enabled",type:"Card type",headingLevel:"Heading marker",extraMarker:"Extra marker",noteType:"Anki note type",questionField:"Question field",answerField:"Answer field"},labels:{headingLevel:"Card marker:",extraMarker:"Extra marker:",noteType:"Anki note type:",questionField:"Question field:",answerField:"Answer field:",mainField:"Main field:",fields:"Fields:",qaGroupTitleField:"Title field:",qaGroupSlotFields:"Q/A fields:",qaGroupWarnings:"Warnings:"},qaGroup:{noModel:"Select an Anki note type first",unavailable:"Read fields from Anki first",detectedSlots:"Detected {{count}} pair(s)",acceptWarnings:"I confirm these warnings can be ignored and sync may continue",warning:{missingAnswer:"Slot {{index}} is missing its answer field, so {{questionField}} / {{answerField}} was ignored.",missingQuestion:"Slot {{index}} is missing its question field, so {{questionField}} / {{answerField}} was ignored."}},rows:{basic:"Q&A (regular paragraph)",qaGroup:"Q&A (nested list)",cloze:"Cloze",semanticQa:"Semantic Q&A"}},syncContent:{title:"Card body sync content",desc:"These options affect rendered content only. Updating them refreshes this card only.",sections:{bodyRange:"1. Choose the card body range",backlink:"2. Add backlinks for card-level jumps from Anki to Obsidian",tags:"3. Read tags",clozeSpecial:"4. Cloze-specific options"}},scope:{title:"Plugin run scope",desc:"Keep the existing scope modes and folder tree. The tree is loaded lazily and can be refreshed locally.",refreshFolders:"Refresh folder list"},deck:{title:"Card deck settings",desc:"Card deck settings are grouped by recommended workflow.",sections:{folderMapping:"1. Recommended: use folder-and-file mapping for Anki decks",fileDeck:"2. Optional: enable file-level custom decks",defaultDeck:"3. Fallback: use the default deck"}},commands:{title:"Command guide",desc:"These are the current commands exposed in the command palette.",items:{syncCurrentFile:"Sync only the active Markdown file to Anki.",syncVault:"Sync all in-scope Markdown files in the vault to Anki.",rebuildIndex:"Rebuild the local card index without creating or updating notes.",clearCurrentFile:"Clear synced card markers and tracked sync state for the active file.",cleanupDecks:"Delete selected empty decks from Anki."}}}},modal:{emptyDeck:{title:"Clean up empty decks",description:"Select the empty decks to delete. A deck is deleted only if it is still empty at deletion time.",selectAll:"Select all",clearAll:"Clear all",invert:"Invert selection",cancel:"Cancel",deleteSelected:"Delete selected empty decks",selectionCount:"Selected {{selected}} / {{total}} empty decks"}},notice:{invalidSettingsRestored:"Invalid plugin settings were detected. Default settings were restored in memory.",failedSavePluginSettings:"Failed to save plugin settings.",noActiveMarkdownForSync:"No active Markdown file is available for sync.",syncUseCaseNotInitialized:"Sync use case is not initialized.",currentFileSyncFailed:"Current file sync failed.",vaultSyncFailed:"Vault sync failed.",rebuildFailed:"Card index rebuild failed.",noActiveMarkdownForDeckTemplateInsertion:"No active Markdown file is available for deck template insertion.",vaultGatewayNotInitialized:"Vault gateway is not initialized.",markdownFileNotFound:"Markdown file not found: {{filePath}}",deckTemplateAlreadyCurrent:"The deck template in the current file is already up to date.",deckTemplateInserted:"Inserted deck template into the current file: {{deck}}",deckTemplateInsertionFailed:"Deck template insertion failed.",noActiveMarkdownForReset:"No active Markdown file is available for reset.",clearCurrentFileUseCaseNotInitialized:"Clear-current-file use case is not initialized.",noTrackedCardsInCurrentFile:"There are no synced cards in the current file.",clearCurrentFileFailed:"Clear current file synced cards failed.",cleanupEmptyDecksUseCaseNotInitialized:"Empty-deck cleanup use case is not initialized.",noEmptyDeckCandidates:"No empty decks were found for cleanup.",cleanupEmptyDecksCancelled:"Empty-deck cleanup was cancelled.",cleanupEmptyDecksFailed:"Cleanup empty decks failed.",summary:{currentFileSync:"Current file sync completed: files {{scannedFiles}}, cards {{scannedCards}}, created {{created}}, updated {{updated}}, migrated note types {{migratedNoteTypes}}, migrated decks {{migratedDecks}}, orphaned {{orphaned}}, media {{uploadedMedia}}, skipped {{skippedUnchangedCards}}.",vaultSync:"Vault sync completed: files {{scannedFiles}}, cards {{scannedCards}}, created {{created}}, updated {{updated}}, migrated note types {{migratedNoteTypes}}, migrated decks {{migratedDecks}}, orphaned {{orphaned}}, media {{uploadedMedia}}, skipped {{skippedUnchangedCards}}.",rebuild:"Card index rebuild completed: files {{scannedFiles}}, cards {{scannedCards}}, migrated decks {{migratedDecks}}, orphaned {{orphaned}}, rewritten markers {{rewrittenMarkers}}, skipped {{skippedUnchangedCards}}.",clearCurrentFile:"Current file synced cards cleared: tracked cards {{trackedCards}}, tracked groups {{trackedGroups}}, deleted notes {{deletedNotes}}, removed markers {{removedMarkers}}, removed ID markers {{removedCardMarkers}}, removed GI markers {{removedGroupMarkers}}, deleted local records {{deletedLocalRecords}}.",cleanupEmptyDecks:"Empty-deck cleanup completed: candidates {{candidateCount}}, selected {{selectedCount}}, deleted {{deletedCount}}, skipped {{skippedCount}}.",markerWriteConflicts:"Marker write conflicts: {{files}}.",warningsCount:"Warnings: {{count}}.",markerRemovalConflicts:"Marker removal conflicts: {{files}}.",failures:"Failures: {{items}}.",skippedDecks:"Skipped decks: {{decks}}."}},errors:{currentFileOutOfScope:"The current file is outside the plugin scope: {{filePath}}",deck:{emptyName:"Deck name cannot be empty. Check the file-level deck declaration or default deck setting."},settings:{headingLevelsRange:"Heading levels must be integers between 1 and 6.",headingLevelsDifferent:"QA and Cloze heading levels must be different.",cardTypeConfigsObject:"Card type configs must be an object.",cardTypeEnabledBoolean:"Each card type enabled flag must be a boolean.",cardTypeExtraMarkerString:"Each card type extra marker must be a string.",cardTypeDefaultConflict:"Only one enabled default card type is allowed at heading H{{headingLevel}}.",cardAnswerCutoffModeInvalid:"Card answer cutoff mode must be heading-block or double-blank-lines.",qaNoteTypeRequired:"QA note type is required.",qaGroupMarkerRequired:"QA Group marker is required.",qaGroupMarkerInvalid:"QA Group marker must be a hashtag-style token like #anki-list.",clozeNoteTypeRequired:"Cloze note type is required.",semanticQaMarkerRequired:"Semantic QA marker is required.",semanticQaMarkerInvalid:"Semantic QA marker must be a hashtag-style token like #anki-list-qa.",qaGroupMarkerConflict:"QA Group marker must be different from Semantic QA marker.",semanticQaNoteTypeRequired:"Semantic QA note type is required.",defaultDeckRequired:"Default deck is required.",fileDeckEnabledBoolean:"File deck enabled must be a boolean.",syncObsidianTagsToAnkiBoolean:"Sync Obsidian tags to Anki must be a boolean.",keepPureTagLinesInCardBodyBoolean:"Keep pure tag lines in card body must be a boolean.",fileDeckMarkerString:"File deck marker must be a string.",fileDeckTemplateString:"File deck template must be a string.",fileDeckInsertLocationInvalid:"File deck insert location must be yaml or body.",folderDeckModeInvalid:"Folder deck mode must be off, folder, or folder-and-file.",scopeModeInvalid:"Scope mode must be one of all, include, or exclude.",obsidianBacklinkPlacementInvalid:"Obsidian backlink placement must be question-last-line, answer-first-line, or answer-last-line.",includeFoldersArray:"Include folders must be an array.",includeFoldersStrings:"Include folders must only contain strings.",excludeFoldersArray:"Exclude folders must be an array.",excludeFoldersStrings:"Exclude folders must only contain strings.",ankiConnectUrlRequired:"AnkiConnect URL is required.",ankiNoteTypeCacheArray:"Anki note type cache must be an array.",ankiNoteTypeCacheStrings:"Anki note type cache can only contain strings.",ankiModelFieldCacheObject:"Anki model field cache must be an object.",ankiModelFieldCacheEntryObject:"Each Anki model field cache entry must be an object.",ankiModelFieldCacheFieldNamesArray:"Anki model field cache fieldNames must be an array.",ankiModelFieldCacheFieldNamesStrings:"Anki model field cache fieldNames can only contain strings.",ankiModelFieldCacheLoadedAt:"Anki model field cache loadedAt must be a finite number.",noteFieldMappingsObject:"Note field mappings must be an object.",noteFieldMappingsCardType:"Note field mappings must use a supported card type.",noteFieldMappingsModelName:"Note field mappings must include a model name.",noteFieldMappingsLoadedFieldNames:"Note field mappings must include loaded field names.",noteFieldMappingsLoadedAt:"Note field mappings must include a loaded timestamp.",noteFieldMappingsQaGroupSlotsArray:"QA Group field mapping slots must be an array.",noteFieldMappingsQaGroupSlotObject:"Each QA Group field mapping slot must be an object.",noteFieldMappingsQaGroupSlotIndex:"Each QA Group field mapping slot.index must be an integer greater than 0.",noteFieldMappingsQaGroupSlotQuestionField:"Each QA Group field mapping slot.questionField must be a string.",noteFieldMappingsQaGroupSlotAnswerField:"Each QA Group field mapping slot.answerField must be a string.",noteFieldMappingsQaGroupWarningsArray:"QA Group field mapping warnings must be an array.",noteFieldMappingsQaGroupWarningsStrings:"QA Group field mapping warnings can only contain strings.",noteFieldMappingsQaGroupAcceptedWarningsArray:"QA Group field mapping acceptedWarnings must be an array.",noteFieldMappingsQaGroupAcceptedWarningsStrings:"QA Group field mapping acceptedWarnings can only contain strings."},noteFieldMapping:{noteTypeNotSelected:{basic:"No Anki note type is selected for basic cards. Choose one in settings before syncing.",cloze:"No Anki note type is selected for cloze cards. Choose one in settings before syncing.",semanticQa:"No Anki note type is selected for semantic QA cards. Choose one in settings before syncing.",qaGroup:"No Anki note type is selected for QA Group cards. Choose one in settings before syncing."},missingSavedMapping:{basic:'No saved field mapping found for basic note type "{{modelName}}". Open plugin settings and read fields from Anki first.',cloze:'No saved field mapping found for cloze note type "{{modelName}}". Open plugin settings and read fields from Anki first.',semanticQa:'No saved field mapping found for semantic QA note type "{{modelName}}". Open plugin settings and read fields from Anki first.'},incompleteSavedMapping:{basic:'Saved field mapping for basic note type "{{modelName}}" is incomplete. Open plugin settings and save both title and body fields.',semanticQa:'Saved field mapping for semantic QA note type "{{modelName}}" is incomplete. Open plugin settings and save both title and body fields.',cloze:'Saved field mapping for cloze note type "{{modelName}}" is incomplete. Open plugin settings and save the main field.'},titleBodyMustDiffer:{basic:'Basic note type "{{modelName}}" must use different title and body fields.',semanticQa:'Semantic QA note type "{{modelName}}" must use different title and body fields.'},stale:'Saved field mapping for note type "{{modelName}}" is stale because these fields no longer exist in Anki: {{fields}}. Open plugin settings and read fields from Anki again.',clozeIncompatible:'Cloze note type "{{modelName}}" is not cloze-compatible in Anki.',qaGroupMissingTitle:'QA Group note type "{{modelName}}" does not expose a recognizable title field. Use one of \u9898\u76EE, \u6807\u9898, \u6B63\u9762, Stem, or Title.',qaGroupNoCompleteSlots:'QA Group note type "{{modelName}}" does not expose any complete question/answer slot pairs.',qaGroupNonContinuousSlots:'QA Group note type "{{modelName}}" must start its question/answer slots at pair {{firstIndex}} = 1. Renumber the first pair to 1.',qaGroupWarningsUnaccepted:'QA Group note type "{{modelName}}" still has unconfirmed field warnings. Confirm them in settings before syncing.',qaGroupSlotCapacityExceeded:'QA Group note type "{{modelName}}" only exposes {{capacity}} question/answer pair(s), but the current block has {{itemCount}} item(s): {{filePath}}:{{blockStartLine}}.'},noteTypeMigration:{failed:'Failed to migrate Anki note {{noteId}} from "{{fromModel}}" to "{{toModel}}"{{location}}: {{reason}}',unsupported:'The current AnkiConnect does not support migrating Anki note {{noteId}} from "{{fromModel}}" to "{{toModel}}"{{location}}. Upgrade AnkiConnect, or clear the Anki ID and sync again. Reason: {{reason}}'},writeBack:{summary:"Markdown marker write-back failed for {{fileCount}} file(s).",markdownFileNotFound:"Markdown file was not found.",missingSourceContent:"Scanned source content is missing for marker write-back.",noteIdMissing:"Cannot write a marker because note ID is missing for the block at line {{blockStartLine}}."},markerRemoval:{markdownFileNotFound:"Markdown file was not found."}},warnings:{deck:{conflictYamlBody:"Conflicting {{marker}} declarations were found in YAML and body. This sync used the YAML value.",multipleBodyDeclarations:"Multiple {{marker}} declarations were found in the file. This sync used the first body declaration.",invalidFolderSegment:"A folder or file name contains ::, so folder-based deck mapping was skipped and the default deck was used.",fallbackDefault:"No explicit deck was found and a folder-based deck could not be generated, so the default deck was used."}}};var Vr={commands:{syncCurrentFileToAnki:"\u540C\u6B65\u5F53\u524D\u6587\u4EF6\u5230 Anki",syncVaultToAnki:"\u540C\u6B65\u5168\u5E93\u5230 Anki",rebuildCardIndex:"\u91CD\u5EFA\u5361\u7247\u7D22\u5F15",clearCurrentFileSyncedCards:"\u6E05\u7A7A\u5F53\u524D\u6587\u4EF6\u5DF2\u540C\u6B65\u5361\u7247",cleanupEmptyDecks:"\u6E05\u7406\u7A7A\u724C\u7EC4"},settings:{pluginTitle:"Anki Heading Sync",ankiConnectUrl:{name:"AnkiConnect URL",desc:"\u9ED8\u8BA4\u662F http://127.0.0.1:8765",placeholder:"http://127.0.0.1:8765"},qaHeadingLevel:{name:"QA \u6807\u9898\u5C42\u7EA7",desc:"\u9ED8\u8BA4\u662F H4"},clozeHeadingLevel:{name:"\u586B\u7A7A\u9898\u6807\u9898\u5C42\u7EA7",desc:"\u9ED8\u8BA4\u662F H5"},cardAnswerCutoffMode:{name:"\u5361\u7247\u6B63\u6587\u622A\u6B62\u6A21\u5F0F",desc:"\u6709\u6548\u540C\u6B65\u6807\u8BB0\u59CB\u7EC8\u4F18\u5148\u3002\u6CA1\u6709\u6709\u6548\u6807\u8BB0\u65F6\uFF0C\u9009\u62E9\u7EE7\u7EED\u5230\u6574\u4E2A\u6807\u9898\u5757\u672B\u5C3E\uFF0C\u6216\u5728\u9996\u4E2A 2+ \u8FDE\u7EED\u7A7A\u884C\u524D\u622A\u6B62\u3002",options:{headingBlock:"heading-block\uFF1A\u6574\u4E2A\u6807\u9898\u5757",doubleBlankLines:"double-blank-lines\uFF1A\u5728\u9996\u4E2A 2+ \u8FDE\u7EED\u7A7A\u884C\u524D\u622A\u6B62"}},qaGroup:{title:"QA Group 12",marker:{name:"QA Group \u6807\u8BB0",desc:"\u5F53 QA \u6807\u9898\u4EE5\u8FD9\u4E2A hashtag \u6807\u8BB0\u7ED3\u5C3E\u65F6\uFF0C\u6574\u4E2A\u6807\u9898\u5757\u4F1A\u4F5C\u4E3A\u4E00\u5F20 ObsiAnki QA Group 12 \u7B14\u8BB0\u540C\u6B65\u3002",placeholder:"#anki-list"},managedNoteType:"\u6258\u7BA1\u7B14\u8BB0\u7C7B\u578B\uFF1A{{modelName}}\u3002QA Group \u540C\u6B65\u4F1A\u76F4\u63A5\u5199\u5165 Stem / GroupId / Src / S01..S12\u3002\u5982\u679C\u4F60\u60F3\u5728\u5176\u4ED6\u540C\u6B65\u8DEF\u5F84\u91CC\u590D\u7528\u5B83\uFF0C\u5B83\u4E5F\u4F1A\u51FA\u73B0\u5728\u4E0B\u9762\u7684\u5B57\u6BB5\u6620\u5C04\u9762\u677F\u4E2D\u3002",managedModelContract:"\u6258\u7BA1\u6A21\u578B\u7EA6\u675F\uFF1A\u540C\u6B65\u65F6\u4F1A\u81EA\u52A8\u68C0\u67E5 {{fieldCount}} \u4E2A\u5B57\u6BB5\u548C {{templateCount}} \u4E2A\u6A21\u677F\u3002"},semanticQa:{title:"\u8BED\u4E49 QA",marker:{name:"\u8BED\u4E49 QA \u6807\u8BB0",desc:"\u5F53 QA \u6807\u9898\u4EE5\u8FD9\u4E2A hashtag \u6807\u8BB0\u7ED3\u5C3E\u65F6\uFF0C\u5E26\u7F29\u8FDB\u5B50\u5185\u5BB9\u7684\u4E00\u7EA7\u5217\u8868\u9879\u4F1A\u62C6\u5206\u6210\u72EC\u7ACB\u5361\u7247\u3002",placeholder:"#anki-list-qa"},previewTitle:"\u8BED\u4E49 QA \u9884\u89C8",triggerHeadingExample:"\u89E6\u53D1\u6807\u9898\u793A\u4F8B\uFF1A{{heading}}",previewUnavailable:"\u5F53\u524D\u65E0\u6CD5\u751F\u6210\u9884\u89C8\u3002\u8BF7\u4F7F\u7528\u7C7B\u4F3C #anki-list-qa \u7684\u5C3E\u968F hashtag \u6807\u8BB0\u3002",questionPreview:"\u95EE\u9898\u9884\u89C8\uFF1A{{question}}",answerPreview:"\u7B54\u6848\u9884\u89C8\uFF1A{{answer}}"},syncOptions:{addObsidianBacklink:{name:"\u6DFB\u52A0 Obsidian \u56DE\u94FE",desc:"\u628A\u6765\u6E90\u6807\u9898\u7684\u56DE\u94FE\u8FFD\u52A0\u5230\u540C\u6B65\u540E\u7684\u5361\u7247\u4E2D\u3002"},obsidianBacklinkLabel:{name:"Obsidian \u56DE\u94FE\u663E\u793A\u540D\u79F0",desc:"\u8BBE\u7F6E\u56DE\u94FE\u663E\u793A\u7684\u6587\u5B57\u3002\u7559\u7A7A\u6216\u53EA\u586B\u7A7A\u683C\u65F6\u4F1A\u56DE\u9000\u4E3A Open in Obsidian\u3002",placeholder:"Open in Obsidian"},obsidianBacklinkPlacement:{name:"Obsidian \u56DE\u94FE\u653E\u7F6E\u4F4D\u7F6E",desc:"\u9009\u62E9\u628A\u56DE\u94FE\u8FFD\u52A0\u5230\u95EE\u9898\u680F\u6700\u540E\u4E00\u884C\uFF0C\u6216\u653E\u5230\u7B54\u6848\u6B63\u6587\u7684\u7B2C\u4E00\u884C / \u6700\u540E\u4E00\u884C\u3002",options:{questionLastLine:"\u95EE\u9898\u680F\u7684\u6700\u540E\u4E00\u884C",answerFirstLine:"\u7B54\u6848\u6B63\u6587\u7684\u7B2C\u4E00\u884C",answerLastLine:"\u7B54\u6848\u6B63\u6587\u7684\u6700\u540E\u4E00\u884C"}},highlightsToCloze:{name:"\u9AD8\u4EAE\u8F6C\u586B\u7A7A\u9898",desc:"\u628A ==highlight== \u7247\u6BB5\u8F6C\u6362\u6210\u586B\u7A7A\u9898\u4F7F\u7528\u7684\u6316\u7A7A\u683C\u5F0F\u3002"},syncObsidianTagsToAnki:{name:"\u540C\u6B65 Obsidian \u6807\u7B7E\u5230 Anki",desc:"\u5C06\u5F53\u524D\u7B14\u8BB0\u4E2D Obsidian \u8BC6\u522B\u5230\u7684\u6807\u7B7E\u540C\u6B65\u4E3A Anki \u7B14\u8BB0\u6807\u7B7E\uFF0C\u652F\u6301\u5D4C\u5957\u6807\u7B7E\u3002\u6BCF\u6B21\u540C\u6B65\u65F6\uFF0C\u8FD9\u4E9B\u6807\u7B7E\u90FD\u4F1A\u4EE5\u5F53\u524D Obsidian \u5185\u5BB9\u4E3A\u51C6\u8986\u76D6 Anki\u3002"},keepPureTagLinesInCardBody:{name:"\u5728\u5361\u7247\u6B63\u6587\u4E2D\u4FDD\u7559\u7EAF\u6807\u7B7E\u884C",desc:"\u5173\u95ED\u540E\uFF0C\u4F1A\u5220\u9664\u6B63\u6587\u4E2D\u6240\u6709\u53EA\u5305\u542B\u6807\u7B7E\u7684\u6574\u884C\uFF0C\u4F8B\u5982 \u201C#\u9879\u76EEA #\u91CD\u70B9/\u6848\u4F8B\u201D\u3002\u50CF\u201C\u8FD9\u662F #\u6807\u7B7E \u7684\u6848\u4F8B\u201D\u8FD9\u7C7B\u884C\u5185\u6807\u7B7E\uFF0C\u6216\u201C\u6807\u7B7E\uFF1A#\u9879\u76EEA\u201D\u8FD9\u7C7B\u5E26\u666E\u901A\u6587\u5B57\u7684\u884C\uFF0C\u4E0D\u4F1A\u88AB\u5220\u9664\u3002\u5220\u9664\u540E\u4F1A\u81EA\u52A8\u6E05\u7406\u591A\u4F59\u7A7A\u884C\u3002"}},mapping:{title:"\u7B14\u8BB0\u7C7B\u578B\u5B57\u6BB5\u6620\u5C04",refresh:{name:"\u4ECE Anki \u5237\u65B0\u7B14\u8BB0\u7C7B\u578B",button:"\u5237\u65B0\u7B14\u8BB0\u7C7B\u578B"},status:{idle:"\u8BF7\u5148\u4ECE Anki \u5237\u65B0\u7B14\u8BB0\u7C7B\u578B\uFF0C\u4EE5\u52A0\u8F7D\u53EF\u7528\u7684\u7B14\u8BB0\u7C7B\u578B\u5217\u8868\u3002",loadedCount:"\u5DF2\u4ECE Anki \u52A0\u8F7D {{count}} \u4E2A\u7B14\u8BB0\u7C7B\u578B\u3002",empty:"Anki \u6CA1\u6709\u8FD4\u56DE\u4EFB\u4F55\u7B14\u8BB0\u7C7B\u578B\u3002",failedLoadNoteTypes:"\u4ECE Anki \u52A0\u8F7D\u7B14\u8BB0\u7C7B\u578B\u5931\u8D25\u3002",loadedSavedMapping:"\u5DF2\u52A0\u8F7D {{modelName}} \u7684\u5DF2\u4FDD\u5B58\u6620\u5C04\u3002",selectedModel:"\u5DF2\u9009\u62E9 {{modelName}}\u3002\u8BF7\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u4EE5\u521B\u5EFA\u6216\u5237\u65B0\u5B83\u7684\u6620\u5C04\u3002",loadedFieldsForModel:"\u5DF2\u52A0\u8F7D {{modelName}} \u7684\u5B57\u6BB5\u3002\u8BF7\u68C0\u67E5\u5EFA\u8BAE\u6620\u5C04\u540E\u4FDD\u5B58\u3002",failedLoadFields:"\u52A0\u8F7D {{modelName}} \u7684\u5B57\u6BB5\u5931\u8D25\u3002",noLoadedFields:"{{modelName}} \u8FD8\u6CA1\u6709\u5DF2\u52A0\u8F7D\u5B57\u6BB5\u3002\u8BF7\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002",savedMapping:"\u5DF2\u4FDD\u5B58 {{modelName}} \u7684\u6620\u5C04\u3002",failedSaveMapping:"\u4FDD\u5B58 {{modelName}} \u7684\u6620\u5C04\u5931\u8D25\u3002",savedMappingReady:"{{title}} \u7684\u5DF2\u4FDD\u5B58\u6620\u5C04\u5DF2\u5C31\u7EEA\u3002",noSavedMapping:"{{title}} \u8FD8\u6CA1\u6709\u5DF2\u4FDD\u5B58\u6620\u5C04\u3002\u8BF7\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002"},section:{basic:{title:"QA / \u57FA\u7840\u5361",description:"\u9009\u62E9 QA \u7B14\u8BB0\u7C7B\u578B\uFF0C\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\uFF0C\u7136\u540E\u786E\u8BA4\u6807\u9898/\u6B63\u6587\u6620\u5C04\u3002"},cloze:{title:"\u586B\u7A7A\u9898",description:"\u9009\u62E9\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B\uFF0C\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\uFF0C\u7136\u540E\u786E\u8BA4\u4E3B\u5B57\u6BB5\u6620\u5C04\u3002"},semanticQa:{title:"\u8BED\u4E49 QA",description:"\u9009\u62E9\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B\uFF0C\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\uFF0C\u7136\u540E\u786E\u8BA4\u5B50\u5361\u7247\u7684\u6807\u9898/\u6B63\u6587\u6620\u5C04\u3002"}},noteTypeLabel:"{{title}} \u7B14\u8BB0\u7C7B\u578B",noteTypeDesc:"\u4ECE Anki \u7684\u7B14\u8BB0\u7C7B\u578B\u5217\u8868\u52A0\u8F7D\u3002\u5982\u679C\u6700\u65B0\u6A21\u578B\u6CA1\u6709\u663E\u793A\uFF0C\u8BF7\u5148\u5237\u65B0\u3002",fieldsLabel:"{{title}} \u5B57\u6BB5",fieldsDesc:"\u4ECE Anki \u8BFB\u53D6\u5F53\u524D\u7B14\u8BB0\u7C7B\u578B\u7684\u5B57\u6BB5\uFF0C\u7136\u540E\u68C0\u67E5\u5EFA\u8BAE\u6620\u5C04\u3002",readFieldsButton:"\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5",loadedFields:"\u5DF2\u52A0\u8F7D\u5B57\u6BB5\uFF1A{{fields}}",loadedFieldsNone:"\u5DF2\u52A0\u8F7D\u5B57\u6BB5\uFF1A\u65E0\u3002\u8BF7\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002",mappingLabel:"{{title}} \u6620\u5C04",mappingDesc:"\u4FDD\u5B58\u5F53\u524D\u7B14\u8BB0\u7C7B\u578B\u7684\u5B57\u6BB5\u6620\u5C04\u3002",saveMappingButton:"\u4FDD\u5B58\u6620\u5C04",titleFieldLabel:"{{title}} \u6807\u9898\u5B57\u6BB5",titleFieldDesc:"\u9009\u62E9\u63A5\u6536\u6807\u9898\u7247\u6BB5\u7684 Anki \u5B57\u6BB5\u3002",bodyFieldLabel:"{{title}} \u6B63\u6587\u5B57\u6BB5",bodyFieldDesc:"\u9009\u62E9\u63A5\u6536\u6B63\u6587\u7247\u6BB5\u7684 Anki \u5B57\u6BB5\u3002",mainField:{name:"\u586B\u7A7A\u9898\u4E3B\u5B57\u6BB5",desc:"\u540C\u6B65\u65F6\uFF0C\u6240\u9009\u5B57\u6BB5\u4F1A\u63A5\u6536 \u6807\u9898 +

+ \u6B63\u6587\u3002"},selectFieldPlaceholder:"-- \u9009\u62E9\u5B57\u6BB5 --"},deck:{defaultSectionTitle:"\u9ED8\u8BA4\u724C\u7EC4",defaultDeck:{name:"\u9ED8\u8BA4\u724C\u7EC4",desc:"\u4F18\u5148\u7EA7\u6700\u4F4E\uFF1A\u5F53\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4\u4E0E\u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4\u90FD\u672A\u547D\u4E2D\u65F6\u4F7F\u7528\u3002"},fileDeckSectionTitle:"\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4",fileDeckEnabled:{name:"\u5F00\u542F\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4",desc:"\u5F00\u542F\u540E\uFF0C\u53EF\u5728 YAML \u6216\u6B63\u6587\u4E2D\u7528\u7EDF\u4E00\u8BC6\u522B\u540D\u4E3A\u6574\u7BC7\u7B14\u8BB0\u6307\u5B9A\u4E00\u4E2A\u724C\u7EC4\u3002"},marker:{name:"\u724C\u7EC4\u8BC6\u522B\u540D",desc:"YAML key \u4E0E\u6B63\u6587\u6807\u8BB0\u5171\u7528\u540C\u4E00\u4E2A\u8BC6\u522B\u540D\u3002\u9ED8\u8BA4\u503C\u662F TARGET DECK\u3002"},template:{name:"\u9ED8\u8BA4\u724C\u7EC4\u6A21\u677F",desc:"\u53EA\u652F\u6301 filename \u53D8\u91CF\u3002\u63D2\u5165\u65F6\u4F1A\u5C55\u5F00\u4E3A\u5F53\u524D\u6587\u4EF6\u540D\uFF08\u4E0D\u542B .md\uFF09\u3002"},insertLocation:{name:"\u6A21\u677F\u63D2\u5165\u4F4D\u7F6E",desc:"\u9009\u62E9\u5C06\u724C\u7EC4\u6A21\u677F\u5199\u5165 YAML frontmatter \u8FD8\u662F\u6B63\u6587\u524D\u90E8\u3002",options:{body:"\u6B63\u6587\u524D\u90E8",yaml:"YAML frontmatter"}},insertTemplate:{name:"\u5411\u5F53\u524D\u6587\u4EF6\u63D2\u5165\u724C\u7EC4\u6A21\u677F",desc:"\u6309\u5F53\u524D\u8BC6\u522B\u540D\u3001\u6A21\u677F\u548C\u63D2\u5165\u4F4D\u7F6E\uFF0C\u628A\u724C\u7EC4\u58F0\u660E\u5199\u5165\u5F53\u524D\u6D3B\u52A8 Markdown \u6587\u4EF6\u3002",button:"\u63D2\u5165\u724C\u7EC4\u6A21\u677F"},folderMappingSectionTitle:"\u9AD8\u7EA7\uFF1A\u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4",folderDeckMode:{name:"\u6587\u4EF6\u5939\u6620\u5C04\u6A21\u5F0F",desc:"\u5173\u95ED / \u4EC5\u7236\u6587\u4EF6\u5939 / \u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u3002",options:{off:"\u5173\u95ED",folder:"\u6587\u4EF6\u5939\u7EA7\u6620\u5C04",folderAndFile:"\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u7EA7\u6620\u5C04"}},examplesTitle:"\u793A\u4F8B\uFF1A",folderExample:"\u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4\u793A\u4F8B\uFF1A\u6570\u5B66/\u7B2C\u4E00\u7AE0/\u7B2C\u4E00\u8282.md -> \u6570\u5B66::\u7B2C\u4E00\u7AE0",folderAndFileExample:"\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u6620\u5C04\u724C\u7EC4\u793A\u4F8B\uFF1A\u6570\u5B66/\u7B2C\u4E00\u7AE0/\u7B2C\u4E00\u8282.md -> \u6570\u5B66::\u7B2C\u4E00\u7AE0::\u7B2C\u4E00\u8282",fallbackDesc:"\u82E5\u5747\u4E0D\u6253\u5F00\u300C\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u300D\u53CA\u300C\u6587\u4EF6\u7EA7\u300D\u724C\u7EC4\uFF0C\u5219\u4EE5\u300C\u9ED8\u8BA4\u724C\u7EC4\u540D\u79F0\u300D\u4F5C\u4E3A Anki \u7684\u724C\u7EC4\u540D\u3002",priorityTitle:"\u6700\u7EC8\u724C\u7EC4\u4F18\u5148\u7EA7\u8BF4\u660E",priorityDesc:"\u6700\u7EC8\u724C\u7EC4\u4F18\u5148\u7EA7\uFF1A\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4 > \u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4 > \u9ED8\u8BA4\u724C\u7EC4\u3002"},scope:{name:"\u63D2\u4EF6\u8FD0\u884C\u8303\u56F4",summary:{all:"\u5904\u7406\u6574\u4E2A vault \u4E2D\u7684 Markdown \u6587\u4EF6",include:"\u4EC5\u5904\u7406\u4E0B\u65B9\u52FE\u9009\u6587\u4EF6\u5939\u4E2D\u7684 Markdown \u6587\u4EF6",exclude:"\u5904\u7406\u6574\u4E2A vault\uFF0C\u4F46\u8DF3\u8FC7\u4E0B\u65B9\u52FE\u9009\u6587\u4EF6\u5939\u4E2D\u7684 Markdown \u6587\u4EF6"},option:{all:"\u5168\u90E8\u6587\u4EF6",include:"\u4EC5\u5728\u6307\u5B9A\u6587\u4EF6\u5939",exclude:"\u6392\u9664\u6307\u5B9A\u6587\u4EF6\u5939"},treeDescription:{include:"\u4EC5\u5728\u6307\u5B9A\u6587\u4EF6\u5939\uFF1A\u53EA\u5904\u7406\u4E0B\u65B9\u52FE\u9009\u6587\u4EF6\u5939\u4E2D\u7684 Markdown \u6587\u4EF6",exclude:"\u6392\u9664\u6307\u5B9A\u6587\u4EF6\u5939\uFF1A\u5904\u7406\u6574\u4E2A vault\uFF0C\u4F46\u8DF3\u8FC7\u4E0B\u65B9\u52FE\u9009\u6587\u4EF6\u5939\u4E2D\u7684 Markdown \u6587\u4EF6"},loading:"\u6B63\u5728\u8BFB\u53D6\u5F53\u524D vault \u6587\u4EF6\u5939...",empty:"\u5F53\u524D vault \u4E2D\u6CA1\u6709\u53EF\u9009\u6587\u4EF6\u5939\u3002",failedLoad:"\u8BFB\u53D6\u5F53\u524D vault \u6587\u4EF6\u5939\u5931\u8D25\u3002",expandFolder:"\u5C55\u5F00 {{name}}",collapseFolder:"\u6536\u8D77 {{name}}"},cards:{cardTypes:{title:"\u5361\u7247\u7C7B\u578B\u53CA\u57FA\u7840\u8BBE\u7F6E",desc:"\u76F4\u63A5\u7F16\u8F91\u8BC6\u522B\u89C4\u5219\uFF0C\u4FEE\u6539\u540E\u81EA\u52A8\u4FDD\u5B58\u3002",advancedHint:"\u9AD8\u7EA7\u9879\uFF1A\u5C06 AnkiConnect URL \u4FDD\u7559\u5728\u8FD9\u91CC\uFF0C\u4E0D\u5355\u72EC\u505A\u8FDE\u63A5\u72B6\u6001\u5361\u7247\u3002",markerPlaceholder:"/",fieldsUnavailable:"-- \u8BF7\u5148\u8BFB\u53D6\u5B57\u6BB5 --",autoManagedField:"\u81EA\u52A8\u7EF4\u62A4",autoComposedAnswer:"\u81EA\u52A8\u62FC\u63A5",qaGroupManagedNoteType:"{{modelName}}\uFF08\u81EA\u52A8\u7EF4\u62A4\uFF09",statusLabel:"\u72B6\u6001\uFF1A",cacheEmpty:"\u5F53\u524D\u6CA1\u6709\u5DF2\u7F13\u5B58\u7684 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u624B\u52A8\u8BFB\u53D6 Anki \u91CC\u7684\u6A21\u677F\u914D\u7F6E\u3002",cacheSummary:"\u5F53\u524D\u4F7F\u7528\u7F13\u5B58\u7684 {{noteTypeCount}} \u4E2A\u7B14\u8BB0\u6A21\u677F\uFF0C\u5DF2\u9009\u62E9\u5E76\u914D\u7F6E {{configuredCount}} \u4E2A\u5361\u7247\u6A21\u5F0F\u3002",cacheChanged:"\u68C0\u6D4B\u5230 Anki \u5F53\u524D\u6709 {{liveCount}} \u4E2A\u7B14\u8BB0\u6A21\u677F\uFF0C\u548C\u672C\u9875\u7F13\u5B58\u7684 {{cachedCount}} \u4E2A\u6A21\u677F\u4E0D\u4E00\u81F4\u3002\u5F53\u524D\u4ECD\u5728\u4F7F\u7528\u7F13\u5B58\uFF0C\u5DF2\u9009\u62E9\u5E76\u914D\u7F6E {{configuredCount}} \u4E2A\u5361\u7247\u6A21\u5F0F\uFF1B\u5982\u9700\u66F4\u65B0\u8BF7\u624B\u52A8\u8BFB\u53D6 Anki \u91CC\u7684\u6A21\u677F\u914D\u7F6E\u3002",cacheCheckFailed:"\u5F53\u524D\u7EE7\u7EED\u4F7F\u7528\u7F13\u5B58\u7684 {{noteTypeCount}} \u4E2A\u7B14\u8BB0\u6A21\u677F\uFF0C\u5DF2\u9009\u62E9\u5E76\u914D\u7F6E {{configuredCount}} \u4E2A\u5361\u7247\u6A21\u5F0F\uFF1B\u540E\u53F0\u68C0\u67E5\u6700\u65B0\u6A21\u677F\u5217\u8868\u5931\u8D25\uFF0C\u5982\u9700\u66F4\u65B0\u8BF7\u624B\u52A8\u8BFB\u53D6 Anki \u91CC\u7684\u6A21\u677F\u914D\u7F6E\u3002",loadedSummary:"\u5DF2\u83B7\u53D6 {{noteTypeCount}} \u4E2A\u7B14\u8BB0\u6A21\u677F\uFF0C\u5DF2\u9009\u62E9\u5E76\u914D\u7F6E {{configuredCount}} \u4E2A\u5361\u7247\u6A21\u5F0F\u3002",loadedFieldsStatus:"\u5DF2\u5237\u65B0 {{count}} \u4E2A\u5F53\u524D\u6240\u9009\u6A21\u677F\u7684\u5B57\u6BB5\u3002",failedLoad:"\u4ECE Anki \u8BFB\u53D6\u6A21\u677F\u6216\u5B57\u6BB5\u5931\u8D25\u3002",failedSave:"\u4FDD\u5B58\u5361\u7247\u7C7B\u578B\u8BBE\u7F6E\u5931\u8D25\u3002",loadAnki:{button:"\u624B\u52A8\u8BFB\u53D6 Anki \u91CC\u7684\u6A21\u677F\u914D\u7F6E",loading:"\u6B63\u5728\u8BFB\u53D6 Anki \u6A21\u677F\u548C\u5B57\u6BB5..."},columns:{enabled:"\u542F\u7528",type:"\u5361\u7247\u7C7B\u578B",headingLevel:"\u5361\u7247\u6807\u8BB0",extraMarker:"\u989D\u5916\u6807\u8BB0",noteType:"Anki \u7B14\u8BB0\u6A21\u677F",questionField:"\u95EE\u9898\u5B57\u6BB5",answerField:"\u7B54\u6848\u5B57\u6BB5"},labels:{headingLevel:"\u5361\u7247\u6807\u8BB0\uFF1A",extraMarker:"\u989D\u5916\u6807\u8BB0\uFF1A",noteType:"Anki \u7B14\u8BB0\u6A21\u677F\uFF1A",questionField:"\u95EE\u9898\u5B57\u6BB5\uFF1A",answerField:"\u7B54\u6848\u5B57\u6BB5\uFF1A",mainField:"\u4E3B\u5B57\u6BB5\uFF1A",fields:"\u5B57\u6BB5\uFF1A",qaGroupTitleField:"\u9898\u76EE\u5B57\u6BB5\uFF1A",qaGroupSlotFields:"\u95EE\u9898/\u7B54\u6848\u5B57\u6BB5\uFF1A",qaGroupWarnings:"\u8B66\u544A\uFF1A"},qaGroup:{noModel:"\u8BF7\u5148\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F",unavailable:"\u8BF7\u5148\u624B\u52A8\u8BFB\u53D6\u5B57\u6BB5",detectedSlots:"\u5DF2\u8BC6\u522B {{count}} \u7EC4",acceptWarnings:"\u6211\u5DF2\u786E\u8BA4\u5FFD\u7565\u5F53\u524D\u8B66\u544A\uFF0C\u5E76\u5141\u8BB8\u540C\u6B65",warning:{missingAnswer:"\u7B2C {{index}} \u7EC4\u7F3A\u5C11\u7B54\u6848\u5B57\u6BB5\uFF0C\u5DF2\u5FFD\u7565 {{questionField}} / {{answerField}}\u3002",missingQuestion:"\u7B2C {{index}} \u7EC4\u7F3A\u5C11\u95EE\u9898\u5B57\u6BB5\uFF0C\u5DF2\u5FFD\u7565 {{questionField}} / {{answerField}}\u3002"}},rows:{basic:"\u95EE\u7B54\u9898\uFF08\u5E38\u89C4\u6BB5\u843D\u5F62\u5F0F\uFF09",qaGroup:"\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\u5F62\u5F0F\uFF09",cloze:"\u586B\u7A7A\u9898",semanticQa:"\u8BED\u4E49\u95EE\u7B54\u9898"}},syncContent:{title:"\u5361\u7247\u6B63\u6587\u540C\u6B65\u5185\u5BB9",desc:"\u8FD9\u4E9B\u9009\u9879\u53EA\u5F71\u54CD\u5361\u7247\u6E32\u67D3\u5185\u5BB9\uFF0C\u4FEE\u6539\u540E\u4EC5\u5237\u65B0\u8FD9\u4E00\u5F20\u5361\u7247\u3002",sections:{bodyRange:"1. \u786E\u5B9A\u300C\u5361\u7247\u6B63\u6587\u300D\u8303\u56F4",backlink:"2. \u786E\u5B9A\u662F\u5426\u589E\u52A0\u56DE\u94FE\uFF0C\u65B9\u4FBF\u4ECE Anki\u300C\u5361\u7247\u7EA7\u8DF3\u8F6C\u300D\u56DE Obsidian",tags:"3. \u786E\u5B9A\u662F\u5426\u8BFB\u53D6\u300C\u6807\u7B7E\u300D",clozeSpecial:"4. \u300C\u586B\u7A7A\u9898\u300D\u4E13\u9879"}},scope:{title:"\u63D2\u4EF6\u8FD0\u884C\u8303\u56F4",desc:"\u4FDD\u7559\u73B0\u6709\u4F5C\u7528\u8303\u56F4\u548C\u6587\u4EF6\u5939\u6811\u903B\u8F91\uFF1B\u6587\u4EF6\u5939\u6811\u6309\u9700\u52A0\u8F7D\uFF0C\u5E76\u652F\u6301\u5C40\u90E8\u5237\u65B0\u3002",refreshFolders:"\u5237\u65B0\u6587\u4EF6\u5939\u5217\u8868"},deck:{title:"\u5361\u7247\u724C\u7EC4\u8BBE\u7F6E",desc:"\u5361\u7247\u724C\u7EC4\u8BBE\u7F6E\u6309\u63A8\u8350\u8DEF\u5F84\u5206\u7EC4\u5C55\u793A\u3002",sections:{folderMapping:"1\uFF0C\u63A8\u8350\u7528\u300C\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u300D\u4F5C\u4E3A\u300CAnki\u724C\u7EC4\u300D",fileDeck:"2\uFF0C\u53EF\u6253\u5F00\u300C\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4\u300D\uFF0C\u4F5C\u4E3A\u4E2A\u6027\u5316\u5B9A\u5236",defaultDeck:"3\uFF0C\u9ED8\u8BA4\u724C\u7EC4\u4F5C\u4E3A\u515C\u5E95"}},commands:{title:"\u547D\u4EE4\u8BF4\u660E",desc:"\u4E0B\u9762\u5C55\u793A\u5F53\u524D\u547D\u4EE4\u9762\u677F\u4E2D\u53EF\u7528\u7684\u63D2\u4EF6\u547D\u4EE4\u3002",items:{syncCurrentFile:"\u53EA\u628A\u5F53\u524D\u6D3B\u52A8 Markdown \u6587\u4EF6\u540C\u6B65\u5230 Anki\u3002",syncVault:"\u628A\u5168\u5E93\u4E2D\u6240\u6709\u5904\u4E8E\u4F5C\u7528\u8303\u56F4\u5185\u7684 Markdown \u6587\u4EF6\u540C\u6B65\u5230 Anki\u3002",rebuildIndex:"\u53EA\u91CD\u5EFA\u672C\u5730\u5361\u7247\u7D22\u5F15\uFF0C\u4E0D\u521B\u5EFA\u6216\u66F4\u65B0\u8FDC\u7AEF\u7B14\u8BB0\u3002",clearCurrentFile:"\u6E05\u7A7A\u5F53\u524D\u6587\u4EF6\u7684\u5DF2\u540C\u6B65\u6807\u8BB0\u548C\u672C\u5730\u8DDF\u8E2A\u72B6\u6001\u3002",cleanupDecks:"\u4ECE Anki \u5220\u9664\u6240\u9009\u7A7A\u724C\u7EC4\u3002"}}}},modal:{emptyDeck:{title:"\u6E05\u7406\u7A7A\u724C\u7EC4",description:"\u52FE\u9009\u8981\u5220\u9664\u7684\u7A7A\u724C\u7EC4\u3002\u53EA\u6709\u5220\u9664\u65F6\u4ECD\u4E3A\u7A7A\u7684\u724C\u7EC4\u4F1A\u88AB\u771F\u6B63\u5220\u9664\u3002",selectAll:"\u5168\u9009\u5168\u90E8",clearAll:"\u5168\u90E8\u4E0D\u9009",invert:"\u53CD\u9009",cancel:"\u53D6\u6D88",deleteSelected:"\u5220\u9664\u6240\u9009\u7A7A\u724C\u7EC4",selectionCount:"\u5DF2\u9009 {{selected}} / \u5171 {{total}} \u4E2A\u7A7A\u724C\u7EC4"}},notice:{invalidSettingsRestored:"\u68C0\u6D4B\u5230\u65E0\u6548\u7684\u63D2\u4EF6\u8BBE\u7F6E\uFF0C\u5DF2\u5728\u5185\u5B58\u4E2D\u6062\u590D\u9ED8\u8BA4\u8BBE\u7F6E\u3002",failedSavePluginSettings:"\u4FDD\u5B58\u63D2\u4EF6\u8BBE\u7F6E\u5931\u8D25\u3002",noActiveMarkdownForSync:"\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u4E8E\u540C\u6B65\u7684\u6D3B\u52A8 Markdown \u6587\u4EF6\u3002",syncUseCaseNotInitialized:"\u540C\u6B65\u7528\u4F8B\u5C1A\u672A\u521D\u59CB\u5316\u3002",currentFileSyncFailed:"\u5F53\u524D\u6587\u4EF6\u540C\u6B65\u5931\u8D25\u3002",vaultSyncFailed:"\u5168\u5E93\u540C\u6B65\u5931\u8D25\u3002",rebuildFailed:"\u5361\u7247\u7D22\u5F15\u91CD\u5EFA\u5931\u8D25\u3002",noActiveMarkdownForDeckTemplateInsertion:"\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u4E8E\u63D2\u5165\u724C\u7EC4\u6A21\u677F\u7684\u6D3B\u52A8 Markdown \u6587\u4EF6\u3002",vaultGatewayNotInitialized:"Vault \u7F51\u5173\u5C1A\u672A\u521D\u59CB\u5316\u3002",markdownFileNotFound:"\u672A\u627E\u5230 Markdown \u6587\u4EF6\uFF1A{{filePath}}",deckTemplateAlreadyCurrent:"\u5F53\u524D\u6587\u4EF6\u4E2D\u7684\u724C\u7EC4\u6A21\u677F\u5DF2\u662F\u6700\u65B0\uFF0C\u65E0\u9700\u91CD\u590D\u5199\u5165\u3002",deckTemplateInserted:"\u5DF2\u5411\u5F53\u524D\u6587\u4EF6\u5199\u5165\u724C\u7EC4\u6A21\u677F\uFF1A{{deck}}",deckTemplateInsertionFailed:"\u63D2\u5165\u724C\u7EC4\u6A21\u677F\u5931\u8D25\u3002",noActiveMarkdownForReset:"\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u4E8E\u91CD\u7F6E\u7684\u6D3B\u52A8 Markdown \u6587\u4EF6\u3002",clearCurrentFileUseCaseNotInitialized:"\u6E05\u7A7A\u5F53\u524D\u6587\u4EF6\u7528\u4F8B\u5C1A\u672A\u521D\u59CB\u5316\u3002",noTrackedCardsInCurrentFile:"\u5F53\u524D\u6587\u4EF6\u6CA1\u6709\u5DF2\u540C\u6B65\u5361\u7247\u3002",clearCurrentFileFailed:"\u6E05\u7A7A\u5F53\u524D\u6587\u4EF6\u5DF2\u540C\u6B65\u5361\u7247\u5931\u8D25\u3002",cleanupEmptyDecksUseCaseNotInitialized:"\u7A7A\u724C\u7EC4\u6E05\u7406\u7528\u4F8B\u5C1A\u672A\u521D\u59CB\u5316\u3002",noEmptyDeckCandidates:"\u672A\u53D1\u73B0\u53EF\u6E05\u7406\u7684\u7A7A\u724C\u7EC4\u3002",cleanupEmptyDecksCancelled:"\u5DF2\u53D6\u6D88\u7A7A\u724C\u7EC4\u6E05\u7406\u3002",cleanupEmptyDecksFailed:"\u6E05\u7406\u7A7A\u724C\u7EC4\u5931\u8D25\u3002",summary:{currentFileSync:"\u5F53\u524D\u6587\u4EF6\u540C\u6B65\u5B8C\u6210\uFF1A\u6587\u4EF6 {{scannedFiles}}\uFF0C\u5361\u7247 {{scannedCards}}\uFF0C\u65B0\u5EFA {{created}}\uFF0C\u66F4\u65B0 {{updated}}\uFF0C\u8FC1\u79FB\u6A21\u677F {{migratedNoteTypes}}\uFF0C\u8FC1\u79FB\u724C\u7EC4 {{migratedDecks}}\uFF0C\u5B64\u513F {{orphaned}}\uFF0C\u5A92\u4F53 {{uploadedMedia}}\uFF0C\u8DF3\u8FC7 {{skippedUnchangedCards}}\u3002",vaultSync:"\u5168\u5E93\u540C\u6B65\u5B8C\u6210\uFF1A\u6587\u4EF6 {{scannedFiles}}\uFF0C\u5361\u7247 {{scannedCards}}\uFF0C\u65B0\u5EFA {{created}}\uFF0C\u66F4\u65B0 {{updated}}\uFF0C\u8FC1\u79FB\u6A21\u677F {{migratedNoteTypes}}\uFF0C\u8FC1\u79FB\u724C\u7EC4 {{migratedDecks}}\uFF0C\u5B64\u513F {{orphaned}}\uFF0C\u5A92\u4F53 {{uploadedMedia}}\uFF0C\u8DF3\u8FC7 {{skippedUnchangedCards}}\u3002",rebuild:"\u5361\u7247\u7D22\u5F15\u91CD\u5EFA\u5B8C\u6210\uFF1A\u6587\u4EF6 {{scannedFiles}}\uFF0C\u5361\u7247 {{scannedCards}}\uFF0C\u8FC1\u79FB\u724C\u7EC4 {{migratedDecks}}\uFF0C\u5B64\u513F {{orphaned}}\uFF0C\u91CD\u5199\u6807\u8BB0 {{rewrittenMarkers}}\uFF0C\u8DF3\u8FC7 {{skippedUnchangedCards}}\u3002",clearCurrentFile:"\u5F53\u524D\u6587\u4EF6\u5DF2\u540C\u6B65\u5361\u7247\u6E05\u7A7A\u5B8C\u6210\uFF1A\u5DF2\u8DDF\u8E2A\u5361\u7247 {{trackedCards}}\uFF0C\u5DF2\u8DDF\u8E2A\u5206\u7EC4 {{trackedGroups}}\uFF0C\u5220\u9664\u7B14\u8BB0 {{deletedNotes}}\uFF0C\u79FB\u9664\u6807\u8BB0 {{removedMarkers}}\uFF0C\u79FB\u9664 ID \u6807\u8BB0 {{removedCardMarkers}}\uFF0C\u79FB\u9664 GI \u6807\u8BB0 {{removedGroupMarkers}}\uFF0C\u5220\u9664\u672C\u5730\u8BB0\u5F55 {{deletedLocalRecords}}\u3002",cleanupEmptyDecks:"\u7A7A\u724C\u7EC4\u6E05\u7406\u5B8C\u6210\uFF1A\u5019\u9009 {{candidateCount}}\uFF0C\u5DF2\u9009 {{selectedCount}}\uFF0C\u5DF2\u5220 {{deletedCount}}\uFF0C\u8DF3\u8FC7 {{skippedCount}}\u3002",markerWriteConflicts:"\u6807\u8BB0\u5199\u56DE\u51B2\u7A81\uFF1A{{files}}\u3002",warningsCount:"\u8B66\u544A\uFF1A{{count}}\u3002",markerRemovalConflicts:"\u6807\u8BB0\u79FB\u9664\u51B2\u7A81\uFF1A{{files}}\u3002",failures:"\u5931\u8D25\u9879\uFF1A{{items}}\u3002",skippedDecks:"\u8DF3\u8FC7\u7684\u724C\u7EC4\uFF1A{{decks}}\u3002"}},errors:{currentFileOutOfScope:"\u5F53\u524D\u6587\u4EF6\u4E0D\u5728\u63D2\u4EF6\u4F5C\u7528\u8303\u56F4\u5185\uFF1A{{filePath}}",deck:{emptyName:"\u724C\u7EC4\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u7EA7\u724C\u7EC4\u58F0\u660E\u6216\u9ED8\u8BA4\u724C\u7EC4\u8BBE\u7F6E\u3002"},settings:{headingLevelsRange:"\u6807\u9898\u5C42\u7EA7\u5FC5\u987B\u662F 1 \u5230 6 \u4E4B\u95F4\u7684\u6574\u6570\u3002",headingLevelsDifferent:"QA \u548C\u586B\u7A7A\u9898\u7684\u6807\u9898\u5C42\u7EA7\u5FC5\u987B\u4E0D\u540C\u3002",cardTypeConfigsObject:"\u5361\u7247\u7C7B\u578B\u914D\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",cardTypeEnabledBoolean:"\u6BCF\u79CD\u5361\u7247\u7C7B\u578B\u7684\u542F\u7528\u72B6\u6001\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002",cardTypeExtraMarkerString:"\u6BCF\u79CD\u5361\u7247\u7C7B\u578B\u7684\u989D\u5916\u6807\u8BB0\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",cardTypeDefaultConflict:"\u540C\u4E00\u4E2A H{{headingLevel}} \u53EA\u80FD\u6709\u4E00\u4E2A\u542F\u7528\u7684\u9ED8\u8BA4\u5361\u7247\u7C7B\u578B\u3002",cardAnswerCutoffModeInvalid:"\u5361\u7247\u6B63\u6587\u622A\u6B62\u6A21\u5F0F\u53EA\u80FD\u662F heading-block \u6216 double-blank-lines\u3002",qaNoteTypeRequired:"QA \u7B14\u8BB0\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u3002",qaGroupMarkerRequired:"QA Group \u6807\u8BB0\u4E0D\u80FD\u4E3A\u7A7A\u3002",qaGroupMarkerInvalid:"QA Group \u6807\u8BB0\u5FC5\u987B\u662F\u7C7B\u4F3C #anki-list \u7684 hashtag \u6837\u5F0F token\u3002",clozeNoteTypeRequired:"\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u3002",semanticQaMarkerRequired:"\u8BED\u4E49 QA \u6807\u8BB0\u4E0D\u80FD\u4E3A\u7A7A\u3002",semanticQaMarkerInvalid:"\u8BED\u4E49 QA \u6807\u8BB0\u5FC5\u987B\u662F\u7C7B\u4F3C #anki-list-qa \u7684 hashtag \u6837\u5F0F token\u3002",qaGroupMarkerConflict:"QA Group \u6807\u8BB0\u5FC5\u987B\u548C\u8BED\u4E49 QA \u6807\u8BB0\u4E0D\u540C\u3002",semanticQaNoteTypeRequired:"\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u3002",defaultDeckRequired:"\u9ED8\u8BA4\u724C\u7EC4\u4E0D\u80FD\u4E3A\u7A7A\u3002",fileDeckEnabledBoolean:"\u6587\u4EF6\u7EA7\u724C\u7EC4\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002",syncObsidianTagsToAnkiBoolean:"\u540C\u6B65 Obsidian \u6807\u7B7E\u5230 Anki \u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002",keepPureTagLinesInCardBodyBoolean:"\u4FDD\u7559\u6B63\u6587\u7EAF\u6807\u7B7E\u884C\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002",fileDeckMarkerString:"\u6587\u4EF6\u7EA7\u724C\u7EC4\u8BC6\u522B\u540D\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",fileDeckTemplateString:"\u6587\u4EF6\u7EA7\u724C\u7EC4\u6A21\u677F\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",fileDeckInsertLocationInvalid:"\u6587\u4EF6\u7EA7\u724C\u7EC4\u6A21\u677F\u63D2\u5165\u4F4D\u7F6E\u53EA\u80FD\u662F yaml \u6216 body\u3002",folderDeckModeInvalid:"\u6587\u4EF6\u5939\u724C\u7EC4\u6A21\u5F0F\u53EA\u80FD\u662F off\u3001folder \u6216 folder-and-file\u3002",scopeModeInvalid:"\u8FD0\u884C\u8303\u56F4\u6A21\u5F0F\u53EA\u80FD\u662F all\u3001include \u6216 exclude\u3002",obsidianBacklinkPlacementInvalid:"Obsidian \u56DE\u94FE\u653E\u7F6E\u4F4D\u7F6E\u53EA\u80FD\u662F question-last-line\u3001answer-first-line \u6216 answer-last-line\u3002",includeFoldersArray:"\u5305\u542B\u6587\u4EF6\u5939\u5FC5\u987B\u662F\u6570\u7EC4\u3002",includeFoldersStrings:"\u5305\u542B\u6587\u4EF6\u5939\u5217\u8868\u4E2D\u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",excludeFoldersArray:"\u6392\u9664\u6587\u4EF6\u5939\u5FC5\u987B\u662F\u6570\u7EC4\u3002",excludeFoldersStrings:"\u6392\u9664\u6587\u4EF6\u5939\u5217\u8868\u4E2D\u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",ankiConnectUrlRequired:"AnkiConnect URL \u4E0D\u80FD\u4E3A\u7A7A\u3002",ankiNoteTypeCacheArray:"Anki \u7B14\u8BB0\u6A21\u677F\u7F13\u5B58\u5FC5\u987B\u662F\u6570\u7EC4\u3002",ankiNoteTypeCacheStrings:"Anki \u7B14\u8BB0\u6A21\u677F\u7F13\u5B58\u4E2D\u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",ankiModelFieldCacheObject:"Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",ankiModelFieldCacheEntryObject:"\u6BCF\u4E2A Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u9879\u90FD\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",ankiModelFieldCacheFieldNamesArray:"Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u4E2D\u7684 fieldNames \u5FC5\u987B\u662F\u6570\u7EC4\u3002",ankiModelFieldCacheFieldNamesStrings:"Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u4E2D\u7684 fieldNames \u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",ankiModelFieldCacheLoadedAt:"Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u4E2D\u7684 loadedAt \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u3002",noteFieldMappingsObject:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",noteFieldMappingsCardType:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u4F7F\u7528\u53D7\u652F\u6301\u7684\u5361\u7247\u7C7B\u578B\u3002",noteFieldMappingsModelName:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u5305\u542B\u6A21\u578B\u540D\u79F0\u3002",noteFieldMappingsLoadedFieldNames:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u5305\u542B\u5DF2\u52A0\u8F7D\u5B57\u6BB5\u540D\u3002",noteFieldMappingsLoadedAt:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u5305\u542B\u5DF2\u52A0\u8F7D\u65F6\u95F4\u6233\u3002",noteFieldMappingsQaGroupSlotsArray:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 slots \u5FC5\u987B\u662F\u6570\u7EC4\u3002",noteFieldMappingsQaGroupSlotObject:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684\u6BCF\u4E2A slot \u90FD\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",noteFieldMappingsQaGroupSlotIndex:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 slot.index \u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570\u3002",noteFieldMappingsQaGroupSlotQuestionField:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 slot.questionField \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",noteFieldMappingsQaGroupSlotAnswerField:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 slot.answerField \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",noteFieldMappingsQaGroupWarningsArray:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 warnings \u5FC5\u987B\u662F\u6570\u7EC4\u3002",noteFieldMappingsQaGroupWarningsStrings:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 warnings \u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",noteFieldMappingsQaGroupAcceptedWarningsArray:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 acceptedWarnings \u5FC5\u987B\u662F\u6570\u7EC4\u3002",noteFieldMappingsQaGroupAcceptedWarningsStrings:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 acceptedWarnings \u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002"},noteFieldMapping:{noteTypeNotSelected:{basic:"\u57FA\u7840\u5361\u5C1A\u672A\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u9009\u62E9\u6A21\u677F\u540E\u518D\u540C\u6B65\u3002",cloze:"\u586B\u7A7A\u9898\u5C1A\u672A\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u9009\u62E9\u6A21\u677F\u540E\u518D\u540C\u6B65\u3002",semanticQa:"\u8BED\u4E49 QA \u5C1A\u672A\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u9009\u62E9\u6A21\u677F\u540E\u518D\u540C\u6B65\u3002",qaGroup:"\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u5C1A\u672A\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u9009\u62E9\u6A21\u677F\u540E\u518D\u540C\u6B65\u3002"},missingSavedMapping:{basic:'\u627E\u4E0D\u5230\u57FA\u7840\u5361\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002',cloze:'\u627E\u4E0D\u5230\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002',semanticQa:'\u627E\u4E0D\u5230\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002'},incompleteSavedMapping:{basic:'\u57FA\u7840\u5361\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u4E0D\u5B8C\u6574\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u4FDD\u5B58\u6807\u9898\u5B57\u6BB5\u548C\u6B63\u6587\u5B57\u6BB5\u3002',semanticQa:'\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u4E0D\u5B8C\u6574\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u4FDD\u5B58\u6807\u9898\u5B57\u6BB5\u548C\u6B63\u6587\u5B57\u6BB5\u3002',cloze:'\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u4E0D\u5B8C\u6574\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u4FDD\u5B58\u4E3B\u5B57\u6BB5\u3002'},titleBodyMustDiffer:{basic:'\u57FA\u7840\u5361\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u6807\u9898\u5B57\u6BB5\u548C\u6B63\u6587\u5B57\u6BB5\u5FC5\u987B\u4E0D\u540C\u3002',semanticQa:'\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u6807\u9898\u5B57\u6BB5\u548C\u6B63\u6587\u5B57\u6BB5\u5FC5\u987B\u4E0D\u540C\u3002'},stale:'\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u5DF2\u8FC7\u671F\uFF0C\u56E0\u4E3A\u8FD9\u4E9B\u5B57\u6BB5\u5728 Anki \u4E2D\u5DF2\u4E0D\u5B58\u5728\uFF1A{{fields}}\u3002\u8BF7\u91CD\u65B0\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002',clozeIncompatible:'\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u5728 Anki \u4E2D\u4E0D\u662F\u586B\u7A7A\u9898\u517C\u5BB9\u6A21\u578B\u3002',qaGroupMissingTitle:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7F3A\u5C11\u53EF\u8BC6\u522B\u7684\u9898\u76EE\u5B57\u6BB5\u3002\u8BF7\u4F7F\u7528 \u9898\u76EE\u3001\u6807\u9898\u3001\u6B63\u9762\u3001Stem \u6216 Title \u4E4B\u4E00\u3002',qaGroupNoCompleteSlots:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u6CA1\u6709\u53EF\u7528\u7684\u5B8C\u6574\u95EE\u9898/\u7B54\u6848\u5B57\u6BB5\u7EC4\u3002',qaGroupNonContinuousSlots:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u7B2C\u4E00\u7EC4\u95EE\u9898/\u7B54\u6848\u5B57\u6BB5\u4E0D\u662F\u4ECE\u7B2C {{firstIndex}} \u7EC4\u5F00\u59CB\u8FDE\u7EED\u7F16\u53F7\u3002\u8BF7\u4ECE\u7B2C 1 \u7EC4\u5F00\u59CB\u3002',qaGroupWarningsUnaccepted:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u4ECD\u6709\u672A\u786E\u8BA4\u7684\u5B57\u6BB5\u8B66\u544A\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u786E\u8BA4\u540E\u518D\u540C\u6B65\u3002',qaGroupSlotCapacityExceeded:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u53EA\u8BC6\u522B\u5230 {{capacity}} \u7EC4\u95EE\u9898/\u7B54\u6848\u5B57\u6BB5\uFF0C\u4F46\u5F53\u524D\u5757\u6709 {{itemCount}} \u9879\uFF1A{{filePath}}:{{blockStartLine}}\u3002'},noteTypeMigration:{failed:"\u65E0\u6CD5\u5C06 Anki \u7B14\u8BB0 {{noteId}} \u4ECE\u201C{{fromModel}}\u201D\u8FC1\u79FB\u5230\u201C{{toModel}}\u201D{{location}}\uFF1A{{reason}}",unsupported:"\u5F53\u524D AnkiConnect \u4E0D\u652F\u6301\u5C06 Anki \u7B14\u8BB0 {{noteId}} \u4ECE\u201C{{fromModel}}\u201D\u8FC1\u79FB\u5230\u201C{{toModel}}\u201D{{location}}\u3002\u8BF7\u5347\u7EA7 AnkiConnect\uFF0C\u6216\u6E05\u7406\u8BE5\u5361\u7247\u7684 Anki ID \u540E\u91CD\u65B0\u540C\u6B65\u3002\u539F\u56E0\uFF1A{{reason}}"},writeBack:{summary:"Markdown \u6807\u8BB0\u5199\u56DE\u5931\u8D25\uFF0C\u5171 {{fileCount}} \u4E2A\u6587\u4EF6\u3002",markdownFileNotFound:"Markdown \u6587\u4EF6\u4E0D\u5B58\u5728\u3002",missingSourceContent:"\u7F3A\u5C11\u7528\u4E8E\u5199\u56DE\u6807\u8BB0\u7684\u626B\u63CF\u6E90\u7801\u5185\u5BB9\u3002",noteIdMissing:"\u65E0\u6CD5\u4E3A\u7B2C {{blockStartLine}} \u884C\u6240\u5728\u5757\u5199\u5165\u6807\u8BB0\uFF0C\u56E0\u4E3A\u7F3A\u5C11 note ID\u3002"},markerRemoval:{markdownFileNotFound:"Markdown \u6587\u4EF6\u4E0D\u5B58\u5728\u3002"}},warnings:{deck:{conflictYamlBody:"\u68C0\u6D4B\u5230 YAML \u548C\u6B63\u6587\u4E2D\u7684 {{marker}} \u58F0\u660E\u4E92\u76F8\u51B2\u7A81\uFF0C\u672C\u6B21\u540C\u6B65\u5DF2\u4F7F\u7528 YAML \u7684\u503C\u3002",multipleBodyDeclarations:"\u68C0\u6D4B\u5230\u6587\u4EF6\u4E2D\u5B58\u5728\u591A\u4E2A {{marker}} \u58F0\u660E\uFF0C\u672C\u6B21\u540C\u6B65\u53EA\u4F7F\u7528\u7B2C\u4E00\u4E2A\u6B63\u6587\u58F0\u660E\u3002",invalidFolderSegment:"\u68C0\u6D4B\u5230\u6587\u4EF6\u5939\u540D\u6216\u6587\u4EF6\u540D\u5305\u542B ::\uFF0C\u5DF2\u8DF3\u8FC7\u6587\u4EF6\u5939\u6620\u5C04\u5E76\u56DE\u9000\u5230\u9ED8\u8BA4\u724C\u7EC4\u3002",fallbackDefault:"\u8BE5\u6587\u4EF6\u6CA1\u6709\u663E\u5F0F\u724C\u7EC4\uFF0C\u4E14\u65E0\u6CD5\u751F\u6210\u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4\uFF0C\u5DF2\u56DE\u9000\u5230\u9ED8\u8BA4\u724C\u7EC4\u3002"}}};function jr(e,t){let n=t.split("."),r=e;for(let i of n){if(!r||typeof r!="object"||!(i in r))return;r=r[i]}return typeof r=="string"?r:void 0}function bo(e,t,n){return t?e.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(r,i)=>{let a=t[i];return a===void 0?"":Array.isArray(a)?ae(n,a.filter(o=>o!==void 0).map(o=>String(o))):String(a)}):e}function m(e,t){let n=ie(),i=jr(n==="zh"?Vr:Mn,e)??jr(Mn,e)??e;return bo(i,t,n)}var C=class extends Error{constructor(t,n,r){super(t),this.name="PluginUserError",this.userMessage={key:t,params:n},this.details=r}};function wn(e){return e instanceof C}function Te(e){return"rawMessage"in e?e.rawMessage:m(e.key,e.params)}function Kr(e){return"rawMessage"in e?e.rawMessage:m(e.key,e.params)}function vn(e){let t=Te(e.userMessage);if(!e.details?.failures?.length)return t;let n=e.details.failures.map(r=>`${r.filePath}: ${Kr(r)}`).join(` +"use strict";var Mn=Object.defineProperty;var mo=Object.getOwnPropertyDescriptor;var ho=Object.getOwnPropertyNames;var ko=Object.prototype.hasOwnProperty;var We=(e,t)=>{for(var n in t)Mn(e,n,{get:t[n],enumerable:!0})},bo=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ho(t))!ko.call(e,i)&&i!==n&&Mn(e,i,{get:()=>t[i],enumerable:!(r=mo(t,i))||r.enumerable});return e};var yo=e=>bo(Mn({},"__esModule",{value:!0}),e);var fl={};We(fl,{default:()=>pl});module.exports=yo(fl);var fo=require("obsidian");function L(e,t){return`${e}:${t}`}function wn(e){return e?.cardType==="basic"||e?.cardType==="semantic-qa"}function jr(e){return e?.cardType==="cloze"}function W(e){return e?.cardType==="qa-group"}var Kr=require("obsidian");function ie(){return(0,Kr.getLanguage)()==="zh"?"zh":"en"}function ae(e,t){return t.join(e==="zh"?"\u3001":", ")}var Fn={commands:{syncCurrentFileToAnki:"Sync current file to Anki",syncVaultToAnki:"Sync vault to Anki",rebuildCardIndex:"Rebuild card index",clearCurrentFileSyncedCards:"Clear synced cards in current file",cleanupEmptyDecks:"Clean up empty decks"},settings:{pluginTitle:"Anki Heading Sync",ankiConnectUrl:{name:"AnkiConnect URL",desc:"Default is http://127.0.0.1:8765",placeholder:"http://127.0.0.1:8765"},qaHeadingLevel:{name:"QA heading level",desc:"Default is H4"},clozeHeadingLevel:{name:"Cloze heading level",desc:"Default is H5"},cardAnswerCutoffMode:{name:"Card answer cutoff mode",desc:"A valid sync marker always wins. Without a valid marker, either keep the whole heading block or stop before the first 2+ consecutive blank lines.",options:{headingBlock:"heading-block: whole heading block",doubleBlankLines:"double-blank-lines: stop before the first 2+ blank lines"}},qaGroup:{title:"QA Group 12",marker:{name:"QA Group marker",desc:"When a QA heading ends with this hashtag marker, the whole heading block syncs as one ObsiAnki QA Group 12 note.",placeholder:"#anki-list"},managedNoteType:"Managed note type: {{modelName}}. QA Group sync writes Stem / GroupId / Src / S01..S12 directly. The same note type can also appear in the field mapping panels below if you want to reuse it for other routes.",managedModelContract:"Managed model contract: {{fieldCount}} fields and {{templateCount}} templates are checked automatically during sync."},semanticQa:{title:"Semantic QA",marker:{name:"Semantic QA marker",desc:"When a QA heading ends with this hashtag marker, first-level list items with indented child content become separate cards.",placeholder:"#anki-list-qa"},previewTitle:"Semantic QA preview",triggerHeadingExample:"Trigger heading example: {{heading}}",previewUnavailable:"Preview unavailable. Use a trailing hashtag marker such as #anki-list-qa.",questionPreview:"Question preview: {{question}}",answerPreview:"Answer preview: {{answer}}"},syncOptions:{addObsidianBacklink:{name:"Add Obsidian backlink",desc:"Append a backlink to the source heading into synced cards."},obsidianBacklinkLabel:{name:"Obsidian backlink label",desc:"The text shown for the backlink. Blank input falls back to Open in Obsidian.",placeholder:"Open in Obsidian"},obsidianBacklinkPlacement:{name:"Obsidian backlink placement",desc:"Choose whether the backlink is appended to the question field or placed at the start or end of the answer body.",options:{questionLastLine:"Last line of question field",answerFirstLine:"First line of answer body",answerLastLine:"Last line of answer body"}},highlightsToCloze:{name:"Highlights to Cloze",desc:"Convert ==highlight== segments into cloze deletions for cloze cards."},syncObsidianTagsToAnki:{name:"Sync Obsidian tags to Anki",desc:"Sync Obsidian-recognized tags from the current note into Anki note tags, including nested tags. On each sync, these tags overwrite the managed tags in Anki based on the current Obsidian content."},keepPureTagLinesInCardBody:{name:"Keep pure tag lines in card body",desc:'When turned off, remove every line in the card body that contains only tags, such as "#ProjectA #\u91CD\u70B9/\u6848\u4F8B". Inline tags like "This is a #tag example" and lines with ordinary text like "\u6807\u7B7E\uFF1A#\u9879\u76EEA" are kept. Extra blank lines created by removal are cleaned up automatically.'}},mapping:{title:"Note type field mappings",refresh:{name:"Refresh note types from Anki",button:"Refresh note types"},status:{idle:"Refresh note types from Anki to load the available note types.",loadedCount:"Loaded {{count}} note types from Anki.",empty:"Anki returned no note types.",failedLoadNoteTypes:"Failed to load note types from Anki.",loadedSavedMapping:"Loaded saved mapping for {{modelName}}.",selectedModel:"Selected {{modelName}}. Read fields from Anki to create or refresh its mapping.",loadedFieldsForModel:"Loaded fields for {{modelName}}. Review the suggested mapping and save it.",failedLoadFields:"Failed to load fields for {{modelName}}.",noLoadedFields:"No loaded fields for {{modelName}}. Read fields from Anki first.",savedMapping:"Saved mapping for {{modelName}}.",failedSaveMapping:"Failed to save mapping for {{modelName}}.",savedMappingReady:"Saved mapping is ready for {{title}}.",noSavedMapping:"No saved mapping for {{title}}. Read fields from Anki first."},section:{basic:{title:"QA / Basic",description:"Choose the QA note type, read its fields from Anki, then confirm the title/body mapping."},cloze:{title:"Cloze",description:"Choose the cloze note type, read its fields from Anki, then confirm the main field mapping."},semanticQa:{title:"Semantic QA",description:"Choose the semantic QA note type, read its fields from Anki, then confirm the title/body mapping for child cards."}},noteTypeLabel:"{{title}} note type",noteTypeDesc:"Loaded from Anki note types. Refresh if the latest models are not shown.",fieldsLabel:"{{title}} fields",fieldsDesc:"Load the current note type fields from Anki, then review the suggested mapping.",readFieldsButton:"Read fields from Anki",loadedFields:"Loaded fields: {{fields}}",loadedFieldsNone:"Loaded fields: none. Read fields from Anki first.",mappingLabel:"{{title}} mapping",mappingDesc:"Save the current field mapping for this specific note type.",saveMappingButton:"Save mapping",titleFieldLabel:"{{title}} title field",titleFieldDesc:"Which Anki field should receive the heading/title fragment.",bodyFieldLabel:"{{title}} body field",bodyFieldDesc:"Which Anki field should receive the body fragment.",mainField:{name:"Cloze main field",desc:"The selected field receives title +

+ body during sync."},selectFieldPlaceholder:"-- Select field --"},deck:{defaultSectionTitle:"Default deck",defaultDeck:{name:"Default deck",desc:"Lowest priority: used when neither a file-level deck nor a folder mapping matches."},fileDeckSectionTitle:"File-level custom deck",fileDeckEnabled:{name:"Enable file-level custom deck",desc:"When enabled, a shared marker can define one deck for the whole note in YAML or body."},marker:{name:"Deck marker name",desc:"YAML key and body marker share the same identifier. The default value is TARGET DECK."},template:{name:"Default deck template",desc:"Only the filename variable is supported. It expands to the current file name without .md when inserted."},insertLocation:{name:"Template insert location",desc:"Choose whether the deck template is written into YAML frontmatter or the body header area.",options:{body:"Body header",yaml:"YAML frontmatter"}},insertTemplate:{name:"Insert deck template into the current file",desc:"Write the deck declaration into the current active Markdown file using the current marker, template, and insert location.",button:"Insert deck template"},folderMappingSectionTitle:"Advanced: folder mapping",folderDeckMode:{name:"Folder mapping mode",desc:"Off / parent folders only / parent folders plus current file name.",options:{off:"Off",folder:"Folder-based mapping",folderAndFile:"Folder-and-file mapping"}},examplesTitle:"Examples:",folderExample:"Folder-based mapping example: \u6570\u5B66/\u7B2C\u4E00\u7AE0/\u7B2C\u4E00\u8282.md -> \u6570\u5B66::\u7B2C\u4E00\u7AE0",folderAndFileExample:"Folder-and-file mapping example: \u6570\u5B66/\u7B2C\u4E00\u7AE0/\u7B2C\u4E00\u8282.md -> \u6570\u5B66::\u7B2C\u4E00\u7AE0::\u7B2C\u4E00\u8282",fallbackDesc:"If neither folder-and-file mapping nor file-level custom decks are used, the default deck name is used as the Anki deck.",priorityTitle:"Final priority",priorityDesc:"Final deck priority: file-level custom deck > folder-mapped deck > default deck."},scope:{name:"Plugin run scope",summary:{all:"Process Markdown files across the whole vault",include:"Only process Markdown files in the checked folders below",exclude:"Process the whole vault, but skip Markdown files in the checked folders below"},option:{all:"All files",include:"Only in selected folders",exclude:"Exclude selected folders"},treeDescription:{include:"Only in selected folders: only process Markdown files in the checked folders below",exclude:"Exclude selected folders: process the whole vault, but skip Markdown files in the checked folders below"},loading:"Loading folders from the current vault...",empty:"There are no selectable folders in the current vault.",failedLoad:"Failed to load folders from the current vault.",expandFolder:"Expand {{name}}",collapseFolder:"Collapse {{name}}"},cards:{cardTypes:{title:"Card types and basics",desc:"Edit recognition rules directly. Changes save automatically.",advancedHint:"Advanced: keep AnkiConnect URL here without promoting it to a separate status card.",markerPlaceholder:"/",fieldsUnavailable:"-- Read fields first --",autoManagedField:"Managed automatically",autoComposedAnswer:"Auto composed",qaGroupManagedNoteType:"{{modelName}} (managed automatically)",statusLabel:"Status: ",cacheEmpty:"There are no cached Anki note templates yet. Read the Anki template config manually.",cacheSummary:"Currently using {{noteTypeCount}} cached note templates with {{configuredCount}} selected card modes configured.",cacheChanged:"Anki currently reports {{liveCount}} note templates, which differs from the {{cachedCount}} cached templates on this page. The UI is still using the cache with {{configuredCount}} selected card modes configured; read the Anki template config manually to refresh.",cacheCheckFailed:"Still using {{noteTypeCount}} cached note templates with {{configuredCount}} selected card modes configured. The background check for the latest template list failed; read the Anki template config manually if you need a refresh.",loadedSummary:"Loaded {{noteTypeCount}} note templates and configured {{configuredCount}} selected card modes.",loadedFieldsStatus:"Refreshed fields for {{count}} selected note types.",failedLoad:"Failed to load note types or fields from Anki.",failedSave:"Failed to save card type settings.",loadAnki:{button:"Read Anki note types and fields manually",loading:"Loading Anki note types and fields..."},columns:{enabled:"Enabled",type:"Card type",headingLevel:"Heading marker",extraMarker:"Extra marker",noteType:"Anki note type",questionField:"Question field",answerField:"Answer field"},labels:{headingLevel:"Card marker:",extraMarker:"Extra marker:",noteType:"Anki note type:",questionField:"Question field:",answerField:"Answer field:",mainField:"Main field:",fields:"Fields:",qaGroupTitleField:"Title field:",qaGroupSlotFields:"Q/A fields:",qaGroupWarnings:"Warnings:"},qaGroup:{noModel:"Select an Anki note type first",unavailable:"Read fields from Anki first",detectedSlots:"Detected {{count}} pair(s)",acceptWarnings:"I confirm these warnings can be ignored and sync may continue",warning:{missingAnswer:"Slot {{index}} is missing its answer field, so {{questionField}} / {{answerField}} was ignored.",missingQuestion:"Slot {{index}} is missing its question field, so {{questionField}} / {{answerField}} was ignored."}},rows:{basic:"Q&A (regular paragraph)",qaGroup:"Q&A (nested list)",cloze:"Cloze",semanticQa:"Semantic Q&A"}},syncContent:{title:"Card body sync content",desc:"These options affect rendered content only. Updating them refreshes this card only.",sections:{bodyRange:"1. Choose the card body range",backlink:"2. Add backlinks for card-level jumps from Anki to Obsidian",tags:"3. Read tags",clozeSpecial:"4. Cloze-specific options"}},scope:{title:"Plugin run scope",desc:"Keep the existing scope modes and folder tree. The tree is loaded lazily and can be refreshed locally.",refreshFolders:"Refresh folder list"},deck:{title:"Card deck settings",desc:"Card deck settings are grouped by recommended workflow.",sections:{folderMapping:"1. Recommended: use folder-and-file mapping for Anki decks",fileDeck:"2. Optional: enable file-level custom decks",defaultDeck:"3. Fallback: use the default deck"}},commands:{title:"Command guide",desc:"These are the current commands exposed in the command palette.",items:{syncCurrentFile:"Sync only the active Markdown file to Anki.",syncVault:"Sync all in-scope Markdown files in the vault to Anki.",rebuildIndex:"Rebuild the local card index without creating or updating notes.",clearCurrentFile:"Clear synced card markers and tracked sync state for the active file.",cleanupDecks:"Delete selected empty decks from Anki."}}}},modal:{emptyDeck:{title:"Clean up empty decks",description:"Select the empty decks to delete. A deck is deleted only if it is still empty at deletion time.",selectAll:"Select all",clearAll:"Clear all",invert:"Invert selection",cancel:"Cancel",deleteSelected:"Delete selected empty decks",selectionCount:"Selected {{selected}} / {{total}} empty decks"}},notice:{invalidSettingsRestored:"Invalid plugin settings were detected. Default settings were restored in memory.",failedSavePluginSettings:"Failed to save plugin settings.",noActiveMarkdownForSync:"No active Markdown file is available for sync.",syncUseCaseNotInitialized:"Sync use case is not initialized.",currentFileSyncFailed:"Current file sync failed.",vaultSyncFailed:"Vault sync failed.",rebuildFailed:"Card index rebuild failed.",noActiveMarkdownForDeckTemplateInsertion:"No active Markdown file is available for deck template insertion.",vaultGatewayNotInitialized:"Vault gateway is not initialized.",markdownFileNotFound:"Markdown file not found: {{filePath}}",deckTemplateAlreadyCurrent:"The deck template in the current file is already up to date.",deckTemplateInserted:"Inserted deck template into the current file: {{deck}}",deckTemplateInsertionFailed:"Deck template insertion failed.",noActiveMarkdownForReset:"No active Markdown file is available for reset.",clearCurrentFileUseCaseNotInitialized:"Clear-current-file use case is not initialized.",noTrackedCardsInCurrentFile:"There are no synced cards in the current file.",clearCurrentFileFailed:"Clear current file synced cards failed.",cleanupEmptyDecksUseCaseNotInitialized:"Empty-deck cleanup use case is not initialized.",noEmptyDeckCandidates:"No empty decks were found for cleanup.",cleanupEmptyDecksCancelled:"Empty-deck cleanup was cancelled.",cleanupEmptyDecksFailed:"Cleanup empty decks failed.",summary:{currentFileSync:"Current file sync completed: files {{scannedFiles}}, cards {{scannedCards}}, created {{created}}, updated {{updated}}, migrated note types {{migratedNoteTypes}}, migrated decks {{migratedDecks}}, orphaned {{orphaned}}, media {{uploadedMedia}}, skipped {{skippedUnchangedCards}}.",vaultSync:"Vault sync completed: files {{scannedFiles}}, cards {{scannedCards}}, created {{created}}, updated {{updated}}, migrated note types {{migratedNoteTypes}}, migrated decks {{migratedDecks}}, orphaned {{orphaned}}, media {{uploadedMedia}}, skipped {{skippedUnchangedCards}}.",rebuild:"Card index rebuild completed: files {{scannedFiles}}, cards {{scannedCards}}, migrated decks {{migratedDecks}}, orphaned {{orphaned}}, rewritten markers {{rewrittenMarkers}}, skipped {{skippedUnchangedCards}}.",clearCurrentFile:"Current file synced cards cleared: tracked cards {{trackedCards}}, tracked groups {{trackedGroups}}, deleted notes {{deletedNotes}}, removed markers {{removedMarkers}}, removed ID markers {{removedCardMarkers}}, removed GI markers {{removedGroupMarkers}}, deleted local records {{deletedLocalRecords}}.",cleanupEmptyDecks:"Empty-deck cleanup completed: candidates {{candidateCount}}, selected {{selectedCount}}, deleted {{deletedCount}}, skipped {{skippedCount}}.",markerWriteConflicts:"Marker write conflicts: {{files}}.",warningsCount:"Warnings: {{count}}.",markerRemovalConflicts:"Marker removal conflicts: {{files}}.",failures:"Failures: {{items}}.",skippedDecks:"Skipped decks: {{decks}}."}},errors:{currentFileOutOfScope:"The current file is outside the plugin scope: {{filePath}}",deck:{emptyName:"Deck name cannot be empty. Check the file-level deck declaration or default deck setting."},settings:{headingLevelsRange:"Heading levels must be integers between 1 and 6.",headingLevelsDifferent:"QA and Cloze heading levels must be different.",cardTypeConfigsObject:"Card type configs must be an object.",cardTypeEnabledBoolean:"Each card type enabled flag must be a boolean.",cardTypeExtraMarkerString:"Each card type extra marker must be a string.",cardTypeDefaultConflict:"Only one enabled default card type is allowed at heading H{{headingLevel}}.",cardAnswerCutoffModeInvalid:"Card answer cutoff mode must be heading-block or double-blank-lines.",qaNoteTypeRequired:"QA note type is required.",qaGroupMarkerRequired:"QA Group marker is required.",qaGroupMarkerInvalid:"QA Group marker must be a hashtag-style token like #anki-list.",clozeNoteTypeRequired:"Cloze note type is required.",semanticQaMarkerRequired:"Semantic QA marker is required.",semanticQaMarkerInvalid:"Semantic QA marker must be a hashtag-style token like #anki-list-qa.",qaGroupMarkerConflict:"QA Group marker must be different from Semantic QA marker.",semanticQaNoteTypeRequired:"Semantic QA note type is required.",defaultDeckRequired:"Default deck is required.",fileDeckEnabledBoolean:"File deck enabled must be a boolean.",syncObsidianTagsToAnkiBoolean:"Sync Obsidian tags to Anki must be a boolean.",keepPureTagLinesInCardBodyBoolean:"Keep pure tag lines in card body must be a boolean.",fileDeckMarkerString:"File deck marker must be a string.",fileDeckTemplateString:"File deck template must be a string.",fileDeckInsertLocationInvalid:"File deck insert location must be yaml or body.",folderDeckModeInvalid:"Folder deck mode must be off, folder, or folder-and-file.",scopeModeInvalid:"Scope mode must be one of all, include, or exclude.",obsidianBacklinkPlacementInvalid:"Obsidian backlink placement must be question-last-line, answer-first-line, or answer-last-line.",includeFoldersArray:"Include folders must be an array.",includeFoldersStrings:"Include folders must only contain strings.",excludeFoldersArray:"Exclude folders must be an array.",excludeFoldersStrings:"Exclude folders must only contain strings.",ankiConnectUrlRequired:"AnkiConnect URL is required.",ankiNoteTypeCacheArray:"Anki note type cache must be an array.",ankiNoteTypeCacheStrings:"Anki note type cache can only contain strings.",ankiModelFieldCacheObject:"Anki model field cache must be an object.",ankiModelFieldCacheEntryObject:"Each Anki model field cache entry must be an object.",ankiModelFieldCacheFieldNamesArray:"Anki model field cache fieldNames must be an array.",ankiModelFieldCacheFieldNamesStrings:"Anki model field cache fieldNames can only contain strings.",ankiModelFieldCacheLoadedAt:"Anki model field cache loadedAt must be a finite number.",noteFieldMappingsObject:"Note field mappings must be an object.",noteFieldMappingsCardType:"Note field mappings must use a supported card type.",noteFieldMappingsModelName:"Note field mappings must include a model name.",noteFieldMappingsLoadedFieldNames:"Note field mappings must include loaded field names.",noteFieldMappingsLoadedAt:"Note field mappings must include a loaded timestamp.",noteFieldMappingsQaGroupSlotsArray:"QA Group field mapping slots must be an array.",noteFieldMappingsQaGroupSlotObject:"Each QA Group field mapping slot must be an object.",noteFieldMappingsQaGroupSlotIndex:"Each QA Group field mapping slot.index must be an integer greater than 0.",noteFieldMappingsQaGroupSlotQuestionField:"Each QA Group field mapping slot.questionField must be a string.",noteFieldMappingsQaGroupSlotAnswerField:"Each QA Group field mapping slot.answerField must be a string.",noteFieldMappingsQaGroupWarningsArray:"QA Group field mapping warnings must be an array.",noteFieldMappingsQaGroupWarningsStrings:"QA Group field mapping warnings can only contain strings.",noteFieldMappingsQaGroupAcceptedWarningsArray:"QA Group field mapping acceptedWarnings must be an array.",noteFieldMappingsQaGroupAcceptedWarningsStrings:"QA Group field mapping acceptedWarnings can only contain strings."},noteFieldMapping:{noteTypeNotSelected:{basic:"No Anki note type is selected for basic cards. Choose one in settings before syncing.",cloze:"No Anki note type is selected for cloze cards. Choose one in settings before syncing.",semanticQa:"No Anki note type is selected for semantic QA cards. Choose one in settings before syncing.",qaGroup:"No Anki note type is selected for QA Group cards. Choose one in settings before syncing."},missingSavedMapping:{basic:'No saved field mapping found for basic note type "{{modelName}}". Open plugin settings and read fields from Anki first.',cloze:'No saved field mapping found for cloze note type "{{modelName}}". Open plugin settings and read fields from Anki first.',semanticQa:'No saved field mapping found for semantic QA note type "{{modelName}}". Open plugin settings and read fields from Anki first.',qaGroup:'No saved field mapping found for QA Group note type "{{modelName}}". Open plugin settings, read fields from Anki, and save the mapping first.'},incompleteSavedMapping:{basic:'Saved field mapping for basic note type "{{modelName}}" is incomplete. Open plugin settings and save both title and body fields.',semanticQa:'Saved field mapping for semantic QA note type "{{modelName}}" is incomplete. Open plugin settings and save both title and body fields.',cloze:'Saved field mapping for cloze note type "{{modelName}}" is incomplete. Open plugin settings and save the main field.'},titleBodyMustDiffer:{basic:'Basic note type "{{modelName}}" must use different title and body fields.',semanticQa:'Semantic QA note type "{{modelName}}" must use different title and body fields.'},stale:'Saved field mapping for note type "{{modelName}}" is stale because these fields no longer exist in Anki: {{fields}}. Open plugin settings and read fields from Anki again.',clozeIncompatible:'Cloze note type "{{modelName}}" is not cloze-compatible in Anki.',qaGroupMissingTitle:'Saved field mapping for QA Group note type "{{modelName}}" is incomplete because the title field is missing. Save the mapping again in settings.',qaGroupNoCompleteSlots:'Saved field mapping for QA Group note type "{{modelName}}" is incomplete because it has no saved question/answer slot pairs. Save the mapping again in settings.',qaGroupNonContinuousSlots:'QA Group note type "{{modelName}}" must start its question/answer slots at pair {{firstIndex}} = 1. Renumber the first pair to 1.',qaGroupWarningsUnaccepted:'QA Group note type "{{modelName}}" still has unconfirmed field warnings. Confirm them in settings before syncing.',qaGroupSlotCapacityExceeded:'Saved field mapping for QA Group note type "{{modelName}}" only includes {{capacity}} question/answer pair(s), but the current block has {{itemCount}} item(s): {{filePath}}:{{blockStartLine}}.'},noteTypeMigration:{failed:'Failed to migrate Anki note {{noteId}} from "{{fromModel}}" to "{{toModel}}"{{location}}: {{reason}}',unsupported:'The current AnkiConnect does not support migrating Anki note {{noteId}} from "{{fromModel}}" to "{{toModel}}"{{location}}. Upgrade AnkiConnect, or clear the Anki ID and sync again. Reason: {{reason}}'},writeBack:{summary:"Markdown marker write-back failed for {{fileCount}} file(s).",markdownFileNotFound:"Markdown file was not found.",missingSourceContent:"Scanned source content is missing for marker write-back.",noteIdMissing:"Cannot write a marker because note ID is missing for the block at line {{blockStartLine}}."},markerRemoval:{markdownFileNotFound:"Markdown file was not found."}},warnings:{deck:{conflictYamlBody:"Conflicting {{marker}} declarations were found in YAML and body. This sync used the YAML value.",multipleBodyDeclarations:"Multiple {{marker}} declarations were found in the file. This sync used the first body declaration.",invalidFolderSegment:"A folder or file name contains ::, so folder-based deck mapping was skipped and the default deck was used.",fallbackDefault:"No explicit deck was found and a folder-based deck could not be generated, so the default deck was used."}}};var Zr={commands:{syncCurrentFileToAnki:"\u540C\u6B65\u5F53\u524D\u6587\u4EF6\u5230 Anki",syncVaultToAnki:"\u540C\u6B65\u5168\u5E93\u5230 Anki",rebuildCardIndex:"\u91CD\u5EFA\u5361\u7247\u7D22\u5F15",clearCurrentFileSyncedCards:"\u6E05\u7A7A\u5F53\u524D\u6587\u4EF6\u5DF2\u540C\u6B65\u5361\u7247",cleanupEmptyDecks:"\u6E05\u7406\u7A7A\u724C\u7EC4"},settings:{pluginTitle:"Anki Heading Sync",ankiConnectUrl:{name:"AnkiConnect URL",desc:"\u9ED8\u8BA4\u662F http://127.0.0.1:8765",placeholder:"http://127.0.0.1:8765"},qaHeadingLevel:{name:"QA \u6807\u9898\u5C42\u7EA7",desc:"\u9ED8\u8BA4\u662F H4"},clozeHeadingLevel:{name:"\u586B\u7A7A\u9898\u6807\u9898\u5C42\u7EA7",desc:"\u9ED8\u8BA4\u662F H5"},cardAnswerCutoffMode:{name:"\u5361\u7247\u6B63\u6587\u622A\u6B62\u6A21\u5F0F",desc:"\u6709\u6548\u540C\u6B65\u6807\u8BB0\u59CB\u7EC8\u4F18\u5148\u3002\u6CA1\u6709\u6709\u6548\u6807\u8BB0\u65F6\uFF0C\u9009\u62E9\u7EE7\u7EED\u5230\u6574\u4E2A\u6807\u9898\u5757\u672B\u5C3E\uFF0C\u6216\u5728\u9996\u4E2A 2+ \u8FDE\u7EED\u7A7A\u884C\u524D\u622A\u6B62\u3002",options:{headingBlock:"heading-block\uFF1A\u6574\u4E2A\u6807\u9898\u5757",doubleBlankLines:"double-blank-lines\uFF1A\u5728\u9996\u4E2A 2+ \u8FDE\u7EED\u7A7A\u884C\u524D\u622A\u6B62"}},qaGroup:{title:"QA Group 12",marker:{name:"QA Group \u6807\u8BB0",desc:"\u5F53 QA \u6807\u9898\u4EE5\u8FD9\u4E2A hashtag \u6807\u8BB0\u7ED3\u5C3E\u65F6\uFF0C\u6574\u4E2A\u6807\u9898\u5757\u4F1A\u4F5C\u4E3A\u4E00\u5F20 ObsiAnki QA Group 12 \u7B14\u8BB0\u540C\u6B65\u3002",placeholder:"#anki-list"},managedNoteType:"\u6258\u7BA1\u7B14\u8BB0\u7C7B\u578B\uFF1A{{modelName}}\u3002QA Group \u540C\u6B65\u4F1A\u76F4\u63A5\u5199\u5165 Stem / GroupId / Src / S01..S12\u3002\u5982\u679C\u4F60\u60F3\u5728\u5176\u4ED6\u540C\u6B65\u8DEF\u5F84\u91CC\u590D\u7528\u5B83\uFF0C\u5B83\u4E5F\u4F1A\u51FA\u73B0\u5728\u4E0B\u9762\u7684\u5B57\u6BB5\u6620\u5C04\u9762\u677F\u4E2D\u3002",managedModelContract:"\u6258\u7BA1\u6A21\u578B\u7EA6\u675F\uFF1A\u540C\u6B65\u65F6\u4F1A\u81EA\u52A8\u68C0\u67E5 {{fieldCount}} \u4E2A\u5B57\u6BB5\u548C {{templateCount}} \u4E2A\u6A21\u677F\u3002"},semanticQa:{title:"\u8BED\u4E49 QA",marker:{name:"\u8BED\u4E49 QA \u6807\u8BB0",desc:"\u5F53 QA \u6807\u9898\u4EE5\u8FD9\u4E2A hashtag \u6807\u8BB0\u7ED3\u5C3E\u65F6\uFF0C\u5E26\u7F29\u8FDB\u5B50\u5185\u5BB9\u7684\u4E00\u7EA7\u5217\u8868\u9879\u4F1A\u62C6\u5206\u6210\u72EC\u7ACB\u5361\u7247\u3002",placeholder:"#anki-list-qa"},previewTitle:"\u8BED\u4E49 QA \u9884\u89C8",triggerHeadingExample:"\u89E6\u53D1\u6807\u9898\u793A\u4F8B\uFF1A{{heading}}",previewUnavailable:"\u5F53\u524D\u65E0\u6CD5\u751F\u6210\u9884\u89C8\u3002\u8BF7\u4F7F\u7528\u7C7B\u4F3C #anki-list-qa \u7684\u5C3E\u968F hashtag \u6807\u8BB0\u3002",questionPreview:"\u95EE\u9898\u9884\u89C8\uFF1A{{question}}",answerPreview:"\u7B54\u6848\u9884\u89C8\uFF1A{{answer}}"},syncOptions:{addObsidianBacklink:{name:"\u6DFB\u52A0 Obsidian \u56DE\u94FE",desc:"\u628A\u6765\u6E90\u6807\u9898\u7684\u56DE\u94FE\u8FFD\u52A0\u5230\u540C\u6B65\u540E\u7684\u5361\u7247\u4E2D\u3002"},obsidianBacklinkLabel:{name:"Obsidian \u56DE\u94FE\u663E\u793A\u540D\u79F0",desc:"\u8BBE\u7F6E\u56DE\u94FE\u663E\u793A\u7684\u6587\u5B57\u3002\u7559\u7A7A\u6216\u53EA\u586B\u7A7A\u683C\u65F6\u4F1A\u56DE\u9000\u4E3A Open in Obsidian\u3002",placeholder:"Open in Obsidian"},obsidianBacklinkPlacement:{name:"Obsidian \u56DE\u94FE\u653E\u7F6E\u4F4D\u7F6E",desc:"\u9009\u62E9\u628A\u56DE\u94FE\u8FFD\u52A0\u5230\u95EE\u9898\u680F\u6700\u540E\u4E00\u884C\uFF0C\u6216\u653E\u5230\u7B54\u6848\u6B63\u6587\u7684\u7B2C\u4E00\u884C / \u6700\u540E\u4E00\u884C\u3002",options:{questionLastLine:"\u95EE\u9898\u680F\u7684\u6700\u540E\u4E00\u884C",answerFirstLine:"\u7B54\u6848\u6B63\u6587\u7684\u7B2C\u4E00\u884C",answerLastLine:"\u7B54\u6848\u6B63\u6587\u7684\u6700\u540E\u4E00\u884C"}},highlightsToCloze:{name:"\u9AD8\u4EAE\u8F6C\u586B\u7A7A\u9898",desc:"\u628A ==highlight== \u7247\u6BB5\u8F6C\u6362\u6210\u586B\u7A7A\u9898\u4F7F\u7528\u7684\u6316\u7A7A\u683C\u5F0F\u3002"},syncObsidianTagsToAnki:{name:"\u540C\u6B65 Obsidian \u6807\u7B7E\u5230 Anki",desc:"\u5C06\u5F53\u524D\u7B14\u8BB0\u4E2D Obsidian \u8BC6\u522B\u5230\u7684\u6807\u7B7E\u540C\u6B65\u4E3A Anki \u7B14\u8BB0\u6807\u7B7E\uFF0C\u652F\u6301\u5D4C\u5957\u6807\u7B7E\u3002\u6BCF\u6B21\u540C\u6B65\u65F6\uFF0C\u8FD9\u4E9B\u6807\u7B7E\u90FD\u4F1A\u4EE5\u5F53\u524D Obsidian \u5185\u5BB9\u4E3A\u51C6\u8986\u76D6 Anki\u3002"},keepPureTagLinesInCardBody:{name:"\u5728\u5361\u7247\u6B63\u6587\u4E2D\u4FDD\u7559\u7EAF\u6807\u7B7E\u884C",desc:"\u5173\u95ED\u540E\uFF0C\u4F1A\u5220\u9664\u6B63\u6587\u4E2D\u6240\u6709\u53EA\u5305\u542B\u6807\u7B7E\u7684\u6574\u884C\uFF0C\u4F8B\u5982 \u201C#\u9879\u76EEA #\u91CD\u70B9/\u6848\u4F8B\u201D\u3002\u50CF\u201C\u8FD9\u662F #\u6807\u7B7E \u7684\u6848\u4F8B\u201D\u8FD9\u7C7B\u884C\u5185\u6807\u7B7E\uFF0C\u6216\u201C\u6807\u7B7E\uFF1A#\u9879\u76EEA\u201D\u8FD9\u7C7B\u5E26\u666E\u901A\u6587\u5B57\u7684\u884C\uFF0C\u4E0D\u4F1A\u88AB\u5220\u9664\u3002\u5220\u9664\u540E\u4F1A\u81EA\u52A8\u6E05\u7406\u591A\u4F59\u7A7A\u884C\u3002"}},mapping:{title:"\u7B14\u8BB0\u7C7B\u578B\u5B57\u6BB5\u6620\u5C04",refresh:{name:"\u4ECE Anki \u5237\u65B0\u7B14\u8BB0\u7C7B\u578B",button:"\u5237\u65B0\u7B14\u8BB0\u7C7B\u578B"},status:{idle:"\u8BF7\u5148\u4ECE Anki \u5237\u65B0\u7B14\u8BB0\u7C7B\u578B\uFF0C\u4EE5\u52A0\u8F7D\u53EF\u7528\u7684\u7B14\u8BB0\u7C7B\u578B\u5217\u8868\u3002",loadedCount:"\u5DF2\u4ECE Anki \u52A0\u8F7D {{count}} \u4E2A\u7B14\u8BB0\u7C7B\u578B\u3002",empty:"Anki \u6CA1\u6709\u8FD4\u56DE\u4EFB\u4F55\u7B14\u8BB0\u7C7B\u578B\u3002",failedLoadNoteTypes:"\u4ECE Anki \u52A0\u8F7D\u7B14\u8BB0\u7C7B\u578B\u5931\u8D25\u3002",loadedSavedMapping:"\u5DF2\u52A0\u8F7D {{modelName}} \u7684\u5DF2\u4FDD\u5B58\u6620\u5C04\u3002",selectedModel:"\u5DF2\u9009\u62E9 {{modelName}}\u3002\u8BF7\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u4EE5\u521B\u5EFA\u6216\u5237\u65B0\u5B83\u7684\u6620\u5C04\u3002",loadedFieldsForModel:"\u5DF2\u52A0\u8F7D {{modelName}} \u7684\u5B57\u6BB5\u3002\u8BF7\u68C0\u67E5\u5EFA\u8BAE\u6620\u5C04\u540E\u4FDD\u5B58\u3002",failedLoadFields:"\u52A0\u8F7D {{modelName}} \u7684\u5B57\u6BB5\u5931\u8D25\u3002",noLoadedFields:"{{modelName}} \u8FD8\u6CA1\u6709\u5DF2\u52A0\u8F7D\u5B57\u6BB5\u3002\u8BF7\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002",savedMapping:"\u5DF2\u4FDD\u5B58 {{modelName}} \u7684\u6620\u5C04\u3002",failedSaveMapping:"\u4FDD\u5B58 {{modelName}} \u7684\u6620\u5C04\u5931\u8D25\u3002",savedMappingReady:"{{title}} \u7684\u5DF2\u4FDD\u5B58\u6620\u5C04\u5DF2\u5C31\u7EEA\u3002",noSavedMapping:"{{title}} \u8FD8\u6CA1\u6709\u5DF2\u4FDD\u5B58\u6620\u5C04\u3002\u8BF7\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002"},section:{basic:{title:"QA / \u57FA\u7840\u5361",description:"\u9009\u62E9 QA \u7B14\u8BB0\u7C7B\u578B\uFF0C\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\uFF0C\u7136\u540E\u786E\u8BA4\u6807\u9898/\u6B63\u6587\u6620\u5C04\u3002"},cloze:{title:"\u586B\u7A7A\u9898",description:"\u9009\u62E9\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B\uFF0C\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\uFF0C\u7136\u540E\u786E\u8BA4\u4E3B\u5B57\u6BB5\u6620\u5C04\u3002"},semanticQa:{title:"\u8BED\u4E49 QA",description:"\u9009\u62E9\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B\uFF0C\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\uFF0C\u7136\u540E\u786E\u8BA4\u5B50\u5361\u7247\u7684\u6807\u9898/\u6B63\u6587\u6620\u5C04\u3002"}},noteTypeLabel:"{{title}} \u7B14\u8BB0\u7C7B\u578B",noteTypeDesc:"\u4ECE Anki \u7684\u7B14\u8BB0\u7C7B\u578B\u5217\u8868\u52A0\u8F7D\u3002\u5982\u679C\u6700\u65B0\u6A21\u578B\u6CA1\u6709\u663E\u793A\uFF0C\u8BF7\u5148\u5237\u65B0\u3002",fieldsLabel:"{{title}} \u5B57\u6BB5",fieldsDesc:"\u4ECE Anki \u8BFB\u53D6\u5F53\u524D\u7B14\u8BB0\u7C7B\u578B\u7684\u5B57\u6BB5\uFF0C\u7136\u540E\u68C0\u67E5\u5EFA\u8BAE\u6620\u5C04\u3002",readFieldsButton:"\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5",loadedFields:"\u5DF2\u52A0\u8F7D\u5B57\u6BB5\uFF1A{{fields}}",loadedFieldsNone:"\u5DF2\u52A0\u8F7D\u5B57\u6BB5\uFF1A\u65E0\u3002\u8BF7\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002",mappingLabel:"{{title}} \u6620\u5C04",mappingDesc:"\u4FDD\u5B58\u5F53\u524D\u7B14\u8BB0\u7C7B\u578B\u7684\u5B57\u6BB5\u6620\u5C04\u3002",saveMappingButton:"\u4FDD\u5B58\u6620\u5C04",titleFieldLabel:"{{title}} \u6807\u9898\u5B57\u6BB5",titleFieldDesc:"\u9009\u62E9\u63A5\u6536\u6807\u9898\u7247\u6BB5\u7684 Anki \u5B57\u6BB5\u3002",bodyFieldLabel:"{{title}} \u6B63\u6587\u5B57\u6BB5",bodyFieldDesc:"\u9009\u62E9\u63A5\u6536\u6B63\u6587\u7247\u6BB5\u7684 Anki \u5B57\u6BB5\u3002",mainField:{name:"\u586B\u7A7A\u9898\u4E3B\u5B57\u6BB5",desc:"\u540C\u6B65\u65F6\uFF0C\u6240\u9009\u5B57\u6BB5\u4F1A\u63A5\u6536 \u6807\u9898 +

+ \u6B63\u6587\u3002"},selectFieldPlaceholder:"-- \u9009\u62E9\u5B57\u6BB5 --"},deck:{defaultSectionTitle:"\u9ED8\u8BA4\u724C\u7EC4",defaultDeck:{name:"\u9ED8\u8BA4\u724C\u7EC4",desc:"\u4F18\u5148\u7EA7\u6700\u4F4E\uFF1A\u5F53\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4\u4E0E\u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4\u90FD\u672A\u547D\u4E2D\u65F6\u4F7F\u7528\u3002"},fileDeckSectionTitle:"\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4",fileDeckEnabled:{name:"\u5F00\u542F\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4",desc:"\u5F00\u542F\u540E\uFF0C\u53EF\u5728 YAML \u6216\u6B63\u6587\u4E2D\u7528\u7EDF\u4E00\u8BC6\u522B\u540D\u4E3A\u6574\u7BC7\u7B14\u8BB0\u6307\u5B9A\u4E00\u4E2A\u724C\u7EC4\u3002"},marker:{name:"\u724C\u7EC4\u8BC6\u522B\u540D",desc:"YAML key \u4E0E\u6B63\u6587\u6807\u8BB0\u5171\u7528\u540C\u4E00\u4E2A\u8BC6\u522B\u540D\u3002\u9ED8\u8BA4\u503C\u662F TARGET DECK\u3002"},template:{name:"\u9ED8\u8BA4\u724C\u7EC4\u6A21\u677F",desc:"\u53EA\u652F\u6301 filename \u53D8\u91CF\u3002\u63D2\u5165\u65F6\u4F1A\u5C55\u5F00\u4E3A\u5F53\u524D\u6587\u4EF6\u540D\uFF08\u4E0D\u542B .md\uFF09\u3002"},insertLocation:{name:"\u6A21\u677F\u63D2\u5165\u4F4D\u7F6E",desc:"\u9009\u62E9\u5C06\u724C\u7EC4\u6A21\u677F\u5199\u5165 YAML frontmatter \u8FD8\u662F\u6B63\u6587\u524D\u90E8\u3002",options:{body:"\u6B63\u6587\u524D\u90E8",yaml:"YAML frontmatter"}},insertTemplate:{name:"\u5411\u5F53\u524D\u6587\u4EF6\u63D2\u5165\u724C\u7EC4\u6A21\u677F",desc:"\u6309\u5F53\u524D\u8BC6\u522B\u540D\u3001\u6A21\u677F\u548C\u63D2\u5165\u4F4D\u7F6E\uFF0C\u628A\u724C\u7EC4\u58F0\u660E\u5199\u5165\u5F53\u524D\u6D3B\u52A8 Markdown \u6587\u4EF6\u3002",button:"\u63D2\u5165\u724C\u7EC4\u6A21\u677F"},folderMappingSectionTitle:"\u9AD8\u7EA7\uFF1A\u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4",folderDeckMode:{name:"\u6587\u4EF6\u5939\u6620\u5C04\u6A21\u5F0F",desc:"\u5173\u95ED / \u4EC5\u7236\u6587\u4EF6\u5939 / \u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u3002",options:{off:"\u5173\u95ED",folder:"\u6587\u4EF6\u5939\u7EA7\u6620\u5C04",folderAndFile:"\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u7EA7\u6620\u5C04"}},examplesTitle:"\u793A\u4F8B\uFF1A",folderExample:"\u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4\u793A\u4F8B\uFF1A\u6570\u5B66/\u7B2C\u4E00\u7AE0/\u7B2C\u4E00\u8282.md -> \u6570\u5B66::\u7B2C\u4E00\u7AE0",folderAndFileExample:"\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u6620\u5C04\u724C\u7EC4\u793A\u4F8B\uFF1A\u6570\u5B66/\u7B2C\u4E00\u7AE0/\u7B2C\u4E00\u8282.md -> \u6570\u5B66::\u7B2C\u4E00\u7AE0::\u7B2C\u4E00\u8282",fallbackDesc:"\u82E5\u5747\u4E0D\u6253\u5F00\u300C\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u300D\u53CA\u300C\u6587\u4EF6\u7EA7\u300D\u724C\u7EC4\uFF0C\u5219\u4EE5\u300C\u9ED8\u8BA4\u724C\u7EC4\u540D\u79F0\u300D\u4F5C\u4E3A Anki \u7684\u724C\u7EC4\u540D\u3002",priorityTitle:"\u6700\u7EC8\u724C\u7EC4\u4F18\u5148\u7EA7\u8BF4\u660E",priorityDesc:"\u6700\u7EC8\u724C\u7EC4\u4F18\u5148\u7EA7\uFF1A\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4 > \u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4 > \u9ED8\u8BA4\u724C\u7EC4\u3002"},scope:{name:"\u63D2\u4EF6\u8FD0\u884C\u8303\u56F4",summary:{all:"\u5904\u7406\u6574\u4E2A vault \u4E2D\u7684 Markdown \u6587\u4EF6",include:"\u4EC5\u5904\u7406\u4E0B\u65B9\u52FE\u9009\u6587\u4EF6\u5939\u4E2D\u7684 Markdown \u6587\u4EF6",exclude:"\u5904\u7406\u6574\u4E2A vault\uFF0C\u4F46\u8DF3\u8FC7\u4E0B\u65B9\u52FE\u9009\u6587\u4EF6\u5939\u4E2D\u7684 Markdown \u6587\u4EF6"},option:{all:"\u5168\u90E8\u6587\u4EF6",include:"\u4EC5\u5728\u6307\u5B9A\u6587\u4EF6\u5939",exclude:"\u6392\u9664\u6307\u5B9A\u6587\u4EF6\u5939"},treeDescription:{include:"\u4EC5\u5728\u6307\u5B9A\u6587\u4EF6\u5939\uFF1A\u53EA\u5904\u7406\u4E0B\u65B9\u52FE\u9009\u6587\u4EF6\u5939\u4E2D\u7684 Markdown \u6587\u4EF6",exclude:"\u6392\u9664\u6307\u5B9A\u6587\u4EF6\u5939\uFF1A\u5904\u7406\u6574\u4E2A vault\uFF0C\u4F46\u8DF3\u8FC7\u4E0B\u65B9\u52FE\u9009\u6587\u4EF6\u5939\u4E2D\u7684 Markdown \u6587\u4EF6"},loading:"\u6B63\u5728\u8BFB\u53D6\u5F53\u524D vault \u6587\u4EF6\u5939...",empty:"\u5F53\u524D vault \u4E2D\u6CA1\u6709\u53EF\u9009\u6587\u4EF6\u5939\u3002",failedLoad:"\u8BFB\u53D6\u5F53\u524D vault \u6587\u4EF6\u5939\u5931\u8D25\u3002",expandFolder:"\u5C55\u5F00 {{name}}",collapseFolder:"\u6536\u8D77 {{name}}"},cards:{cardTypes:{title:"\u5361\u7247\u7C7B\u578B\u53CA\u57FA\u7840\u8BBE\u7F6E",desc:"\u76F4\u63A5\u7F16\u8F91\u8BC6\u522B\u89C4\u5219\uFF0C\u4FEE\u6539\u540E\u81EA\u52A8\u4FDD\u5B58\u3002",advancedHint:"\u9AD8\u7EA7\u9879\uFF1A\u5C06 AnkiConnect URL \u4FDD\u7559\u5728\u8FD9\u91CC\uFF0C\u4E0D\u5355\u72EC\u505A\u8FDE\u63A5\u72B6\u6001\u5361\u7247\u3002",markerPlaceholder:"/",fieldsUnavailable:"-- \u8BF7\u5148\u8BFB\u53D6\u5B57\u6BB5 --",autoManagedField:"\u81EA\u52A8\u7EF4\u62A4",autoComposedAnswer:"\u81EA\u52A8\u62FC\u63A5",qaGroupManagedNoteType:"{{modelName}}\uFF08\u81EA\u52A8\u7EF4\u62A4\uFF09",statusLabel:"\u72B6\u6001\uFF1A",cacheEmpty:"\u5F53\u524D\u6CA1\u6709\u5DF2\u7F13\u5B58\u7684 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u624B\u52A8\u8BFB\u53D6 Anki \u91CC\u7684\u6A21\u677F\u914D\u7F6E\u3002",cacheSummary:"\u5F53\u524D\u4F7F\u7528\u7F13\u5B58\u7684 {{noteTypeCount}} \u4E2A\u7B14\u8BB0\u6A21\u677F\uFF0C\u5DF2\u9009\u62E9\u5E76\u914D\u7F6E {{configuredCount}} \u4E2A\u5361\u7247\u6A21\u5F0F\u3002",cacheChanged:"\u68C0\u6D4B\u5230 Anki \u5F53\u524D\u6709 {{liveCount}} \u4E2A\u7B14\u8BB0\u6A21\u677F\uFF0C\u548C\u672C\u9875\u7F13\u5B58\u7684 {{cachedCount}} \u4E2A\u6A21\u677F\u4E0D\u4E00\u81F4\u3002\u5F53\u524D\u4ECD\u5728\u4F7F\u7528\u7F13\u5B58\uFF0C\u5DF2\u9009\u62E9\u5E76\u914D\u7F6E {{configuredCount}} \u4E2A\u5361\u7247\u6A21\u5F0F\uFF1B\u5982\u9700\u66F4\u65B0\u8BF7\u624B\u52A8\u8BFB\u53D6 Anki \u91CC\u7684\u6A21\u677F\u914D\u7F6E\u3002",cacheCheckFailed:"\u5F53\u524D\u7EE7\u7EED\u4F7F\u7528\u7F13\u5B58\u7684 {{noteTypeCount}} \u4E2A\u7B14\u8BB0\u6A21\u677F\uFF0C\u5DF2\u9009\u62E9\u5E76\u914D\u7F6E {{configuredCount}} \u4E2A\u5361\u7247\u6A21\u5F0F\uFF1B\u540E\u53F0\u68C0\u67E5\u6700\u65B0\u6A21\u677F\u5217\u8868\u5931\u8D25\uFF0C\u5982\u9700\u66F4\u65B0\u8BF7\u624B\u52A8\u8BFB\u53D6 Anki \u91CC\u7684\u6A21\u677F\u914D\u7F6E\u3002",loadedSummary:"\u5DF2\u83B7\u53D6 {{noteTypeCount}} \u4E2A\u7B14\u8BB0\u6A21\u677F\uFF0C\u5DF2\u9009\u62E9\u5E76\u914D\u7F6E {{configuredCount}} \u4E2A\u5361\u7247\u6A21\u5F0F\u3002",loadedFieldsStatus:"\u5DF2\u5237\u65B0 {{count}} \u4E2A\u5F53\u524D\u6240\u9009\u6A21\u677F\u7684\u5B57\u6BB5\u3002",failedLoad:"\u4ECE Anki \u8BFB\u53D6\u6A21\u677F\u6216\u5B57\u6BB5\u5931\u8D25\u3002",failedSave:"\u4FDD\u5B58\u5361\u7247\u7C7B\u578B\u8BBE\u7F6E\u5931\u8D25\u3002",loadAnki:{button:"\u624B\u52A8\u8BFB\u53D6 Anki \u91CC\u7684\u6A21\u677F\u914D\u7F6E",loading:"\u6B63\u5728\u8BFB\u53D6 Anki \u6A21\u677F\u548C\u5B57\u6BB5..."},columns:{enabled:"\u542F\u7528",type:"\u5361\u7247\u7C7B\u578B",headingLevel:"\u5361\u7247\u6807\u8BB0",extraMarker:"\u989D\u5916\u6807\u8BB0",noteType:"Anki \u7B14\u8BB0\u6A21\u677F",questionField:"\u95EE\u9898\u5B57\u6BB5",answerField:"\u7B54\u6848\u5B57\u6BB5"},labels:{headingLevel:"\u5361\u7247\u6807\u8BB0\uFF1A",extraMarker:"\u989D\u5916\u6807\u8BB0\uFF1A",noteType:"Anki \u7B14\u8BB0\u6A21\u677F\uFF1A",questionField:"\u95EE\u9898\u5B57\u6BB5\uFF1A",answerField:"\u7B54\u6848\u5B57\u6BB5\uFF1A",mainField:"\u4E3B\u5B57\u6BB5\uFF1A",fields:"\u5B57\u6BB5\uFF1A",qaGroupTitleField:"\u9898\u76EE\u5B57\u6BB5\uFF1A",qaGroupSlotFields:"\u95EE\u9898/\u7B54\u6848\u5B57\u6BB5\uFF1A",qaGroupWarnings:"\u8B66\u544A\uFF1A"},qaGroup:{noModel:"\u8BF7\u5148\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F",unavailable:"\u8BF7\u5148\u624B\u52A8\u8BFB\u53D6\u5B57\u6BB5",detectedSlots:"\u5DF2\u8BC6\u522B {{count}} \u7EC4",acceptWarnings:"\u6211\u5DF2\u786E\u8BA4\u5FFD\u7565\u5F53\u524D\u8B66\u544A\uFF0C\u5E76\u5141\u8BB8\u540C\u6B65",warning:{missingAnswer:"\u7B2C {{index}} \u7EC4\u7F3A\u5C11\u7B54\u6848\u5B57\u6BB5\uFF0C\u5DF2\u5FFD\u7565 {{questionField}} / {{answerField}}\u3002",missingQuestion:"\u7B2C {{index}} \u7EC4\u7F3A\u5C11\u95EE\u9898\u5B57\u6BB5\uFF0C\u5DF2\u5FFD\u7565 {{questionField}} / {{answerField}}\u3002"}},rows:{basic:"\u95EE\u7B54\u9898\uFF08\u5E38\u89C4\u6BB5\u843D\u5F62\u5F0F\uFF09",qaGroup:"\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\u5F62\u5F0F\uFF09",cloze:"\u586B\u7A7A\u9898",semanticQa:"\u8BED\u4E49\u95EE\u7B54\u9898"}},syncContent:{title:"\u5361\u7247\u6B63\u6587\u540C\u6B65\u5185\u5BB9",desc:"\u8FD9\u4E9B\u9009\u9879\u53EA\u5F71\u54CD\u5361\u7247\u6E32\u67D3\u5185\u5BB9\uFF0C\u4FEE\u6539\u540E\u4EC5\u5237\u65B0\u8FD9\u4E00\u5F20\u5361\u7247\u3002",sections:{bodyRange:"1. \u786E\u5B9A\u300C\u5361\u7247\u6B63\u6587\u300D\u8303\u56F4",backlink:"2. \u786E\u5B9A\u662F\u5426\u589E\u52A0\u56DE\u94FE\uFF0C\u65B9\u4FBF\u4ECE Anki\u300C\u5361\u7247\u7EA7\u8DF3\u8F6C\u300D\u56DE Obsidian",tags:"3. \u786E\u5B9A\u662F\u5426\u8BFB\u53D6\u300C\u6807\u7B7E\u300D",clozeSpecial:"4. \u300C\u586B\u7A7A\u9898\u300D\u4E13\u9879"}},scope:{title:"\u63D2\u4EF6\u8FD0\u884C\u8303\u56F4",desc:"\u4FDD\u7559\u73B0\u6709\u4F5C\u7528\u8303\u56F4\u548C\u6587\u4EF6\u5939\u6811\u903B\u8F91\uFF1B\u6587\u4EF6\u5939\u6811\u6309\u9700\u52A0\u8F7D\uFF0C\u5E76\u652F\u6301\u5C40\u90E8\u5237\u65B0\u3002",refreshFolders:"\u5237\u65B0\u6587\u4EF6\u5939\u5217\u8868"},deck:{title:"\u5361\u7247\u724C\u7EC4\u8BBE\u7F6E",desc:"\u5361\u7247\u724C\u7EC4\u8BBE\u7F6E\u6309\u63A8\u8350\u8DEF\u5F84\u5206\u7EC4\u5C55\u793A\u3002",sections:{folderMapping:"1\uFF0C\u63A8\u8350\u7528\u300C\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u300D\u4F5C\u4E3A\u300CAnki\u724C\u7EC4\u300D",fileDeck:"2\uFF0C\u53EF\u6253\u5F00\u300C\u6587\u4EF6\u7EA7\u81EA\u5B9A\u4E49\u724C\u7EC4\u300D\uFF0C\u4F5C\u4E3A\u4E2A\u6027\u5316\u5B9A\u5236",defaultDeck:"3\uFF0C\u9ED8\u8BA4\u724C\u7EC4\u4F5C\u4E3A\u515C\u5E95"}},commands:{title:"\u547D\u4EE4\u8BF4\u660E",desc:"\u4E0B\u9762\u5C55\u793A\u5F53\u524D\u547D\u4EE4\u9762\u677F\u4E2D\u53EF\u7528\u7684\u63D2\u4EF6\u547D\u4EE4\u3002",items:{syncCurrentFile:"\u53EA\u628A\u5F53\u524D\u6D3B\u52A8 Markdown \u6587\u4EF6\u540C\u6B65\u5230 Anki\u3002",syncVault:"\u628A\u5168\u5E93\u4E2D\u6240\u6709\u5904\u4E8E\u4F5C\u7528\u8303\u56F4\u5185\u7684 Markdown \u6587\u4EF6\u540C\u6B65\u5230 Anki\u3002",rebuildIndex:"\u53EA\u91CD\u5EFA\u672C\u5730\u5361\u7247\u7D22\u5F15\uFF0C\u4E0D\u521B\u5EFA\u6216\u66F4\u65B0\u8FDC\u7AEF\u7B14\u8BB0\u3002",clearCurrentFile:"\u6E05\u7A7A\u5F53\u524D\u6587\u4EF6\u7684\u5DF2\u540C\u6B65\u6807\u8BB0\u548C\u672C\u5730\u8DDF\u8E2A\u72B6\u6001\u3002",cleanupDecks:"\u4ECE Anki \u5220\u9664\u6240\u9009\u7A7A\u724C\u7EC4\u3002"}}}},modal:{emptyDeck:{title:"\u6E05\u7406\u7A7A\u724C\u7EC4",description:"\u52FE\u9009\u8981\u5220\u9664\u7684\u7A7A\u724C\u7EC4\u3002\u53EA\u6709\u5220\u9664\u65F6\u4ECD\u4E3A\u7A7A\u7684\u724C\u7EC4\u4F1A\u88AB\u771F\u6B63\u5220\u9664\u3002",selectAll:"\u5168\u9009\u5168\u90E8",clearAll:"\u5168\u90E8\u4E0D\u9009",invert:"\u53CD\u9009",cancel:"\u53D6\u6D88",deleteSelected:"\u5220\u9664\u6240\u9009\u7A7A\u724C\u7EC4",selectionCount:"\u5DF2\u9009 {{selected}} / \u5171 {{total}} \u4E2A\u7A7A\u724C\u7EC4"}},notice:{invalidSettingsRestored:"\u68C0\u6D4B\u5230\u65E0\u6548\u7684\u63D2\u4EF6\u8BBE\u7F6E\uFF0C\u5DF2\u5728\u5185\u5B58\u4E2D\u6062\u590D\u9ED8\u8BA4\u8BBE\u7F6E\u3002",failedSavePluginSettings:"\u4FDD\u5B58\u63D2\u4EF6\u8BBE\u7F6E\u5931\u8D25\u3002",noActiveMarkdownForSync:"\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u4E8E\u540C\u6B65\u7684\u6D3B\u52A8 Markdown \u6587\u4EF6\u3002",syncUseCaseNotInitialized:"\u540C\u6B65\u7528\u4F8B\u5C1A\u672A\u521D\u59CB\u5316\u3002",currentFileSyncFailed:"\u5F53\u524D\u6587\u4EF6\u540C\u6B65\u5931\u8D25\u3002",vaultSyncFailed:"\u5168\u5E93\u540C\u6B65\u5931\u8D25\u3002",rebuildFailed:"\u5361\u7247\u7D22\u5F15\u91CD\u5EFA\u5931\u8D25\u3002",noActiveMarkdownForDeckTemplateInsertion:"\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u4E8E\u63D2\u5165\u724C\u7EC4\u6A21\u677F\u7684\u6D3B\u52A8 Markdown \u6587\u4EF6\u3002",vaultGatewayNotInitialized:"Vault \u7F51\u5173\u5C1A\u672A\u521D\u59CB\u5316\u3002",markdownFileNotFound:"\u672A\u627E\u5230 Markdown \u6587\u4EF6\uFF1A{{filePath}}",deckTemplateAlreadyCurrent:"\u5F53\u524D\u6587\u4EF6\u4E2D\u7684\u724C\u7EC4\u6A21\u677F\u5DF2\u662F\u6700\u65B0\uFF0C\u65E0\u9700\u91CD\u590D\u5199\u5165\u3002",deckTemplateInserted:"\u5DF2\u5411\u5F53\u524D\u6587\u4EF6\u5199\u5165\u724C\u7EC4\u6A21\u677F\uFF1A{{deck}}",deckTemplateInsertionFailed:"\u63D2\u5165\u724C\u7EC4\u6A21\u677F\u5931\u8D25\u3002",noActiveMarkdownForReset:"\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u4E8E\u91CD\u7F6E\u7684\u6D3B\u52A8 Markdown \u6587\u4EF6\u3002",clearCurrentFileUseCaseNotInitialized:"\u6E05\u7A7A\u5F53\u524D\u6587\u4EF6\u7528\u4F8B\u5C1A\u672A\u521D\u59CB\u5316\u3002",noTrackedCardsInCurrentFile:"\u5F53\u524D\u6587\u4EF6\u6CA1\u6709\u5DF2\u540C\u6B65\u5361\u7247\u3002",clearCurrentFileFailed:"\u6E05\u7A7A\u5F53\u524D\u6587\u4EF6\u5DF2\u540C\u6B65\u5361\u7247\u5931\u8D25\u3002",cleanupEmptyDecksUseCaseNotInitialized:"\u7A7A\u724C\u7EC4\u6E05\u7406\u7528\u4F8B\u5C1A\u672A\u521D\u59CB\u5316\u3002",noEmptyDeckCandidates:"\u672A\u53D1\u73B0\u53EF\u6E05\u7406\u7684\u7A7A\u724C\u7EC4\u3002",cleanupEmptyDecksCancelled:"\u5DF2\u53D6\u6D88\u7A7A\u724C\u7EC4\u6E05\u7406\u3002",cleanupEmptyDecksFailed:"\u6E05\u7406\u7A7A\u724C\u7EC4\u5931\u8D25\u3002",summary:{currentFileSync:"\u5F53\u524D\u6587\u4EF6\u540C\u6B65\u5B8C\u6210\uFF1A\u6587\u4EF6 {{scannedFiles}}\uFF0C\u5361\u7247 {{scannedCards}}\uFF0C\u65B0\u5EFA {{created}}\uFF0C\u66F4\u65B0 {{updated}}\uFF0C\u8FC1\u79FB\u6A21\u677F {{migratedNoteTypes}}\uFF0C\u8FC1\u79FB\u724C\u7EC4 {{migratedDecks}}\uFF0C\u5B64\u513F {{orphaned}}\uFF0C\u5A92\u4F53 {{uploadedMedia}}\uFF0C\u8DF3\u8FC7 {{skippedUnchangedCards}}\u3002",vaultSync:"\u5168\u5E93\u540C\u6B65\u5B8C\u6210\uFF1A\u6587\u4EF6 {{scannedFiles}}\uFF0C\u5361\u7247 {{scannedCards}}\uFF0C\u65B0\u5EFA {{created}}\uFF0C\u66F4\u65B0 {{updated}}\uFF0C\u8FC1\u79FB\u6A21\u677F {{migratedNoteTypes}}\uFF0C\u8FC1\u79FB\u724C\u7EC4 {{migratedDecks}}\uFF0C\u5B64\u513F {{orphaned}}\uFF0C\u5A92\u4F53 {{uploadedMedia}}\uFF0C\u8DF3\u8FC7 {{skippedUnchangedCards}}\u3002",rebuild:"\u5361\u7247\u7D22\u5F15\u91CD\u5EFA\u5B8C\u6210\uFF1A\u6587\u4EF6 {{scannedFiles}}\uFF0C\u5361\u7247 {{scannedCards}}\uFF0C\u8FC1\u79FB\u724C\u7EC4 {{migratedDecks}}\uFF0C\u5B64\u513F {{orphaned}}\uFF0C\u91CD\u5199\u6807\u8BB0 {{rewrittenMarkers}}\uFF0C\u8DF3\u8FC7 {{skippedUnchangedCards}}\u3002",clearCurrentFile:"\u5F53\u524D\u6587\u4EF6\u5DF2\u540C\u6B65\u5361\u7247\u6E05\u7A7A\u5B8C\u6210\uFF1A\u5DF2\u8DDF\u8E2A\u5361\u7247 {{trackedCards}}\uFF0C\u5DF2\u8DDF\u8E2A\u5206\u7EC4 {{trackedGroups}}\uFF0C\u5220\u9664\u7B14\u8BB0 {{deletedNotes}}\uFF0C\u79FB\u9664\u6807\u8BB0 {{removedMarkers}}\uFF0C\u79FB\u9664 ID \u6807\u8BB0 {{removedCardMarkers}}\uFF0C\u79FB\u9664 GI \u6807\u8BB0 {{removedGroupMarkers}}\uFF0C\u5220\u9664\u672C\u5730\u8BB0\u5F55 {{deletedLocalRecords}}\u3002",cleanupEmptyDecks:"\u7A7A\u724C\u7EC4\u6E05\u7406\u5B8C\u6210\uFF1A\u5019\u9009 {{candidateCount}}\uFF0C\u5DF2\u9009 {{selectedCount}}\uFF0C\u5DF2\u5220 {{deletedCount}}\uFF0C\u8DF3\u8FC7 {{skippedCount}}\u3002",markerWriteConflicts:"\u6807\u8BB0\u5199\u56DE\u51B2\u7A81\uFF1A{{files}}\u3002",warningsCount:"\u8B66\u544A\uFF1A{{count}}\u3002",markerRemovalConflicts:"\u6807\u8BB0\u79FB\u9664\u51B2\u7A81\uFF1A{{files}}\u3002",failures:"\u5931\u8D25\u9879\uFF1A{{items}}\u3002",skippedDecks:"\u8DF3\u8FC7\u7684\u724C\u7EC4\uFF1A{{decks}}\u3002"}},errors:{currentFileOutOfScope:"\u5F53\u524D\u6587\u4EF6\u4E0D\u5728\u63D2\u4EF6\u4F5C\u7528\u8303\u56F4\u5185\uFF1A{{filePath}}",deck:{emptyName:"\u724C\u7EC4\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u7EA7\u724C\u7EC4\u58F0\u660E\u6216\u9ED8\u8BA4\u724C\u7EC4\u8BBE\u7F6E\u3002"},settings:{headingLevelsRange:"\u6807\u9898\u5C42\u7EA7\u5FC5\u987B\u662F 1 \u5230 6 \u4E4B\u95F4\u7684\u6574\u6570\u3002",headingLevelsDifferent:"QA \u548C\u586B\u7A7A\u9898\u7684\u6807\u9898\u5C42\u7EA7\u5FC5\u987B\u4E0D\u540C\u3002",cardTypeConfigsObject:"\u5361\u7247\u7C7B\u578B\u914D\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",cardTypeEnabledBoolean:"\u6BCF\u79CD\u5361\u7247\u7C7B\u578B\u7684\u542F\u7528\u72B6\u6001\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002",cardTypeExtraMarkerString:"\u6BCF\u79CD\u5361\u7247\u7C7B\u578B\u7684\u989D\u5916\u6807\u8BB0\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",cardTypeDefaultConflict:"\u540C\u4E00\u4E2A H{{headingLevel}} \u53EA\u80FD\u6709\u4E00\u4E2A\u542F\u7528\u7684\u9ED8\u8BA4\u5361\u7247\u7C7B\u578B\u3002",cardAnswerCutoffModeInvalid:"\u5361\u7247\u6B63\u6587\u622A\u6B62\u6A21\u5F0F\u53EA\u80FD\u662F heading-block \u6216 double-blank-lines\u3002",qaNoteTypeRequired:"QA \u7B14\u8BB0\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u3002",qaGroupMarkerRequired:"QA Group \u6807\u8BB0\u4E0D\u80FD\u4E3A\u7A7A\u3002",qaGroupMarkerInvalid:"QA Group \u6807\u8BB0\u5FC5\u987B\u662F\u7C7B\u4F3C #anki-list \u7684 hashtag \u6837\u5F0F token\u3002",clozeNoteTypeRequired:"\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u3002",semanticQaMarkerRequired:"\u8BED\u4E49 QA \u6807\u8BB0\u4E0D\u80FD\u4E3A\u7A7A\u3002",semanticQaMarkerInvalid:"\u8BED\u4E49 QA \u6807\u8BB0\u5FC5\u987B\u662F\u7C7B\u4F3C #anki-list-qa \u7684 hashtag \u6837\u5F0F token\u3002",qaGroupMarkerConflict:"QA Group \u6807\u8BB0\u5FC5\u987B\u548C\u8BED\u4E49 QA \u6807\u8BB0\u4E0D\u540C\u3002",semanticQaNoteTypeRequired:"\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u3002",defaultDeckRequired:"\u9ED8\u8BA4\u724C\u7EC4\u4E0D\u80FD\u4E3A\u7A7A\u3002",fileDeckEnabledBoolean:"\u6587\u4EF6\u7EA7\u724C\u7EC4\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002",syncObsidianTagsToAnkiBoolean:"\u540C\u6B65 Obsidian \u6807\u7B7E\u5230 Anki \u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002",keepPureTagLinesInCardBodyBoolean:"\u4FDD\u7559\u6B63\u6587\u7EAF\u6807\u7B7E\u884C\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002",fileDeckMarkerString:"\u6587\u4EF6\u7EA7\u724C\u7EC4\u8BC6\u522B\u540D\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",fileDeckTemplateString:"\u6587\u4EF6\u7EA7\u724C\u7EC4\u6A21\u677F\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",fileDeckInsertLocationInvalid:"\u6587\u4EF6\u7EA7\u724C\u7EC4\u6A21\u677F\u63D2\u5165\u4F4D\u7F6E\u53EA\u80FD\u662F yaml \u6216 body\u3002",folderDeckModeInvalid:"\u6587\u4EF6\u5939\u724C\u7EC4\u6A21\u5F0F\u53EA\u80FD\u662F off\u3001folder \u6216 folder-and-file\u3002",scopeModeInvalid:"\u8FD0\u884C\u8303\u56F4\u6A21\u5F0F\u53EA\u80FD\u662F all\u3001include \u6216 exclude\u3002",obsidianBacklinkPlacementInvalid:"Obsidian \u56DE\u94FE\u653E\u7F6E\u4F4D\u7F6E\u53EA\u80FD\u662F question-last-line\u3001answer-first-line \u6216 answer-last-line\u3002",includeFoldersArray:"\u5305\u542B\u6587\u4EF6\u5939\u5FC5\u987B\u662F\u6570\u7EC4\u3002",includeFoldersStrings:"\u5305\u542B\u6587\u4EF6\u5939\u5217\u8868\u4E2D\u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",excludeFoldersArray:"\u6392\u9664\u6587\u4EF6\u5939\u5FC5\u987B\u662F\u6570\u7EC4\u3002",excludeFoldersStrings:"\u6392\u9664\u6587\u4EF6\u5939\u5217\u8868\u4E2D\u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",ankiConnectUrlRequired:"AnkiConnect URL \u4E0D\u80FD\u4E3A\u7A7A\u3002",ankiNoteTypeCacheArray:"Anki \u7B14\u8BB0\u6A21\u677F\u7F13\u5B58\u5FC5\u987B\u662F\u6570\u7EC4\u3002",ankiNoteTypeCacheStrings:"Anki \u7B14\u8BB0\u6A21\u677F\u7F13\u5B58\u4E2D\u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",ankiModelFieldCacheObject:"Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",ankiModelFieldCacheEntryObject:"\u6BCF\u4E2A Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u9879\u90FD\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",ankiModelFieldCacheFieldNamesArray:"Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u4E2D\u7684 fieldNames \u5FC5\u987B\u662F\u6570\u7EC4\u3002",ankiModelFieldCacheFieldNamesStrings:"Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u4E2D\u7684 fieldNames \u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",ankiModelFieldCacheLoadedAt:"Anki \u6A21\u677F\u5B57\u6BB5\u7F13\u5B58\u4E2D\u7684 loadedAt \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u3002",noteFieldMappingsObject:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",noteFieldMappingsCardType:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u4F7F\u7528\u53D7\u652F\u6301\u7684\u5361\u7247\u7C7B\u578B\u3002",noteFieldMappingsModelName:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u5305\u542B\u6A21\u578B\u540D\u79F0\u3002",noteFieldMappingsLoadedFieldNames:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u5305\u542B\u5DF2\u52A0\u8F7D\u5B57\u6BB5\u540D\u3002",noteFieldMappingsLoadedAt:"\u5B57\u6BB5\u6620\u5C04\u5FC5\u987B\u5305\u542B\u5DF2\u52A0\u8F7D\u65F6\u95F4\u6233\u3002",noteFieldMappingsQaGroupSlotsArray:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 slots \u5FC5\u987B\u662F\u6570\u7EC4\u3002",noteFieldMappingsQaGroupSlotObject:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684\u6BCF\u4E2A slot \u90FD\u5FC5\u987B\u662F\u5BF9\u8C61\u3002",noteFieldMappingsQaGroupSlotIndex:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 slot.index \u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570\u3002",noteFieldMappingsQaGroupSlotQuestionField:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 slot.questionField \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",noteFieldMappingsQaGroupSlotAnswerField:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 slot.answerField \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",noteFieldMappingsQaGroupWarningsArray:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 warnings \u5FC5\u987B\u662F\u6570\u7EC4\u3002",noteFieldMappingsQaGroupWarningsStrings:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 warnings \u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002",noteFieldMappingsQaGroupAcceptedWarningsArray:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 acceptedWarnings \u5FC5\u987B\u662F\u6570\u7EC4\u3002",noteFieldMappingsQaGroupAcceptedWarningsStrings:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 acceptedWarnings \u53EA\u80FD\u5305\u542B\u5B57\u7B26\u4E32\u3002"},noteFieldMapping:{noteTypeNotSelected:{basic:"\u57FA\u7840\u5361\u5C1A\u672A\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u9009\u62E9\u6A21\u677F\u540E\u518D\u540C\u6B65\u3002",cloze:"\u586B\u7A7A\u9898\u5C1A\u672A\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u9009\u62E9\u6A21\u677F\u540E\u518D\u540C\u6B65\u3002",semanticQa:"\u8BED\u4E49 QA \u5C1A\u672A\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u9009\u62E9\u6A21\u677F\u540E\u518D\u540C\u6B65\u3002",qaGroup:"\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u5C1A\u672A\u9009\u62E9 Anki \u7B14\u8BB0\u6A21\u677F\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u9009\u62E9\u6A21\u677F\u540E\u518D\u540C\u6B65\u3002"},missingSavedMapping:{basic:'\u627E\u4E0D\u5230\u57FA\u7840\u5361\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002',cloze:'\u627E\u4E0D\u5230\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002',semanticQa:'\u627E\u4E0D\u5230\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u5148\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002',qaGroup:'\u627E\u4E0D\u5230\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u5E76\u4FDD\u5B58\u6620\u5C04\u3002'},incompleteSavedMapping:{basic:'\u57FA\u7840\u5361\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u4E0D\u5B8C\u6574\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u4FDD\u5B58\u6807\u9898\u5B57\u6BB5\u548C\u6B63\u6587\u5B57\u6BB5\u3002',semanticQa:'\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u4E0D\u5B8C\u6574\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u4FDD\u5B58\u6807\u9898\u5B57\u6BB5\u548C\u6B63\u6587\u5B57\u6BB5\u3002',cloze:'\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u4E0D\u5B8C\u6574\u3002\u8BF7\u6253\u5F00\u63D2\u4EF6\u8BBE\u7F6E\u5E76\u4FDD\u5B58\u4E3B\u5B57\u6BB5\u3002'},titleBodyMustDiffer:{basic:'\u57FA\u7840\u5361\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u6807\u9898\u5B57\u6BB5\u548C\u6B63\u6587\u5B57\u6BB5\u5FC5\u987B\u4E0D\u540C\u3002',semanticQa:'\u8BED\u4E49 QA \u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u6807\u9898\u5B57\u6BB5\u548C\u6B63\u6587\u5B57\u6BB5\u5FC5\u987B\u4E0D\u540C\u3002'},stale:'\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u5DF2\u8FC7\u671F\uFF0C\u56E0\u4E3A\u8FD9\u4E9B\u5B57\u6BB5\u5728 Anki \u4E2D\u5DF2\u4E0D\u5B58\u5728\uFF1A{{fields}}\u3002\u8BF7\u91CD\u65B0\u4ECE Anki \u8BFB\u53D6\u5B57\u6BB5\u3002',clozeIncompatible:'\u586B\u7A7A\u9898\u7B14\u8BB0\u7C7B\u578B "{{modelName}}" \u5728 Anki \u4E2D\u4E0D\u662F\u586B\u7A7A\u9898\u517C\u5BB9\u6A21\u578B\u3002',qaGroupMissingTitle:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11\u6807\u9898\u5B57\u6BB5\u3002\u8BF7\u5728\u8BBE\u7F6E\u9875\u91CD\u65B0\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002',qaGroupNoCompleteSlots:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u4E0D\u5B8C\u6574\uFF0C\u81F3\u5C11\u9700\u8981\u4E00\u7EC4\u95EE\u9898/\u7B54\u6848\u5B57\u6BB5\u3002\u8BF7\u5728\u8BBE\u7F6E\u9875\u91CD\u65B0\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u3002',qaGroupNonContinuousSlots:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u7B2C\u4E00\u7EC4\u95EE\u9898/\u7B54\u6848\u5B57\u6BB5\u4E0D\u662F\u4ECE\u7B2C {{firstIndex}} \u7EC4\u5F00\u59CB\u8FDE\u7EED\u7F16\u53F7\u3002\u8BF7\u4ECE\u7B2C 1 \u7EC4\u5F00\u59CB\u3002',qaGroupWarningsUnaccepted:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u4ECD\u6709\u672A\u786E\u8BA4\u7684\u5B57\u6BB5\u8B66\u544A\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u9875\u786E\u8BA4\u540E\u518D\u540C\u6B65\u3002',qaGroupSlotCapacityExceeded:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u5DF2\u4FDD\u5B58\u5B57\u6BB5\u6620\u5C04\u53EA\u5305\u542B {{capacity}} \u7EC4\u95EE\u9898/\u7B54\u6848\u5B57\u6BB5\uFF0C\u4F46\u5F53\u524D\u5757\u6709 {{itemCount}} \u9879\uFF1A{{filePath}}:{{blockStartLine}}\u3002'},noteTypeMigration:{failed:"\u65E0\u6CD5\u5C06 Anki \u7B14\u8BB0 {{noteId}} \u4ECE\u201C{{fromModel}}\u201D\u8FC1\u79FB\u5230\u201C{{toModel}}\u201D{{location}}\uFF1A{{reason}}",unsupported:"\u5F53\u524D AnkiConnect \u4E0D\u652F\u6301\u5C06 Anki \u7B14\u8BB0 {{noteId}} \u4ECE\u201C{{fromModel}}\u201D\u8FC1\u79FB\u5230\u201C{{toModel}}\u201D{{location}}\u3002\u8BF7\u5347\u7EA7 AnkiConnect\uFF0C\u6216\u6E05\u7406\u8BE5\u5361\u7247\u7684 Anki ID \u540E\u91CD\u65B0\u540C\u6B65\u3002\u539F\u56E0\uFF1A{{reason}}"},writeBack:{summary:"Markdown \u6807\u8BB0\u5199\u56DE\u5931\u8D25\uFF0C\u5171 {{fileCount}} \u4E2A\u6587\u4EF6\u3002",markdownFileNotFound:"Markdown \u6587\u4EF6\u4E0D\u5B58\u5728\u3002",missingSourceContent:"\u7F3A\u5C11\u7528\u4E8E\u5199\u56DE\u6807\u8BB0\u7684\u626B\u63CF\u6E90\u7801\u5185\u5BB9\u3002",noteIdMissing:"\u65E0\u6CD5\u4E3A\u7B2C {{blockStartLine}} \u884C\u6240\u5728\u5757\u5199\u5165\u6807\u8BB0\uFF0C\u56E0\u4E3A\u7F3A\u5C11 note ID\u3002"},markerRemoval:{markdownFileNotFound:"Markdown \u6587\u4EF6\u4E0D\u5B58\u5728\u3002"}},warnings:{deck:{conflictYamlBody:"\u68C0\u6D4B\u5230 YAML \u548C\u6B63\u6587\u4E2D\u7684 {{marker}} \u58F0\u660E\u4E92\u76F8\u51B2\u7A81\uFF0C\u672C\u6B21\u540C\u6B65\u5DF2\u4F7F\u7528 YAML \u7684\u503C\u3002",multipleBodyDeclarations:"\u68C0\u6D4B\u5230\u6587\u4EF6\u4E2D\u5B58\u5728\u591A\u4E2A {{marker}} \u58F0\u660E\uFF0C\u672C\u6B21\u540C\u6B65\u53EA\u4F7F\u7528\u7B2C\u4E00\u4E2A\u6B63\u6587\u58F0\u660E\u3002",invalidFolderSegment:"\u68C0\u6D4B\u5230\u6587\u4EF6\u5939\u540D\u6216\u6587\u4EF6\u540D\u5305\u542B ::\uFF0C\u5DF2\u8DF3\u8FC7\u6587\u4EF6\u5939\u6620\u5C04\u5E76\u56DE\u9000\u5230\u9ED8\u8BA4\u724C\u7EC4\u3002",fallbackDefault:"\u8BE5\u6587\u4EF6\u6CA1\u6709\u663E\u5F0F\u724C\u7EC4\uFF0C\u4E14\u65E0\u6CD5\u751F\u6210\u6587\u4EF6\u5939\u6620\u5C04\u724C\u7EC4\uFF0C\u5DF2\u56DE\u9000\u5230\u9ED8\u8BA4\u724C\u7EC4\u3002"}}};function Yr(e,t){let n=t.split("."),r=e;for(let i of n){if(!r||typeof r!="object"||!(i in r))return;r=r[i]}return typeof r=="string"?r:void 0}function xo(e,t,n){return t?e.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(r,i)=>{let a=t[i];return a===void 0?"":Array.isArray(a)?ae(n,a.filter(o=>o!==void 0).map(o=>String(o))):String(a)}):e}function m(e,t){let n=ie(),i=Yr(n==="zh"?Zr:Fn,e)??Yr(Fn,e)??e;return xo(i,t,n)}var C=class extends Error{constructor(t,n,r){super(t),this.name="PluginUserError",this.userMessage={key:t,params:n},this.details=r}};function vn(e){return e instanceof C}function Te(e){return"rawMessage"in e?e.rawMessage:m(e.key,e.params)}function Xr(e){return"rawMessage"in e?e.rawMessage:m(e.key,e.params)}function Tn(e){let t=Te(e.userMessage);if(!e.details?.failures?.length)return t;let n=e.details.failures.map(r=>`${r.filePath}: ${Xr(r)}`).join(` `);return`${t} -${n}`}function Ae(e,t,n){return wn(e)?e.userMessage:e instanceof Error?{rawMessage:e.message}:{key:t,params:n}}function le(e,t){return wn(e)?vn(e):Te(Ae(e,t))}function ot(e,t){return wn(t)?{filePath:e,...t.userMessage}:t instanceof Error?{filePath:e,rawMessage:t.message}:{filePath:e,rawMessage:String(t)}}function Zr(e){let t=ie();return ae(t,e.map(n=>`${n.filePath} (${Kr(n)})`))}var yo=["\u9898\u76EE","\u6807\u9898","\u6B63\u9762","Stem","Title"],xo=[/^问题0*(\d+)$/i,/^Q0*(\d+)$/i,/^S0*(\d+)_Q$/i],So=[/^答案0*(\d+)$/i,/^A0*(\d+)$/i,/^S0*(\d+)_A$/i],pe=class{suggest(t,n,r=Date.now(),i,a){let o=a&&n.includes(a)?a:Mo(n,yo),u=Co(n,t);return{cardType:"qa-group",modelName:t,loadedFieldNames:[...n],titleField:o,slots:u.slots,warnings:u.warnings,acceptedWarnings:u.warnings.length>0&&ut(u.warnings,i)?[...u.warnings]:void 0,loadedAt:r}}validateMapping(t,n){if(!t.titleField)throw new C("errors.noteFieldMapping.qaGroupMissingTitle",{modelName:t.modelName});if(t.slots.length===0)throw new C("errors.noteFieldMapping.qaGroupNoCompleteSlots",{modelName:t.modelName});let r=new Set(n),i=new Set;r.has(t.titleField)||i.add(t.titleField);for(let a of t.slots)r.has(a.questionField)||i.add(a.questionField),r.has(a.answerField)||i.add(a.answerField);if(i.size>0)throw new C("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:[...i].map(a=>`"${a}"`)})}validateWarningsAccepted(t){if(!(!t.warnings.length||ut(t.warnings,t.acceptedWarnings)))throw new C("errors.noteFieldMapping.qaGroupWarningsUnaccepted",{modelName:t.modelName})}};function ut(e,t){return e.length===0?!0:!t||e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function Jr(e){try{let t=JSON.parse(e);return t.kind!=="missing-answer"&&t.kind!=="missing-question"||typeof t.index!="number"||!Number.isInteger(t.index)||t.index<1||typeof t.questionField!="string"||typeof t.answerField!="string"?void 0:{kind:t.kind,index:t.index,questionField:t.questionField,answerField:t.answerField}}catch{return}}function Co(e,t){let n=new Map,r=new Map;for(let u of e){let s=Yr(u,xo);if(s&&!n.has(s)){n.set(s,u);continue}let c=Yr(u,So);c&&!r.has(c)&&r.set(c,u)}let i=[...new Set([...n.keys(),...r.keys()])].sort((u,s)=>u-s);if(i.length>0&&i[0]!==1)throw new C("errors.noteFieldMapping.qaGroupNonContinuousSlots",{modelName:t,firstIndex:i[0]});let a=[],o=[];for(let u of i){let s=n.get(u),c=r.get(u);if(!s||!c){o.push(wo({kind:s?"missing-answer":"missing-question",index:u,questionField:s??Xr("question",u),answerField:c??Xr("answer",u)}));continue}if(u!==a.length+1)break;a.push({index:u,questionField:s,answerField:c})}if(a.length===0)throw new C("errors.noteFieldMapping.qaGroupNoCompleteSlots",{modelName:t});return{slots:a,warnings:o}}function Yr(e,t){for(let n of t){let r=e.match(n);if(!r)continue;let i=Number.parseInt(r[1]??"",10);if(Number.isInteger(i)&&i>0)return i}}function Mo(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function wo(e){return JSON.stringify(e)}function Xr(e,t){return`${e==="question"?"\u95EE\u9898":"\u7B54\u6848"}${String(t).padStart(2,"0")}`}var ii=["basic","qa-group","cloze","semantic-qa"],Qe="Open in Obsidian",st=4,ei=5,ct=4,ai="",oi="",vo="",Fn="#anki-cloze",ui="Semantic QA",si="#anki-list",ci="#anki-list-qa",Fo=new pe,P={qaHeadingLevel:st,clozeHeadingLevel:ct,cardAnswerCutoffMode:"heading-block",qaGroupMarker:si,qaNoteType:ai,clozeNoteType:oi,semanticQaMarker:ci,semanticQaNoteType:ui,cardTypeConfigs:li(),noteFieldMappings:{},ankiNoteTypeCache:[],ankiModelFieldCache:{},defaultDeck:"Obsidian",fileDeckEnabled:!1,fileDeckMarker:"TARGET DECK",fileDeckTemplate:"obsidian::filename",fileDeckInsertLocation:"body",folderDeckMode:"folder-and-file",scopeMode:"all",includeFolders:[],excludeFolders:[],addObsidianBacklink:!0,obsidianBacklinkLabel:Qe,obsidianBacklinkPlacement:"answer-last-line",convertHighlightsToCloze:!0,syncObsidianTagsToAnki:!0,keepPureTagLinesInCardBody:!0,ankiConnectUrl:"http://127.0.0.1:8765"};function To(e){if(typeof e!="string")return Qe;let t=e.trim();return t.length>0?t:Qe}function ke(e){let t=pi(e.cardTypeConfigs,e),n=Po(t);return{...e,...n,cardTypeConfigs:t,noteFieldMappings:fi(e.noteFieldMappings),ankiNoteTypeCache:Bo(e.ankiNoteTypeCache),ankiModelFieldCache:Go(e.ankiModelFieldCache),obsidianBacklinkLabel:To(e.obsidianBacklinkLabel)}}function di(e){let t=e??{},n=pi(t.cardTypeConfigs,t);return ke({...P,...t,cardTypeConfigs:n,noteFieldMappings:fi(t.noteFieldMappings??P.noteFieldMappings),ankiModelFieldCache:t.ankiModelFieldCache??P.ankiModelFieldCache,includeFolders:t.includeFolders??P.includeFolders,excludeFolders:t.excludeFolders??P.excludeFolders})}function oe(e){if(Eo(e.cardTypeConfigs),e.cardAnswerCutoffMode!=="heading-block"&&e.cardAnswerCutoffMode!=="double-blank-lines")throw new C("errors.settings.cardAnswerCutoffModeInvalid");if(_o(e.noteFieldMappings),Ao(e.ankiNoteTypeCache),Do(e.ankiModelFieldCache),!e.defaultDeck.trim())throw new C("errors.settings.defaultDeckRequired");if(typeof e.fileDeckEnabled!="boolean")throw new C("errors.settings.fileDeckEnabledBoolean");if(typeof e.syncObsidianTagsToAnki!="boolean")throw new C("errors.settings.syncObsidianTagsToAnkiBoolean");if(typeof e.keepPureTagLinesInCardBody!="boolean")throw new C("errors.settings.keepPureTagLinesInCardBodyBoolean");if(typeof e.fileDeckMarker!="string")throw new C("errors.settings.fileDeckMarkerString");if(typeof e.fileDeckTemplate!="string")throw new C("errors.settings.fileDeckTemplateString");if(e.fileDeckInsertLocation!=="yaml"&&e.fileDeckInsertLocation!=="body")throw new C("errors.settings.fileDeckInsertLocationInvalid");if(e.folderDeckMode!=="off"&&e.folderDeckMode!=="folder"&&e.folderDeckMode!=="folder-and-file")throw new C("errors.settings.folderDeckModeInvalid");if(e.scopeMode!=="all"&&e.scopeMode!=="include"&&e.scopeMode!=="exclude")throw new C("errors.settings.scopeModeInvalid");if(e.obsidianBacklinkPlacement!=="question-last-line"&&e.obsidianBacklinkPlacement!=="answer-first-line"&&e.obsidianBacklinkPlacement!=="answer-last-line")throw new C("errors.settings.obsidianBacklinkPlacementInvalid");if(ti(e.includeFolders,"include"),ti(e.excludeFolders,"exclude"),!e.ankiConnectUrl.trim())throw new C("errors.settings.ankiConnectUrlRequired")}function Ao(e){if(!Array.isArray(e))throw new C("errors.settings.ankiNoteTypeCacheArray");for(let t of e)if(typeof t!="string")throw new C("errors.settings.ankiNoteTypeCacheStrings")}function Do(e){if(!e||typeof e!="object"||Array.isArray(e))throw new C("errors.settings.ankiModelFieldCacheObject");for(let t of Object.values(e)){if(!t||typeof t!="object"||Array.isArray(t))throw new C("errors.settings.ankiModelFieldCacheEntryObject");if(!Array.isArray(t.fieldNames))throw new C("errors.settings.ankiModelFieldCacheFieldNamesArray");for(let n of t.fieldNames)if(typeof n!="string")throw new C("errors.settings.ankiModelFieldCacheFieldNamesStrings");if(!Number.isFinite(t.loadedAt))throw new C("errors.settings.ankiModelFieldCacheLoadedAt")}}function ti(e,t){if(!Array.isArray(e))throw new C(t==="include"?"errors.settings.includeFoldersArray":"errors.settings.excludeFoldersArray");for(let n of e)if(typeof n!="string")throw new C(t==="include"?"errors.settings.includeFoldersStrings":"errors.settings.excludeFoldersStrings")}function Eo(e){if(!e||typeof e!="object"||Array.isArray(e))throw new C("errors.settings.cardTypeConfigsObject");let t=new Map;for(let n of ii){let r=e[n];if(!r||typeof r!="object"||Array.isArray(r))throw new C("errors.settings.cardTypeConfigsObject");if(typeof r.enabled!="boolean")throw new C("errors.settings.cardTypeEnabledBoolean");if(!Number.isInteger(r.headingLevel)||r.headingLevel<1||r.headingLevel>6)throw new C("errors.settings.headingLevelsRange");if(typeof r.extraMarker!="string")throw new C("errors.settings.cardTypeExtraMarkerString");if(n==="semantic-qa"&&!r.noteType.trim())throw new C("errors.settings.semanticQaNoteTypeRequired");if(!r.enabled||r.extraMarker.trim().length>0)continue;let i=t.get(r.headingLevel)??[];i.push(n),t.set(r.headingLevel,i)}for(let[n,r]of t.entries())if(r.length>1)throw new C("errors.settings.cardTypeDefaultConflict",{headingLevel:n})}function _o(e){if(!e||typeof e!="object"||Array.isArray(e))throw new C("errors.settings.noteFieldMappingsObject");for(let t of Object.values(e)){if(t.cardType!=="basic"&&t.cardType!=="qa-group"&&t.cardType!=="cloze"&&t.cardType!=="semantic-qa")throw new C("errors.settings.noteFieldMappingsCardType");if(!t.modelName.trim())throw new C("errors.settings.noteFieldMappingsModelName");if(!Array.isArray(t.loadedFieldNames))throw new C("errors.settings.noteFieldMappingsLoadedFieldNames");if(!Number.isFinite(t.loadedAt))throw new C("errors.settings.noteFieldMappingsLoadedAt");if(B(t)){if(!Array.isArray(t.slots))throw new C("errors.settings.noteFieldMappingsQaGroupSlotsArray");for(let n of t.slots){if(!n||typeof n!="object"||Array.isArray(n))throw new C("errors.settings.noteFieldMappingsQaGroupSlotObject");if(!Number.isInteger(n.index)||n.index<1)throw new C("errors.settings.noteFieldMappingsQaGroupSlotIndex");if(typeof n.questionField!="string")throw new C("errors.settings.noteFieldMappingsQaGroupSlotQuestionField");if(typeof n.answerField!="string")throw new C("errors.settings.noteFieldMappingsQaGroupSlotAnswerField")}ri(t.warnings,"errors.settings.noteFieldMappingsQaGroupWarningsArray","errors.settings.noteFieldMappingsQaGroupWarningsStrings"),ri(t.acceptedWarnings,"errors.settings.noteFieldMappingsQaGroupAcceptedWarningsArray","errors.settings.noteFieldMappingsQaGroupAcceptedWarningsStrings",!0)}}}function li(){return{basic:{enabled:!0,headingLevel:st,extraMarker:"",noteType:ai},"qa-group":{enabled:!0,headingLevel:st,extraMarker:si,noteType:""},cloze:{enabled:!0,headingLevel:ct,extraMarker:Fn,noteType:oi},"semantic-qa":{enabled:!0,headingLevel:st,extraMarker:ci,noteType:ui}}}function Io(e){let t=li();return{basic:{...t.basic,headingLevel:$e(e.qaHeadingLevel,t.basic.headingLevel),noteType:Ue(e.qaNoteType,t.basic.noteType)},"qa-group":{...t["qa-group"],headingLevel:$e(e.qaHeadingLevel,t["qa-group"].headingLevel),extraMarker:Tn(e.qaGroupMarker,t["qa-group"].extraMarker),noteType:Ue(e.cardTypeConfigs?.["qa-group"]?.noteType,t["qa-group"].noteType)},cloze:{...t.cloze,headingLevel:$e(e.clozeHeadingLevel,t.cloze.headingLevel),noteType:Ue(e.clozeNoteType,t.cloze.noteType)},"semantic-qa":{...t["semantic-qa"],headingLevel:$e(e.qaHeadingLevel,t["semantic-qa"].headingLevel),extraMarker:Tn(e.semanticQaMarker,t["semantic-qa"].extraMarker),noteType:Ue(e.semanticQaNoteType,t["semantic-qa"].noteType)}}}function pi(e,t){let n=Io(t),r={};for(let i of ii){let a=e?.[i],o=n[i],u=a&&typeof a=="object"&&!Array.isArray(a)?{...o,...a}:o,s={enabled:typeof u.enabled=="boolean"?u.enabled:o.enabled,headingLevel:$e(u.headingLevel,o.headingLevel),extraMarker:Tn(u.extraMarker,o.extraMarker),noteType:Ue(u.noteType,o.noteType)};r[i]=i==="cloze"?Lo(s,a,t):s}return r}function Lo(e,t,n){return e.headingLevel===ei&&e.extraMarker===vo?{...e,headingLevel:ct,extraMarker:Fn}:!No(t)&&n.clozeHeadingLevel===ei?{...e,headingLevel:ct,extraMarker:Fn}:e}function No(e){return!e||typeof e!="object"||Array.isArray(e)?!1:"headingLevel"in e||"extraMarker"in e}function Po(e){return{qaHeadingLevel:e.basic.headingLevel,clozeHeadingLevel:e.cloze.headingLevel,qaGroupMarker:e["qa-group"].extraMarker,qaNoteType:e.basic.noteType,clozeNoteType:e.cloze.noteType,semanticQaMarker:e["semantic-qa"].extraMarker,semanticQaNoteType:e["semantic-qa"].noteType}}function $e(e,t){return typeof e=="number"&&Number.isInteger(e)&&e>=1&&e<=6?e:t}function Tn(e,t){return typeof e!="string"?t:e.trim()}function Ue(e,t){if(typeof e!="string")return t;let n=e.trim();return n.length>0?n:t}function fi(e){if(!e||typeof e!="object"||Array.isArray(e))return{};let t={};for(let n of Object.values(e)){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n;if(r.cardType!=="basic"&&r.cardType!=="qa-group"&&r.cardType!=="cloze"&&r.cardType!=="semantic-qa")continue;let i=typeof r.modelName=="string"?r.modelName.trim():"";if(i.length===0)continue;let a=gi(r.loadedFieldNames),o=typeof r.loadedAt=="number"&&Number.isFinite(r.loadedAt)?r.loadedAt:0;if(r.cardType==="qa-group"){let u=Ro(r,i,a,o);t[L(u.cardType,u.modelName)]=u;continue}if(r.cardType==="cloze"){t[L(r.cardType,i)]={cardType:r.cardType,modelName:i,loadedFieldNames:a,mainField:De(r.mainField),loadedAt:o};continue}t[L(r.cardType,i)]={cardType:r.cardType,modelName:i,loadedFieldNames:a,titleField:De(r.titleField),bodyField:De(r.bodyField),loadedAt:o}}return t}function Ro(e,t,n,r){let i=ni(e.acceptedWarnings),a=qo(e.slots),o=ni(e.warnings),u=De(e.titleField);if(a.length>0||o.length>0||i.length>0)return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:a,warnings:o,acceptedWarnings:i.length>0?i:void 0,loadedAt:r};if(n.length>0)try{return Fo.suggest(t,n,r,i)}catch{return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:[],warnings:[],acceptedWarnings:void 0,loadedAt:r}}return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:[],warnings:[],acceptedWarnings:void 0,loadedAt:r}}function Bo(e){if(!Array.isArray(e))return[];let t=new Set;for(let n of e){if(typeof n!="string")continue;let r=n.trim();r.length>0&&t.add(r)}return[...t].sort((n,r)=>n.localeCompare(r))}function Go(e){if(!e||typeof e!="object"||Array.isArray(e))return{};let t=Object.entries(e).flatMap(([n,r])=>{let i=n.trim();if(i.length===0||!r||typeof r!="object"||Array.isArray(r))return[];let a=r,o=typeof a.loadedAt=="number"&&Number.isFinite(a.loadedAt)?a.loadedAt:0;return[[i,{fieldNames:gi(a.fieldNames),loadedAt:o}]]});return t.sort(([n],[r])=>n.localeCompare(r)),Object.fromEntries(t)}function gi(e){if(!Array.isArray(e))return[];let t=[],n=new Set;for(let r of e){if(typeof r!="string")continue;let i=r.trim();i.length===0||n.has(i)||(n.add(i),t.push(i))}return t}function qo(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n;if(!Number.isInteger(r.index)||r.index<1)continue;let i=De(r.questionField),a=De(r.answerField);!i||!a||t.push({index:r.index,questionField:i,answerField:a})}return t}function De(e){if(typeof e!="string")return;let t=e.trim();return t.length>0?t:void 0}function ni(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(typeof n!="string")continue;let r=n.trim();r.length!==0&&t.push(r)}return t}function ri(e,t,n,r=!1){if(!(typeof e>"u"&&r)){if(!Array.isArray(e))throw new C(t);for(let i of e)if(typeof i!="string")throw new C(n)}}var Z=class{normalize(t){let r=t.trim().replace(/\\/g,"/").replace(/\/+?/g,"::").split(/::+/).map(i=>i.trim().replace(/^:+|:+$/g,"")).filter(Boolean);if(r.length===0)throw new C("errors.deck.emptyName");return r.join("::")}};var dt=class{constructor(t=new Z){this.deckNormalizationService=t}insert(t,n,r,i){let a=this.expandTemplate(r,t.basename),o=i==="yaml"?Ho(t.content,n,a):zo(t.content,n,a);return{expectedContent:t.content,nextContent:o,insertedDeck:a}}expandTemplate(t,n){return this.deckNormalizationService.normalize(t.replace(/\bfilename\b/g,n))}};function Ho(e,t,n){let r=e.split(/\r?\n/),i=mi(r),a=`${t}: ${n}`;if(!i)return["---",a,"---","",...r].join(` -`);let o=[...r],u=Uo(t),s=i.start+1,c=i.end,d=o.slice(s,c).findIndex(l=>u.test(l));return d>=0?(o[s+d]=a,o.join(` +${n}`}function Ae(e,t,n){return vn(e)?e.userMessage:e instanceof Error?{rawMessage:e.message}:{key:t,params:n}}function le(e,t){return vn(e)?Tn(e):Te(Ae(e,t))}function ot(e,t){return vn(t)?{filePath:e,...t.userMessage}:t instanceof Error?{filePath:e,rawMessage:t.message}:{filePath:e,rawMessage:String(t)}}function Jr(e){let t=ie();return ae(t,e.map(n=>`${n.filePath} (${Xr(n)})`))}var So=["\u9898\u76EE","\u6807\u9898","\u6B63\u9762","Stem","Title"],Co=[/^问题0*(\d+)$/i,/^Q0*(\d+)$/i,/^S0*(\d+)_Q$/i],Mo=[/^答案0*(\d+)$/i,/^A0*(\d+)$/i,/^S0*(\d+)_A$/i],pe=class{suggest(t,n,r=Date.now(),i,a){let o=a&&n.includes(a)?a:Fo(n,So),u=wo(n,t);return{cardType:"qa-group",modelName:t,loadedFieldNames:[...n],titleField:o,slots:u.slots,warnings:u.warnings,acceptedWarnings:u.warnings.length>0&&ut(u.warnings,i)?[...u.warnings]:void 0,loadedAt:r}}validateMapping(t,n){if(!t.titleField)throw new C("errors.noteFieldMapping.qaGroupMissingTitle",{modelName:t.modelName});if(t.slots.length===0)throw new C("errors.noteFieldMapping.qaGroupNoCompleteSlots",{modelName:t.modelName});let r=new Set(n),i=new Set;r.has(t.titleField)||i.add(t.titleField);for(let a of t.slots)r.has(a.questionField)||i.add(a.questionField),r.has(a.answerField)||i.add(a.answerField);if(i.size>0)throw new C("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:[...i].map(a=>`"${a}"`)})}validateWarningsAccepted(t){if(!(!t.warnings.length||ut(t.warnings,t.acceptedWarnings)))throw new C("errors.noteFieldMapping.qaGroupWarningsUnaccepted",{modelName:t.modelName})}};function ut(e,t){return e.length===0?!0:!t||e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function ni(e){try{let t=JSON.parse(e);return t.kind!=="missing-answer"&&t.kind!=="missing-question"||typeof t.index!="number"||!Number.isInteger(t.index)||t.index<1||typeof t.questionField!="string"||typeof t.answerField!="string"?void 0:{kind:t.kind,index:t.index,questionField:t.questionField,answerField:t.answerField}}catch{return}}function wo(e,t){let n=new Map,r=new Map;for(let u of e){let s=ei(u,Co);if(s&&!n.has(s)){n.set(s,u);continue}let c=ei(u,Mo);c&&!r.has(c)&&r.set(c,u)}let i=[...new Set([...n.keys(),...r.keys()])].sort((u,s)=>u-s);if(i.length>0&&i[0]!==1)throw new C("errors.noteFieldMapping.qaGroupNonContinuousSlots",{modelName:t,firstIndex:i[0]});let a=[],o=[];for(let u of i){let s=n.get(u),c=r.get(u);if(!s||!c){o.push(vo({kind:s?"missing-answer":"missing-question",index:u,questionField:s??ti("question",u),answerField:c??ti("answer",u)}));continue}if(u!==a.length+1)break;a.push({index:u,questionField:s,answerField:c})}if(a.length===0)throw new C("errors.noteFieldMapping.qaGroupNoCompleteSlots",{modelName:t});return{slots:a,warnings:o}}function ei(e,t){for(let n of t){let r=e.match(n);if(!r)continue;let i=Number.parseInt(r[1]??"",10);if(Number.isInteger(i)&&i>0)return i}}function Fo(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function vo(e){return JSON.stringify(e)}function ti(e,t){return`${e==="question"?"\u95EE\u9898":"\u7B54\u6848"}${String(t).padStart(2,"0")}`}var En=["basic","qa-group","cloze","semantic-qa"],Ue="Open in Obsidian",ct=4,ri=5,dt=4,ui="",si="",To="",An="#anki-cloze",ci="Semantic QA",di="#anki-list",li="#anki-list-qa",Ao=new pe,P={qaHeadingLevel:ct,clozeHeadingLevel:dt,cardAnswerCutoffMode:"heading-block",qaGroupMarker:di,qaNoteType:ui,clozeNoteType:si,semanticQaMarker:li,semanticQaNoteType:ci,cardTypeConfigs:fi(),noteFieldMappings:{},ankiNoteTypeCache:[],ankiModelFieldCache:{},defaultDeck:"Obsidian",fileDeckEnabled:!1,fileDeckMarker:"TARGET DECK",fileDeckTemplate:"obsidian::filename",fileDeckInsertLocation:"body",folderDeckMode:"folder-and-file",scopeMode:"all",includeFolders:[],excludeFolders:[],addObsidianBacklink:!0,obsidianBacklinkLabel:Ue,obsidianBacklinkPlacement:"answer-last-line",convertHighlightsToCloze:!0,syncObsidianTagsToAnki:!0,keepPureTagLinesInCardBody:!0,ankiConnectUrl:"http://127.0.0.1:8765"};function Do(e){if(typeof e!="string")return Ue;let t=e.trim();return t.length>0?t:Ue}function ke(e){let t=gi(e.cardTypeConfigs,e),n=Bo(t),r={...e,...n,cardTypeConfigs:t,noteFieldMappings:mi(e.noteFieldMappings),ankiNoteTypeCache:Ho(e.ankiNoteTypeCache),ankiModelFieldCache:zo(e.ankiModelFieldCache),obsidianBacklinkLabel:Do(e.obsidianBacklinkLabel)};return{...r,noteFieldMappings:Go(r)}}function pi(e){let t=e??{},n=gi(t.cardTypeConfigs,t);return ke({...P,...t,cardTypeConfigs:n,noteFieldMappings:mi(t.noteFieldMappings??P.noteFieldMappings),ankiModelFieldCache:t.ankiModelFieldCache??P.ankiModelFieldCache,includeFolders:t.includeFolders??P.includeFolders,excludeFolders:t.excludeFolders??P.excludeFolders})}function oe(e){if(Io(e.cardTypeConfigs),e.cardAnswerCutoffMode!=="heading-block"&&e.cardAnswerCutoffMode!=="double-blank-lines")throw new C("errors.settings.cardAnswerCutoffModeInvalid");if(Lo(e.noteFieldMappings),Eo(e.ankiNoteTypeCache),_o(e.ankiModelFieldCache),!e.defaultDeck.trim())throw new C("errors.settings.defaultDeckRequired");if(typeof e.fileDeckEnabled!="boolean")throw new C("errors.settings.fileDeckEnabledBoolean");if(typeof e.syncObsidianTagsToAnki!="boolean")throw new C("errors.settings.syncObsidianTagsToAnkiBoolean");if(typeof e.keepPureTagLinesInCardBody!="boolean")throw new C("errors.settings.keepPureTagLinesInCardBodyBoolean");if(typeof e.fileDeckMarker!="string")throw new C("errors.settings.fileDeckMarkerString");if(typeof e.fileDeckTemplate!="string")throw new C("errors.settings.fileDeckTemplateString");if(e.fileDeckInsertLocation!=="yaml"&&e.fileDeckInsertLocation!=="body")throw new C("errors.settings.fileDeckInsertLocationInvalid");if(e.folderDeckMode!=="off"&&e.folderDeckMode!=="folder"&&e.folderDeckMode!=="folder-and-file")throw new C("errors.settings.folderDeckModeInvalid");if(e.scopeMode!=="all"&&e.scopeMode!=="include"&&e.scopeMode!=="exclude")throw new C("errors.settings.scopeModeInvalid");if(e.obsidianBacklinkPlacement!=="question-last-line"&&e.obsidianBacklinkPlacement!=="answer-first-line"&&e.obsidianBacklinkPlacement!=="answer-last-line")throw new C("errors.settings.obsidianBacklinkPlacementInvalid");if(ii(e.includeFolders,"include"),ii(e.excludeFolders,"exclude"),!e.ankiConnectUrl.trim())throw new C("errors.settings.ankiConnectUrlRequired")}function Eo(e){if(!Array.isArray(e))throw new C("errors.settings.ankiNoteTypeCacheArray");for(let t of e)if(typeof t!="string")throw new C("errors.settings.ankiNoteTypeCacheStrings")}function _o(e){if(!e||typeof e!="object"||Array.isArray(e))throw new C("errors.settings.ankiModelFieldCacheObject");for(let t of Object.values(e)){if(!t||typeof t!="object"||Array.isArray(t))throw new C("errors.settings.ankiModelFieldCacheEntryObject");if(!Array.isArray(t.fieldNames))throw new C("errors.settings.ankiModelFieldCacheFieldNamesArray");for(let n of t.fieldNames)if(typeof n!="string")throw new C("errors.settings.ankiModelFieldCacheFieldNamesStrings");if(!Number.isFinite(t.loadedAt))throw new C("errors.settings.ankiModelFieldCacheLoadedAt")}}function ii(e,t){if(!Array.isArray(e))throw new C(t==="include"?"errors.settings.includeFoldersArray":"errors.settings.excludeFoldersArray");for(let n of e)if(typeof n!="string")throw new C(t==="include"?"errors.settings.includeFoldersStrings":"errors.settings.excludeFoldersStrings")}function Io(e){if(!e||typeof e!="object"||Array.isArray(e))throw new C("errors.settings.cardTypeConfigsObject");let t=new Map;for(let n of En){let r=e[n];if(!r||typeof r!="object"||Array.isArray(r))throw new C("errors.settings.cardTypeConfigsObject");if(typeof r.enabled!="boolean")throw new C("errors.settings.cardTypeEnabledBoolean");if(!Number.isInteger(r.headingLevel)||r.headingLevel<1||r.headingLevel>6)throw new C("errors.settings.headingLevelsRange");if(typeof r.extraMarker!="string")throw new C("errors.settings.cardTypeExtraMarkerString");if(n==="semantic-qa"&&!r.noteType.trim())throw new C("errors.settings.semanticQaNoteTypeRequired");if(!r.enabled||r.extraMarker.trim().length>0)continue;let i=t.get(r.headingLevel)??[];i.push(n),t.set(r.headingLevel,i)}for(let[n,r]of t.entries())if(r.length>1)throw new C("errors.settings.cardTypeDefaultConflict",{headingLevel:n})}function Lo(e){if(!e||typeof e!="object"||Array.isArray(e))throw new C("errors.settings.noteFieldMappingsObject");for(let t of Object.values(e)){if(t.cardType!=="basic"&&t.cardType!=="qa-group"&&t.cardType!=="cloze"&&t.cardType!=="semantic-qa")throw new C("errors.settings.noteFieldMappingsCardType");if(!t.modelName.trim())throw new C("errors.settings.noteFieldMappingsModelName");if(!Array.isArray(t.loadedFieldNames))throw new C("errors.settings.noteFieldMappingsLoadedFieldNames");if(!Number.isFinite(t.loadedAt))throw new C("errors.settings.noteFieldMappingsLoadedAt");if(W(t)){if(!Array.isArray(t.slots))throw new C("errors.settings.noteFieldMappingsQaGroupSlotsArray");for(let n of t.slots){if(!n||typeof n!="object"||Array.isArray(n))throw new C("errors.settings.noteFieldMappingsQaGroupSlotObject");if(!Number.isInteger(n.index)||n.index<1)throw new C("errors.settings.noteFieldMappingsQaGroupSlotIndex");if(typeof n.questionField!="string")throw new C("errors.settings.noteFieldMappingsQaGroupSlotQuestionField");if(typeof n.answerField!="string")throw new C("errors.settings.noteFieldMappingsQaGroupSlotAnswerField")}oi(t.warnings,"errors.settings.noteFieldMappingsQaGroupWarningsArray","errors.settings.noteFieldMappingsQaGroupWarningsStrings"),oi(t.acceptedWarnings,"errors.settings.noteFieldMappingsQaGroupAcceptedWarningsArray","errors.settings.noteFieldMappingsQaGroupAcceptedWarningsStrings",!0)}}}function fi(){return{basic:{enabled:!0,headingLevel:ct,extraMarker:"",noteType:ui},"qa-group":{enabled:!0,headingLevel:ct,extraMarker:di,noteType:""},cloze:{enabled:!0,headingLevel:dt,extraMarker:An,noteType:si},"semantic-qa":{enabled:!0,headingLevel:ct,extraMarker:li,noteType:ci}}}function No(e){let t=fi();return{basic:{...t.basic,headingLevel:$e(e.qaHeadingLevel,t.basic.headingLevel),noteType:Qe(e.qaNoteType,t.basic.noteType)},"qa-group":{...t["qa-group"],headingLevel:$e(e.qaHeadingLevel,t["qa-group"].headingLevel),extraMarker:Dn(e.qaGroupMarker,t["qa-group"].extraMarker),noteType:Qe(e.cardTypeConfigs?.["qa-group"]?.noteType,t["qa-group"].noteType)},cloze:{...t.cloze,headingLevel:$e(e.clozeHeadingLevel,t.cloze.headingLevel),noteType:Qe(e.clozeNoteType,t.cloze.noteType)},"semantic-qa":{...t["semantic-qa"],headingLevel:$e(e.qaHeadingLevel,t["semantic-qa"].headingLevel),extraMarker:Dn(e.semanticQaMarker,t["semantic-qa"].extraMarker),noteType:Qe(e.semanticQaNoteType,t["semantic-qa"].noteType)}}}function gi(e,t){let n=No(t),r={};for(let i of En){let a=e?.[i],o=n[i],u=a&&typeof a=="object"&&!Array.isArray(a)?{...o,...a}:o,s={enabled:typeof u.enabled=="boolean"?u.enabled:o.enabled,headingLevel:$e(u.headingLevel,o.headingLevel),extraMarker:Dn(u.extraMarker,o.extraMarker),noteType:Qe(u.noteType,o.noteType)};r[i]=i==="cloze"?Po(s,a,t):s}return r}function Po(e,t,n){return e.headingLevel===ri&&e.extraMarker===To?{...e,headingLevel:dt,extraMarker:An}:!Ro(t)&&n.clozeHeadingLevel===ri?{...e,headingLevel:dt,extraMarker:An}:e}function Ro(e){return!e||typeof e!="object"||Array.isArray(e)?!1:"headingLevel"in e||"extraMarker"in e}function Bo(e){return{qaHeadingLevel:e.basic.headingLevel,clozeHeadingLevel:e.cloze.headingLevel,qaGroupMarker:e["qa-group"].extraMarker,qaNoteType:e.basic.noteType,clozeNoteType:e.cloze.noteType,semanticQaMarker:e["semantic-qa"].extraMarker,semanticQaNoteType:e["semantic-qa"].noteType}}function $e(e,t){return typeof e=="number"&&Number.isInteger(e)&&e>=1&&e<=6?e:t}function Dn(e,t){return typeof e!="string"?t:e.trim()}function Qe(e,t){if(typeof e!="string")return t;let n=e.trim();return n.length>0?n:t}function mi(e){if(!e||typeof e!="object"||Array.isArray(e))return{};let t={};for(let n of Object.values(e)){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n;if(r.cardType!=="basic"&&r.cardType!=="qa-group"&&r.cardType!=="cloze"&&r.cardType!=="semantic-qa")continue;let i=typeof r.modelName=="string"?r.modelName.trim():"";if(i.length===0)continue;let a=hi(r.loadedFieldNames),o=typeof r.loadedAt=="number"&&Number.isFinite(r.loadedAt)?r.loadedAt:0;if(r.cardType==="qa-group"){let u=qo(r,i,a,o);t[L(u.cardType,u.modelName)]=u;continue}if(r.cardType==="cloze"){t[L(r.cardType,i)]={cardType:r.cardType,modelName:i,loadedFieldNames:a,mainField:De(r.mainField),loadedAt:o};continue}t[L(r.cardType,i)]={cardType:r.cardType,modelName:i,loadedFieldNames:a,titleField:De(r.titleField),bodyField:De(r.bodyField),loadedAt:o}}return t}function Go(e){let t={...e.noteFieldMappings};for(let n of En){if(n==="qa-group")continue;let r=e.cardTypeConfigs[n];if(!r.enabled)continue;let i=r.noteType.trim();if(i.length===0)continue;let a=n==="cloze"?"cloze":n==="semantic-qa"?"semantic-qa":"basic",o=L(a,i);if(t[o])continue;let u=e.ankiModelFieldCache[i];if(!u||u.fieldNames.length===0)continue;let s=[...u.fieldNames];t[o]=a==="cloze"?{cardType:a,modelName:i,loadedFieldNames:s,mainField:st(s,["Text","Body","Content"])??s[0],loadedAt:u.loadedAt}:{cardType:a,modelName:i,loadedFieldNames:s,titleField:st(s,["Front","Title"])??s[0],bodyField:st(s,["Back","Body","Answer"])??s.find(c=>c!==(st(s,["Front","Title"])??s[0])),loadedAt:u.loadedAt}}return t}function st(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function qo(e,t,n,r){let i=ai(e.acceptedWarnings),a=Oo(e.slots),o=ai(e.warnings),u=De(e.titleField);if(a.length>0||o.length>0||i.length>0)return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:a,warnings:o,acceptedWarnings:i.length>0?i:void 0,loadedAt:r};if(n.length>0)try{return Ao.suggest(t,n,r,i)}catch{return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:[],warnings:[],acceptedWarnings:void 0,loadedAt:r}}return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:[],warnings:[],acceptedWarnings:void 0,loadedAt:r}}function Ho(e){if(!Array.isArray(e))return[];let t=new Set;for(let n of e){if(typeof n!="string")continue;let r=n.trim();r.length>0&&t.add(r)}return[...t].sort((n,r)=>n.localeCompare(r))}function zo(e){if(!e||typeof e!="object"||Array.isArray(e))return{};let t=Object.entries(e).flatMap(([n,r])=>{let i=n.trim();if(i.length===0||!r||typeof r!="object"||Array.isArray(r))return[];let a=r,o=typeof a.loadedAt=="number"&&Number.isFinite(a.loadedAt)?a.loadedAt:0;return[[i,{fieldNames:hi(a.fieldNames),loadedAt:o}]]});return t.sort(([n],[r])=>n.localeCompare(r)),Object.fromEntries(t)}function hi(e){if(!Array.isArray(e))return[];let t=[],n=new Set;for(let r of e){if(typeof r!="string")continue;let i=r.trim();i.length===0||n.has(i)||(n.add(i),t.push(i))}return t}function Oo(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n;if(!Number.isInteger(r.index)||r.index<1)continue;let i=De(r.questionField),a=De(r.answerField);!i||!a||t.push({index:r.index,questionField:i,answerField:a})}return t}function De(e){if(typeof e!="string")return;let t=e.trim();return t.length>0?t:void 0}function ai(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(typeof n!="string")continue;let r=n.trim();r.length!==0&&t.push(r)}return t}function oi(e,t,n,r=!1){if(!(typeof e>"u"&&r)){if(!Array.isArray(e))throw new C(t);for(let i of e)if(typeof i!="string")throw new C(n)}}var Z=class{normalize(t){let r=t.trim().replace(/\\/g,"/").replace(/\/+?/g,"::").split(/::+/).map(i=>i.trim().replace(/^:+|:+$/g,"")).filter(Boolean);if(r.length===0)throw new C("errors.deck.emptyName");return r.join("::")}};var lt=class{constructor(t=new Z){this.deckNormalizationService=t}insert(t,n,r,i){let a=this.expandTemplate(r,t.basename),o=i==="yaml"?Wo(t.content,n,a):$o(t.content,n,a);return{expectedContent:t.content,nextContent:o,insertedDeck:a}}expandTemplate(t,n){return this.deckNormalizationService.normalize(t.replace(/\bfilename\b/g,n))}};function Wo(e,t,n){let r=e.split(/\r?\n/),i=ki(r),a=`${t}: ${n}`;if(!i)return["---",a,"---","",...r].join(` +`);let o=[...r],u=jo(t),s=i.start+1,c=i.end,d=o.slice(s,c).findIndex(l=>u.test(l));return d>=0?(o[s+d]=a,o.join(` `)):(o.splice(c,0,a),o.join(` -`))}function zo(e,t,n){let r=e.split(/\r?\n/),i=mi(r),a=i?i.end+1:0,o=r.slice(0,a),u=r.slice(a),s=Oo(u,t),c=`${t}: ${n}`,d=[...u];if(s)return d.splice(s.start,s.end-s.start+1,c),[...o,...d].join(` -`);let l=$o(u),f=l.length>0?[c,"",...l]:[c];return i?[...o,"",...f].join(` +`))}function $o(e,t,n){let r=e.split(/\r?\n/),i=ki(r),a=i?i.end+1:0,o=r.slice(0,a),u=r.slice(a),s=Qo(u,t),c=`${t}: ${n}`,d=[...u];if(s)return d.splice(s.start,s.end-s.start+1,c),[...o,...d].join(` +`);let l=Vo(u),f=l.length>0?[c,"",...l]:[c];return i?[...o,"",...f].join(` `):f.join(` -`)}function mi(e){if(e[0]?.trim()==="---"){for(let t=1;ti.noteCount===0).map(i=>i.deckName).sort((i,a)=>i.localeCompare(a))}async execute(t,n){let r=Array.from(new Set(t));if(r.length===0)return{candidateCount:n.length,selectedCount:0,deletedCount:0,deletedDeckNames:[],skippedDeckNames:[]};let[i,a]=await Promise.all([this.ankiGateway.listDeckNames(),this.ankiGateway.getDeckStats(r)]),o=new Set(hi(i)),u=new Map(a.map(l=>[l.deckName,l.noteCount])),s=r.filter(l=>o.has(l)&&u.get(l)===0),c=r.filter(l=>!o.has(l)||u.get(l)!==0),d=[];for(let l of s)try{await this.ankiGateway.deleteDecks([l]),d.push(l)}catch{c.push(l)}return{candidateCount:n.length,selectedCount:r.length,deletedCount:d.length,deletedDeckNames:d,skippedDeckNames:c}}};function hi(e){return e.filter(t=>!e.some(n=>n!==t&&n.startsWith(`${t}::`)))}var fe=class extends Error{constructor(t){super(`Markdown file changed before AHS write-back: ${t}`),this.name="MarkdownWriteConflictError"}},pt=class extends Error{constructor(t){super(`Markdown file not found: ${t}`),this.name="MarkdownFileNotFoundError"}};function ft(e,t){let n=new Set(t.additionalRemovalLineIndexes??[]);t.markerLine!==void 0&&n.add(t.markerLine-1);for(let a=t.contentEndLine;ao-a),i=t.contentEndLine-[...n].filter(a=>a\s*$/,X=class{isCandidate(t){return Qo.test(t)}parse(t,n){let r=t.match(Vo);return r?{noteId:Number(r[1]),raw:r[0].trim(),lineIndex:n}:null}create(t){return{noteId:t,raw:``,lineIndex:-1}}createForCard(t){if(t.noteId===void 0)throw new Y("Cannot create an ID marker without a noteId.");return this.create(t.noteId)}applyBatch(t,n){if(n.length===0)return t;this.validateBatch(t,n);let r=t.includes(`\r +`)}function ki(e){if(e[0]?.trim()==="---"){for(let t=1;ti.noteCount===0).map(i=>i.deckName).sort((i,a)=>i.localeCompare(a))}async execute(t,n){let r=Array.from(new Set(t));if(r.length===0)return{candidateCount:n.length,selectedCount:0,deletedCount:0,deletedDeckNames:[],skippedDeckNames:[]};let[i,a]=await Promise.all([this.ankiGateway.listDeckNames(),this.ankiGateway.getDeckStats(r)]),o=new Set(bi(i)),u=new Map(a.map(l=>[l.deckName,l.noteCount])),s=r.filter(l=>o.has(l)&&u.get(l)===0),c=r.filter(l=>!o.has(l)||u.get(l)!==0),d=[];for(let l of s)try{await this.ankiGateway.deleteDecks([l]),d.push(l)}catch{c.push(l)}return{candidateCount:n.length,selectedCount:r.length,deletedCount:d.length,deletedDeckNames:d,skippedDeckNames:c}}};function bi(e){return e.filter(t=>!e.some(n=>n!==t&&n.startsWith(`${t}::`)))}var fe=class extends Error{constructor(t){super(`Markdown file changed before AHS write-back: ${t}`),this.name="MarkdownWriteConflictError"}},ft=class extends Error{constructor(t){super(`Markdown file not found: ${t}`),this.name="MarkdownFileNotFoundError"}};function gt(e,t){let n=new Set(t.additionalRemovalLineIndexes??[]);t.markerLine!==void 0&&n.add(t.markerLine-1);for(let a=t.contentEndLine;ao-a),i=t.contentEndLine-[...n].filter(a=>a\s*$/,X=class{isCandidate(t){return Ko.test(t)}parse(t,n){let r=t.match(Zo);return r?{noteId:Number(r[1]),raw:r[0].trim(),lineIndex:n}:null}create(t){return{noteId:t,raw:``,lineIndex:-1}}createForCard(t){if(t.noteId===void 0)throw new Y("Cannot create an ID marker without a noteId.");return this.create(t.noteId)}applyBatch(t,n){if(n.length===0)return t;this.validateBatch(t,n);let r=t.includes(`\r `)?`\r `:` -`,i=t.split(/\r?\n/),a=[...n].sort((o,u)=>u.blockStartLine-o.blockStartLine);for(let o of a)this.applyWrite(i,o);return i.join(r)}validateBatch(t,n){let r=n[0]?.filePath,i=new Set;for(let a of n){if(a.filePath!==r)throw new Y("Batch marker writes must belong to the same Markdown file.");if(a.sourceContent!==t)throw new Y(`Marker writes for ${a.filePath} must share the scanned source content.`);if(a.markerLine===void 0&&a.contentEndLine>a.blockEndLine)throw new Y(`Cannot insert marker outside the heading block in ${a.filePath}.`);if(a.markerLine!==void 0&&a.markerLinea.blockEndLine)throw new Y(`Cannot write marker outside the content range in ${a.filePath}.`);if(i.has(a.blockStartLine))throw new Y(`Duplicate marker write detected for block ${a.blockStartLine} in ${a.filePath}.`);i.add(a.blockStartLine)}}applyWrite(t,n){let r=n.markerLine!==void 0?n.blockEndLine-1:n.blockEndLine;if(n.contentEndLiner)throw new Y(`Cannot write marker outside the heading block in ${n.filePath}.`);ft(t,{contentEndLine:n.contentEndLine,blockEndLine:n.blockEndLine,markerLine:n.markerLine,markerIndent:n.markerIndent,renderedMarker:this.create(n.noteId).raw})}};var $=class extends Error{constructor(t){super(t),this.name="GroupMarkerError"}},jo=/\s*$/,Zo=/^[A-Za-z][A-Za-z0-9_-]*$/,V=class{isCandidate(t){return jo.test(t)}parse(t,n){let r=t.match(Ko);if(!r)return null;let i=Number(r[1]),a=Yo(r[2]),o=Xo(r[3]);return Dn(a,o),{noteId:i,itemToSlot:a,freeSlots:o,raw:r[0].trim(),lineIndex:n}}create(t,n,r){return Dn(n,r),{noteId:t,itemToSlot:{...n},freeSlots:[...new Set(r)].sort((i,a)=>i-a),raw:gt(t,n,r),lineIndex:-1}}isEquivalent(t,n,r,i){if(!t||t.noteId!==n)return!1;let a=Object.entries(t.itemToSlot).sort(ki),o=Object.entries(r).sort(ki);if(a.length!==o.length)return!1;for(let c=0;cc-d),s=[...i].sort((c,d)=>c-d);return u.length!==s.length?!1:u.every((c,d)=>c===s[d])}validateBatch(t,n){if(n.length===0)return;let r=n[0]?.filePath,i=new Set;for(let a of n){if(a.filePath!==r)throw new $("Batch GI marker writes must belong to the same Markdown file.");if(a.sourceContent!==t)throw new $(`GI marker writes for ${a.filePath} must share the scanned source content.`);if(a.markerLine!==void 0&&a.markerLinea.blockEndLine)throw new $(`Cannot place GI marker outside the content range in ${a.filePath}.`);if(i.has(a.blockStartLine))throw new $(`Duplicate GI marker write detected for block ${a.blockStartLine} in ${a.filePath}.`);i.add(a.blockStartLine)}}applyBatch(t,n){if(n.length===0)return t;this.validateBatch(t,n);let r=t.includes(`\r +`,i=t.split(/\r?\n/),a=[...n].sort((o,u)=>u.blockStartLine-o.blockStartLine);for(let o of a)this.applyWrite(i,o);return i.join(r)}validateBatch(t,n){let r=n[0]?.filePath,i=new Set;for(let a of n){if(a.filePath!==r)throw new Y("Batch marker writes must belong to the same Markdown file.");if(a.sourceContent!==t)throw new Y(`Marker writes for ${a.filePath} must share the scanned source content.`);if(a.markerLine===void 0&&a.contentEndLine>a.blockEndLine)throw new Y(`Cannot insert marker outside the heading block in ${a.filePath}.`);if(a.markerLine!==void 0&&a.markerLinea.blockEndLine)throw new Y(`Cannot write marker outside the content range in ${a.filePath}.`);if(i.has(a.blockStartLine))throw new Y(`Duplicate marker write detected for block ${a.blockStartLine} in ${a.filePath}.`);i.add(a.blockStartLine)}}applyWrite(t,n){let r=n.markerLine!==void 0?n.blockEndLine-1:n.blockEndLine;if(n.contentEndLiner)throw new Y(`Cannot write marker outside the heading block in ${n.filePath}.`);gt(t,{contentEndLine:n.contentEndLine,blockEndLine:n.blockEndLine,markerLine:n.markerLine,markerIndent:n.markerIndent,renderedMarker:this.create(n.noteId).raw})}};var $=class extends Error{constructor(t){super(t),this.name="GroupMarkerError"}},Yo=/\s*$/,Jo=/^[A-Za-z][A-Za-z0-9_-]*$/,V=class{isCandidate(t){return Yo.test(t)}parse(t,n){let r=t.match(Xo);if(!r)return null;let i=Number(r[1]),a=eu(r[2]),o=tu(r[3]);return In(a,o),{noteId:i,itemToSlot:a,freeSlots:o,raw:r[0].trim(),lineIndex:n}}create(t,n,r){return In(n,r),{noteId:t,itemToSlot:{...n},freeSlots:[...new Set(r)].sort((i,a)=>i-a),raw:mt(t,n,r),lineIndex:-1}}isEquivalent(t,n,r,i){if(!t||t.noteId!==n)return!1;let a=Object.entries(t.itemToSlot).sort(yi),o=Object.entries(r).sort(yi);if(a.length!==o.length)return!1;for(let c=0;cc-d),s=[...i].sort((c,d)=>c-d);return u.length!==s.length?!1:u.every((c,d)=>c===s[d])}validateBatch(t,n){if(n.length===0)return;let r=n[0]?.filePath,i=new Set;for(let a of n){if(a.filePath!==r)throw new $("Batch GI marker writes must belong to the same Markdown file.");if(a.sourceContent!==t)throw new $(`GI marker writes for ${a.filePath} must share the scanned source content.`);if(a.markerLine!==void 0&&a.markerLinea.blockEndLine)throw new $(`Cannot place GI marker outside the content range in ${a.filePath}.`);if(i.has(a.blockStartLine))throw new $(`Duplicate GI marker write detected for block ${a.blockStartLine} in ${a.filePath}.`);i.add(a.blockStartLine)}}applyBatch(t,n){if(n.length===0)return t;this.validateBatch(t,n);let r=t.includes(`\r `)?`\r `:` -`,i=t.split(/\r?\n/),a=[...n].sort((o,u)=>u.blockStartLine-o.blockStartLine);for(let o of a)this.applyWrite(i,o);return i.join(r)}applyWrite(t,n){ft(t,{contentEndLine:n.contentEndLine,blockEndLine:n.blockEndLine,markerLine:n.markerLine,markerIndent:n.markerIndent,renderedMarker:gt(n.noteId,n.itemToSlot,n.freeSlots),additionalRemovalLineIndexes:Jo(t,n.blockStartLine,n.blockEndLine)})}};function gt(e,t,n){Dn(t,n);let r=Object.entries(t).sort((a,o)=>a[1]-o[1]||a[0].localeCompare(o[0])).map(([a,o])=>`${a}:${o}`).join(","),i=[...new Set(n)].sort((a,o)=>a-o).join(",");return``}function Yo(e){if(!e.trim())return{};let t={},n=new Set;for(let r of e.split(",")){let i=r.trim();if(!i)continue;let[a,o]=i.split(":");if(!a||!o||!Zo.test(a))throw new $(`Invalid GI item mapping entry: ${r}`);let u=Number(o);if(!Number.isInteger(u)||u<1)throw new $(`Invalid GI slot value: ${o}`);if(t[a]!==void 0||n.has(u))throw new $(`Duplicate GI mapping entry detected: ${r}`);t[a]=u,n.add(u)}return t}function Xo(e){if(!e.trim())return[];let t=[],n=new Set;for(let r of e.split(",")){let i=r.trim();if(!i)continue;let a=Number(i);if(!Number.isInteger(a)||a<1)throw new $(`Invalid GI free slot value: ${i}`);if(n.has(a))throw new $(`Duplicate GI free slot detected: ${i}`);n.add(a),t.push(a)}return t.sort((r,i)=>r-i)}function Dn(e,t){let n=new Set;for(let r of Object.values(e)){if(!Number.isInteger(r)||r<1)throw new $(`GI item slot must be a positive integer. Received: ${r}`);n.add(r)}for(let r of t){if(!Number.isInteger(r)||r<1)throw new $(`GI free slot must be a positive integer. Received: ${r}`);if(n.has(r))throw new $(`GI free slot ${r} overlaps with an occupied slot.`)}}function Jo(e,t,n){let r=[];for(let i=t;io.noteId)),new Set(r.map(o=>o.noteId)),this.cardMarkerService,this.groupMarkerService);try{return a.nextContent!==i.content&&await this.vaultGateway.replaceMarkdownFile(t,i.content,a.nextContent),{removedCardMarkers:a.removedCardMarkers,removedGroupMarkers:a.removedGroupMarkers,removedMarkers:a.removedCardMarkers+a.removedGroupMarkers,conflictFiles:[],failureFiles:[]}}catch(o){return o instanceof fe?{...mt(),conflictFiles:[t]}:{...mt(),failureFiles:[ot(t,o)]}}}};function eu(e,t,n,r,i){let a=e.includes(`\r +`,i=t.split(/\r?\n/),a=[...n].sort((o,u)=>u.blockStartLine-o.blockStartLine);for(let o of a)this.applyWrite(i,o);return i.join(r)}applyWrite(t,n){gt(t,{contentEndLine:n.contentEndLine,blockEndLine:n.blockEndLine,markerLine:n.markerLine,markerIndent:n.markerIndent,renderedMarker:mt(n.noteId,n.itemToSlot,n.freeSlots),additionalRemovalLineIndexes:nu(t,n.blockStartLine,n.blockEndLine)})}};function mt(e,t,n){In(t,n);let r=Object.entries(t).sort((a,o)=>a[1]-o[1]||a[0].localeCompare(o[0])).map(([a,o])=>`${a}:${o}`).join(","),i=[...new Set(n)].sort((a,o)=>a-o).join(",");return``}function eu(e){if(!e.trim())return{};let t={},n=new Set;for(let r of e.split(",")){let i=r.trim();if(!i)continue;let[a,o]=i.split(":");if(!a||!o||!Jo.test(a))throw new $(`Invalid GI item mapping entry: ${r}`);let u=Number(o);if(!Number.isInteger(u)||u<1)throw new $(`Invalid GI slot value: ${o}`);if(t[a]!==void 0||n.has(u))throw new $(`Duplicate GI mapping entry detected: ${r}`);t[a]=u,n.add(u)}return t}function tu(e){if(!e.trim())return[];let t=[],n=new Set;for(let r of e.split(",")){let i=r.trim();if(!i)continue;let a=Number(i);if(!Number.isInteger(a)||a<1)throw new $(`Invalid GI free slot value: ${i}`);if(n.has(a))throw new $(`Duplicate GI free slot detected: ${i}`);n.add(a),t.push(a)}return t.sort((r,i)=>r-i)}function In(e,t){let n=new Set;for(let r of Object.values(e)){if(!Number.isInteger(r)||r<1)throw new $(`GI item slot must be a positive integer. Received: ${r}`);n.add(r)}for(let r of t){if(!Number.isInteger(r)||r<1)throw new $(`GI free slot must be a positive integer. Received: ${r}`);if(n.has(r))throw new $(`GI free slot ${r} overlaps with an occupied slot.`)}}function nu(e,t,n){let r=[];for(let i=t;io.noteId)),new Set(r.map(o=>o.noteId)),this.cardMarkerService,this.groupMarkerService);try{return a.nextContent!==i.content&&await this.vaultGateway.replaceMarkdownFile(t,i.content,a.nextContent),{removedCardMarkers:a.removedCardMarkers,removedGroupMarkers:a.removedGroupMarkers,removedMarkers:a.removedCardMarkers+a.removedGroupMarkers,conflictFiles:[],failureFiles:[]}}catch(o){return o instanceof fe?{...ht(),conflictFiles:[t]}:{...ht(),failureFiles:[ot(t,o)]}}}};function ru(e,t,n,r,i){let a=e.includes(`\r `)?`\r `:` -`,o=e.split(/\r?\n/),u=[],s=0,c=0;for(let d=0;d0||r.trackedGroups.length>0}async execute(t){let n=await this.pluginStateRepository.load(),r=yi(n,t);if(r.trackedCards.length===0&&r.trackedGroups.length===0)return nu();let i=r.noteIds;i.length>0&&await this.ankiGateway.deleteNotes(i);let a=await this.markdownMarkerRemovalService.remove(t,r.trackedCards.map(u=>({noteId:u.noteId})),r.trackedGroups.map(u=>({noteId:u.noteId,groupId:u.groupId,blockStartLine:u.blockStartLine}))),o=tu(n,t,r);return await this.pluginStateRepository.save(o),{trackedCards:r.trackedCards.length,trackedGroups:r.trackedGroups.length,deletedNotes:i.length,removedMarkers:a.removedMarkers,removedCardMarkers:a.removedCardMarkers,removedGroupMarkers:a.removedGroupMarkers,deletedLocalRecords:r.trackedCards.length+r.trackedGroups.length,conflictFiles:a.conflictFiles,failureFiles:a.failureFiles}}};function yi(e,t){let n=new Set,r=new Set,i=e.groupBlocks??{};for(let u of e.files[t]?.noteIds??[]){let s=N(u);e.cards[s]&&n.add(s)}for(let u of e.files[t]?.groupIds??[])i[u]&&r.add(u);for(let u of Object.values(e.cards))u.filePath===t&&n.add(N(u.noteId));for(let[u,s]of Object.entries(i))s.filePath===t&&r.add(u);let a=Array.from(n).map(u=>e.cards[u]).filter(u=>!!u),o=Array.from(r).map(u=>i[u]).filter(u=>!!u);return{trackedCards:a,trackedGroups:o,noteIds:Array.from(new Set([...a.map(u=>u.noteId),...o.map(u=>u.noteId)]))}}function tu(e,t,n){let r={...e.cards},i={...e.groupBlocks??{}};for(let o of n.trackedCards)delete r[N(o.noteId)];for(let o of n.trackedGroups)delete i[o.groupId];let a={...e.files};return delete a[t],{files:a,cards:r,groupBlocks:e.groupBlocks?i:void 0,pendingWriteBack:e.pendingWriteBack.filter(o=>o.filePath!==t)}}function nu(){return{trackedCards:0,trackedGroups:0,deletedNotes:0,removedMarkers:0,removedCardMarkers:0,removedGroupMarkers:0,deletedLocalRecords:0,conflictFiles:[],failureFiles:[]}}var bt=class{constructor(t){this.manualSyncService=t}async execute(t,n){return this.manualSyncService.syncFile(t,n)}};var yt=class{constructor(t){this.manualSyncService=t}async execute(t){return this.manualSyncService.rebuildIndex(t)}};var xt=class{constructor(t){this.manualSyncService=t}async execute(t){return this.manualSyncService.syncVault(t)}};var Si=require("obsidian");function xi(e,t){return{model:{name:e,...t}}}var St=class{constructor(t){this.getBaseUrl=t}async ensureDeckExists(t){await this.invoke("createDeck",{deck:t})}async ensureDecks(t){let n=Array.from(new Set(t));await this.invokeMulti(n.map(r=>({action:"createDeck",params:{deck:r}})))}async listNoteModels(){return this.invoke("modelNames",{})}async listDeckNames(){let t=await this.invoke("deckNamesAndIds",{});return Object.keys(t)}async getModelFieldNames(t){return this.invoke("modelFieldNames",{modelName:t})}async getModelFieldNamesByModelNames(t){let n=Array.from(new Set(t.map(i=>i.trim()).filter(i=>i.length>0)));if(n.length===0)return{};let r=await this.invoke("multi",{actions:n.map(i=>({action:"modelFieldNames",params:{modelName:i}}))});return n.reduce((i,a,o)=>{let u=ru(r[o]);return u&&(i[a]=u),i},{})}async getModelTemplates(t){let n=await this.invoke("modelTemplates",{modelName:t});return Object.fromEntries(Object.entries(n).map(([r,i])=>[r,{name:r,front:i.Front??"",back:i.Back??""}]))}async getModelStyling(t){let n=await this.invoke("modelStyling",{modelName:t});return typeof n=="string"?n:n.css??""}async createModel(t){await this.invoke("createModel",{modelName:t.modelName,inOrderFields:t.fieldNames,css:t.css,isCloze:!!t.isCloze,cardTemplates:t.templates.map(n=>({Name:n.name,Front:n.front,Back:n.back}))})}async addModelField(t,n){await this.invoke("modelFieldAdd",{modelName:t,fieldName:n})}async addModelTemplate(t,n){await this.invoke("modelTemplateAdd",{modelName:t,templateName:n.name,Front:n.front,Back:n.back})}async updateModelTemplate(t,n){await this.invoke("updateModelTemplates",xi(t,{templates:{[n.name]:{Front:n.front,Back:n.back}}}))}async updateModelStyling(t,n){await this.invoke("updateModelStyling",xi(t,{css:n}))}async findNoteIds(t){return this.invoke("findNotes",{query:t})}async getNoteDetails(t){if(t.length===0)return[];let n=await this.invoke("notesInfo",{notes:t}),r=n.flatMap(a=>Array.isArray(a?.cards)?a.cards:[]),i=new Map;if(r.length>0){let a=await this.invoke("cardsInfo",{cards:r});for(let o of a)!o||typeof o.cardId!="number"||typeof o.deckName!="string"||i.set(o.cardId,o.deckName)}return n.flatMap(a=>{if(!a||typeof a.noteId!="number"||typeof a.modelName!="string")return[];let o=Array.isArray(a.cards)?a.cards:[],u=Object.fromEntries(Object.entries(a.fields??{}).map(([s,c])=>[s,c?.value??""]));return[{noteId:a.noteId,modelName:a.modelName,cardIds:o,deckNames:Array.from(new Set(o.map(s=>i.get(s)).filter(s=>typeof s=="string"))),tags:Array.isArray(a.tags)?a.tags.filter(s=>typeof s=="string"):[],fields:u}]})}async getModelDetails(t){let n=await this.getModelFieldNames(t),r=t.toLowerCase().includes("cloze");try{let i=await this.getModelTemplates(t);r=r||Object.keys(i).some(a=>a.toLowerCase().includes("cloze"))}catch{r=r||n.some(i=>i.toLowerCase()==="text")}return{fieldNames:n,isCloze:r}}async getDeckStats(t){if(t.length===0)return[];let n=await this.invoke("deckNamesAndIds",{}),r=await this.invoke("getDeckStats",{decks:t});return t.map(i=>({deckName:i,noteCount:iu(r,n[i])}))}async getNoteSummaries(t){return(await this.getNoteDetails(t)).map(n=>({noteId:n.noteId,modelName:n.modelName,cardIds:n.cardIds,deckNames:n.deckNames,tags:n.tags}))}async addNote(t){return this.invoke("addNote",{note:{deckName:t.deckName,modelName:t.modelName,fields:t.fields,options:{allowDuplicate:!1,duplicateScope:"deck"},tags:t.tags}})}async addNotes(t){return this.invokeMulti(t.map(n=>({action:"addNote",params:{note:{deckName:n.deckName,modelName:n.modelName,fields:n.fields,options:{allowDuplicate:!1,duplicateScope:"deck"},tags:n.tags}}})))}async deleteNotes(t){t.length!==0&&await this.invoke("deleteNotes",{notes:t})}async updateNote(t){if(await this.invoke("updateNoteFields",{note:{id:t.noteId,fields:t.fields}}),!t.deckName)return;let r=(await this.invoke("notesInfo",{notes:[t.noteId]}))[0]?.cards??[];r.length>0&&await this.invoke("changeDeck",{cards:r,deck:t.deckName})}async updateNoteModel(t){try{await this.invoke("updateNoteModel",{note:{id:t.noteId,modelName:t.modelName,fields:t.fields}})}catch(n){throw new Error(au("updateNoteModel",{noteId:t.noteId,modelName:t.modelName},n))}}async updateNotes(t){await this.invokeMulti(t.map(n=>({action:"updateNoteFields",params:{note:{id:n.noteId,fields:n.fields}}})))}async syncNoteTags(t){let n=[];for(let r of t)r.removeTags.length>0&&n.push({action:"removeTags",params:{notes:[r.noteId],tags:r.removeTags.join(" ")}}),r.addTags.length>0&&n.push({action:"addTags",params:{notes:[r.noteId],tags:r.addTags.join(" ")}});await this.invokeMulti(n)}async changeDecks(t){await this.invokeMulti(t.filter(n=>n.cardIds.length>0).map(n=>({action:"changeDeck",params:{cards:n.cardIds,deck:n.deckName}})))}async deleteDecks(t){let n=Array.from(new Set(t));n.length!==0&&await this.invoke("deleteDecks",{decks:n,cardsToo:!0})}async storeMedia(t){await this.invoke("storeMediaFile",{filename:t.fileName,path:t.absolutePath})}async storeMediaFiles(t){await this.invokeMulti(t.map(n=>({action:"storeMediaFile",params:{filename:n.fileName,path:n.absolutePath}})))}async invoke(t,n){let i=(await(0,Si.requestUrl)({url:this.getBaseUrl(),method:"POST",contentType:"application/json",body:JSON.stringify({action:t,version:6,params:n})})).json;if(i.error)throw new Error(i.error);return i.result}async invokeMulti(t){return t.length===0?[]:this.invoke("multi",{actions:t})}};function ru(e){if(Array.isArray(e))return e.filter(n=>typeof n=="string");if(!e||typeof e!="object"||Array.isArray(e))return;let t=e;if(!t.error&&Array.isArray(t.result))return t.result.filter(n=>typeof n=="string")}function iu(e,t){if(!e||typeof e!="object"||typeof t!="number")return;let n=e[String(t)];if(!n||typeof n!="object")return;let i=n.total_in_deck;if(typeof i=="number"&&Number.isFinite(i))return i}function au(e,t,n){let r=typeof t.noteId=="number"&&typeof t.modelName=="string"?` for note ${t.noteId} to model ${t.modelName}`:typeof t.noteId=="number"?` for note ${t.noteId}`:"";return`AnkiConnect ${e} failed${r}: ${ou(n)}`}function ou(e){return e instanceof Error&&e.message.trim().length>0?e.message.trim():String(e)}var Ct=class{constructor(t){this.plugin=t}async load(){return await this.plugin.loadData()??null}async save(t){await this.plugin.saveData(t)}};var ue=require("obsidian");function z(e){let t=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}function Mt(e){if(!e)return[];let t=[],n=new Set;for(let r of e){if(typeof r!="string")continue;let a=(r.startsWith("#")?r.slice(1):r).split("/").map(u=>u.trim()).filter(u=>u.length>0);if(a.length===0)continue;let o=a.join("::");n.has(o)||(n.add(o),t.push(o))}return t}var uu=new Set(["png","jpg","jpeg","gif","bmp","svg","webp","tiff"]),su=new Set(["wav","m4a","flac","mp3","wma","aac","webm","ogg"]),vt=class{constructor(t){this.app=t}async listFolderTree(){return this.app.vault.getRoot().children.filter(t=>t instanceof ue.TFolder).map(t=>this.toFolderTreeNode(t))}async listMarkdownFileRefs(){return this.app.vault.getMarkdownFiles().map(t=>({path:t.path,basename:t.basename,mtime:t.stat.mtime,size:t.stat.size}))}async listMarkdownFiles(){let t=this.app.vault.getMarkdownFiles();return Promise.all(t.map(n=>this.toSourceFile(n)))}async getMarkdownFile(t){let n=this.app.vault.getAbstractFileByPath(t);return!(n instanceof ue.TFile)||n.extension.toLowerCase()!=="md"?null:this.toSourceFile(n)}async readMarkdownFile(t){return this.getMarkdownFile(t)}async replaceMarkdownFile(t,n,r){let i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof ue.TFile)||i.extension.toLowerCase()!=="md")throw new pt(t);if(await this.app.vault.cachedRead(i)!==n)throw new fe(t);await this.app.vault.modify(i,r)}resolveWikiLink(t,n){let{alias:r,linkPath:i}=Ci(t),o=this.app.metadataCache.getFirstLinkpathDest(wt(i),n)?.path??wt(i),u=r||cu(i);return{url:this.createObsidianUrl(i.includes("#")?`${o}${i.slice(i.indexOf("#"))}`:o),displayText:u}}resolveEmbed(t,n){let{alias:r,linkPath:i}=Ci(t),a=this.app.metadataCache.getFirstLinkpathDest(wt(i),n);if(!(a instanceof ue.TFile))return null;let o=a.extension.toLowerCase(),u=uu.has(o)?"image":su.has(o)?"audio":null;if(!u)return null;let s=du(this.app,a.path),c=`${z(a.path)}-${a.name}`;return{kind:u,fileName:c,absolutePath:s,altText:r||a.name}}createBacklink(t){return this.createObsidianUrl(`${t.filePath}#${lu(t.headingText)}`)}async toSourceFile(t){let n=this.app.metadataCache.getFileCache(t);return{path:t.path,basename:t.basename,content:await this.app.vault.cachedRead(t),tags:pu(n)}}createObsidianUrl(t){return`obsidian://open?vault=${encodeURIComponent(this.app.vault.getName())}&file=${encodeURIComponent(t)}`}toFolderTreeNode(t){return{path:t.path,name:t.name,children:t.children.filter(n=>n instanceof ue.TFolder).map(n=>this.toFolderTreeNode(n))}}};function Ci(e){let[t,n]=e.split("|",2).map(r=>r.trim());return{linkPath:t,alias:n||void 0}}function wt(e){return e.split("#",1)[0]}function cu(e){let t=wt(e);return(t.split("/").pop()??t).replace(/\.[^.]+$/,"")||e}function du(e,t){let n=e.vault.adapter;if(!n.getFullPath)throw new Error("The active vault adapter does not expose an absolute filesystem path.");return n.getFullPath(t)}function lu(e){return e.replace(/(?:\s+#\S+)+$/g,t=>t.replace(/(^|\s)#(\S+)/g,"$1$2"))}function pu(e){return e?Mt((0,ue.getAllTags)(e)):[]}var Ft=class{constructor(t){this.pluginDataStore=t}async load(){let t=await this.pluginDataStore.load()??{},n=di(t.settings);return oe(n),n}async save(t){let n=ke(t);oe(n);let r=await this.pluginDataStore.load()??{};await this.pluginDataStore.save({...r,settings:n})}};var Tt=class{constructor(t){this.pluginDataStore=t}async load(){let t=await this.pluginDataStore.load()??{};return fu(t.pluginState)}async save(t){let n=await this.pluginDataStore.load()??{};await this.pluginDataStore.save({...n,pluginState:t})}};function fu(e){if(!e)return bi();let t=e.cards??{},n={};for(let a of Object.values(t)){let o=At(a.noteId);if(o===void 0)continue;let u=gu(a,o),s=N(o),c=n[s];(!c||c.lastSyncedAt<=u.lastSyncedAt)&&(n[s]=u)}let r={};for(let[a,o]of Object.entries(e.files??{}))r[a]={filePath:a,fileHash:typeof o.fileHash=="string"?o.fileHash:"",fileStamp:typeof o.fileStamp=="string"?o.fileStamp:"",deckRulesFingerprint:typeof o.deckRulesFingerprint=="string"?o.deckRulesFingerprint:void 0,lastIndexedAt:typeof o.lastIndexedAt=="number"?o.lastIndexedAt:0,noteIds:ku(o,t,n),groupIds:bu(o,e.groupBlocks??{})};let i={};for(let[a,o]of Object.entries(e.groupBlocks??{})){let u=hu(o,a);if(!u)continue;let s=i[a];(!s||s.lastSyncedAt<=u.lastSyncedAt)&&(i[a]=u)}return{files:r,cards:n,groupBlocks:i,pendingWriteBack:[]}}function gu(e,t){return{noteId:t,filePath:typeof e.filePath=="string"?e.filePath:"",heading:typeof e.heading=="string"?e.heading:"",backlinkHeadingText:typeof e.backlinkHeadingText=="string"?e.backlinkHeadingText:typeof e.heading=="string"?e.heading:"",headingLevel:typeof e.headingLevel=="number"?e.headingLevel:1,bodyMarkdown:typeof e.bodyMarkdown=="string"?e.bodyMarkdown:"",cardType:mu(e.cardType),blockStartOffset:typeof e.blockStartOffset=="number"?e.blockStartOffset:0,blockEndOffset:typeof e.blockEndOffset=="number"?e.blockEndOffset:0,blockStartLine:typeof e.blockStartLine=="number"?e.blockStartLine:1,bodyStartLine:typeof e.bodyStartLine=="number"?e.bodyStartLine:1,blockEndLine:typeof e.blockEndLine=="number"?e.blockEndLine:1,contentEndLine:typeof e.contentEndLine=="number"?e.contentEndLine:1,markerLine:typeof e.markerLine=="number"?e.markerLine:void 0,rawBlockText:typeof e.rawBlockText=="string"?e.rawBlockText:"",rawBlockHash:typeof e.rawBlockHash=="string"?e.rawBlockHash:"",renderConfigHash:typeof e.renderConfigHash=="string"?e.renderConfigHash:"",deck:typeof e.deck=="string"?e.deck:"",deckHint:typeof e.deckHint=="string"?e.deckHint:void 0,deckHintSource:e.deckHintSource==="frontmatter"||e.deckHintSource==="body"?e.deckHintSource:void 0,deckWarnings:Array.isArray(e.deckWarnings)?[...e.deckWarnings]:[],tagsHint:Array.isArray(e.tagsHint)?e.tagsHint.filter(n=>typeof n=="string"):[],lastSyncedAt:typeof e.lastSyncedAt=="number"?e.lastSyncedAt:0,orphan:!!e.orphan}}function mu(e){return e==="cloze"||e==="semantic-qa"?e:"basic"}function hu(e,t){let n=At(e.noteId);return n===void 0||!t.trim()?null:{groupId:t,noteId:n,filePath:typeof e.filePath=="string"?e.filePath:"",headingText:typeof e.headingText=="string"?e.headingText:"",backlinkHeadingText:typeof e.backlinkHeadingText=="string"?e.backlinkHeadingText:typeof e.headingText=="string"?e.headingText:"",headingLevel:typeof e.headingLevel=="number"?e.headingLevel:1,stem:typeof e.stem=="string"?e.stem:"",src:typeof e.src=="string"?e.src:"",blockStartOffset:typeof e.blockStartOffset=="number"?e.blockStartOffset:0,blockEndOffset:typeof e.blockEndOffset=="number"?e.blockEndOffset:0,blockStartLine:typeof e.blockStartLine=="number"?e.blockStartLine:1,bodyStartLine:typeof e.bodyStartLine=="number"?e.bodyStartLine:1,blockEndLine:typeof e.blockEndLine=="number"?e.blockEndLine:1,contentEndLine:typeof e.contentEndLine=="number"?e.contentEndLine:1,markerLine:typeof e.markerLine=="number"?e.markerLine:void 0,markerIndent:typeof e.markerIndent=="string"?e.markerIndent:void 0,rawBlockText:typeof e.rawBlockText=="string"?e.rawBlockText:"",rawBlockHash:typeof e.rawBlockHash=="string"?e.rawBlockHash:"",deck:typeof e.deck=="string"?e.deck:"",deckHint:typeof e.deckHint=="string"?e.deckHint:void 0,deckHintSource:e.deckHintSource==="frontmatter"||e.deckHintSource==="body"?e.deckHintSource:void 0,deckWarnings:Array.isArray(e.deckWarnings)?[...e.deckWarnings]:[],tagsHint:Array.isArray(e.tagsHint)?e.tagsHint.filter(r=>typeof r=="string"):[],items:Array.isArray(e.items)?e.items.flatMap(r=>{if(!r||typeof r!="object")return[];let i=r;return typeof i.title!="string"||typeof i.answer!="string"||typeof i.ordinalInMarkdown!="number"?[]:[{itemId:typeof i.itemId=="string"?i.itemId:void 0,title:i.title,answer:i.answer,slot:typeof i.slot=="number"?i.slot:void 0,ordinalInMarkdown:i.ordinalInMarkdown}]}):[],freeSlots:Array.isArray(e.freeSlots)?e.freeSlots.filter(r=>typeof r=="number"&&Number.isInteger(r)&&r>0):[],lastSyncedAt:typeof e.lastSyncedAt=="number"?e.lastSyncedAt:0,orphan:!!e.orphan}}function ku(e,t,n){let r=new Set;if(Array.isArray(e.noteIds))for(let i of e.noteIds){let a=At(i);a!==void 0&&n[N(a)]&&r.add(a)}if(Array.isArray(e.cardIds))for(let i of e.cardIds){let a=At(t[i]?.noteId);a!==void 0&&n[N(a)]&&r.add(a)}return Array.from(r)}function bu(e,t){return Array.isArray(e.groupIds)?e.groupIds.filter(n=>typeof n=="string"&&!!t[n]):[]}function At(e){return typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0}function Mi(e){e.addCommand({id:"sync-current-file-to-anki",name:m("commands.syncCurrentFileToAnki"),callback:()=>{e.runSyncCurrentFile()}}),e.addCommand({id:"sync-vault-to-anki",name:m("commands.syncVaultToAnki"),callback:()=>{e.runSyncVault()}}),e.addCommand({id:"clear-current-file-synced-cards",name:m("commands.clearCurrentFileSyncedCards"),callback:()=>{e.runClearCurrentFileSyncedCards()}}),e.addCommand({id:"cleanup-empty-decks",name:m("commands.cleanupEmptyDecks"),callback:()=>{e.runCleanupEmptyDecks()}})}var Ve=require("obsidian");var Dt=class extends Ve.Modal{constructor(n,r){super(n);this.candidateDeckNames=r;this.deckToggles=new Map;this.selectedDeckNames=new Set;this.resolvedValue=null}openAndGetSelection(){return new Promise(n=>{this.resolver=n,this.open()})}onOpen(){let{contentEl:n}=this;n.empty(),n.createEl("h2",{text:m("modal.emptyDeck.title")}),n.createEl("p",{text:m("modal.emptyDeck.description")});for(let i of this.candidateDeckNames)new Ve.Setting(n).setName(i).addToggle(a=>{this.deckToggles.set(i,a),a.setValue(!1).onChange(o=>{o?this.selectedDeckNames.add(i):this.selectedDeckNames.delete(i),this.refreshSelectionState()})});let r=new Ve.Setting(n).addButton(i=>{i.setButtonText(m("modal.emptyDeck.selectAll")).onClick(()=>{this.selectAllDecks()})}).addButton(i=>{i.setButtonText(m("modal.emptyDeck.clearAll")).onClick(()=>{this.clearSelectedDecks()})}).addButton(i=>{i.setButtonText(m("modal.emptyDeck.invert")).onClick(()=>{this.invertSelectedDecks()})}).addButton(i=>{i.setButtonText(m("modal.emptyDeck.cancel")).onClick(()=>{this.finish(null)})}).addButton(i=>{this.deleteButton=i,i.setButtonText(m("modal.emptyDeck.deleteSelected")).setCta().onClick(()=>{this.finish(Array.from(this.selectedDeckNames))})});this.selectionCountEl=r.settingEl.createEl("span",{text:this.getSelectionCountText()}),this.selectionCountEl.addClass("anki-helper-empty-deck-selection-count"),this.refreshSelectionState()}onClose(){let n=this.resolver,r=this.resolvedValue;this.contentEl.empty(),this.deckToggles.clear(),this.deleteButton=void 0,this.selectionCountEl=void 0,this.resolver=void 0,this.resolvedValue=null,this.selectedDeckNames.clear(),n?.(r)}finish(n){this.resolvedValue=n,this.close()}selectAllDecks(){this.selectedDeckNames.clear();for(let n of this.candidateDeckNames)this.selectedDeckNames.add(n),this.deckToggles.get(n)?.setValue(!0);this.refreshSelectionState()}clearSelectedDecks(){this.selectedDeckNames.clear();for(let n of this.candidateDeckNames)this.deckToggles.get(n)?.setValue(!1);this.refreshSelectionState()}invertSelectedDecks(){let n=new Set;for(let r of this.candidateDeckNames){let i=!this.selectedDeckNames.has(r);this.deckToggles.get(r)?.setValue(i),i&&n.add(r)}this.selectedDeckNames.clear();for(let r of n)this.selectedDeckNames.add(r);this.refreshSelectionState()}refreshSelectionState(){this.deleteButton?.setDisabled(this.selectedDeckNames.size===0),this.selectionCountEl&&(this.selectionCountEl.textContent=this.getSelectionCountText())}getSelectionCountText(){return m("modal.emptyDeck.selectionCount",{selected:this.selectedDeckNames.size,total:this.candidateDeckNames.length})}};var En=require("obsidian");var Et=class{info(t){new En.Notice(t,5e3)}error(t){new En.Notice(t,8e3)}showSyncSummary(t,n){let r=ie(),o=[m(t==="currentFile"?"notice.summary.currentFileSync":"notice.summary.vaultSync",{scannedFiles:n.scannedFiles,scannedCards:n.scannedCards,created:n.created,updated:n.updated,migratedNoteTypes:n.migratedNoteTypes,migratedDecks:n.migratedDecks,orphaned:n.orphaned,uploadedMedia:n.uploadedMedia,skippedUnchangedCards:n.skippedUnchangedCards})];n.markerWriteConflictFiles.length>0&&o.push(m("notice.summary.markerWriteConflicts",{files:ae(r,n.markerWriteConflictFiles)})),n.warnings.length>0&&o.push(m("notice.summary.warningsCount",{count:n.warnings.length})),this.info(o.join(" "));for(let u of n.warnings.slice(0,3))this.info(this.renderDeckWarning(u))}showRebuildSummary(t){let n=ie(),r=[m("notice.summary.rebuild",{scannedFiles:t.scannedFiles,scannedCards:t.scannedCards,migratedDecks:t.migratedDecks,orphaned:t.orphaned,rewrittenMarkers:t.rewrittenMarkers,skippedUnchangedCards:t.skippedUnchangedCards})];t.markerWriteConflictFiles.length>0&&r.push(m("notice.summary.markerWriteConflicts",{files:ae(n,t.markerWriteConflictFiles)})),t.warnings.length>0&&r.push(m("notice.summary.warningsCount",{count:t.warnings.length})),this.info(r.join(" "));for(let i of t.warnings.slice(0,3))this.info(this.renderDeckWarning(i))}showClearCurrentFileSummary(t){let n=ie(),r=[m("notice.summary.clearCurrentFile",{trackedCards:t.trackedCards,trackedGroups:t.trackedGroups,deletedNotes:t.deletedNotes,removedMarkers:t.removedMarkers,removedCardMarkers:t.removedCardMarkers,removedGroupMarkers:t.removedGroupMarkers,deletedLocalRecords:t.deletedLocalRecords})];t.conflictFiles.length>0&&r.push(m("notice.summary.markerRemovalConflicts",{files:ae(n,t.conflictFiles)})),t.failureFiles.length>0&&r.push(m("notice.summary.failures",{items:Zr(t.failureFiles)})),this.info(r.join(" "))}showCleanupEmptyDecksSummary(t){let n=ie(),r=[m("notice.summary.cleanupEmptyDecks",{candidateCount:t.candidateCount,selectedCount:t.selectedCount,deletedCount:t.deletedCount,skippedCount:t.skippedDeckNames.length})];t.skippedDeckNames.length>0&&r.push(m("notice.summary.skippedDecks",{decks:ae(n,t.skippedDeckNames)})),this.info(r.join(" "))}renderDeckWarning(t){return m(yu(t.code),t.params)}};function yu(e){switch(e){case"deck_conflict_yaml_body":return"warnings.deck.conflictYamlBody";case"deck_multiple_body_declarations":return"warnings.deck.multipleBodyDeclarations";case"deck_invalid_folder_segment":return"warnings.deck.invalidFolderSegment";case"deck_fallback_default":return"warnings.deck.fallbackDefault"}}var G=require("obsidian");function wi(e){return e==="cloze"}function vi(e){return e!=="cloze"}var _e=class{map(t,n,r){return this.mapRenderedCard(t,n,r)}mapRenderedCard(t,n,r){let i=this.getRequiredMapping(t,r);return this.validateMapping(i,n),vi(t.type)?this.mapBasic(t,i):this.mapCloze(t,n,i)}suggest(t,n,r,i=Date.now()){if(t==="qa-group")throw new Error("QaGroupFieldMappingService must be used for qa-group mappings.");return xu(t)?{cardType:t,modelName:n,loadedFieldNames:[...r],titleField:_t(r,["Front","Title"])??r[0],bodyField:_t(r,["Back","Body","Answer"])??r.find(a=>a!==(_t(r,["Front","Title"])??r[0])),loadedAt:i}:{cardType:t,modelName:n,loadedFieldNames:[...r],mainField:_t(r,["Text","Body","Content"])??r[0],loadedAt:i}}validateMapping(t,n){if(!Cn(t)&&!Ur(t))throw new Error("QaGroupFieldMappingService validates qa-group mappings.");let r=new Set(n.fieldNames);if(Cn(t)){if(!t.titleField||!t.bodyField)throw new C(Fi(t.cardType),{modelName:t.modelName});if(t.titleField===t.bodyField)throw new C(Cu(t.cardType),{modelName:t.modelName});let i=[t.titleField,t.bodyField].filter(a=>!r.has(a));if(i.length>0)throw new C("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:i.map(a=>`"${a}"`)});return}if(!t.mainField)throw new C("errors.noteFieldMapping.incompleteSavedMapping.cloze",{modelName:t.modelName});if(!n.isCloze)throw new C("errors.noteFieldMapping.clozeIncompatible",{modelName:t.modelName});if(!r.has(t.mainField))throw new C("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:[`"${t.mainField}"`]})}mapBasic(t,n){let r=n.titleField,i=n.bodyField;if(!r||!i)throw new C(Fi(t.type),{modelName:t.noteModel});return{[r]:t.renderedFields.title,[i]:t.renderedFields.body}}mapCloze(t,n,r){if(!n.isCloze)throw new C("errors.noteFieldMapping.clozeIncompatible",{modelName:t.noteModel});if(!r.mainField)throw new C("errors.noteFieldMapping.incompleteSavedMapping.cloze",{modelName:t.noteModel});return{[r.mainField]:`${t.renderedFields.title}

${t.renderedFields.body}`}}getRequiredMapping(t,n){let r=n[L(t.type,t.noteModel)];if(!r)throw new C(Su(t.type),{modelName:t.noteModel});return r}};function xu(e){return e==="basic"||e==="semantic-qa"}function Su(e){return e==="cloze"?"errors.noteFieldMapping.missingSavedMapping.cloze":e==="semantic-qa"?"errors.noteFieldMapping.missingSavedMapping.semanticQa":"errors.noteFieldMapping.missingSavedMapping.basic"}function Fi(e){return e==="cloze"?"errors.noteFieldMapping.incompleteSavedMapping.cloze":e==="semantic-qa"?"errors.noteFieldMapping.incompleteSavedMapping.semanticQa":"errors.noteFieldMapping.incompleteSavedMapping.basic"}function Cu(e){return e==="semantic-qa"?"errors.noteFieldMapping.titleBodyMustDiffer.semanticQa":"errors.noteFieldMapping.titleBodyMustDiffer.basic"}function _t(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function Di(e,t){let n=new Set(_n(t));return e.map(r=>_i(r,n,!1))}function Ei(e,t,n,r){let i=Mu(e),a=new Set(_n(t).filter(u=>i.nodeByPath.has(u)));if(!i.nodeByPath.has(n))return It(e,Array.from(a));if(r)return Ti(n,a,i.parentByPath)||(Ai(a,n),a.add(n)),It(e,Array.from(a));let o=Ti(n,a,i.parentByPath);if(o&&(a.delete(o),o!==n)){let u=i.nodeByPath.get(o);if(u)for(let s of Li(u,n))a.add(s)}return Ai(a,n),It(e,Array.from(a))}function It(e,t){let n=new Set(_n(t));return e.flatMap(r=>Ii(r,n).paths)}function _i(e,t,n){let r=n||t.has(e.path),i=e.children.map(o=>_i(o,t,r));if(r)return{...e,checked:!0,indeterminate:!1,children:i};let a=i.some(o=>o.checked||o.indeterminate);return{...e,checked:!1,indeterminate:a,children:i}}function Ii(e,t){return t.has(e.path)?{paths:[e.path]}:e.children.length===0?{paths:[]}:{paths:e.children.map(r=>Ii(r,t)).flatMap(r=>r.paths)}}function Mu(e){let t=new Map,n=new Map,r=(i,a)=>{t.set(i.path,i),n.set(i.path,a);for(let o of i.children)r(o,i.path)};for(let i of e)r(i,void 0);return{nodeByPath:t,parentByPath:n}}function Ti(e,t,n){let r=e;for(;r;){if(t.has(r))return r;r=n.get(r)}}function Ai(e,t){for(let n of Array.from(e))(n===t||Ni(n,t))&&e.delete(n)}function Li(e,t){if(e.path===t)return[];let n=e.children.find(i=>i.path===t||Ni(t,i.path));if(!n)return[e.path];let r=[];for(let i of e.children){if(i.path===n.path){r.push(...Li(i,t));continue}r.push(i.path)}return r}function _n(e){return Array.from(new Set(e.map(t=>wu(t)).filter(Boolean)))}function wu(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function Ni(e,t){return e===t||e.startsWith(`${t}/`)}var Pi={key:"settings.scope.loading"},vu=500,Ri=["card-types","sync-content","deck","scope","commands"],In=["basic","qa-group","cloze"],Fu=8,Tu=64,Ie="var(--modal-background, var(--background-primary))",Ln="--ahs-settings-page-header-height",zi="--ahs-settings-sticky-card-gap",Oi=`${Tu}px`,Wi=`${Fu}px`,Au=`var(${Ln}, ${Oi})`,Du=`var(${zi}, ${Wi})`,Bi="12px",Eu="-128px",Gi="-24px",qi="32px",Lt=class extends G.PluginSettingTab{constructor(n){super(n.app,n);this.noteFieldMappingService=new _e;this.qaGroupFieldMappingService=new pe;this.availableNoteModels=[];this.draftMappings={};this.loadedModelDetails={};this.debouncedTextSaves=new Map;this.textDraftValues=new Map;this.cardShells=new Map;this.expandedCardIds=new Set;this.expandedFolderPaths=new Set;this.folderTree=[];this.folderTreeStatus=Pi;this.folderTreeLoadPromise=null;this.hasLoadedFolderTree=!1;this.displayInitialized=!1;this.ankiConfigLoading=!1;this.cardTypeStatusOverride=null;this.noteTypeCacheCheckStatus="idle";this.noteTypeCacheCheckPromise=null;this.detectedAnkiNoteTypeCache=null;this.noteTypeCacheCheckToken=0;this.pageHeaderResizeObserver=null;this.scopeNeedsSelectedAncestorExpansion=!0;this.plugin=n}hide(){this.disconnectPageHeaderResizeObserver(),super.hide(),this.displayInitialized=!1,this.cardShells.clear(),this.clearDebouncedTextSaves(),this.cardTypeStatusOverride=null,this.noteTypeCacheCheckStatus="idle",this.noteTypeCacheCheckPromise=null,this.detectedAnkiNoteTypeCache=null,this.noteTypeCacheCheckToken+=1,this.scopeNeedsSelectedAncestorExpansion=!0}display(){let{containerEl:n}=this,r=n.scrollTop;if(!this.displayInitialized){n.style.setProperty(Ln,Oi),n.style.setProperty(zi,Wi),n.empty();let i=n.createDiv();i.dataset.settingsPageHeader="true",i.style.position="sticky",i.style.top="0px",i.style.zIndex="300",i.style.width="100%",i.style.boxSizing="border-box",i.style.paddingTop=Bi,i.style.paddingBottom=`calc(${Bi} + ${Du})`,i.style.marginBottom="0",i.style.overflow="visible",i.style.background=Ie,i.style.backgroundColor=Ie,i.style.boxShadow="none";let a=i.createDiv();a.dataset.settingsPageHeaderMask="true",a.style.position="absolute",a.style.top=Eu,a.style.left=Gi,a.style.right=Gi,a.style.bottom="0px",a.style.zIndex="0",a.style.pointerEvents="none",a.style.background=Ie,a.style.backgroundColor=Ie;let o=i.createEl("h2",{text:m("settings.pluginTitle")});o.style.margin="0",o.style.position="relative",o.style.zIndex="1",this.observePageHeaderHeight(i);let u=n.createDiv();u.dataset.settingsCardsContainer="true",this.initializeCards(u),this.displayInitialized=!0}for(let i of Ri)this.renderCard(i);n.scrollTop=r}initializeCards(n){this.cardShells.clear();for(let r of Ri){let i=n.createDiv();i.dataset.settingsCard=r;let a=i.createEl("button");a.type="button",a.dataset.settingsCardToggle=r,a.style.display="flex",a.style.alignItems="center",a.style.justifyContent="flex-start",a.style.position="sticky",a.style.top=Au,a.style.zIndex="200",a.style.width="100%",a.style.maxWidth="100%",a.style.boxSizing="border-box",a.style.padding="10px 14px",a.style.fontSize="1.5em",a.style.fontWeight="600",a.style.background=Ie,a.style.backgroundColor=Ie,a.style.border="2px solid var(--background-modifier-border)",a.style.borderRadius="0",a.style.marginBottom="8px",a.style.textAlign="left",a.style.boxShadow="none",a.addEventListener("click",()=>{this.toggleCard(r)});let o=i.createDiv();o.dataset.settingsCardBody=r,this.cardShells.set(r,{cardEl:i,headerEl:a,bodyEl:o})}}toggleCard(n){this.expandedCardIds.has(n)?this.expandedCardIds.delete(n):this.expandedCardIds.add(n),this.renderCard(n)}renderCard(n){let r=this.cardShells.get(n);if(!r)return;let i=this.expandedCardIds.has(n);if(r.headerEl.textContent=`${i?"\u25BE":"\u25B8"} ${this.getCardTitle(n)}`,r.headerEl.setAttr("aria-expanded",String(i)),r.bodyEl.style.display=i?"block":"none",r.bodyEl.empty(),!!i){if(n==="card-types"){this.renderCardTypesCard(r.bodyEl);return}if(n==="sync-content"){this.renderSyncContentCard(r.bodyEl);return}if(n==="scope"){this.renderScopeCard(r.bodyEl);return}if(n==="deck"){this.renderDeckCard(r.bodyEl);return}this.renderCommandsCard(r.bodyEl)}}observePageHeaderHeight(n){this.disconnectPageHeaderResizeObserver(),this.updatePageHeaderHeight(n),!(typeof ResizeObserver>"u")&&(this.pageHeaderResizeObserver=new ResizeObserver(()=>{this.updatePageHeaderHeight(n)}),this.pageHeaderResizeObserver.observe(n))}updatePageHeaderHeight(n){let r=n.getBoundingClientRect().height;!Number.isFinite(r)||r<=0||this.containerEl.style.setProperty(Ln,`${Math.round(r)}px`)}disconnectPageHeaderResizeObserver(){this.pageHeaderResizeObserver?.disconnect(),this.pageHeaderResizeObserver=null}renderCardTypesCard(n){this.hydrateVisibleCardTypeCaches(),this.maybeStartNoteTypeCacheCheck();let r=n.createDiv();r.style.display="flex",r.style.flexDirection="column",r.style.alignItems="flex-start",r.style.gap="8px";let i=r.createEl("button",{text:this.ankiConfigLoading?m("settings.cards.cardTypes.loadAnki.loading"):m("settings.cards.cardTypes.loadAnki.button")});i.type="button",i.dataset.cardTypesRefresh="true",i.disabled=this.ankiConfigLoading,i.addEventListener("click",()=>this.loadAnkiCardTypeConfig()),r.createEl("span",{text:`${m("settings.cards.cardTypes.statusLabel")}${Te(this.getCardTypeStatusMessage())}`});let a=n.createDiv();a.dataset.cardTypeList="true",a.style.display="flex",a.style.flexDirection="column",a.style.gap="14px";for(let o of In)this.renderCardTypeBlock(a,o)}renderCardTypeBlock(n,r){let i=this.plugin.settings.cardTypeConfigs[r],a=n.createDiv();a.dataset.cardTypeConfig=r,a.style.display="flex",a.style.flexDirection="column",a.style.gap="8px",a.style.padding="12px",a.style.border="1px solid var(--background-modifier-border)",a.style.borderRadius="8px";let o=a.createDiv();o.style.display="flex",o.style.alignItems="center",o.style.gap="10px";let u=o.createEl("input");u.type="checkbox",u.checked=i.enabled,u.dataset.cardTypeEnabled=r,u.addEventListener("change",()=>this.saveCardTypeConfig(r,{enabled:u.checked}));let s=o.createEl("strong",{text:this.getCardTypeLabel(r)});s.style.fontSize="var(--font-ui-medium)";let c=a.createDiv();c.style.display="flex",c.style.flexWrap="wrap",c.style.alignItems="center",c.style.gap="10px 14px";let d=this.createInlineControlGroup(c,m("settings.cards.cardTypes.labels.headingLevel")),l=this.createSelect(d,`card-type-heading:${r}`);l.dataset.cardTypeHeading=r,l.style.width="88px";for(let k=1;k<=6;k+=1)this.appendOption(l,String(k),`H${k}`);l.value=String(i.headingLevel),l.addEventListener("change",()=>this.saveCardTypeConfig(r,{headingLevel:Number(l.value)}));let g=this.createInlineControlGroup(c,m("settings.cards.cardTypes.labels.extraMarker")).createEl("input");g.type="text",g.dataset.cardTypeMarker=r,g.placeholder=m("settings.cards.cardTypes.markerPlaceholder"),g.style.width="220px",g.value=this.getDraftValue(`card-type-marker:${r}`,i.extraMarker),g.addEventListener("input",()=>{this.scheduleDebouncedTextSave(`card-type-marker:${r}`,g.value,async k=>{await this.saveCardTypeConfig(r,{extraMarker:k})&&this.textDraftValues.delete(`card-type-marker:${r}`)})});let p=a.createDiv();p.style.display="grid",p.style.gridTemplateColumns="minmax(0, 1.1fr) minmax(0, 0.75fr) minmax(220px, 0.95fr)",p.style.alignItems="center",p.style.columnGap="16px",p.style.rowGap="8px",p.style.overflow="visible",p.style.width="100%";let M=this.createGridControlSlot(p,m("settings.cards.cardTypes.labels.noteType")),b=this.createSelect(M,`card-type-note-type:${r}`);b.dataset.cardTypeNoteType=r,this.applyFluidEllipsis(b);for(let k of this.getSelectableNoteModels(i.noteType))this.appendOption(b,k,k);b.value=i.noteType,b.disabled=this.ankiConfigLoading,b.addEventListener("change",()=>this.saveCardTypeConfig(r,{noteType:b.value})),this.renderCardTypeFieldControls(p,r)}renderCardTypeFieldControls(n,r){if(r==="qa-group"){this.renderQaGroupFieldControls(n,r);return}let i=this.getCurrentMappingForConfig(r);if(r==="cloze"){let d=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.mainField")),l=this.createFieldSelect(d,`card-type-question-field:${r}`),f=i&&"mainField"in i?i:void 0;l.dataset.cardTypeQuestionField=r,this.applyFluidEllipsis(l),this.populateFieldSelect(l,f?.loadedFieldNames??[],f?.mainField),l.addEventListener("change",()=>this.saveFieldMapping(r,{mainField:l.value||void 0}));return}let a=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.questionField")),o=this.createFieldSelect(a,`card-type-question-field:${r}`),u=i&&"bodyField"in i?i:void 0;o.dataset.cardTypeQuestionField=r,this.applyFluidEllipsis(o),this.populateFieldSelect(o,u?.loadedFieldNames??[],u?.titleField),o.addEventListener("change",()=>this.saveFieldMapping(r,{titleField:o.value||void 0}));let s=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.answerField")),c=this.createFieldSelect(s,`card-type-answer-field:${r}`);c.dataset.cardTypeAnswerField=r,this.applyFluidEllipsis(c),this.populateFieldSelect(c,u?.loadedFieldNames??[],u?.bodyField),c.addEventListener("change",()=>this.saveFieldMapping(r,{bodyField:c.value||void 0}))}renderQaGroupFieldControls(n,r){let i=this.plugin.settings.cardTypeConfigs[r].noteType.trim(),a=this.getQaGroupFieldState(r),o=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.qaGroupTitleField"));if(a.mapping){let f=this.createFieldSelect(o,`card-type-qa-group-title-field:${r}`);f.dataset.qaGroupTitleField=r,this.applyFluidEllipsis(f),this.populateFieldSelect(f,a.mapping.loadedFieldNames,a.mapping.titleField),f.addEventListener("change",()=>this.saveFieldMapping(r,{titleField:f.value||void 0}))}else o.createEl("span",{text:i.length>0?m("settings.cards.cardTypes.qaGroup.unavailable"):m("settings.cards.cardTypes.qaGroup.noModel")}).dataset.qaGroupTitleField=r;let s=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.qaGroupSlotFields")).createEl("span",{text:a.mapping?m("settings.cards.cardTypes.qaGroup.detectedSlots",{count:a.mapping.slots.length}):i.length>0?m("settings.cards.cardTypes.qaGroup.unavailable"):m("settings.cards.cardTypes.qaGroup.noModel")});if(s.dataset.qaGroupSlotSummary=r,this.applyFluidEllipsis(s),a.error){let f=n.createDiv({text:Te(a.error)});f.dataset.qaGroupError=r,f.style.gridColumn="1 / -1";return}if(!a.mapping||a.mapping.warnings.length===0)return;let c=n.createDiv();c.dataset.qaGroupWarnings=r,c.style.gridColumn="1 / -1",c.style.display="flex",c.style.flexDirection="column",c.style.gap="6px",c.createEl("strong",{text:m("settings.cards.cardTypes.labels.qaGroupWarnings")});for(let f of a.mapping.warnings)c.createEl("div",{text:this.renderQaGroupWarning(f)}).dataset.qaGroupWarning=r;let d=c.createEl("label");d.style.display="inline-flex",d.style.alignItems="center",d.style.gap="8px";let l=d.createEl("input");l.type="checkbox",l.checked=ut(a.mapping.warnings,a.mapping.acceptedWarnings),l.dataset.qaGroupWarningAccept=r,l.addEventListener("change",()=>this.saveQaGroupWarningAcceptance(r,l.checked)),d.createEl("span",{text:m("settings.cards.cardTypes.qaGroup.acceptWarnings")})}renderSyncContentCard(n){let r=this.createSyncContentSection(n,"body-range",m("settings.cards.syncContent.sections.bodyRange"));new G.Setting(r).setName(m("settings.cardAnswerCutoffMode.name")).setDesc(m("settings.cardAnswerCutoffMode.desc")).addDropdown(u=>{u.addOption("heading-block",m("settings.cardAnswerCutoffMode.options.headingBlock")),u.addOption("double-blank-lines",m("settings.cardAnswerCutoffMode.options.doubleBlankLines")),u.setValue(this.plugin.settings.cardAnswerCutoffMode).onChange(s=>{this.plugin.updateSettings({cardAnswerCutoffMode:s})})});let i=this.createSyncContentSection(n,"backlink",m("settings.cards.syncContent.sections.backlink"));new G.Setting(i).setName(m("settings.syncOptions.addObsidianBacklink.name")).setDesc(m("settings.syncOptions.addObsidianBacklink.desc")).addToggle(u=>{u.setValue(this.plugin.settings.addObsidianBacklink).onChange(s=>{this.plugin.updateSettings({addObsidianBacklink:s})})}),new G.Setting(i).setName(m("settings.syncOptions.obsidianBacklinkLabel.name")).setDesc(m("settings.syncOptions.obsidianBacklinkLabel.desc")).addText(u=>{u.setPlaceholder(m("settings.syncOptions.obsidianBacklinkLabel.placeholder")).setValue(this.getDraftValue("obsidian-backlink-label",this.plugin.settings.obsidianBacklinkLabel)).onChange(s=>{this.scheduleDebouncedTextSave("obsidian-backlink-label",s,async c=>{let d=c.trim();await this.plugin.updateSettings({obsidianBacklinkLabel:d||Qe}),this.textDraftValues.delete("obsidian-backlink-label")})})}),new G.Setting(i).setName(m("settings.syncOptions.obsidianBacklinkPlacement.name")).setDesc(m("settings.syncOptions.obsidianBacklinkPlacement.desc")).addDropdown(u=>{u.addOption("question-last-line",m("settings.syncOptions.obsidianBacklinkPlacement.options.questionLastLine")),u.addOption("answer-first-line",m("settings.syncOptions.obsidianBacklinkPlacement.options.answerFirstLine")),u.addOption("answer-last-line",m("settings.syncOptions.obsidianBacklinkPlacement.options.answerLastLine")),u.setValue(this.plugin.settings.obsidianBacklinkPlacement).onChange(s=>{this.plugin.updateSettings({obsidianBacklinkPlacement:s})})});let a=this.createSyncContentSection(n,"tags",m("settings.cards.syncContent.sections.tags"));new G.Setting(a).setName(m("settings.syncOptions.syncObsidianTagsToAnki.name")).setDesc(m("settings.syncOptions.syncObsidianTagsToAnki.desc")).addToggle(u=>{u.setValue(this.plugin.settings.syncObsidianTagsToAnki).onChange(s=>{this.plugin.updateSettings({syncObsidianTagsToAnki:s})})}),new G.Setting(a).setName(m("settings.syncOptions.keepPureTagLinesInCardBody.name")).setDesc(m("settings.syncOptions.keepPureTagLinesInCardBody.desc")).addToggle(u=>{u.setValue(this.plugin.settings.keepPureTagLinesInCardBody).onChange(s=>{this.plugin.updateSettings({keepPureTagLinesInCardBody:s})})});let o=this.createSyncContentSection(n,"cloze-special",m("settings.cards.syncContent.sections.clozeSpecial"));new G.Setting(o).setName(m("settings.syncOptions.highlightsToCloze.name")).setDesc(m("settings.syncOptions.highlightsToCloze.desc")).addToggle(u=>{u.setValue(this.plugin.settings.convertHighlightsToCloze).onChange(s=>{this.plugin.updateSettings({convertHighlightsToCloze:s})})})}createSyncContentSection(n,r,i){let a=n.createDiv();a.dataset.syncContentSection=r,a.style.display="flex",a.style.flexDirection="column",a.style.gap="8px",a.style.marginTop="16px";let o=a.createEl("h4",{text:i});return o.dataset.syncContentSectionTitle=r,o.style.margin="0",a}renderScopeCard(n){if(new G.Setting(n).setName(m("settings.scope.name")).setDesc(_u(this.plugin.settings.scopeMode)).addDropdown(s=>{s.addOption("all",m("settings.scope.option.all")).addOption("include",m("settings.scope.option.include")).addOption("exclude",m("settings.scope.option.exclude")).setValue(this.plugin.settings.scopeMode).onChange(c=>{c!=="all"&&c!=="include"&&c!=="exclude"||this.updateScopeMode(c)})}),this.plugin.settings.scopeMode==="all")return;let i=n.createDiv().createEl("button",{text:m("settings.cards.scope.refreshFolders")});if(i.type="button",i.dataset.scopeRefreshFolders="true",i.disabled=!!this.folderTreeLoadPromise,i.addEventListener("click",()=>{this.refreshFolderTree()}),this.ensureFolderTreeLoaded(),n.createEl("p",{text:Nu(this.plugin.settings.scopeMode)}),this.folderTreeLoadPromise||this.folderTree.length===0){n.createEl("p",{text:Te(this.folderTreeStatus)});return}this.expandSelectedFolderAncestorsIfNeeded(this.plugin.settings.scopeMode);let a=this.getSelectedFoldersForScopeMode(this.plugin.settings.scopeMode),o=Di(this.folderTree,a),u=n.createDiv();u.dataset.scopeTree="true",u.style.display="flex",u.style.flexDirection="column",u.style.gap="2px";for(let s of o)this.renderFolderNode(u,s,this.plugin.settings.scopeMode,0)}renderDeckCard(n){let r=this.createDeckSection(n,"folder-mapping",m("settings.cards.deck.sections.folderMapping"));new G.Setting(r).setName(m("settings.deck.folderDeckMode.name")).setDesc(m("settings.deck.folderDeckMode.desc")).addDropdown(o=>{this.populateFolderDeckModeDropdown(o,this.plugin.settings.folderDeckMode),o.onChange(u=>{u!=="off"&&u!=="folder"&&u!=="folder-and-file"||this.plugin.updateSettings({folderDeckMode:u})})}),this.renderDeckExampleBlock(r);let i=this.createDeckSection(n,"file-deck",m("settings.cards.deck.sections.fileDeck"));new G.Setting(i).setName(m("settings.deck.fileDeckEnabled.name")).setDesc(m("settings.deck.fileDeckEnabled.desc")).addToggle(o=>{o.setValue(this.plugin.settings.fileDeckEnabled).onChange(async u=>{await this.plugin.updateSettings({fileDeckEnabled:u}),this.renderCard("deck")})}),this.plugin.settings.fileDeckEnabled&&(new G.Setting(i).setName(m("settings.deck.marker.name")).setDesc(m("settings.deck.marker.desc")).addText(o=>{o.setValue(this.getDraftValue("file-deck-marker",this.plugin.settings.fileDeckMarker)).onChange(u=>{this.scheduleDebouncedTextSave("file-deck-marker",u,async s=>{let c=s.trim();if(!c){this.textDraftValues.delete("file-deck-marker"),this.renderCard("deck");return}await this.plugin.updateSettings({fileDeckMarker:c}),this.textDraftValues.delete("file-deck-marker")})})}),new G.Setting(i).setName(m("settings.deck.template.name")).setDesc(m("settings.deck.template.desc")).addText(o=>{o.setValue(this.getDraftValue("file-deck-template",this.plugin.settings.fileDeckTemplate)).onChange(u=>{this.scheduleDebouncedTextSave("file-deck-template",u,async s=>{let c=s.trim();if(!c){this.textDraftValues.delete("file-deck-template"),this.renderCard("deck");return}await this.plugin.updateSettings({fileDeckTemplate:c}),this.textDraftValues.delete("file-deck-template")})})}),new G.Setting(i).setName(m("settings.deck.insertLocation.name")).setDesc(m("settings.deck.insertLocation.desc")).addDropdown(o=>{this.populateFileDeckInsertLocationDropdown(o,this.plugin.settings.fileDeckInsertLocation),o.onChange(u=>{u!=="yaml"&&u!=="body"||this.plugin.updateSettings({fileDeckInsertLocation:u})})}),new G.Setting(i).setName(m("settings.deck.insertTemplate.name")).setDesc(m("settings.deck.insertTemplate.desc")).addButton(o=>{o.setButtonText(m("settings.deck.insertTemplate.button")).onClick(()=>{this.plugin.insertDeckTemplateToCurrentFile()})}));let a=this.createDeckSection(n,"default-deck",m("settings.cards.deck.sections.defaultDeck"));new G.Setting(a).setName(m("settings.deck.defaultDeck.name")).setDesc(m("settings.deck.defaultDeck.desc")).addText(o=>{o.setValue(this.getDraftValue("default-deck",this.plugin.settings.defaultDeck)).onChange(u=>{this.scheduleDebouncedTextSave("default-deck",u,async s=>{let c=s.trim();if(!c){this.textDraftValues.delete("default-deck"),this.renderCard("deck");return}await this.plugin.updateSettings({defaultDeck:c}),this.textDraftValues.delete("default-deck")})})}),this.createDeckHelperText(a,m("settings.deck.fallbackDesc"),"fallback"),this.createDeckPriorityFooter(n)}renderDeckExampleBlock(n){let r=n.createDiv();r.dataset.deckExampleBlock="true",r.style.display="flex",r.style.flexDirection="column",r.style.gap="4px",r.style.marginTop="2px",r.style.marginLeft=qi;let i=r.createEl("strong",{text:m("settings.deck.examplesTitle")});i.style.fontSize="var(--font-ui-small)";for(let a of[m("settings.deck.folderExample"),m("settings.deck.folderAndFileExample")]){let o=r.createDiv({text:a});o.dataset.deckExampleRow="true",o.style.color="var(--text-muted)",o.style.fontSize="var(--font-ui-small)",o.style.lineHeight="1.4"}}createDeckHelperText(n,r,i){let a=n.createDiv({text:r});return a.dataset.deckHelperText=i,a.style.color="var(--text-muted)",a.style.fontSize="var(--font-ui-small)",a.style.lineHeight="1.4",a.style.marginTop="2px",a.style.marginLeft=qi,a}createDeckPriorityFooter(n){let r=this.createDeckHelperText(n,m("settings.deck.priorityDesc"),"priority");r.dataset.deckPriorityFooter="true",r.style.marginTop="12px"}createDeckSection(n,r,i){let a=n.createDiv();a.dataset.deckSection=r,a.style.display="flex",a.style.flexDirection="column",a.style.gap="8px",a.style.marginTop="16px";let o=a.createEl("h4",{text:i});return o.dataset.deckSectionTitle=r,o.style.margin="0",a}renderCommandsCard(n){n.createEl("p",{text:m("settings.cards.commands.desc")});let r=n.createEl("ul");for(let[i,a]of[[m("commands.syncCurrentFileToAnki"),m("settings.cards.commands.items.syncCurrentFile")],[m("commands.syncVaultToAnki"),m("settings.cards.commands.items.syncVault")],[m("commands.clearCurrentFileSyncedCards"),m("settings.cards.commands.items.clearCurrentFile")],[m("commands.cleanupEmptyDecks"),m("settings.cards.commands.items.cleanupDecks")]])r.createEl("li",{text:`${i}: ${a}`})}async saveCardTypeConfig(n,r){let i={...this.plugin.settings.cardTypeConfigs,[n]:{...this.plugin.settings.cardTypeConfigs[n],...r}};try{oe(ke({...this.plugin.settings,cardTypeConfigs:i}))}catch(a){return this.cardTypeStatusOverride=Ae(a,"settings.cards.cardTypes.failedSave"),this.renderCard("card-types"),!1}if(this.cardTypeStatusOverride=null,await this.plugin.updateSettings({cardTypeConfigs:i}),n==="qa-group"&&typeof r.noteType=="string"){await this.syncQaGroupMappingFromCache(i[n].noteType);let a=L("qa-group",i[n].noteType);if(!this.plugin.settings.noteFieldMappings[a]){let o=this.plugin.settings.ankiModelFieldCache[i[n].noteType];if(o){let u=this.qaGroupFieldMappingService.suggest(i[n].noteType,o.fieldNames,o.loadedAt);await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[a]:u}})}}}return this.renderCard("card-types"),!0}async saveFieldMapping(n,r){let i=this.getCurrentMappingForConfig(n),a=this.getRuntimeCardType(n),o=this.plugin.settings.cardTypeConfigs[n].noteType,u=L(a,o),s={...i??this.createFallbackMapping(a,o),...r};this.cardTypeStatusOverride=null,this.draftMappings[u]=s,await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[u]:{...s,loadedFieldNames:[...s.loadedFieldNames]}}}),this.renderCard("card-types")}async loadAnkiCardTypeConfig(){this.noteTypeCacheCheckToken+=1,this.noteTypeCacheCheckPromise=null,this.cardTypeStatusOverride=null,this.noteTypeCacheCheckStatus=this.resolveManualRefreshCacheStatus(),this.ankiConfigLoading=!0,this.renderCard("card-types");try{let n=await this.plugin.listNoteModels(),r=Hi(n);this.availableNoteModels.splice(0,this.availableNoteModels.length,...r);let i=await this.plugin.getModelFieldNamesByModelNames(r),a=Date.now(),o=Object.entries(i).reduce((s,[c,d])=>(s[c]={fieldNames:[...d],loadedAt:a},s),{});await this.plugin.updateSettings({ankiNoteTypeCache:this.getAvailableNoteModels(),ankiModelFieldCache:o}),this.hydrateVisibleCardTypeCaches(o),await this.syncQaGroupMappingFromCache(this.plugin.settings.cardTypeConfigs["qa-group"].noteType,o);let u=this.countConfiguredCardTypes(o);this.detectedAnkiNoteTypeCache=[...r],this.noteTypeCacheCheckStatus="same",this.cardTypeStatusOverride={key:"settings.cards.cardTypes.loadedSummary",params:{noteTypeCount:this.availableNoteModels.length,configuredCount:u}}}catch(n){this.cardTypeStatusOverride=Ae(n,"settings.cards.cardTypes.failedLoad")}finally{this.ankiConfigLoading=!1,this.renderCard("card-types")}}maybeStartNoteTypeCacheCheck(){if(this.ankiConfigLoading||this.plugin.settings.ankiNoteTypeCache.length===0||this.noteTypeCacheCheckStatus!=="idle"||this.noteTypeCacheCheckPromise)return;this.noteTypeCacheCheckStatus="checking";let n=++this.noteTypeCacheCheckToken,r=this.checkNoteTypeCacheFreshness(n).finally(()=>{this.noteTypeCacheCheckPromise===r&&(this.noteTypeCacheCheckPromise=null),n===this.noteTypeCacheCheckToken&&this.renderCard("card-types")});this.noteTypeCacheCheckPromise=r}async checkNoteTypeCacheFreshness(n){try{let r=Hi(await this.plugin.listNoteModels());if(n!==this.noteTypeCacheCheckToken)return;this.detectedAnkiNoteTypeCache=r,this.noteTypeCacheCheckStatus=Lu(this.plugin.settings.ankiNoteTypeCache,r)?"same":"changed"}catch{if(n!==this.noteTypeCacheCheckToken)return;this.noteTypeCacheCheckStatus="failed"}}getCardTypeStatusMessage(){if(this.ankiConfigLoading)return{key:"settings.cards.cardTypes.loadAnki.loading"};if(this.cardTypeStatusOverride)return this.cardTypeStatusOverride;let n=this.plugin.settings.ankiNoteTypeCache.length;if(n===0)return{key:"settings.cards.cardTypes.cacheEmpty"};let r=this.countConfiguredCardTypes(this.plugin.settings.ankiModelFieldCache);return this.noteTypeCacheCheckStatus==="changed"?{key:"settings.cards.cardTypes.cacheChanged",params:{cachedCount:n,liveCount:this.detectedAnkiNoteTypeCache?.length??n,configuredCount:r}}:this.noteTypeCacheCheckStatus==="failed"?{key:"settings.cards.cardTypes.cacheCheckFailed",params:{noteTypeCount:n,configuredCount:r}}:{key:"settings.cards.cardTypes.cacheSummary",params:{noteTypeCount:n,configuredCount:r}}}resolveManualRefreshCacheStatus(){return this.noteTypeCacheCheckStatus==="changed"||this.noteTypeCacheCheckStatus==="failed"?this.noteTypeCacheCheckStatus:this.plugin.settings.ankiNoteTypeCache.length>0?"same":"idle"}hydrateVisibleCardTypeCaches(n=this.plugin.settings.ankiModelFieldCache){for(let r of In)this.hydrateCardTypeCache(r,n)}hydrateCardTypeCache(n,r){let i=this.getRuntimeCardType(n),a=this.plugin.settings.cardTypeConfigs[n].noteType,o=L(i,a),u=r[a];if(!u)return;let s=this.createCachedModelDetails(a,u.fieldNames);this.loadedModelDetails[o]=s,this.seedDraftMapping(i,a,s,u.loadedAt)}createCachedModelDetails(n,r){return{fieldNames:[...r],isCloze:n.toLowerCase().includes("cloze")}}countConfiguredCardTypes(n){return In.reduce((r,i)=>{let a=this.plugin.settings.cardTypeConfigs[i];return a.enabled?r+(n[a.noteType]?1:0):r},0)}seedDraftMapping(n,r,i,a=Date.now()){let o=L(n,r),u=this.plugin.settings.noteFieldMappings[o]??this.draftMappings[o];if(n==="qa-group"){try{this.draftMappings[o]=this.qaGroupFieldMappingService.suggest(r,i.fieldNames,a,B(u)?u.acceptedWarnings:void 0,B(u)?u.titleField:void 0)}catch{delete this.draftMappings[o]}return}if(u){this.draftMappings[o]={...u,loadedFieldNames:[...i.fieldNames],loadedAt:a};return}this.draftMappings[o]=this.noteFieldMappingService.suggest(n,r,i.fieldNames,a)}getSelectableNoteModels(n){let r=this.availableNoteModels.length>0?this.getAvailableNoteModels():[...this.plugin.settings.ankiNoteTypeCache];return r.includes(n)||r.unshift(n),r}getAvailableNoteModels(){return[...this.availableNoteModels]}getCurrentMappingForConfig(n){let r=this.getRuntimeCardType(n),i=this.plugin.settings.cardTypeConfigs[n].noteType,a=L(r,i),o=this.draftMappings[a]??this.plugin.settings.noteFieldMappings[a];if(o)return{...o,loadedFieldNames:[...o.loadedFieldNames]};let u=this.loadedModelDetails[a];if(!u)return;if(r==="qa-group")try{let c=this.plugin.settings.noteFieldMappings[a]??this.draftMappings[a],d=this.qaGroupFieldMappingService.suggest(i,u.fieldNames,Date.now(),B(c)?c.acceptedWarnings:void 0,B(c)?c.titleField:void 0);return this.draftMappings[a]=d,{...d,loadedFieldNames:[...d.loadedFieldNames],slots:d.slots.map(l=>({...l})),warnings:[...d.warnings],acceptedWarnings:d.acceptedWarnings?[...d.acceptedWarnings]:void 0}}catch{return}let s=this.noteFieldMappingService.suggest(r,i,u.fieldNames);return this.draftMappings[a]=s,{...s,loadedFieldNames:[...s.loadedFieldNames]}}createFallbackMapping(n,r){let i=L(n,r),a=this.loadedModelDetails[i];if(a){if(n==="qa-group"){let o=this.plugin.settings.noteFieldMappings[i]??this.draftMappings[i];return this.qaGroupFieldMappingService.suggest(r,a.fieldNames,Date.now(),B(o)?o.acceptedWarnings:void 0,B(o)?o.titleField:void 0)}return this.noteFieldMappingService.suggest(n,r,a.fieldNames)}return n==="qa-group"?{cardType:n,modelName:r,titleField:void 0,slots:[],warnings:[],acceptedWarnings:void 0,loadedFieldNames:[],loadedAt:Date.now()}:{cardType:n,modelName:r,loadedFieldNames:[],loadedAt:Date.now()}}async saveQaGroupWarningAcceptance(n,r){let i=this.getCurrentMappingForConfig(n);if(!i||!B(i))return;let a=this.getRuntimeCardType(n),o=L(a,i.modelName),u={...i,slots:i.slots.map(s=>({...s})),warnings:[...i.warnings],acceptedWarnings:r?[...i.warnings]:void 0,loadedFieldNames:[...i.loadedFieldNames]};this.cardTypeStatusOverride=null,this.draftMappings[o]=u,await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[o]:u}}),this.renderCard("card-types")}async syncQaGroupMappingFromCache(n,r=this.plugin.settings.ankiModelFieldCache){let i=n.trim();if(i.length===0)return;let a=r[i];if(!a)return;let o=L("qa-group",i),u=this.plugin.settings.noteFieldMappings[o]??this.draftMappings[o];try{let s=this.qaGroupFieldMappingService.suggest(i,a.fieldNames,a.loadedAt,B(u)?u.acceptedWarnings:void 0,B(u)?u.titleField:void 0);this.draftMappings[o]=s,Iu(this.plugin.settings.noteFieldMappings[o],s)||await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[o]:s}})}catch{if(delete this.draftMappings[o],this.plugin.settings.noteFieldMappings[o]){let s={...this.plugin.settings.noteFieldMappings};delete s[o],await this.plugin.updateSettings({noteFieldMappings:s})}}}getQaGroupFieldState(n){let r=this.plugin.settings.cardTypeConfigs[n].noteType,i=L("qa-group",r),a=this.draftMappings[i]??this.plugin.settings.noteFieldMappings[i];if(a&&B(a))return{mapping:{...a,loadedFieldNames:[...a.loadedFieldNames],slots:a.slots.map(u=>({...u})),warnings:[...a.warnings],acceptedWarnings:a.acceptedWarnings?[...a.acceptedWarnings]:void 0}};let o=this.loadedModelDetails[i];if(!o)return{};try{let u=this.plugin.settings.noteFieldMappings[i]??this.draftMappings[i];return{mapping:this.qaGroupFieldMappingService.suggest(r,o.fieldNames,Date.now(),B(u)?u.acceptedWarnings:void 0,B(u)?u.titleField:void 0)}}catch(u){return{error:Ae(u,"settings.cards.cardTypes.failedSave")}}}renderQaGroupWarning(n){let r=Jr(n);if(!r)return n;let i=String(r.index).padStart(2,"0");return r.kind==="missing-answer"?m("settings.cards.cardTypes.qaGroup.warning.missingAnswer",{index:i,questionField:r.questionField,answerField:r.answerField}):m("settings.cards.cardTypes.qaGroup.warning.missingQuestion",{index:i,questionField:r.questionField,answerField:r.answerField})}getRuntimeCardType(n){return n==="qa-group"?"qa-group":n==="cloze"?"cloze":n==="semantic-qa"?"semantic-qa":"basic"}ensureFolderTreeLoaded(n=!1){n&&(this.hasLoadedFolderTree=!1,this.folderTree=[]),!(this.hasLoadedFolderTree||this.folderTreeLoadPromise)&&(this.folderTreeStatus=Pi,this.folderTreeLoadPromise=this.plugin.listFolderTree().then(r=>{this.folderTree=r,this.folderTreeStatus=r.length>0?{rawMessage:""}:{key:"settings.scope.empty"},this.requestSelectedFolderAncestorExpansion()}).catch(r=>{this.folderTree=[],this.folderTreeStatus=Ae(r,"settings.scope.failedLoad")}).finally(()=>{this.hasLoadedFolderTree=!0,this.folderTreeLoadPromise=null,this.renderCard("scope")}))}async refreshFolderTree(){this.expandedFolderPaths.clear(),this.ensureFolderTreeLoaded(!0),this.renderCard("scope")}async updateScopeMode(n){await this.plugin.updateSettings({scopeMode:n}),n!=="all"&&(this.requestSelectedFolderAncestorExpansion(),this.ensureFolderTreeLoaded()),this.renderCard("scope")}async updateFolderSelection(n,r,i){let a=n==="include"?this.plugin.settings.includeFolders:this.plugin.settings.excludeFolders,o=Ei(this.folderTree,a,r,i);await this.plugin.updateSettings(n==="include"?{includeFolders:o}:{excludeFolders:o}),this.renderCard("scope")}renderFolderNode(n,r,i,a){let o=n.createDiv();o.dataset.folderRow=r.path,o.style.display="grid",o.style.gridTemplateColumns="24px 24px minmax(0, 1fr)",o.style.alignItems="center",o.style.columnGap="0px",o.style.minHeight="28px",o.style.marginLeft=`${a*18}px`,o.style.width="100%",o.style.boxSizing="border-box";let u=r.children.length>0,s=u&&this.expandedFolderPaths.has(r.path),c=o.createEl(u?"button":"span");c.dataset.folderToggle=r.path,c.textContent=u?s?"\u25BE":"\u25B8":"",c.style.width="24px",c.style.height="24px",c.style.display="inline-flex",c.style.alignItems="center",c.style.justifyContent="center",c.style.padding="0",c.style.margin="0",c.style.border="0",c.style.background="transparent",c.style.boxShadow="none",c.style.fontSize="2em",c.style.lineHeight="1",c.style.color="var(--text-muted)",u&&(c.setAttr("aria-label",s?m("settings.scope.collapseFolder",{name:r.name}):m("settings.scope.expandFolder",{name:r.name})),c.setAttr("title",s?m("settings.scope.collapseFolder",{name:r.name}):m("settings.scope.expandFolder",{name:r.name})),c.style.cursor="pointer",c.addEventListener("click",()=>{this.expandedFolderPaths.has(r.path)?this.expandedFolderPaths.delete(r.path):this.expandedFolderPaths.add(r.path),this.renderCard("scope")}));let d=o.createEl("input");d.type="checkbox",d.checked=r.checked,d.indeterminate=r.indeterminate,d.dataset.folderPath=r.path,d.style.margin="0",d.style.justifySelf="center",d.addEventListener("change",()=>{this.updateFolderSelection(i,r.path,d.checked)});let l=o.createEl("span",{text:r.name});if(l.dataset.folderPathLabel=r.path,l.style.minWidth="0",l.style.overflow="hidden",l.style.textOverflow="ellipsis",l.style.whiteSpace="nowrap",!u||!s)return;let f=n.createDiv();f.dataset.folderChildren=r.path,f.style.display="flex",f.style.flexDirection="column",f.style.gap="2px";for(let g of r.children)this.renderFolderNode(f,g,i,a+1)}requestSelectedFolderAncestorExpansion(){this.scopeNeedsSelectedAncestorExpansion=!0}expandSelectedFolderAncestorsIfNeeded(n){if(this.scopeNeedsSelectedAncestorExpansion){this.scopeNeedsSelectedAncestorExpansion=!1;for(let r of this.getSelectedFoldersForScopeMode(n))for(let i of Pu(r))this.expandedFolderPaths.add(i)}}getSelectedFoldersForScopeMode(n){return n==="include"?this.plugin.settings.includeFolders:this.plugin.settings.excludeFolders}createInlineControlGroup(n,r){let i=n.createEl("label");i.style.display="inline-flex",i.style.alignItems="center",i.style.gap="6px",i.style.flexWrap="nowrap";let a=i.createEl("span",{text:r});return a.style.whiteSpace="nowrap",i}createGridControlSlot(n,r){let i=n.createEl("label");i.style.display="flex",i.style.alignItems="center",i.style.gap="8px",i.style.minWidth="0",i.style.overflow="visible";let a=i.createEl("span",{text:r});a.style.whiteSpace="nowrap",a.style.flex="0 0 auto";let o=i.createDiv();return o.style.flex="1 1 0",o.style.minWidth="0",o.style.overflow="visible",o}applyFluidEllipsis(n){let r=(n.tagName||n.tag||"").toLowerCase(),i=r==="select"||r==="input";n.style.boxSizing="border-box",n.style.width=i?"calc(100% - 2px)":"100%",n.style.maxWidth=i?"calc(100% - 2px)":"100%",n.style.minWidth="0",n.style.margin=i?"1px":"0",n.style.overflow=i?"visible":"hidden",n.style.textOverflow="ellipsis",n.style.whiteSpace="nowrap"}scheduleDebouncedTextSave(n,r,i){this.textDraftValues.set(n,r);let a=this.debouncedTextSaves.get(n);a&&globalThis.clearTimeout(a);let o=globalThis.setTimeout(()=>{i(this.textDraftValues.get(n)??r).finally(()=>{this.debouncedTextSaves.delete(n)})},vu);this.debouncedTextSaves.set(n,o)}clearDebouncedTextSaves(){for(let n of this.debouncedTextSaves.values())globalThis.clearTimeout(n);this.debouncedTextSaves.clear()}getDraftValue(n,r){return this.textDraftValues.get(n)??r}createSelect(n,r){let i=n.createEl("select");return i.dataset.selectKey=r,i}createFieldSelect(n,r){return this.createSelect(n,r)}appendOption(n,r,i){let a=n.createEl("option",{text:i});a.value=r}populateFieldSelect(n,r,i){n.empty(),this.appendOption(n,"",r.length>0?m("settings.mapping.selectFieldPlaceholder"):m("settings.cards.cardTypes.fieldsUnavailable"));for(let a of r)this.appendOption(n,a,a);n.value=i??""}populateFileDeckInsertLocationDropdown(n,r){n.addOption("body",m("settings.deck.insertLocation.options.body")),n.addOption("yaml",m("settings.deck.insertLocation.options.yaml")),n.setValue(r)}populateFolderDeckModeDropdown(n,r){n.addOption("off",m("settings.deck.folderDeckMode.options.off")),n.addOption("folder",m("settings.deck.folderDeckMode.options.folder")),n.addOption("folder-and-file",m("settings.deck.folderDeckMode.options.folderAndFile")),n.setValue(r)}getCardTitle(n){return n==="card-types"?m("settings.cards.cardTypes.title"):n==="sync-content"?m("settings.cards.syncContent.title"):n==="scope"?m("settings.cards.scope.title"):n==="deck"?m("settings.cards.deck.title"):m("settings.cards.commands.title")}getCardTypeLabel(n){return n==="basic"?m("settings.cards.cardTypes.rows.basic"):n==="qa-group"?m("settings.cards.cardTypes.rows.qaGroup"):n==="cloze"?m("settings.cards.cardTypes.rows.cloze"):m("settings.cards.cardTypes.rows.semanticQa")}};function _u(e){return e==="include"?m("settings.scope.summary.include"):e==="exclude"?m("settings.scope.summary.exclude"):m("settings.scope.summary.all")}function Iu(e,t){return JSON.stringify(e)===JSON.stringify(t)}function Hi(e){let t=new Set;for(let n of e){if(typeof n!="string")continue;let r=n.trim();r.length>0&&t.add(r)}return[...t].sort((n,r)=>n.localeCompare(r))}function Lu(e,t){return e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function Nu(e){return e==="include"?m("settings.scope.treeDescription.include"):m("settings.scope.treeDescription.exclude")}function Pu(e){let t=e.split("/").filter(r=>r.length>0),n=[];for(let r=1;r0?e.message.trim():String(e)}var Pt=class{async runCollectBatches(t,n,r,i){if(t.length===0)return[];let a=Gu(t,n),o=new Array(a.length),u=0;return await Promise.all(Array.from({length:Math.min(r,a.length)},async()=>{for(;u(await i(a),[]))}};function Gu(e,t){let n=[];for(let r=0;ri.has(a))}function je(e,t){let n=Rt(e),r=Rt(t),i=new Set(n),a=new Set(r);return{addTags:n.filter(o=>!a.has(o)),removeTags:r.filter(o=>!i.has(o))}}var Bt=class{constructor(t,n=new _e,r=new Pt){this.ankiGateway=t;this.noteFieldMappingService=n;this.batchScheduler=r}async execute(t,n,r,i){let a=new Map,o=new Map,u=new Set,s=new Map,c=0,d=0,l=0,f=0,g=Array.from(new Set([...t.toUpdate,...t.toVerifyDeck,...t.toRewriteMarker,...t.toChangeDeck].flatMap(y=>y.noteId?[y.noteId]:[]))),p=await this.batchScheduler.runCollectBatches(g,100,1,y=>this.ankiGateway.getNoteSummaries(y)),M=new Map(p.map(y=>[y.noteId,y])),b=[],k=[],S=[],x=[],h=new Set(t.toChangeDeck.map(y=>y.card.syncKey));for(let y of t.toCreate)b.push(await this.requireRenderedCard(y,n,r));for(let y of t.toUpdate){if(y.noteId&&M.has(y.noteId)){let T=await this.requireRenderedCard(y,n,r),D=M.get(y.noteId);D&&D.modelName!==T.noteModel?S.push({plannedCard:y,renderedCard:T,summary:D}):k.push({plannedCard:y,renderedCard:T});continue}b.push(await this.requireRenderedCard(y,n,r)),s.set(y.card.syncKey,y)}for(let y of t.toRewriteMarker)if(!s.has(y.card.syncKey)){if(y.noteId&&M.has(y.noteId)){s.set(y.card.syncKey,y),o.set(y.card.syncKey,y.noteId);continue}b.push(await this.requireRenderedCard(y,n,r)),s.set(y.card.syncKey,y)}for(let y of t.toVerifyDeck){if(!y.noteId)continue;let T=M.get(y.noteId);T&&qu(T,y.deck,h.has(y.card.syncKey))&&(x.push(y),o.set(y.card.syncKey,y.noteId))}await this.batchScheduler.runVoidBatches(Array.from(new Set([...b.map(y=>y.deck),...x.map(y=>y.deck)])),50,1,y=>this.ankiGateway.ensureDecks(y));let w=await this.uploadMedia([...b,...k.map(y=>y.renderedCard),...S.map(y=>y.renderedCard)]),F=await this.batchScheduler.runCollectBatches(b,50,1,async y=>this.ankiGateway.addNotes(await Promise.all(y.map(async T=>({deckName:T.deck,modelName:T.noteModel,fields:await this.mapFields(T,i,a),tags:T.card.tagsHint})))));for(let y=0;y{await this.ankiGateway.updateNotes(await Promise.all(y.map(async({plannedCard:T,renderedCard:D})=>({noteId:T.noteId??0,fields:await this.mapFields(D,i,a)}))))}),await this.batchScheduler.runVoidBatches(S,25,1,async y=>{for(let{plannedCard:T,renderedCard:D,summary:O}of y){let W=await this.mapFields(D,i,a);try{await this.ankiGateway.updateNoteModel({noteId:T.noteId??0,modelName:D.noteModel,fields:W})}catch(v){throw Nt({noteId:T.noteId??0,fromModel:O.modelName,toModel:D.noteModel,error:v,location:`${T.card.filePath}:${T.card.blockStartLine}`})}}});let _=[...k,...S].flatMap(({plannedCard:y})=>{if(!y.noteId)return[];let T=M.get(y.noteId);if(!T)return[];let D=je(y.card.tagsHint,T.tags);return D.addTags.length===0&&D.removeTags.length===0?[]:[{noteId:y.noteId,addTags:D.addTags,removeTags:D.removeTags}]});await this.batchScheduler.runVoidBatches(_,50,1,y=>this.ankiGateway.syncNoteTags(y)),d+=k.length+S.length,l=S.length;for(let{plannedCard:y}of[...k,...S])y.noteId&&(u.add(y.card.syncKey),o.set(y.card.syncKey,y.noteId));let A=new Map;for(let y of x){let T=y.noteId;if(!T)continue;let D=M.get(T);if(!D||D.cardIds.length===0)continue;let O=A.get(y.deck)??new Set;for(let W of D.cardIds)O.add(W);A.set(y.deck,O)}await this.batchScheduler.runVoidBatches(Array.from(A.entries()).map(([y,T])=>({deckName:y,cardIds:Array.from(T)})),25,1,y=>this.ankiGateway.changeDecks(y)),f=x.length;for(let y of x)u.add(y.card.syncKey);return{created:c,updated:d,migratedNoteTypes:l,migratedDecks:f,uploadedMedia:w,markerWrites:Array.from(s.values()).map(y=>({...y,noteId:o.get(y.card.syncKey)??y.noteId})),resolvedNoteIds:o,touchedSyncKeys:u}}async requireRenderedCard(t,n,r){let i=n.get(t.card.syncKey);if(i)return i;let a=await r(t);return n.set(t.card.syncKey,a),a}async mapFields(t,n,r){let i=await this.getModelDetails(t.noteModel,r);return this.noteFieldMappingService.mapRenderedCard({type:t.card.cardType,noteModel:t.noteModel,renderedFields:t.renderedFields},i,n)}async getModelDetails(t,n){let r=n.get(t);if(r)return r;let i=this.ankiGateway.getModelDetails(t).catch(a=>{throw n.delete(t),a});return n.set(t,i),i}async uploadMedia(t){let n=new Map;for(let r of t)for(let i of r.media)n.set(`${i.kind}:${i.absolutePath}:${i.fileName}`,i);return await this.batchScheduler.runVoidBatches(Array.from(n.values()),10,3,r=>this.ankiGateway.storeMediaFiles(r)),n.size}};function qu(e,t,n){let r=e.deckNames?.filter(i=>i.length>0)??[];return r.length===0?n:r.some(i=>i!==t)}var Le=class{filter(t,n,r,i){let a=Gt(r),o=Gt(i);return t.filter(u=>u.path.toLowerCase().endsWith(".md")?this.isPathInScope(u.path,n,a,o):!1)}isPathInScope(t,n,r,i){let a=zu(t),o=Gt(r),u=Gt(i);return n==="include"?o.some(s=>Qi(a,s)):n==="exclude"?!u.some(s=>Qi(a,s)):!0}};function Gt(e){return e.map(Hu).filter(Boolean)}function Hu(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function zu(e){return e.trim().replace(/\\/g,"/").replace(/^\/+/,"")}function Qi(e,t){return e===t||e.startsWith(`${t}/`)}function Ke(e,t,n){return`${e}\0${t}\0${n}`}function qt(e,t,n){return`${e}\0group\0${t}\0${n}`}function be(e,t){return`${e}#${t}`}function Ne(e){let t=Ou(e.lines,e.startLine,e.markerAdapter),n=t.find(o=>o.valid);if(n?.marker){let o=e.lines.slice(0,n.index);return{contentLines:o,trailingLines:Uu(e.lines.slice(n.index+1)),contentEndLine:Ht(o,e.startLine,e.fallbackLine),markerLine:e.startLine+n.index,markerIndent:n.indent,marker:n.marker,markerState:"present-valid"}}let r=e.cutoffMode==="double-blank-lines"?Wu(e.lines):void 0;if(r){let o=t.find(s=>!s.valid&&s.index>=r.end),u=e.lines.slice(0,r.start);return{contentLines:u,trailingLines:e.lines.slice(r.end),contentEndLine:Ht(u,e.startLine,e.fallbackLine),markerLine:o?e.startLine+o.index:void 0,markerIndent:o?.indent,markerState:o?"present-invalid":"missing"}}let i=$u(e.lines),a=i===void 0?void 0:t.find(o=>!o.valid&&o.index===i);if(a){let o=e.lines.filter((u,s)=>s!==a.index);return{contentLines:o,trailingLines:[],contentEndLine:Ht(o,e.startLine,e.fallbackLine),markerLine:e.startLine+a.index,markerIndent:a.indent,markerState:"present-invalid"}}return{contentLines:e.lines,trailingLines:[],contentEndLine:Ht(e.lines,e.startLine,e.fallbackLine),markerState:"missing"}}function Ou(e,t,n){let r=[],i=null;for(let a=0;a=2&&n!==void 0)return{start:n,end:i};t=t?null:a.slice(0,3),n=void 0,r=0;continue}if(!t){if(!a){n??(n=i),r+=1;continue}if(r>=2&&n!==void 0)return{start:n,end:i};n=void 0,r=0}}if(r>=2&&n!==void 0)return{start:n,end:e.length}}function Ht(e,t,n){for(let r=e.length-1;r>=0;r-=1)if(e[r].trim())return t+r;return n}function $u(e){for(let t=e.length-1;t>=0;t-=1)if(e[t].trim())return t}function Uu(e){let t=0;for(;t1&&a.push({filePath:r,code:"deck_multiple_body_declarations",params:{marker:i}}),{bodyDeck:o[0],warnings:a}}};function Vu(e){if(e[0]?.trim()==="---"){for(let t=1;t!as(s))),u=[`qa-group:${n}`,...a.map(s=>`${s.title} +`,o=e.split(/\r?\n/),u=[],s=0,c=0;for(let d=0;d0||r.trackedGroups.length>0}async execute(t){let n=await this.pluginStateRepository.load(),r=Si(n,t);if(r.trackedCards.length===0&&r.trackedGroups.length===0)return au();let i=r.noteIds;i.length>0&&await this.ankiGateway.deleteNotes(i);let a=await this.markdownMarkerRemovalService.remove(t,r.trackedCards.map(u=>({noteId:u.noteId})),r.trackedGroups.map(u=>({noteId:u.noteId,groupId:u.groupId,blockStartLine:u.blockStartLine}))),o=iu(n,t,r);return await this.pluginStateRepository.save(o),{trackedCards:r.trackedCards.length,trackedGroups:r.trackedGroups.length,deletedNotes:i.length,removedMarkers:a.removedMarkers,removedCardMarkers:a.removedCardMarkers,removedGroupMarkers:a.removedGroupMarkers,deletedLocalRecords:r.trackedCards.length+r.trackedGroups.length,conflictFiles:a.conflictFiles,failureFiles:a.failureFiles}}};function Si(e,t){let n=new Set,r=new Set,i=e.groupBlocks??{};for(let u of e.files[t]?.noteIds??[]){let s=N(u);e.cards[s]&&n.add(s)}for(let u of e.files[t]?.groupIds??[])i[u]&&r.add(u);for(let u of Object.values(e.cards))u.filePath===t&&n.add(N(u.noteId));for(let[u,s]of Object.entries(i))s.filePath===t&&r.add(u);let a=Array.from(n).map(u=>e.cards[u]).filter(u=>!!u),o=Array.from(r).map(u=>i[u]).filter(u=>!!u);return{trackedCards:a,trackedGroups:o,noteIds:Array.from(new Set([...a.map(u=>u.noteId),...o.map(u=>u.noteId)]))}}function iu(e,t,n){let r={...e.cards},i={...e.groupBlocks??{}};for(let o of n.trackedCards)delete r[N(o.noteId)];for(let o of n.trackedGroups)delete i[o.groupId];let a={...e.files};return delete a[t],{files:a,cards:r,groupBlocks:e.groupBlocks?i:void 0,pendingWriteBack:e.pendingWriteBack.filter(o=>o.filePath!==t)}}function au(){return{trackedCards:0,trackedGroups:0,deletedNotes:0,removedMarkers:0,removedCardMarkers:0,removedGroupMarkers:0,deletedLocalRecords:0,conflictFiles:[],failureFiles:[]}}var yt=class{constructor(t){this.manualSyncService=t}async execute(t,n){return this.manualSyncService.syncFile(t,n)}};var xt=class{constructor(t){this.manualSyncService=t}async execute(t){return this.manualSyncService.rebuildIndex(t)}};var St=class{constructor(t){this.manualSyncService=t}async execute(t){return this.manualSyncService.syncVault(t)}};var Mi=require("obsidian");function Ci(e,t){return{model:{name:e,...t}}}var Ct=class{constructor(t){this.getBaseUrl=t}async ensureDeckExists(t){await this.invoke("createDeck",{deck:t})}async ensureDecks(t){let n=Array.from(new Set(t));await this.invokeMulti(n.map(r=>({action:"createDeck",params:{deck:r}})))}async listNoteModels(){return this.invoke("modelNames",{})}async listDeckNames(){let t=await this.invoke("deckNamesAndIds",{});return Object.keys(t)}async getModelFieldNames(t){return this.invoke("modelFieldNames",{modelName:t})}async getModelFieldNamesByModelNames(t){let n=Array.from(new Set(t.map(i=>i.trim()).filter(i=>i.length>0)));if(n.length===0)return{};let r=await this.invoke("multi",{actions:n.map(i=>({action:"modelFieldNames",params:{modelName:i}}))});return n.reduce((i,a,o)=>{let u=ou(r[o]);return u&&(i[a]=u),i},{})}async getModelTemplates(t){let n=await this.invoke("modelTemplates",{modelName:t});return Object.fromEntries(Object.entries(n).map(([r,i])=>[r,{name:r,front:i.Front??"",back:i.Back??""}]))}async getModelStyling(t){let n=await this.invoke("modelStyling",{modelName:t});return typeof n=="string"?n:n.css??""}async createModel(t){await this.invoke("createModel",{modelName:t.modelName,inOrderFields:t.fieldNames,css:t.css,isCloze:!!t.isCloze,cardTemplates:t.templates.map(n=>({Name:n.name,Front:n.front,Back:n.back}))})}async addModelField(t,n){await this.invoke("modelFieldAdd",{modelName:t,fieldName:n})}async addModelTemplate(t,n){await this.invoke("modelTemplateAdd",{modelName:t,templateName:n.name,Front:n.front,Back:n.back})}async updateModelTemplate(t,n){await this.invoke("updateModelTemplates",Ci(t,{templates:{[n.name]:{Front:n.front,Back:n.back}}}))}async updateModelStyling(t,n){await this.invoke("updateModelStyling",Ci(t,{css:n}))}async findNoteIds(t){return this.invoke("findNotes",{query:t})}async getNoteDetails(t){if(t.length===0)return[];let n=await this.invoke("notesInfo",{notes:t}),r=n.flatMap(a=>Array.isArray(a?.cards)?a.cards:[]),i=new Map;if(r.length>0){let a=await this.invoke("cardsInfo",{cards:r});for(let o of a)!o||typeof o.cardId!="number"||typeof o.deckName!="string"||i.set(o.cardId,o.deckName)}return n.flatMap(a=>{if(!a||typeof a.noteId!="number"||typeof a.modelName!="string")return[];let o=Array.isArray(a.cards)?a.cards:[],u=Object.fromEntries(Object.entries(a.fields??{}).map(([s,c])=>[s,c?.value??""]));return[{noteId:a.noteId,modelName:a.modelName,cardIds:o,deckNames:Array.from(new Set(o.map(s=>i.get(s)).filter(s=>typeof s=="string"))),tags:Array.isArray(a.tags)?a.tags.filter(s=>typeof s=="string"):[],fields:u}]})}async getModelDetails(t){return{fieldNames:await this.getModelFieldNames(t),isCloze:!1}}async getDeckStats(t){if(t.length===0)return[];let n=await this.invoke("deckNamesAndIds",{}),r=await this.invoke("getDeckStats",{decks:t});return t.map(i=>({deckName:i,noteCount:uu(r,n[i])}))}async getNoteSummaries(t){return(await this.getNoteDetails(t)).map(n=>({noteId:n.noteId,modelName:n.modelName,cardIds:n.cardIds,deckNames:n.deckNames,tags:n.tags}))}async addNote(t){return this.invoke("addNote",{note:{deckName:t.deckName,modelName:t.modelName,fields:t.fields,options:{allowDuplicate:!1,duplicateScope:"deck"},tags:t.tags}})}async addNotes(t){return this.invokeMulti(t.map(n=>({action:"addNote",params:{note:{deckName:n.deckName,modelName:n.modelName,fields:n.fields,options:{allowDuplicate:!1,duplicateScope:"deck"},tags:n.tags}}})))}async deleteNotes(t){t.length!==0&&await this.invoke("deleteNotes",{notes:t})}async updateNote(t){if(await this.invoke("updateNoteFields",{note:{id:t.noteId,fields:t.fields}}),!t.deckName)return;let r=(await this.invoke("notesInfo",{notes:[t.noteId]}))[0]?.cards??[];r.length>0&&await this.invoke("changeDeck",{cards:r,deck:t.deckName})}async updateNoteModel(t){try{await this.invoke("updateNoteModel",{note:{id:t.noteId,modelName:t.modelName,fields:t.fields}})}catch(n){throw new Error(su("updateNoteModel",{noteId:t.noteId,modelName:t.modelName},n))}}async updateNotes(t){await this.invokeMulti(t.map(n=>({action:"updateNoteFields",params:{note:{id:n.noteId,fields:n.fields}}})))}async syncNoteTags(t){let n=[];for(let r of t)r.removeTags.length>0&&n.push({action:"removeTags",params:{notes:[r.noteId],tags:r.removeTags.join(" ")}}),r.addTags.length>0&&n.push({action:"addTags",params:{notes:[r.noteId],tags:r.addTags.join(" ")}});await this.invokeMulti(n)}async changeDecks(t){await this.invokeMulti(t.filter(n=>n.cardIds.length>0).map(n=>({action:"changeDeck",params:{cards:n.cardIds,deck:n.deckName}})))}async deleteDecks(t){let n=Array.from(new Set(t));n.length!==0&&await this.invoke("deleteDecks",{decks:n,cardsToo:!0})}async storeMedia(t){await this.invoke("storeMediaFile",{filename:t.fileName,path:t.absolutePath})}async storeMediaFiles(t){await this.invokeMulti(t.map(n=>({action:"storeMediaFile",params:{filename:n.fileName,path:n.absolutePath}})))}async invoke(t,n){let i=(await(0,Mi.requestUrl)({url:this.getBaseUrl(),method:"POST",contentType:"application/json",body:JSON.stringify({action:t,version:6,params:n})})).json;if(i.error)throw new Error(i.error);return i.result}async invokeMulti(t){return t.length===0?[]:this.invoke("multi",{actions:t})}};function ou(e){if(Array.isArray(e))return e.filter(n=>typeof n=="string");if(!e||typeof e!="object"||Array.isArray(e))return;let t=e;if(!t.error&&Array.isArray(t.result))return t.result.filter(n=>typeof n=="string")}function uu(e,t){if(!e||typeof e!="object"||typeof t!="number")return;let n=e[String(t)];if(!n||typeof n!="object")return;let i=n.total_in_deck;if(typeof i=="number"&&Number.isFinite(i))return i}function su(e,t,n){let r=typeof t.noteId=="number"&&typeof t.modelName=="string"?` for note ${t.noteId} to model ${t.modelName}`:typeof t.noteId=="number"?` for note ${t.noteId}`:"";return`AnkiConnect ${e} failed${r}: ${cu(n)}`}function cu(e){return e instanceof Error&&e.message.trim().length>0?e.message.trim():String(e)}var Mt=class{constructor(t){this.plugin=t}async load(){return await this.plugin.loadData()??null}async save(t){await this.plugin.saveData(t)}};var ue=require("obsidian");function H(e){let t=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}function wt(e){if(!e)return[];let t=[],n=new Set;for(let r of e){if(typeof r!="string")continue;let a=(r.startsWith("#")?r.slice(1):r).split("/").map(u=>u.trim()).filter(u=>u.length>0);if(a.length===0)continue;let o=a.join("::");n.has(o)||(n.add(o),t.push(o))}return t}var du=new Set(["png","jpg","jpeg","gif","bmp","svg","webp","tiff"]),lu=new Set(["wav","m4a","flac","mp3","wma","aac","webm","ogg"]),vt=class{constructor(t){this.app=t}async listFolderTree(){return this.app.vault.getRoot().children.filter(t=>t instanceof ue.TFolder).map(t=>this.toFolderTreeNode(t))}async listMarkdownFileRefs(){return this.app.vault.getMarkdownFiles().map(t=>({path:t.path,basename:t.basename,mtime:t.stat.mtime,size:t.stat.size}))}async listMarkdownFiles(){let t=this.app.vault.getMarkdownFiles();return Promise.all(t.map(n=>this.toSourceFile(n)))}async getMarkdownFile(t){let n=this.app.vault.getAbstractFileByPath(t);return!(n instanceof ue.TFile)||n.extension.toLowerCase()!=="md"?null:this.toSourceFile(n)}async readMarkdownFile(t){return this.getMarkdownFile(t)}async replaceMarkdownFile(t,n,r){let i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof ue.TFile)||i.extension.toLowerCase()!=="md")throw new ft(t);if(await this.app.vault.cachedRead(i)!==n)throw new fe(t);await this.app.vault.modify(i,r)}resolveWikiLink(t,n){let{alias:r,linkPath:i}=wi(t),o=this.app.metadataCache.getFirstLinkpathDest(Ft(i),n)?.path??Ft(i),u=r||pu(i);return{url:this.createObsidianUrl(i.includes("#")?`${o}${i.slice(i.indexOf("#"))}`:o),displayText:u}}resolveEmbed(t,n){let{alias:r,linkPath:i}=wi(t),a=this.app.metadataCache.getFirstLinkpathDest(Ft(i),n);if(!(a instanceof ue.TFile))return null;let o=a.extension.toLowerCase(),u=du.has(o)?"image":lu.has(o)?"audio":null;if(!u)return null;let s=fu(this.app,a.path),c=`${H(a.path)}-${a.name}`;return{kind:u,fileName:c,absolutePath:s,altText:r||a.name}}createBacklink(t){return this.createObsidianUrl(`${t.filePath}#${gu(t.headingText)}`)}async toSourceFile(t){let n=this.app.metadataCache.getFileCache(t);return{path:t.path,basename:t.basename,content:await this.app.vault.cachedRead(t),tags:mu(n)}}createObsidianUrl(t){return`obsidian://open?vault=${encodeURIComponent(this.app.vault.getName())}&file=${encodeURIComponent(t)}`}toFolderTreeNode(t){return{path:t.path,name:t.name,children:t.children.filter(n=>n instanceof ue.TFolder).map(n=>this.toFolderTreeNode(n))}}};function wi(e){let[t,n]=e.split("|",2).map(r=>r.trim());return{linkPath:t,alias:n||void 0}}function Ft(e){return e.split("#",1)[0]}function pu(e){let t=Ft(e);return(t.split("/").pop()??t).replace(/\.[^.]+$/,"")||e}function fu(e,t){let n=e.vault.adapter;if(!n.getFullPath)throw new Error("The active vault adapter does not expose an absolute filesystem path.");return n.getFullPath(t)}function gu(e){return e.replace(/(?:\s+#\S+)+$/g,t=>t.replace(/(^|\s)#(\S+)/g,"$1$2"))}function mu(e){return e?wt((0,ue.getAllTags)(e)):[]}var Tt=class{constructor(t){this.pluginDataStore=t}async load(){let t=await this.pluginDataStore.load()??{},n=pi(t.settings);return oe(n),n}async save(t){let n=ke(t);oe(n);let r=await this.pluginDataStore.load()??{};await this.pluginDataStore.save({...r,settings:n})}};var At=class{constructor(t){this.pluginDataStore=t}async load(){let t=await this.pluginDataStore.load()??{};return hu(t.pluginState)}async save(t){let n=await this.pluginDataStore.load()??{};await this.pluginDataStore.save({...n,pluginState:t})}};function hu(e){if(!e)return xi();let t=e.cards??{},n={};for(let a of Object.values(t)){let o=Dt(a.noteId);if(o===void 0)continue;let u=ku(a,o),s=N(o),c=n[s];(!c||c.lastSyncedAt<=u.lastSyncedAt)&&(n[s]=u)}let r={};for(let[a,o]of Object.entries(e.files??{}))r[a]={filePath:a,fileHash:typeof o.fileHash=="string"?o.fileHash:"",fileStamp:typeof o.fileStamp=="string"?o.fileStamp:"",deckRulesFingerprint:typeof o.deckRulesFingerprint=="string"?o.deckRulesFingerprint:void 0,lastIndexedAt:typeof o.lastIndexedAt=="number"?o.lastIndexedAt:0,noteIds:xu(o,t,n),groupIds:Su(o,e.groupBlocks??{})};let i={};for(let[a,o]of Object.entries(e.groupBlocks??{})){let u=yu(o,a);if(!u)continue;let s=i[a];(!s||s.lastSyncedAt<=u.lastSyncedAt)&&(i[a]=u)}return{files:r,cards:n,groupBlocks:i,pendingWriteBack:[]}}function ku(e,t){return{noteId:t,filePath:typeof e.filePath=="string"?e.filePath:"",heading:typeof e.heading=="string"?e.heading:"",backlinkHeadingText:typeof e.backlinkHeadingText=="string"?e.backlinkHeadingText:typeof e.heading=="string"?e.heading:"",headingLevel:typeof e.headingLevel=="number"?e.headingLevel:1,bodyMarkdown:typeof e.bodyMarkdown=="string"?e.bodyMarkdown:"",cardType:bu(e.cardType),blockStartOffset:typeof e.blockStartOffset=="number"?e.blockStartOffset:0,blockEndOffset:typeof e.blockEndOffset=="number"?e.blockEndOffset:0,blockStartLine:typeof e.blockStartLine=="number"?e.blockStartLine:1,bodyStartLine:typeof e.bodyStartLine=="number"?e.bodyStartLine:1,blockEndLine:typeof e.blockEndLine=="number"?e.blockEndLine:1,contentEndLine:typeof e.contentEndLine=="number"?e.contentEndLine:1,markerLine:typeof e.markerLine=="number"?e.markerLine:void 0,rawBlockText:typeof e.rawBlockText=="string"?e.rawBlockText:"",rawBlockHash:typeof e.rawBlockHash=="string"?e.rawBlockHash:"",renderConfigHash:typeof e.renderConfigHash=="string"?e.renderConfigHash:"",deck:typeof e.deck=="string"?e.deck:"",deckHint:typeof e.deckHint=="string"?e.deckHint:void 0,deckHintSource:e.deckHintSource==="frontmatter"||e.deckHintSource==="body"?e.deckHintSource:void 0,deckWarnings:Array.isArray(e.deckWarnings)?[...e.deckWarnings]:[],tagsHint:Array.isArray(e.tagsHint)?e.tagsHint.filter(n=>typeof n=="string"):[],lastSyncedAt:typeof e.lastSyncedAt=="number"?e.lastSyncedAt:0,orphan:!!e.orphan}}function bu(e){return e==="cloze"||e==="semantic-qa"?e:"basic"}function yu(e,t){let n=Dt(e.noteId);return n===void 0||!t.trim()?null:{groupId:t,noteId:n,filePath:typeof e.filePath=="string"?e.filePath:"",headingText:typeof e.headingText=="string"?e.headingText:"",backlinkHeadingText:typeof e.backlinkHeadingText=="string"?e.backlinkHeadingText:typeof e.headingText=="string"?e.headingText:"",headingLevel:typeof e.headingLevel=="number"?e.headingLevel:1,stem:typeof e.stem=="string"?e.stem:"",src:typeof e.src=="string"?e.src:"",blockStartOffset:typeof e.blockStartOffset=="number"?e.blockStartOffset:0,blockEndOffset:typeof e.blockEndOffset=="number"?e.blockEndOffset:0,blockStartLine:typeof e.blockStartLine=="number"?e.blockStartLine:1,bodyStartLine:typeof e.bodyStartLine=="number"?e.bodyStartLine:1,blockEndLine:typeof e.blockEndLine=="number"?e.blockEndLine:1,contentEndLine:typeof e.contentEndLine=="number"?e.contentEndLine:1,markerLine:typeof e.markerLine=="number"?e.markerLine:void 0,markerIndent:typeof e.markerIndent=="string"?e.markerIndent:void 0,rawBlockText:typeof e.rawBlockText=="string"?e.rawBlockText:"",rawBlockHash:typeof e.rawBlockHash=="string"?e.rawBlockHash:"",deck:typeof e.deck=="string"?e.deck:"",deckHint:typeof e.deckHint=="string"?e.deckHint:void 0,deckHintSource:e.deckHintSource==="frontmatter"||e.deckHintSource==="body"?e.deckHintSource:void 0,deckWarnings:Array.isArray(e.deckWarnings)?[...e.deckWarnings]:[],tagsHint:Array.isArray(e.tagsHint)?e.tagsHint.filter(r=>typeof r=="string"):[],items:Array.isArray(e.items)?e.items.flatMap(r=>{if(!r||typeof r!="object")return[];let i=r;return typeof i.title!="string"||typeof i.answer!="string"||typeof i.ordinalInMarkdown!="number"?[]:[{itemId:typeof i.itemId=="string"?i.itemId:void 0,title:i.title,answer:i.answer,slot:typeof i.slot=="number"?i.slot:void 0,ordinalInMarkdown:i.ordinalInMarkdown}]}):[],freeSlots:Array.isArray(e.freeSlots)?e.freeSlots.filter(r=>typeof r=="number"&&Number.isInteger(r)&&r>0):[],lastSyncedAt:typeof e.lastSyncedAt=="number"?e.lastSyncedAt:0,orphan:!!e.orphan}}function xu(e,t,n){let r=new Set;if(Array.isArray(e.noteIds))for(let i of e.noteIds){let a=Dt(i);a!==void 0&&n[N(a)]&&r.add(a)}if(Array.isArray(e.cardIds))for(let i of e.cardIds){let a=Dt(t[i]?.noteId);a!==void 0&&n[N(a)]&&r.add(a)}return Array.from(r)}function Su(e,t){return Array.isArray(e.groupIds)?e.groupIds.filter(n=>typeof n=="string"&&!!t[n]):[]}function Dt(e){return typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0}function Fi(e){e.addCommand({id:"sync-current-file-to-anki",name:m("commands.syncCurrentFileToAnki"),callback:()=>{e.runSyncCurrentFile()}}),e.addCommand({id:"sync-vault-to-anki",name:m("commands.syncVaultToAnki"),callback:()=>{e.runSyncVault()}}),e.addCommand({id:"clear-current-file-synced-cards",name:m("commands.clearCurrentFileSyncedCards"),callback:()=>{e.runClearCurrentFileSyncedCards()}}),e.addCommand({id:"cleanup-empty-decks",name:m("commands.cleanupEmptyDecks"),callback:()=>{e.runCleanupEmptyDecks()}})}var Ve=require("obsidian");var Et=class extends Ve.Modal{constructor(n,r){super(n);this.candidateDeckNames=r;this.deckToggles=new Map;this.selectedDeckNames=new Set;this.resolvedValue=null}openAndGetSelection(){return new Promise(n=>{this.resolver=n,this.open()})}onOpen(){let{contentEl:n}=this;n.empty(),n.createEl("h2",{text:m("modal.emptyDeck.title")}),n.createEl("p",{text:m("modal.emptyDeck.description")});for(let i of this.candidateDeckNames)new Ve.Setting(n).setName(i).addToggle(a=>{this.deckToggles.set(i,a),a.setValue(!1).onChange(o=>{o?this.selectedDeckNames.add(i):this.selectedDeckNames.delete(i),this.refreshSelectionState()})});let r=new Ve.Setting(n).addButton(i=>{i.setButtonText(m("modal.emptyDeck.selectAll")).onClick(()=>{this.selectAllDecks()})}).addButton(i=>{i.setButtonText(m("modal.emptyDeck.clearAll")).onClick(()=>{this.clearSelectedDecks()})}).addButton(i=>{i.setButtonText(m("modal.emptyDeck.invert")).onClick(()=>{this.invertSelectedDecks()})}).addButton(i=>{i.setButtonText(m("modal.emptyDeck.cancel")).onClick(()=>{this.finish(null)})}).addButton(i=>{this.deleteButton=i,i.setButtonText(m("modal.emptyDeck.deleteSelected")).setCta().onClick(()=>{this.finish(Array.from(this.selectedDeckNames))})});this.selectionCountEl=r.settingEl.createEl("span",{text:this.getSelectionCountText()}),this.selectionCountEl.addClass("anki-helper-empty-deck-selection-count"),this.refreshSelectionState()}onClose(){let n=this.resolver,r=this.resolvedValue;this.contentEl.empty(),this.deckToggles.clear(),this.deleteButton=void 0,this.selectionCountEl=void 0,this.resolver=void 0,this.resolvedValue=null,this.selectedDeckNames.clear(),n?.(r)}finish(n){this.resolvedValue=n,this.close()}selectAllDecks(){this.selectedDeckNames.clear();for(let n of this.candidateDeckNames)this.selectedDeckNames.add(n),this.deckToggles.get(n)?.setValue(!0);this.refreshSelectionState()}clearSelectedDecks(){this.selectedDeckNames.clear();for(let n of this.candidateDeckNames)this.deckToggles.get(n)?.setValue(!1);this.refreshSelectionState()}invertSelectedDecks(){let n=new Set;for(let r of this.candidateDeckNames){let i=!this.selectedDeckNames.has(r);this.deckToggles.get(r)?.setValue(i),i&&n.add(r)}this.selectedDeckNames.clear();for(let r of n)this.selectedDeckNames.add(r);this.refreshSelectionState()}refreshSelectionState(){this.deleteButton?.setDisabled(this.selectedDeckNames.size===0),this.selectionCountEl&&(this.selectionCountEl.textContent=this.getSelectionCountText())}getSelectionCountText(){return m("modal.emptyDeck.selectionCount",{selected:this.selectedDeckNames.size,total:this.candidateDeckNames.length})}};var Ln=require("obsidian");var _t=class{info(t){new Ln.Notice(t,5e3)}error(t){new Ln.Notice(t,8e3)}showSyncSummary(t,n){let r=ie(),o=[m(t==="currentFile"?"notice.summary.currentFileSync":"notice.summary.vaultSync",{scannedFiles:n.scannedFiles,scannedCards:n.scannedCards,created:n.created,updated:n.updated,migratedNoteTypes:n.migratedNoteTypes,migratedDecks:n.migratedDecks,orphaned:n.orphaned,uploadedMedia:n.uploadedMedia,skippedUnchangedCards:n.skippedUnchangedCards})];n.markerWriteConflictFiles.length>0&&o.push(m("notice.summary.markerWriteConflicts",{files:ae(r,n.markerWriteConflictFiles)})),n.warnings.length>0&&o.push(m("notice.summary.warningsCount",{count:n.warnings.length})),this.info(o.join(" "));for(let u of n.warnings.slice(0,3))this.info(this.renderDeckWarning(u))}showRebuildSummary(t){let n=ie(),r=[m("notice.summary.rebuild",{scannedFiles:t.scannedFiles,scannedCards:t.scannedCards,migratedDecks:t.migratedDecks,orphaned:t.orphaned,rewrittenMarkers:t.rewrittenMarkers,skippedUnchangedCards:t.skippedUnchangedCards})];t.markerWriteConflictFiles.length>0&&r.push(m("notice.summary.markerWriteConflicts",{files:ae(n,t.markerWriteConflictFiles)})),t.warnings.length>0&&r.push(m("notice.summary.warningsCount",{count:t.warnings.length})),this.info(r.join(" "));for(let i of t.warnings.slice(0,3))this.info(this.renderDeckWarning(i))}showClearCurrentFileSummary(t){let n=ie(),r=[m("notice.summary.clearCurrentFile",{trackedCards:t.trackedCards,trackedGroups:t.trackedGroups,deletedNotes:t.deletedNotes,removedMarkers:t.removedMarkers,removedCardMarkers:t.removedCardMarkers,removedGroupMarkers:t.removedGroupMarkers,deletedLocalRecords:t.deletedLocalRecords})];t.conflictFiles.length>0&&r.push(m("notice.summary.markerRemovalConflicts",{files:ae(n,t.conflictFiles)})),t.failureFiles.length>0&&r.push(m("notice.summary.failures",{items:Jr(t.failureFiles)})),this.info(r.join(" "))}showCleanupEmptyDecksSummary(t){let n=ie(),r=[m("notice.summary.cleanupEmptyDecks",{candidateCount:t.candidateCount,selectedCount:t.selectedCount,deletedCount:t.deletedCount,skippedCount:t.skippedDeckNames.length})];t.skippedDeckNames.length>0&&r.push(m("notice.summary.skippedDecks",{decks:ae(n,t.skippedDeckNames)})),this.info(r.join(" "))}renderDeckWarning(t){return m(Cu(t.code),t.params)}};function Cu(e){switch(e){case"deck_conflict_yaml_body":return"warnings.deck.conflictYamlBody";case"deck_multiple_body_declarations":return"warnings.deck.multipleBodyDeclarations";case"deck_invalid_folder_segment":return"warnings.deck.invalidFolderSegment";case"deck_fallback_default":return"warnings.deck.fallbackDefault"}}var B=require("obsidian");function vi(e){return e==="cloze"}function Ti(e){return e!=="cloze"}var _e=class{map(t,n,r){return this.mapRenderedCard(t,n,r)}mapRenderedCard(t,n,r){let i=this.getRequiredMapping(t,r);return this.validateMapping(i,n),Ti(t.type)?this.mapBasic(t,i):this.mapCloze(t,i)}suggest(t,n,r,i=Date.now()){if(t==="qa-group")throw new Error("QaGroupFieldMappingService must be used for qa-group mappings.");return Mu(t)?{cardType:t,modelName:n,loadedFieldNames:[...r],titleField:It(r,["Front","Title"])??r[0],bodyField:It(r,["Back","Body","Answer"])??r.find(a=>a!==(It(r,["Front","Title"])??r[0])),loadedAt:i}:{cardType:t,modelName:n,loadedFieldNames:[...r],mainField:It(r,["Text","Body","Content"])??r[0],loadedAt:i}}validateMapping(t,n){if(!wn(t)&&!jr(t))throw new Error("QaGroupFieldMappingService validates qa-group mappings.");let r=new Set(n.fieldNames);if(wn(t)){if(!t.titleField||!t.bodyField)throw new C(Ai(t.cardType),{modelName:t.modelName});if(t.titleField===t.bodyField)throw new C(Fu(t.cardType),{modelName:t.modelName});let i=[t.titleField,t.bodyField].filter(a=>!r.has(a));if(i.length>0)throw new C("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:i.map(a=>`"${a}"`)});return}if(!t.mainField)throw new C("errors.noteFieldMapping.incompleteSavedMapping.cloze",{modelName:t.modelName});if(!r.has(t.mainField))throw new C("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:[`"${t.mainField}"`]})}mapBasic(t,n){let r=n.titleField,i=n.bodyField;if(!r||!i)throw new C(Ai(t.type),{modelName:t.noteModel});return{[r]:t.renderedFields.title,[i]:t.renderedFields.body}}mapCloze(t,n){if(!n.mainField)throw new C("errors.noteFieldMapping.incompleteSavedMapping.cloze",{modelName:t.noteModel});return{[n.mainField]:`${t.renderedFields.title}

${t.renderedFields.body}`}}getRequiredMapping(t,n){let r=n[L(t.type,t.noteModel)];if(!r)throw new C(wu(t.type),{modelName:t.noteModel});return r}};function Mu(e){return e==="basic"||e==="semantic-qa"}function wu(e){return e==="cloze"?"errors.noteFieldMapping.missingSavedMapping.cloze":e==="semantic-qa"?"errors.noteFieldMapping.missingSavedMapping.semanticQa":"errors.noteFieldMapping.missingSavedMapping.basic"}function Ai(e){return e==="cloze"?"errors.noteFieldMapping.incompleteSavedMapping.cloze":e==="semantic-qa"?"errors.noteFieldMapping.incompleteSavedMapping.semanticQa":"errors.noteFieldMapping.incompleteSavedMapping.basic"}function Fu(e){return e==="semantic-qa"?"errors.noteFieldMapping.titleBodyMustDiffer.semanticQa":"errors.noteFieldMapping.titleBodyMustDiffer.basic"}function It(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function _i(e,t){let n=new Set(Nn(t));return e.map(r=>Li(r,n,!1))}function Ii(e,t,n,r){let i=vu(e),a=new Set(Nn(t).filter(u=>i.nodeByPath.has(u)));if(!i.nodeByPath.has(n))return Lt(e,Array.from(a));if(r)return Di(n,a,i.parentByPath)||(Ei(a,n),a.add(n)),Lt(e,Array.from(a));let o=Di(n,a,i.parentByPath);if(o&&(a.delete(o),o!==n)){let u=i.nodeByPath.get(o);if(u)for(let s of Pi(u,n))a.add(s)}return Ei(a,n),Lt(e,Array.from(a))}function Lt(e,t){let n=new Set(Nn(t));return e.flatMap(r=>Ni(r,n).paths)}function Li(e,t,n){let r=n||t.has(e.path),i=e.children.map(o=>Li(o,t,r));if(r)return{...e,checked:!0,indeterminate:!1,children:i};let a=i.some(o=>o.checked||o.indeterminate);return{...e,checked:!1,indeterminate:a,children:i}}function Ni(e,t){return t.has(e.path)?{paths:[e.path]}:e.children.length===0?{paths:[]}:{paths:e.children.map(r=>Ni(r,t)).flatMap(r=>r.paths)}}function vu(e){let t=new Map,n=new Map,r=(i,a)=>{t.set(i.path,i),n.set(i.path,a);for(let o of i.children)r(o,i.path)};for(let i of e)r(i,void 0);return{nodeByPath:t,parentByPath:n}}function Di(e,t,n){let r=e;for(;r;){if(t.has(r))return r;r=n.get(r)}}function Ei(e,t){for(let n of Array.from(e))(n===t||Ri(n,t))&&e.delete(n)}function Pi(e,t){if(e.path===t)return[];let n=e.children.find(i=>i.path===t||Ri(t,i.path));if(!n)return[e.path];let r=[];for(let i of e.children){if(i.path===n.path){r.push(...Pi(i,t));continue}r.push(i.path)}return r}function Nn(e){return Array.from(new Set(e.map(t=>Tu(t)).filter(Boolean)))}function Tu(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function Ri(e,t){return e===t||e.startsWith(`${t}/`)}var Bi={key:"settings.scope.loading"},Au=500,Gi=["card-types","sync-content","deck","scope","commands"],Nt=["basic","qa-group","cloze"],Du=8,Eu=64,Ie="var(--modal-background, var(--background-primary))",Rn="--ahs-settings-page-header-height",Wi="--ahs-settings-sticky-card-gap",$i=`${Eu}px`,Qi=`${Du}px`,_u=`var(${Rn}, ${$i})`,Iu=`var(${Wi}, ${Qi})`,qi="12px",Lu="-128px",Hi="-24px",zi="32px",Pt=class extends B.PluginSettingTab{constructor(n){super(n.app,n);this.noteFieldMappingService=new _e;this.qaGroupFieldMappingService=new pe;this.availableNoteModels=[];this.draftMappings={};this.loadedModelDetails={};this.debouncedTextSaves=new Map;this.textDraftValues=new Map;this.cardShells=new Map;this.expandedCardIds=new Set;this.expandedFolderPaths=new Set;this.folderTree=[];this.folderTreeStatus=Bi;this.folderTreeLoadPromise=null;this.hasLoadedFolderTree=!1;this.displayInitialized=!1;this.ankiConfigLoading=!1;this.cardTypeStatusOverride=null;this.noteTypeCacheCheckStatus="idle";this.noteTypeCacheCheckPromise=null;this.detectedAnkiNoteTypeCache=null;this.noteTypeCacheCheckToken=0;this.pageHeaderResizeObserver=null;this.scopeNeedsSelectedAncestorExpansion=!0;this.plugin=n}hide(){this.disconnectPageHeaderResizeObserver(),super.hide(),this.displayInitialized=!1,this.cardShells.clear(),this.clearDebouncedTextSaves(),this.cardTypeStatusOverride=null,this.noteTypeCacheCheckStatus="idle",this.noteTypeCacheCheckPromise=null,this.detectedAnkiNoteTypeCache=null,this.noteTypeCacheCheckToken+=1,this.scopeNeedsSelectedAncestorExpansion=!0}display(){let{containerEl:n}=this,r=n.scrollTop;if(!this.displayInitialized){n.style.setProperty(Rn,$i),n.style.setProperty(Wi,Qi),n.empty();let i=n.createDiv();i.dataset.settingsPageHeader="true",i.style.position="sticky",i.style.top="0px",i.style.zIndex="300",i.style.width="100%",i.style.boxSizing="border-box",i.style.paddingTop=qi,i.style.paddingBottom=`calc(${qi} + ${Iu})`,i.style.marginBottom="0",i.style.overflow="visible",i.style.background=Ie,i.style.backgroundColor=Ie,i.style.boxShadow="none";let a=i.createDiv();a.dataset.settingsPageHeaderMask="true",a.style.position="absolute",a.style.top=Lu,a.style.left=Hi,a.style.right=Hi,a.style.bottom="0px",a.style.zIndex="0",a.style.pointerEvents="none",a.style.background=Ie,a.style.backgroundColor=Ie;let o=i.createEl("h2",{text:m("settings.pluginTitle")});o.style.margin="0",o.style.position="relative",o.style.zIndex="1",this.observePageHeaderHeight(i);let u=n.createDiv();u.dataset.settingsCardsContainer="true",this.initializeCards(u),this.displayInitialized=!0}for(let i of Gi)this.renderCard(i);n.scrollTop=r}initializeCards(n){this.cardShells.clear();for(let r of Gi){let i=n.createDiv();i.dataset.settingsCard=r;let a=i.createEl("button");a.type="button",a.dataset.settingsCardToggle=r,a.style.display="flex",a.style.alignItems="center",a.style.justifyContent="flex-start",a.style.position="sticky",a.style.top=_u,a.style.zIndex="200",a.style.width="100%",a.style.maxWidth="100%",a.style.boxSizing="border-box",a.style.padding="10px 14px",a.style.fontSize="1.5em",a.style.fontWeight="600",a.style.background=Ie,a.style.backgroundColor=Ie,a.style.border="2px solid var(--background-modifier-border)",a.style.borderRadius="0",a.style.marginBottom="8px",a.style.textAlign="left",a.style.boxShadow="none",a.addEventListener("click",()=>{this.toggleCard(r)});let o=i.createDiv();o.dataset.settingsCardBody=r,this.cardShells.set(r,{cardEl:i,headerEl:a,bodyEl:o})}}toggleCard(n){this.expandedCardIds.has(n)?this.expandedCardIds.delete(n):this.expandedCardIds.add(n),this.renderCard(n)}renderCard(n){let r=this.cardShells.get(n);if(!r)return;let i=this.expandedCardIds.has(n);if(r.headerEl.textContent=`${i?"\u25BE":"\u25B8"} ${this.getCardTitle(n)}`,r.headerEl.setAttr("aria-expanded",String(i)),r.bodyEl.style.display=i?"block":"none",r.bodyEl.empty(),!!i){if(n==="card-types"){this.renderCardTypesCard(r.bodyEl);return}if(n==="sync-content"){this.renderSyncContentCard(r.bodyEl);return}if(n==="scope"){this.renderScopeCard(r.bodyEl);return}if(n==="deck"){this.renderDeckCard(r.bodyEl);return}this.renderCommandsCard(r.bodyEl)}}observePageHeaderHeight(n){this.disconnectPageHeaderResizeObserver(),this.updatePageHeaderHeight(n),!(typeof ResizeObserver>"u")&&(this.pageHeaderResizeObserver=new ResizeObserver(()=>{this.updatePageHeaderHeight(n)}),this.pageHeaderResizeObserver.observe(n))}updatePageHeaderHeight(n){let r=n.getBoundingClientRect().height;!Number.isFinite(r)||r<=0||this.containerEl.style.setProperty(Rn,`${Math.round(r)}px`)}disconnectPageHeaderResizeObserver(){this.pageHeaderResizeObserver?.disconnect(),this.pageHeaderResizeObserver=null}renderCardTypesCard(n){this.hydrateVisibleCardTypeCaches(),this.maybeStartNoteTypeCacheCheck();let r=n.createDiv();r.style.display="flex",r.style.flexDirection="column",r.style.alignItems="flex-start",r.style.gap="8px";let i=r.createEl("button",{text:this.ankiConfigLoading?m("settings.cards.cardTypes.loadAnki.loading"):m("settings.cards.cardTypes.loadAnki.button")});i.type="button",i.dataset.cardTypesRefresh="true",i.disabled=this.ankiConfigLoading,i.addEventListener("click",()=>this.loadAnkiCardTypeConfig()),r.createEl("span",{text:`${m("settings.cards.cardTypes.statusLabel")}${Te(this.getCardTypeStatusMessage())}`});let a=n.createDiv();a.dataset.cardTypeList="true",a.style.display="flex",a.style.flexDirection="column",a.style.gap="14px";for(let o of Nt)this.renderCardTypeBlock(a,o)}renderCardTypeBlock(n,r){let i=this.plugin.settings.cardTypeConfigs[r],a=n.createDiv();a.dataset.cardTypeConfig=r,a.style.display="flex",a.style.flexDirection="column",a.style.gap="8px",a.style.padding="12px",a.style.border="1px solid var(--background-modifier-border)",a.style.borderRadius="8px";let o=a.createDiv();o.style.display="flex",o.style.alignItems="center",o.style.gap="10px";let u=o.createEl("input");u.type="checkbox",u.checked=i.enabled,u.dataset.cardTypeEnabled=r,u.addEventListener("change",()=>this.saveCardTypeConfig(r,{enabled:u.checked}));let s=o.createEl("strong",{text:this.getCardTypeLabel(r)});s.style.fontSize="var(--font-ui-medium)";let c=a.createDiv();c.style.display="flex",c.style.flexWrap="wrap",c.style.alignItems="center",c.style.gap="10px 14px";let d=this.createInlineControlGroup(c,m("settings.cards.cardTypes.labels.headingLevel")),l=this.createSelect(d,`card-type-heading:${r}`);l.dataset.cardTypeHeading=r,l.style.width="88px";for(let k=1;k<=6;k+=1)this.appendOption(l,String(k),`H${k}`);l.value=String(i.headingLevel),l.addEventListener("change",()=>this.saveCardTypeConfig(r,{headingLevel:Number(l.value)}));let g=this.createInlineControlGroup(c,m("settings.cards.cardTypes.labels.extraMarker")).createEl("input");g.type="text",g.dataset.cardTypeMarker=r,g.placeholder=m("settings.cards.cardTypes.markerPlaceholder"),g.style.width="220px",g.value=this.getDraftValue(`card-type-marker:${r}`,i.extraMarker),g.addEventListener("input",()=>{this.scheduleDebouncedTextSave(`card-type-marker:${r}`,g.value,async k=>{await this.saveCardTypeConfig(r,{extraMarker:k})&&this.textDraftValues.delete(`card-type-marker:${r}`)})});let p=a.createDiv();p.style.display="grid",p.style.gridTemplateColumns="minmax(0, 1.1fr) minmax(0, 0.75fr) minmax(220px, 0.95fr)",p.style.alignItems="center",p.style.columnGap="16px",p.style.rowGap="8px",p.style.overflow="visible",p.style.width="100%";let M=this.createGridControlSlot(p,m("settings.cards.cardTypes.labels.noteType")),b=this.createSelect(M,`card-type-note-type:${r}`);b.dataset.cardTypeNoteType=r,this.applyFluidEllipsis(b);for(let k of this.getSelectableNoteModels(i.noteType))this.appendOption(b,k,k);b.value=i.noteType,b.disabled=this.ankiConfigLoading,b.addEventListener("change",()=>this.saveCardTypeConfig(r,{noteType:b.value})),this.renderCardTypeFieldControls(p,r)}renderCardTypeFieldControls(n,r){if(r==="qa-group"){this.renderQaGroupFieldControls(n,r);return}let i=this.getCurrentMappingForConfig(r);if(r==="cloze"){let d=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.mainField")),l=this.createFieldSelect(d,`card-type-question-field:${r}`),f=i&&"mainField"in i?i:void 0;l.dataset.cardTypeQuestionField=r,this.applyFluidEllipsis(l),this.populateFieldSelect(l,f?.loadedFieldNames??[],f?.mainField),l.addEventListener("change",()=>this.saveFieldMapping(r,{mainField:l.value||void 0}));return}let a=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.questionField")),o=this.createFieldSelect(a,`card-type-question-field:${r}`),u=i&&"bodyField"in i?i:void 0;o.dataset.cardTypeQuestionField=r,this.applyFluidEllipsis(o),this.populateFieldSelect(o,u?.loadedFieldNames??[],u?.titleField),o.addEventListener("change",()=>this.saveFieldMapping(r,{titleField:o.value||void 0}));let s=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.answerField")),c=this.createFieldSelect(s,`card-type-answer-field:${r}`);c.dataset.cardTypeAnswerField=r,this.applyFluidEllipsis(c),this.populateFieldSelect(c,u?.loadedFieldNames??[],u?.bodyField),c.addEventListener("change",()=>this.saveFieldMapping(r,{bodyField:c.value||void 0}))}renderQaGroupFieldControls(n,r){let i=this.plugin.settings.cardTypeConfigs[r].noteType.trim(),a=this.getQaGroupFieldState(r),o=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.qaGroupTitleField"));if(a.mapping){let f=this.createFieldSelect(o,`card-type-qa-group-title-field:${r}`);f.dataset.qaGroupTitleField=r,this.applyFluidEllipsis(f),this.populateFieldSelect(f,a.mapping.loadedFieldNames,a.mapping.titleField),f.addEventListener("change",()=>this.saveFieldMapping(r,{titleField:f.value||void 0}))}else o.createEl("span",{text:i.length>0?m("settings.cards.cardTypes.qaGroup.unavailable"):m("settings.cards.cardTypes.qaGroup.noModel")}).dataset.qaGroupTitleField=r;let s=this.createGridControlSlot(n,m("settings.cards.cardTypes.labels.qaGroupSlotFields")).createEl("span",{text:a.mapping?m("settings.cards.cardTypes.qaGroup.detectedSlots",{count:a.mapping.slots.length}):i.length>0?m("settings.cards.cardTypes.qaGroup.unavailable"):m("settings.cards.cardTypes.qaGroup.noModel")});if(s.dataset.qaGroupSlotSummary=r,this.applyFluidEllipsis(s),a.error){let f=n.createDiv({text:Te(a.error)});f.dataset.qaGroupError=r,f.style.gridColumn="1 / -1";return}if(!a.mapping||a.mapping.warnings.length===0)return;let c=n.createDiv();c.dataset.qaGroupWarnings=r,c.style.gridColumn="1 / -1",c.style.display="flex",c.style.flexDirection="column",c.style.gap="6px",c.createEl("strong",{text:m("settings.cards.cardTypes.labels.qaGroupWarnings")});for(let f of a.mapping.warnings)c.createEl("div",{text:this.renderQaGroupWarning(f)}).dataset.qaGroupWarning=r;let d=c.createEl("label");d.style.display="inline-flex",d.style.alignItems="center",d.style.gap="8px";let l=d.createEl("input");l.type="checkbox",l.checked=ut(a.mapping.warnings,a.mapping.acceptedWarnings),l.dataset.qaGroupWarningAccept=r,l.addEventListener("change",()=>this.saveQaGroupWarningAcceptance(r,l.checked)),d.createEl("span",{text:m("settings.cards.cardTypes.qaGroup.acceptWarnings")})}renderSyncContentCard(n){let r=this.createSyncContentSection(n,"body-range",m("settings.cards.syncContent.sections.bodyRange"));new B.Setting(r).setName(m("settings.cardAnswerCutoffMode.name")).setDesc(m("settings.cardAnswerCutoffMode.desc")).addDropdown(u=>{u.addOption("heading-block",m("settings.cardAnswerCutoffMode.options.headingBlock")),u.addOption("double-blank-lines",m("settings.cardAnswerCutoffMode.options.doubleBlankLines")),u.setValue(this.plugin.settings.cardAnswerCutoffMode).onChange(s=>{this.plugin.updateSettings({cardAnswerCutoffMode:s})})});let i=this.createSyncContentSection(n,"backlink",m("settings.cards.syncContent.sections.backlink"));new B.Setting(i).setName(m("settings.syncOptions.addObsidianBacklink.name")).setDesc(m("settings.syncOptions.addObsidianBacklink.desc")).addToggle(u=>{u.setValue(this.plugin.settings.addObsidianBacklink).onChange(s=>{this.plugin.updateSettings({addObsidianBacklink:s})})}),new B.Setting(i).setName(m("settings.syncOptions.obsidianBacklinkLabel.name")).setDesc(m("settings.syncOptions.obsidianBacklinkLabel.desc")).addText(u=>{u.setPlaceholder(m("settings.syncOptions.obsidianBacklinkLabel.placeholder")).setValue(this.getDraftValue("obsidian-backlink-label",this.plugin.settings.obsidianBacklinkLabel)).onChange(s=>{this.scheduleDebouncedTextSave("obsidian-backlink-label",s,async c=>{let d=c.trim();await this.plugin.updateSettings({obsidianBacklinkLabel:d||Ue}),this.textDraftValues.delete("obsidian-backlink-label")})})}),new B.Setting(i).setName(m("settings.syncOptions.obsidianBacklinkPlacement.name")).setDesc(m("settings.syncOptions.obsidianBacklinkPlacement.desc")).addDropdown(u=>{u.addOption("question-last-line",m("settings.syncOptions.obsidianBacklinkPlacement.options.questionLastLine")),u.addOption("answer-first-line",m("settings.syncOptions.obsidianBacklinkPlacement.options.answerFirstLine")),u.addOption("answer-last-line",m("settings.syncOptions.obsidianBacklinkPlacement.options.answerLastLine")),u.setValue(this.plugin.settings.obsidianBacklinkPlacement).onChange(s=>{this.plugin.updateSettings({obsidianBacklinkPlacement:s})})});let a=this.createSyncContentSection(n,"tags",m("settings.cards.syncContent.sections.tags"));new B.Setting(a).setName(m("settings.syncOptions.syncObsidianTagsToAnki.name")).setDesc(m("settings.syncOptions.syncObsidianTagsToAnki.desc")).addToggle(u=>{u.setValue(this.plugin.settings.syncObsidianTagsToAnki).onChange(s=>{this.plugin.updateSettings({syncObsidianTagsToAnki:s})})}),new B.Setting(a).setName(m("settings.syncOptions.keepPureTagLinesInCardBody.name")).setDesc(m("settings.syncOptions.keepPureTagLinesInCardBody.desc")).addToggle(u=>{u.setValue(this.plugin.settings.keepPureTagLinesInCardBody).onChange(s=>{this.plugin.updateSettings({keepPureTagLinesInCardBody:s})})});let o=this.createSyncContentSection(n,"cloze-special",m("settings.cards.syncContent.sections.clozeSpecial"));new B.Setting(o).setName(m("settings.syncOptions.highlightsToCloze.name")).setDesc(m("settings.syncOptions.highlightsToCloze.desc")).addToggle(u=>{u.setValue(this.plugin.settings.convertHighlightsToCloze).onChange(s=>{this.plugin.updateSettings({convertHighlightsToCloze:s})})})}createSyncContentSection(n,r,i){let a=n.createDiv();a.dataset.syncContentSection=r,a.style.display="flex",a.style.flexDirection="column",a.style.gap="8px",a.style.marginTop="16px";let o=a.createEl("h4",{text:i});return o.dataset.syncContentSectionTitle=r,o.style.margin="0",a}renderScopeCard(n){if(new B.Setting(n).setName(m("settings.scope.name")).setDesc(Nu(this.plugin.settings.scopeMode)).addDropdown(s=>{s.addOption("all",m("settings.scope.option.all")).addOption("include",m("settings.scope.option.include")).addOption("exclude",m("settings.scope.option.exclude")).setValue(this.plugin.settings.scopeMode).onChange(c=>{c!=="all"&&c!=="include"&&c!=="exclude"||this.updateScopeMode(c)})}),this.plugin.settings.scopeMode==="all")return;let i=n.createDiv().createEl("button",{text:m("settings.cards.scope.refreshFolders")});if(i.type="button",i.dataset.scopeRefreshFolders="true",i.disabled=!!this.folderTreeLoadPromise,i.addEventListener("click",()=>{this.refreshFolderTree()}),this.ensureFolderTreeLoaded(),n.createEl("p",{text:Ru(this.plugin.settings.scopeMode)}),this.folderTreeLoadPromise||this.folderTree.length===0){n.createEl("p",{text:Te(this.folderTreeStatus)});return}this.expandSelectedFolderAncestorsIfNeeded(this.plugin.settings.scopeMode);let a=this.getSelectedFoldersForScopeMode(this.plugin.settings.scopeMode),o=_i(this.folderTree,a),u=n.createDiv();u.dataset.scopeTree="true",u.style.display="flex",u.style.flexDirection="column",u.style.gap="2px";for(let s of o)this.renderFolderNode(u,s,this.plugin.settings.scopeMode,0)}renderDeckCard(n){let r=this.createDeckSection(n,"folder-mapping",m("settings.cards.deck.sections.folderMapping"));new B.Setting(r).setName(m("settings.deck.folderDeckMode.name")).setDesc(m("settings.deck.folderDeckMode.desc")).addDropdown(o=>{this.populateFolderDeckModeDropdown(o,this.plugin.settings.folderDeckMode),o.onChange(u=>{u!=="off"&&u!=="folder"&&u!=="folder-and-file"||this.plugin.updateSettings({folderDeckMode:u})})}),this.renderDeckExampleBlock(r);let i=this.createDeckSection(n,"file-deck",m("settings.cards.deck.sections.fileDeck"));new B.Setting(i).setName(m("settings.deck.fileDeckEnabled.name")).setDesc(m("settings.deck.fileDeckEnabled.desc")).addToggle(o=>{o.setValue(this.plugin.settings.fileDeckEnabled).onChange(async u=>{await this.plugin.updateSettings({fileDeckEnabled:u}),this.renderCard("deck")})}),this.plugin.settings.fileDeckEnabled&&(new B.Setting(i).setName(m("settings.deck.marker.name")).setDesc(m("settings.deck.marker.desc")).addText(o=>{o.setValue(this.getDraftValue("file-deck-marker",this.plugin.settings.fileDeckMarker)).onChange(u=>{this.scheduleDebouncedTextSave("file-deck-marker",u,async s=>{let c=s.trim();if(!c){this.textDraftValues.delete("file-deck-marker"),this.renderCard("deck");return}await this.plugin.updateSettings({fileDeckMarker:c}),this.textDraftValues.delete("file-deck-marker")})})}),new B.Setting(i).setName(m("settings.deck.template.name")).setDesc(m("settings.deck.template.desc")).addText(o=>{o.setValue(this.getDraftValue("file-deck-template",this.plugin.settings.fileDeckTemplate)).onChange(u=>{this.scheduleDebouncedTextSave("file-deck-template",u,async s=>{let c=s.trim();if(!c){this.textDraftValues.delete("file-deck-template"),this.renderCard("deck");return}await this.plugin.updateSettings({fileDeckTemplate:c}),this.textDraftValues.delete("file-deck-template")})})}),new B.Setting(i).setName(m("settings.deck.insertLocation.name")).setDesc(m("settings.deck.insertLocation.desc")).addDropdown(o=>{this.populateFileDeckInsertLocationDropdown(o,this.plugin.settings.fileDeckInsertLocation),o.onChange(u=>{u!=="yaml"&&u!=="body"||this.plugin.updateSettings({fileDeckInsertLocation:u})})}),new B.Setting(i).setName(m("settings.deck.insertTemplate.name")).setDesc(m("settings.deck.insertTemplate.desc")).addButton(o=>{o.setButtonText(m("settings.deck.insertTemplate.button")).onClick(()=>{this.plugin.insertDeckTemplateToCurrentFile()})}));let a=this.createDeckSection(n,"default-deck",m("settings.cards.deck.sections.defaultDeck"));new B.Setting(a).setName(m("settings.deck.defaultDeck.name")).setDesc(m("settings.deck.defaultDeck.desc")).addText(o=>{o.setValue(this.getDraftValue("default-deck",this.plugin.settings.defaultDeck)).onChange(u=>{this.scheduleDebouncedTextSave("default-deck",u,async s=>{let c=s.trim();if(!c){this.textDraftValues.delete("default-deck"),this.renderCard("deck");return}await this.plugin.updateSettings({defaultDeck:c}),this.textDraftValues.delete("default-deck")})})}),this.createDeckHelperText(a,m("settings.deck.fallbackDesc"),"fallback"),this.createDeckPriorityFooter(n)}renderDeckExampleBlock(n){let r=n.createDiv();r.dataset.deckExampleBlock="true",r.style.display="flex",r.style.flexDirection="column",r.style.gap="4px",r.style.marginTop="2px",r.style.marginLeft=zi;let i=r.createEl("strong",{text:m("settings.deck.examplesTitle")});i.style.fontSize="var(--font-ui-small)";for(let a of[m("settings.deck.folderExample"),m("settings.deck.folderAndFileExample")]){let o=r.createDiv({text:a});o.dataset.deckExampleRow="true",o.style.color="var(--text-muted)",o.style.fontSize="var(--font-ui-small)",o.style.lineHeight="1.4"}}createDeckHelperText(n,r,i){let a=n.createDiv({text:r});return a.dataset.deckHelperText=i,a.style.color="var(--text-muted)",a.style.fontSize="var(--font-ui-small)",a.style.lineHeight="1.4",a.style.marginTop="2px",a.style.marginLeft=zi,a}createDeckPriorityFooter(n){let r=this.createDeckHelperText(n,m("settings.deck.priorityDesc"),"priority");r.dataset.deckPriorityFooter="true",r.style.marginTop="12px"}createDeckSection(n,r,i){let a=n.createDiv();a.dataset.deckSection=r,a.style.display="flex",a.style.flexDirection="column",a.style.gap="8px",a.style.marginTop="16px";let o=a.createEl("h4",{text:i});return o.dataset.deckSectionTitle=r,o.style.margin="0",a}renderCommandsCard(n){n.createEl("p",{text:m("settings.cards.commands.desc")});let r=n.createEl("ul");for(let[i,a]of[[m("commands.syncCurrentFileToAnki"),m("settings.cards.commands.items.syncCurrentFile")],[m("commands.syncVaultToAnki"),m("settings.cards.commands.items.syncVault")],[m("commands.clearCurrentFileSyncedCards"),m("settings.cards.commands.items.clearCurrentFile")],[m("commands.cleanupEmptyDecks"),m("settings.cards.commands.items.cleanupDecks")]])r.createEl("li",{text:`${i}: ${a}`})}async saveCardTypeConfig(n,r){let i={...this.plugin.settings.cardTypeConfigs,[n]:{...this.plugin.settings.cardTypeConfigs[n],...r}};try{oe(ke({...this.plugin.settings,cardTypeConfigs:i}))}catch(a){return this.cardTypeStatusOverride=Ae(a,"settings.cards.cardTypes.failedSave"),this.renderCard("card-types"),!1}if(this.cardTypeStatusOverride=null,await this.plugin.updateSettings({cardTypeConfigs:i}),n==="qa-group"&&typeof r.noteType=="string"){await this.syncQaGroupMappingFromCache(i[n].noteType);let a=L("qa-group",i[n].noteType);if(!this.plugin.settings.noteFieldMappings[a]){let o=this.plugin.settings.ankiModelFieldCache[i[n].noteType];if(o){let u=this.qaGroupFieldMappingService.suggest(i[n].noteType,o.fieldNames,o.loadedAt);await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[a]:u}})}}}return(n==="basic"||n==="cloze")&&typeof r.noteType=="string"&&await this.syncFieldMappingFromCache(n),this.renderCard("card-types"),!0}async saveFieldMapping(n,r){let i=this.getCurrentMappingForConfig(n),a=this.getRuntimeCardType(n),o=this.plugin.settings.cardTypeConfigs[n].noteType,u=L(a,o),s={...i??this.createFallbackMapping(a,o),...r};this.cardTypeStatusOverride=null,this.draftMappings[u]=s,await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[u]:{...s,loadedFieldNames:[...s.loadedFieldNames]}}}),this.renderCard("card-types")}async loadAnkiCardTypeConfig(){this.noteTypeCacheCheckToken+=1,this.noteTypeCacheCheckPromise=null,this.cardTypeStatusOverride=null,this.noteTypeCacheCheckStatus=this.resolveManualRefreshCacheStatus(),this.ankiConfigLoading=!0,this.renderCard("card-types");try{let n=await this.plugin.listNoteModels(),r=Oi(n);this.availableNoteModels.splice(0,this.availableNoteModels.length,...r);let i=await this.plugin.getModelFieldNamesByModelNames(r),a=Date.now(),o=Object.entries(i).reduce((s,[c,d])=>(s[c]={fieldNames:[...d],loadedAt:a},s),{});await this.plugin.updateSettings({ankiNoteTypeCache:this.getAvailableNoteModels(),ankiModelFieldCache:o}),this.hydrateVisibleCardTypeCaches(o),await this.syncVisibleFieldMappingsFromCache(o),await this.syncQaGroupMappingFromCache(this.plugin.settings.cardTypeConfigs["qa-group"].noteType,o);let u=this.countConfiguredCardTypes(o);this.detectedAnkiNoteTypeCache=[...r],this.noteTypeCacheCheckStatus="same",this.cardTypeStatusOverride={key:"settings.cards.cardTypes.loadedSummary",params:{noteTypeCount:this.availableNoteModels.length,configuredCount:u}}}catch(n){this.cardTypeStatusOverride=Ae(n,"settings.cards.cardTypes.failedLoad")}finally{this.ankiConfigLoading=!1,this.renderCard("card-types")}}maybeStartNoteTypeCacheCheck(){if(this.ankiConfigLoading||this.plugin.settings.ankiNoteTypeCache.length===0||this.noteTypeCacheCheckStatus!=="idle"||this.noteTypeCacheCheckPromise)return;this.noteTypeCacheCheckStatus="checking";let n=++this.noteTypeCacheCheckToken,r=this.checkNoteTypeCacheFreshness(n).finally(()=>{this.noteTypeCacheCheckPromise===r&&(this.noteTypeCacheCheckPromise=null),n===this.noteTypeCacheCheckToken&&this.renderCard("card-types")});this.noteTypeCacheCheckPromise=r}async checkNoteTypeCacheFreshness(n){try{let r=Oi(await this.plugin.listNoteModels());if(n!==this.noteTypeCacheCheckToken)return;this.detectedAnkiNoteTypeCache=r,this.noteTypeCacheCheckStatus=Pu(this.plugin.settings.ankiNoteTypeCache,r)?"same":"changed"}catch{if(n!==this.noteTypeCacheCheckToken)return;this.noteTypeCacheCheckStatus="failed"}}getCardTypeStatusMessage(){if(this.ankiConfigLoading)return{key:"settings.cards.cardTypes.loadAnki.loading"};if(this.cardTypeStatusOverride)return this.cardTypeStatusOverride;let n=this.plugin.settings.ankiNoteTypeCache.length;if(n===0)return{key:"settings.cards.cardTypes.cacheEmpty"};let r=this.countConfiguredCardTypes(this.plugin.settings.ankiModelFieldCache);return this.noteTypeCacheCheckStatus==="changed"?{key:"settings.cards.cardTypes.cacheChanged",params:{cachedCount:n,liveCount:this.detectedAnkiNoteTypeCache?.length??n,configuredCount:r}}:this.noteTypeCacheCheckStatus==="failed"?{key:"settings.cards.cardTypes.cacheCheckFailed",params:{noteTypeCount:n,configuredCount:r}}:{key:"settings.cards.cardTypes.cacheSummary",params:{noteTypeCount:n,configuredCount:r}}}resolveManualRefreshCacheStatus(){return this.noteTypeCacheCheckStatus==="changed"||this.noteTypeCacheCheckStatus==="failed"?this.noteTypeCacheCheckStatus:this.plugin.settings.ankiNoteTypeCache.length>0?"same":"idle"}hydrateVisibleCardTypeCaches(n=this.plugin.settings.ankiModelFieldCache){for(let r of Nt)this.hydrateCardTypeCache(r,n)}hydrateCardTypeCache(n,r){let i=this.getRuntimeCardType(n),a=this.plugin.settings.cardTypeConfigs[n].noteType,o=L(i,a),u=r[a];if(!u)return;let s=this.createCachedModelDetails(a,u.fieldNames);this.loadedModelDetails[o]=s,this.seedDraftMapping(i,a,s,u.loadedAt)}async syncVisibleFieldMappingsFromCache(n=this.plugin.settings.ankiModelFieldCache){for(let r of Nt)r!=="qa-group"&&await this.syncFieldMappingFromCache(r,n)}async syncFieldMappingFromCache(n,r=this.plugin.settings.ankiModelFieldCache){let i=this.getRuntimeCardType(n),a=this.plugin.settings.cardTypeConfigs[n].noteType.trim(),o=r[a];if(!o)return;let u=L(i,a),s=this.plugin.settings.noteFieldMappings[u]??this.draftMappings[u],c=s?{...s,loadedFieldNames:[...o.fieldNames],loadedAt:o.loadedAt}:this.noteFieldMappingService.suggest(i,a,o.fieldNames,o.loadedAt);this.draftMappings[u]=c,!Pn(this.plugin.settings.noteFieldMappings[u],c)&&await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[u]:c}})}createCachedModelDetails(n,r){return{fieldNames:[...r],isCloze:!1}}countConfiguredCardTypes(n){return Nt.reduce((r,i)=>{let a=this.plugin.settings.cardTypeConfigs[i];return a.enabled?r+(n[a.noteType]?1:0):r},0)}seedDraftMapping(n,r,i,a=Date.now()){let o=L(n,r),u=this.plugin.settings.noteFieldMappings[o]??this.draftMappings[o];if(n==="qa-group"){if(W(u)){this.draftMappings[o]=this.refreshSavedQaGroupMapping(u,i.fieldNames,a);return}try{this.draftMappings[o]=this.qaGroupFieldMappingService.suggest(r,i.fieldNames,a,void 0,void 0)}catch{delete this.draftMappings[o]}return}if(u){this.draftMappings[o]={...u,loadedFieldNames:[...i.fieldNames],loadedAt:a};return}this.draftMappings[o]=this.noteFieldMappingService.suggest(n,r,i.fieldNames,a)}getSelectableNoteModels(n){let r=this.availableNoteModels.length>0?this.getAvailableNoteModels():[...this.plugin.settings.ankiNoteTypeCache];return r.includes(n)||r.unshift(n),r}getAvailableNoteModels(){return[...this.availableNoteModels]}getCurrentMappingForConfig(n){let r=this.getRuntimeCardType(n),i=this.plugin.settings.cardTypeConfigs[n].noteType,a=L(r,i),o=this.draftMappings[a]??this.plugin.settings.noteFieldMappings[a];if(o)return{...o,loadedFieldNames:[...o.loadedFieldNames]};let u=this.loadedModelDetails[a];if(!u)return;if(r==="qa-group")try{let c=this.plugin.settings.noteFieldMappings[a]??this.draftMappings[a],d=this.qaGroupFieldMappingService.suggest(i,u.fieldNames,Date.now(),W(c)?c.acceptedWarnings:void 0,W(c)?c.titleField:void 0);return this.draftMappings[a]=d,{...d,loadedFieldNames:[...d.loadedFieldNames],slots:d.slots.map(l=>({...l})),warnings:[...d.warnings],acceptedWarnings:d.acceptedWarnings?[...d.acceptedWarnings]:void 0}}catch{return}let s=this.noteFieldMappingService.suggest(r,i,u.fieldNames);return this.draftMappings[a]=s,{...s,loadedFieldNames:[...s.loadedFieldNames]}}createFallbackMapping(n,r){let i=L(n,r),a=this.loadedModelDetails[i];if(a){if(n==="qa-group"){let o=this.plugin.settings.noteFieldMappings[i]??this.draftMappings[i];return this.qaGroupFieldMappingService.suggest(r,a.fieldNames,Date.now(),W(o)?o.acceptedWarnings:void 0,W(o)?o.titleField:void 0)}return this.noteFieldMappingService.suggest(n,r,a.fieldNames)}return n==="qa-group"?{cardType:n,modelName:r,titleField:void 0,slots:[],warnings:[],acceptedWarnings:void 0,loadedFieldNames:[],loadedAt:Date.now()}:{cardType:n,modelName:r,loadedFieldNames:[],loadedAt:Date.now()}}async saveQaGroupWarningAcceptance(n,r){let i=this.getCurrentMappingForConfig(n);if(!i||!W(i))return;let a=this.getRuntimeCardType(n),o=L(a,i.modelName),u={...i,slots:i.slots.map(s=>({...s})),warnings:[...i.warnings],acceptedWarnings:r?[...i.warnings]:void 0,loadedFieldNames:[...i.loadedFieldNames]};this.cardTypeStatusOverride=null,this.draftMappings[o]=u,await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[o]:u}}),this.renderCard("card-types")}async syncQaGroupMappingFromCache(n,r=this.plugin.settings.ankiModelFieldCache){let i=n.trim();if(i.length===0)return;let a=r[i];if(!a)return;let o=L("qa-group",i),u=this.plugin.settings.noteFieldMappings[o]??this.draftMappings[o];if(W(u)){let s=this.refreshSavedQaGroupMapping(u,a.fieldNames,a.loadedAt);this.draftMappings[o]=s,Pn(this.plugin.settings.noteFieldMappings[o],s)||await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[o]:s}});return}try{let s=this.qaGroupFieldMappingService.suggest(i,a.fieldNames,a.loadedAt,void 0,void 0);this.draftMappings[o]=s,Pn(this.plugin.settings.noteFieldMappings[o],s)||await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[o]:s}})}catch{if(delete this.draftMappings[o],this.plugin.settings.noteFieldMappings[o]){let s={...this.plugin.settings.noteFieldMappings};delete s[o],await this.plugin.updateSettings({noteFieldMappings:s})}}}getQaGroupFieldState(n){let r=this.plugin.settings.cardTypeConfigs[n].noteType,i=L("qa-group",r),a=this.draftMappings[i]??this.plugin.settings.noteFieldMappings[i];if(a&&W(a))return{mapping:{...a,loadedFieldNames:[...a.loadedFieldNames],slots:a.slots.map(u=>({...u})),warnings:[...a.warnings],acceptedWarnings:a.acceptedWarnings?[...a.acceptedWarnings]:void 0}};let o=this.loadedModelDetails[i];if(!o)return{};try{let u=this.plugin.settings.noteFieldMappings[i]??this.draftMappings[i];return{mapping:this.qaGroupFieldMappingService.suggest(r,o.fieldNames,Date.now(),W(u)?u.acceptedWarnings:void 0,W(u)?u.titleField:void 0)}}catch(u){return{error:Ae(u,"settings.cards.cardTypes.failedSave")}}}refreshSavedQaGroupMapping(n,r,i){return{...n,loadedFieldNames:[...r],slots:n.slots.map(a=>({...a})),warnings:[...n.warnings],acceptedWarnings:n.acceptedWarnings?[...n.acceptedWarnings]:void 0,loadedAt:i}}renderQaGroupWarning(n){let r=ni(n);if(!r)return n;let i=String(r.index).padStart(2,"0");return r.kind==="missing-answer"?m("settings.cards.cardTypes.qaGroup.warning.missingAnswer",{index:i,questionField:r.questionField,answerField:r.answerField}):m("settings.cards.cardTypes.qaGroup.warning.missingQuestion",{index:i,questionField:r.questionField,answerField:r.answerField})}getRuntimeCardType(n){return n==="qa-group"?"qa-group":n==="cloze"?"cloze":n==="semantic-qa"?"semantic-qa":"basic"}ensureFolderTreeLoaded(n=!1){n&&(this.hasLoadedFolderTree=!1,this.folderTree=[]),!(this.hasLoadedFolderTree||this.folderTreeLoadPromise)&&(this.folderTreeStatus=Bi,this.folderTreeLoadPromise=this.plugin.listFolderTree().then(r=>{this.folderTree=r,this.folderTreeStatus=r.length>0?{rawMessage:""}:{key:"settings.scope.empty"},this.requestSelectedFolderAncestorExpansion()}).catch(r=>{this.folderTree=[],this.folderTreeStatus=Ae(r,"settings.scope.failedLoad")}).finally(()=>{this.hasLoadedFolderTree=!0,this.folderTreeLoadPromise=null,this.renderCard("scope")}))}async refreshFolderTree(){this.expandedFolderPaths.clear(),this.ensureFolderTreeLoaded(!0),this.renderCard("scope")}async updateScopeMode(n){await this.plugin.updateSettings({scopeMode:n}),n!=="all"&&(this.requestSelectedFolderAncestorExpansion(),this.ensureFolderTreeLoaded()),this.renderCard("scope")}async updateFolderSelection(n,r,i){let a=n==="include"?this.plugin.settings.includeFolders:this.plugin.settings.excludeFolders,o=Ii(this.folderTree,a,r,i);await this.plugin.updateSettings(n==="include"?{includeFolders:o}:{excludeFolders:o}),this.renderCard("scope")}renderFolderNode(n,r,i,a){let o=n.createDiv();o.dataset.folderRow=r.path,o.style.display="grid",o.style.gridTemplateColumns="24px 24px minmax(0, 1fr)",o.style.alignItems="center",o.style.columnGap="0px",o.style.minHeight="28px",o.style.marginLeft=`${a*18}px`,o.style.width="100%",o.style.boxSizing="border-box";let u=r.children.length>0,s=u&&this.expandedFolderPaths.has(r.path),c=o.createEl(u?"button":"span");c.dataset.folderToggle=r.path,c.textContent=u?s?"\u25BE":"\u25B8":"",c.style.width="24px",c.style.height="24px",c.style.display="inline-flex",c.style.alignItems="center",c.style.justifyContent="center",c.style.padding="0",c.style.margin="0",c.style.border="0",c.style.background="transparent",c.style.boxShadow="none",c.style.fontSize="2em",c.style.lineHeight="1",c.style.color="var(--text-muted)",u&&(c.setAttr("aria-label",s?m("settings.scope.collapseFolder",{name:r.name}):m("settings.scope.expandFolder",{name:r.name})),c.setAttr("title",s?m("settings.scope.collapseFolder",{name:r.name}):m("settings.scope.expandFolder",{name:r.name})),c.style.cursor="pointer",c.addEventListener("click",()=>{this.expandedFolderPaths.has(r.path)?this.expandedFolderPaths.delete(r.path):this.expandedFolderPaths.add(r.path),this.renderCard("scope")}));let d=o.createEl("input");d.type="checkbox",d.checked=r.checked,d.indeterminate=r.indeterminate,d.dataset.folderPath=r.path,d.style.margin="0",d.style.justifySelf="center",d.addEventListener("change",()=>{this.updateFolderSelection(i,r.path,d.checked)});let l=o.createEl("span",{text:r.name});if(l.dataset.folderPathLabel=r.path,l.style.minWidth="0",l.style.overflow="hidden",l.style.textOverflow="ellipsis",l.style.whiteSpace="nowrap",!u||!s)return;let f=n.createDiv();f.dataset.folderChildren=r.path,f.style.display="flex",f.style.flexDirection="column",f.style.gap="2px";for(let g of r.children)this.renderFolderNode(f,g,i,a+1)}requestSelectedFolderAncestorExpansion(){this.scopeNeedsSelectedAncestorExpansion=!0}expandSelectedFolderAncestorsIfNeeded(n){if(this.scopeNeedsSelectedAncestorExpansion){this.scopeNeedsSelectedAncestorExpansion=!1;for(let r of this.getSelectedFoldersForScopeMode(n))for(let i of Bu(r))this.expandedFolderPaths.add(i)}}getSelectedFoldersForScopeMode(n){return n==="include"?this.plugin.settings.includeFolders:this.plugin.settings.excludeFolders}createInlineControlGroup(n,r){let i=n.createEl("label");i.style.display="inline-flex",i.style.alignItems="center",i.style.gap="6px",i.style.flexWrap="nowrap";let a=i.createEl("span",{text:r});return a.style.whiteSpace="nowrap",i}createGridControlSlot(n,r){let i=n.createEl("label");i.style.display="flex",i.style.alignItems="center",i.style.gap="8px",i.style.minWidth="0",i.style.overflow="visible";let a=i.createEl("span",{text:r});a.style.whiteSpace="nowrap",a.style.flex="0 0 auto";let o=i.createDiv();return o.style.flex="1 1 0",o.style.minWidth="0",o.style.overflow="visible",o}applyFluidEllipsis(n){let r=(n.tagName||n.tag||"").toLowerCase(),i=r==="select"||r==="input";n.style.boxSizing="border-box",n.style.width=i?"calc(100% - 2px)":"100%",n.style.maxWidth=i?"calc(100% - 2px)":"100%",n.style.minWidth="0",n.style.margin=i?"1px":"0",n.style.overflow=i?"visible":"hidden",n.style.textOverflow="ellipsis",n.style.whiteSpace="nowrap"}scheduleDebouncedTextSave(n,r,i){this.textDraftValues.set(n,r);let a=this.debouncedTextSaves.get(n);a&&globalThis.clearTimeout(a);let o=globalThis.setTimeout(()=>{i(this.textDraftValues.get(n)??r).finally(()=>{this.debouncedTextSaves.delete(n)})},Au);this.debouncedTextSaves.set(n,o)}clearDebouncedTextSaves(){for(let n of this.debouncedTextSaves.values())globalThis.clearTimeout(n);this.debouncedTextSaves.clear()}getDraftValue(n,r){return this.textDraftValues.get(n)??r}createSelect(n,r){let i=n.createEl("select");return i.dataset.selectKey=r,i}createFieldSelect(n,r){return this.createSelect(n,r)}appendOption(n,r,i){let a=n.createEl("option",{text:i});a.value=r}populateFieldSelect(n,r,i){n.empty(),this.appendOption(n,"",r.length>0?m("settings.mapping.selectFieldPlaceholder"):m("settings.cards.cardTypes.fieldsUnavailable"));for(let a of r)this.appendOption(n,a,a);n.value=i??""}populateFileDeckInsertLocationDropdown(n,r){n.addOption("body",m("settings.deck.insertLocation.options.body")),n.addOption("yaml",m("settings.deck.insertLocation.options.yaml")),n.setValue(r)}populateFolderDeckModeDropdown(n,r){n.addOption("off",m("settings.deck.folderDeckMode.options.off")),n.addOption("folder",m("settings.deck.folderDeckMode.options.folder")),n.addOption("folder-and-file",m("settings.deck.folderDeckMode.options.folderAndFile")),n.setValue(r)}getCardTitle(n){return n==="card-types"?m("settings.cards.cardTypes.title"):n==="sync-content"?m("settings.cards.syncContent.title"):n==="scope"?m("settings.cards.scope.title"):n==="deck"?m("settings.cards.deck.title"):m("settings.cards.commands.title")}getCardTypeLabel(n){return n==="basic"?m("settings.cards.cardTypes.rows.basic"):n==="qa-group"?m("settings.cards.cardTypes.rows.qaGroup"):n==="cloze"?m("settings.cards.cardTypes.rows.cloze"):m("settings.cards.cardTypes.rows.semanticQa")}};function Nu(e){return e==="include"?m("settings.scope.summary.include"):e==="exclude"?m("settings.scope.summary.exclude"):m("settings.scope.summary.all")}function Pn(e,t){return JSON.stringify(e)===JSON.stringify(t)}function Oi(e){let t=new Set;for(let n of e){if(typeof n!="string")continue;let r=n.trim();r.length>0&&t.add(r)}return[...t].sort((n,r)=>n.localeCompare(r))}function Pu(e,t){return e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function Ru(e){return e==="include"?m("settings.scope.treeDescription.include"):m("settings.scope.treeDescription.exclude")}function Bu(e){let t=e.split("/").filter(r=>r.length>0),n=[];for(let r=1;r0?e.message.trim():String(e)}var Bt=class{async runCollectBatches(t,n,r,i){if(t.length===0)return[];let a=Hu(t,n),o=new Array(a.length),u=0;return await Promise.all(Array.from({length:Math.min(r,a.length)},async()=>{for(;u(await i(a),[]))}};function Hu(e,t){let n=[];for(let r=0;ri.has(a))}function je(e,t){let n=Gt(e),r=Gt(t),i=new Set(n),a=new Set(r);return{addTags:n.filter(o=>!a.has(o)),removeTags:r.filter(o=>!i.has(o))}}var qt=class{constructor(t,n=new _e,r=new Bt){this.ankiGateway=t;this.noteFieldMappingService=n;this.batchScheduler=r}async execute(t,n,r,i){let a=new Map,o=new Map,u=new Set,s=new Map,c=0,d=0,l=0,f=0,g=Array.from(new Set([...t.toUpdate,...t.toVerifyDeck,...t.toRewriteMarker,...t.toChangeDeck].flatMap(y=>y.noteId?[y.noteId]:[]))),p=await this.batchScheduler.runCollectBatches(g,100,1,y=>this.ankiGateway.getNoteSummaries(y)),M=new Map(p.map(y=>[y.noteId,y])),b=[],k=[],S=[],x=[],h=new Set(t.toChangeDeck.map(y=>y.card.syncKey));for(let y of t.toCreate)b.push(await this.requireRenderedCard(y,n,r));for(let y of t.toUpdate){if(y.noteId&&M.has(y.noteId)){let T=await this.requireRenderedCard(y,n,r),D=M.get(y.noteId);D&&D.modelName!==T.noteModel?S.push({plannedCard:y,renderedCard:T,summary:D}):k.push({plannedCard:y,renderedCard:T});continue}b.push(await this.requireRenderedCard(y,n,r)),s.set(y.card.syncKey,y)}for(let y of t.toRewriteMarker)if(!s.has(y.card.syncKey)){if(y.noteId&&M.has(y.noteId)){s.set(y.card.syncKey,y),o.set(y.card.syncKey,y.noteId);continue}b.push(await this.requireRenderedCard(y,n,r)),s.set(y.card.syncKey,y)}for(let y of t.toVerifyDeck){if(!y.noteId)continue;let T=M.get(y.noteId);T&&zu(T,y.deck,h.has(y.card.syncKey))&&(x.push(y),o.set(y.card.syncKey,y.noteId))}await this.batchScheduler.runVoidBatches(Array.from(new Set([...b.map(y=>y.deck),...x.map(y=>y.deck)])),50,1,y=>this.ankiGateway.ensureDecks(y));let w=await this.uploadMedia([...b,...k.map(y=>y.renderedCard),...S.map(y=>y.renderedCard)]),v=await this.batchScheduler.runCollectBatches(b,50,1,async y=>this.ankiGateway.addNotes(await Promise.all(y.map(async T=>({deckName:T.deck,modelName:T.noteModel,fields:await this.mapFields(T,i,a),tags:T.card.tagsHint})))));for(let y=0;y{await this.ankiGateway.updateNotes(await Promise.all(y.map(async({plannedCard:T,renderedCard:D})=>({noteId:T.noteId??0,fields:await this.mapFields(D,i,a)}))))}),await this.batchScheduler.runVoidBatches(S,25,1,async y=>{for(let{plannedCard:T,renderedCard:D,summary:z}of y){let O=await this.mapFields(D,i,a);try{await this.ankiGateway.updateNoteModel({noteId:T.noteId??0,modelName:D.noteModel,fields:O})}catch(F){throw Rt({noteId:T.noteId??0,fromModel:z.modelName,toModel:D.noteModel,error:F,location:`${T.card.filePath}:${T.card.blockStartLine}`})}}});let _=[...k,...S].flatMap(({plannedCard:y})=>{if(!y.noteId)return[];let T=M.get(y.noteId);if(!T)return[];let D=je(y.card.tagsHint,T.tags);return D.addTags.length===0&&D.removeTags.length===0?[]:[{noteId:y.noteId,addTags:D.addTags,removeTags:D.removeTags}]});await this.batchScheduler.runVoidBatches(_,50,1,y=>this.ankiGateway.syncNoteTags(y)),d+=k.length+S.length,l=S.length;for(let{plannedCard:y}of[...k,...S])y.noteId&&(u.add(y.card.syncKey),o.set(y.card.syncKey,y.noteId));let A=new Map;for(let y of x){let T=y.noteId;if(!T)continue;let D=M.get(T);if(!D||D.cardIds.length===0)continue;let z=A.get(y.deck)??new Set;for(let O of D.cardIds)z.add(O);A.set(y.deck,z)}await this.batchScheduler.runVoidBatches(Array.from(A.entries()).map(([y,T])=>({deckName:y,cardIds:Array.from(T)})),25,1,y=>this.ankiGateway.changeDecks(y)),f=x.length;for(let y of x)u.add(y.card.syncKey);return{created:c,updated:d,migratedNoteTypes:l,migratedDecks:f,uploadedMedia:w,markerWrites:Array.from(s.values()).map(y=>({...y,noteId:o.get(y.card.syncKey)??y.noteId})),resolvedNoteIds:o,touchedSyncKeys:u}}async requireRenderedCard(t,n,r){let i=n.get(t.card.syncKey);if(i)return i;let a=await r(t);return n.set(t.card.syncKey,a),a}async mapFields(t,n,r){let i=await this.getModelDetails(t.noteModel,r);return this.noteFieldMappingService.mapRenderedCard({type:t.card.cardType,noteModel:t.noteModel,renderedFields:t.renderedFields},i,n)}async getModelDetails(t,n){let r=n.get(t);if(r)return r;let i=this.ankiGateway.getModelDetails(t).catch(a=>{throw n.delete(t),a});return n.set(t,i),i}async uploadMedia(t){let n=new Map;for(let r of t)for(let i of r.media)n.set(`${i.kind}:${i.absolutePath}:${i.fileName}`,i);return await this.batchScheduler.runVoidBatches(Array.from(n.values()),10,3,r=>this.ankiGateway.storeMediaFiles(r)),n.size}};function zu(e,t,n){let r=e.deckNames?.filter(i=>i.length>0)??[];return r.length===0?n:r.some(i=>i!==t)}var Le=class{filter(t,n,r,i){let a=Ht(r),o=Ht(i);return t.filter(u=>u.path.toLowerCase().endsWith(".md")?this.isPathInScope(u.path,n,a,o):!1)}isPathInScope(t,n,r,i){let a=Wu(t),o=Ht(r),u=Ht(i);return n==="include"?o.some(s=>ji(a,s)):n==="exclude"?!u.some(s=>ji(a,s)):!0}};function Ht(e){return e.map(Ou).filter(Boolean)}function Ou(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function Wu(e){return e.trim().replace(/\\/g,"/").replace(/^\/+/,"")}function ji(e,t){return e===t||e.startsWith(`${t}/`)}function Ke(e,t,n){return`${e}\0${t}\0${n}`}function zt(e,t,n){return`${e}\0group\0${t}\0${n}`}function be(e,t){return`${e}#${t}`}function Ne(e){let t=$u(e.lines,e.startLine,e.markerAdapter),n=t.find(o=>o.valid);if(n?.marker){let o=e.lines.slice(0,n.index);return{contentLines:o,trailingLines:Vu(e.lines.slice(n.index+1)),contentEndLine:Ot(o,e.startLine,e.fallbackLine),markerLine:e.startLine+n.index,markerIndent:n.indent,marker:n.marker,markerState:"present-valid"}}let r=e.cutoffMode==="double-blank-lines"?Qu(e.lines):void 0;if(r){let o=t.find(s=>!s.valid&&s.index>=r.end),u=e.lines.slice(0,r.start);return{contentLines:u,trailingLines:e.lines.slice(r.end),contentEndLine:Ot(u,e.startLine,e.fallbackLine),markerLine:o?e.startLine+o.index:void 0,markerIndent:o?.indent,markerState:o?"present-invalid":"missing"}}let i=Uu(e.lines),a=i===void 0?void 0:t.find(o=>!o.valid&&o.index===i);if(a){let o=e.lines.filter((u,s)=>s!==a.index);return{contentLines:o,trailingLines:[],contentEndLine:Ot(o,e.startLine,e.fallbackLine),markerLine:e.startLine+a.index,markerIndent:a.indent,markerState:"present-invalid"}}return{contentLines:e.lines,trailingLines:[],contentEndLine:Ot(e.lines,e.startLine,e.fallbackLine),markerState:"missing"}}function $u(e,t,n){let r=[],i=null;for(let a=0;a=2&&n!==void 0)return{start:n,end:i};t=t?null:a.slice(0,3),n=void 0,r=0;continue}if(!t){if(!a){n??(n=i),r+=1;continue}if(r>=2&&n!==void 0)return{start:n,end:i};n=void 0,r=0}}if(r>=2&&n!==void 0)return{start:n,end:e.length}}function Ot(e,t,n){for(let r=e.length-1;r>=0;r-=1)if(e[r].trim())return t+r;return n}function Uu(e){for(let t=e.length-1;t>=0;t-=1)if(e[t].trim())return t}function Vu(e){let t=0;for(;t1&&a.push({filePath:r,code:"deck_multiple_body_declarations",params:{marker:i}}),{bodyDeck:o[0],warnings:a}}};function Ku(e){if(e[0]?.trim()==="---"){for(let t=1;t!us(s))),u=[`qa-group:${n}`,...a.map(s=>`${s.title} ${s.answer}`),...o].join(` -`).trimEnd();return{stem:n,items:a,markerState:r.markerState,groupMarker:r.marker,contentEndLine:r.contentEndLine,markerLine:r.markerLine,markerIndent:r.markerIndent,rawBlockText:u,rawBlockHash:z(u)}}};function Ju(e,t){let n=e.trimEnd();return n.endsWith(t)?n.slice(0,n.length-t.length).trimEnd():n}function es(e){let t=[],n=null;for(let i=0;ii.indent.length));return t.filter(i=>i.indent.length===r)}function ts(e,t,n,r){let i,a=t-1,o=null;for(let u=t;ua.indent.length));return n.find(a=>a.indent.length===i)??null}function rs(e){let t=0,n=e.length;for(;tt&&!e[n-1].trim();)n-=1;return e.slice(t,n)}function is(e){return e.match(/^[ \t]*/)?.[0]??""}function Pn(e){return e.startsWith("```")||e.startsWith("~~~")}function as(e){return/^\s*",Pc="<[?][\\s\\S]*?[?]>",Rc="]*>",Bc="",Ia=new RegExp("^(?:"+Ea+"|"+_a+"|"+Nc+"|"+Pc+"|"+Rc+"|"+Bc+")"),La=new RegExp("^(?:"+Ea+"|"+_a+")");var He=[[/^<(script|pre|style|textarea)(?=(\s|>|$))/i,/<\/(script|pre|style|textarea)>/i,!0],[/^/,!0],[/^<\?/,/\?>/,!0],[/^/,!0],[/^/,!0],[new RegExp("^|$))","i"),/^$/,!0],[new RegExp(La.source+"\\s*$"),/^$/,!1]];function mr(e,t,n,r){let i=e.bMarks[t]+e.tShift[t],a=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4||!e.md.options.html||e.src.charCodeAt(i)!==60)return!1;let o=e.src.slice(i,a),u=0;for(;u=4)return!1;let o=e.src.charCodeAt(i);if(o!==35||i>=a)return!1;let u=1;for(o=e.src.charCodeAt(++i);o===35&&i6||ii&&E(e.src.charCodeAt(s-1))&&(a=s),e.line=t+1;let c=e.push("heading_open","h"+String(u),1);c.markup="########".slice(0,u),c.map=[t,e.line];let d=e.push("inline","",0);d.content=e.src.slice(i,a).trim(),d.map=[t,e.line],d.children=[];let l=e.push("heading_close","h"+String(u),-1);return l.markup="########".slice(0,u),!0}function kr(e,t,n){let r=e.md.block.ruler.getRules("paragraph");if(e.sCount[t]-e.blkIndent>=4)return!1;let i=e.parentType;e.parentType="paragraph";let a=0,o,u=t+1;for(;u3)continue;if(e.sCount[u]>=e.blkIndent){let g=e.bMarks[u]+e.tShift[u],p=e.eMarks[u];if(g=p))){a=o===61?1:2;break}}if(e.sCount[u]<0)continue;let f=!1;for(let g=0,p=r.length;g3||e.sCount[a]<0)continue;let c=!1;for(let d=0,l=r.length;d=n||e.sCount[o]=a){e.line=n;break}let s=e.line,c=!1;for(let d=0;d=e.line)throw new Error("block rule didn't increment state.line");break}if(!c)throw new Error("none of the block rules matched");e.tight=!u,e.isEmpty(e.line-1)&&(u=!0),o=e.line,o0&&(this.level++,this._prev_delimiters.push(this.delimiters),this.delimiters=[],i={delimiters:this.delimiters}),this.pendingLevel=this.level,this.tokens.push(r),this.tokens_meta.push(i),r};Je.prototype.scanDelims=function(e,t){let n=this.posMax,r=this.src.charCodeAt(e),i=e>0?this.src.charCodeAt(e-1):32,a=e;for(;a0)return!1;let n=e.pos,r=e.posMax;if(n+3>r||e.src.charCodeAt(n)!==58||e.src.charCodeAt(n+1)!==47||e.src.charCodeAt(n+2)!==47)return!1;let i=e.pending.match(qc);if(!i)return!1;let a=i[1],o=e.md.linkify.matchAtStart(e.src.slice(n-a.length));if(!o)return!1;let u=o.url;if(u.length<=a.length)return!1;let s=u.length;for(;s>0&&u.charCodeAt(s-1)===42;)s--;s!==u.length&&(u=u.slice(0,s));let c=e.md.normalizeLink(u);if(!e.md.validateLink(c))return!1;if(!t){e.pending=e.pending.slice(0,-a.length);let d=e.push("link_open","a",1);d.attrs=[["href",c]],d.markup="linkify",d.info="auto";let l=e.push("text","",0);l.content=e.md.normalizeLinkText(u);let f=e.push("link_close","a",-1);f.markup="linkify",f.info="auto"}return e.pos+=u.length-a.length,!0}function Sr(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==10)return!1;let r=e.pending.length-1,i=e.posMax;if(!t)if(r>=0&&e.pending.charCodeAt(r)===32)if(r>=1&&e.pending.charCodeAt(r-1)===32){let a=r-1;for(;a>=1&&e.pending.charCodeAt(a-1)===32;)a--;e.pending=e.pending.slice(0,a),e.push("hardbreak","br",0)}else e.pending=e.pending.slice(0,-1),e.push("softbreak","br",0);else e.push("softbreak","br",0);for(n++;n?@[]^_`{|}~-".split("").forEach(function(e){Cr[e.charCodeAt(0)]=1});function Mr(e,t){let n=e.pos,r=e.posMax;if(e.src.charCodeAt(n)!==92||(n++,n>=r))return!1;let i=e.src.charCodeAt(n);if(i===10){for(t||e.push("hardbreak","br",0),n++;n=55296&&i<=56319&&n+1=56320&&u<=57343&&(a+=e.src[n+1],n++)}let o="\\"+a;if(!t){let u=e.push("text_special","",0);i<256&&Cr[i]!==0?u.content=a:u.content=o,u.markup=o,u.info="escape"}return e.pos=n+1,!0}function wr(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==96)return!1;let i=n;n++;let a=e.posMax;for(;n=0;r--){let i=t[r];if(i.marker!==95&&i.marker!==42||i.end===-1)continue;let a=t[i.end],o=r>0&&t[r-1].end===i.end+1&&t[r-1].marker===i.marker&&t[r-1].token===i.token-1&&t[i.end+1].token===a.token+1,u=String.fromCharCode(i.marker),s=e.tokens[i.token];s.type=o?"strong_open":"em_open",s.tag=o?"strong":"em",s.nesting=1,s.markup=o?u+u:u,s.content="";let c=e.tokens[a.token];c.type=o?"strong_close":"em_close",c.tag=o?"strong":"em",c.nesting=-1,c.markup=o?u+u:u,c.content="",o&&(e.tokens[t[r-1].token].content="",e.tokens[t[i.end+1].token].content="",r--)}}function Wc(e){let t=e.tokens_meta,n=e.tokens_meta.length;Ba(e,e.delimiters);for(let r=0;r=l)return!1;if(s=p,i=e.md.helpers.parseLinkDestination(e.src,p,e.posMax),i.ok){for(o=e.md.normalizeLink(i.str),e.md.validateLink(o)?p=i.pos:o="",s=p;p=l||e.src.charCodeAt(p)!==41)&&(c=!0),p++}if(c){if(typeof e.env.references>"u")return!1;if(p=0?r=e.src.slice(s,p++):p=g+1):p=g+1,r||(r=e.src.slice(f,g)),a=e.env.references[Ce(r)],!a)return e.pos=d,!1;o=a.href,u=a.title}if(!t){e.pos=f,e.posMax=g;let M=e.push("link_open","a",1),b=[["href",o]];M.attrs=b,u&&b.push(["title",u]),e.linkLevel++,e.md.inline.tokenize(e),e.linkLevel--,e.push("link_close","a",-1)}return e.pos=p,e.posMax=l,!0}function Ar(e,t){let n,r,i,a,o,u,s,c,d="",l=e.pos,f=e.posMax;if(e.src.charCodeAt(e.pos)!==33||e.src.charCodeAt(e.pos+1)!==91)return!1;let g=e.pos+2,p=e.md.helpers.parseLinkLabel(e,e.pos+1,!1);if(p<0)return!1;if(a=p+1,a=f)return!1;for(c=a,u=e.md.helpers.parseLinkDestination(e.src,a,e.posMax),u.ok&&(d=e.md.normalizeLink(u.str),e.md.validateLink(d)?a=u.pos:d=""),c=a;a=f||e.src.charCodeAt(a)!==41)return e.pos=l,!1;a++}else{if(typeof e.env.references>"u")return!1;if(a=0?i=e.src.slice(c,a++):a=p+1):a=p+1,i||(i=e.src.slice(g,p)),o=e.env.references[Ce(i)],!o)return e.pos=l,!1;d=o.href,s=o.title}if(!t){r=e.src.slice(g,p);let M=[];e.md.inline.parse(r,e.md,e.env,M);let b=e.push("image","img",0),k=[["src",d],["alt",""]];b.attrs=k,b.children=M,b.content=r,s&&k.push(["title",s])}return e.pos=a,e.posMax=f,!0}var $c=/^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/,Uc=/^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;function Dr(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==60)return!1;let r=e.pos,i=e.posMax;for(;;){if(++n>=i)return!1;let o=e.src.charCodeAt(n);if(o===60)return!1;if(o===62)break}let a=e.src.slice(r+1,n);if(Uc.test(a)){let o=e.md.normalizeLink(a);if(!e.md.validateLink(o))return!1;if(!t){let u=e.push("link_open","a",1);u.attrs=[["href",o]],u.markup="autolink",u.info="auto";let s=e.push("text","",0);s.content=e.md.normalizeLinkText(a);let c=e.push("link_close","a",-1);c.markup="autolink",c.info="auto"}return e.pos+=a.length+2,!0}if($c.test(a)){let o=e.md.normalizeLink("mailto:"+a);if(!e.md.validateLink(o))return!1;if(!t){let u=e.push("link_open","a",1);u.attrs=[["href",o]],u.markup="autolink",u.info="auto";let s=e.push("text","",0);s.content=e.md.normalizeLinkText(a);let c=e.push("link_close","a",-1);c.markup="autolink",c.info="auto"}return e.pos+=a.length+2,!0}return!1}function Qc(e){return/^\s]/i.test(e)}function Vc(e){return/^<\/a\s*>/i.test(e)}function jc(e){let t=e|32;return t>=97&&t<=122}function Er(e,t){if(!e.md.options.html)return!1;let n=e.posMax,r=e.pos;if(e.src.charCodeAt(r)!==60||r+2>=n)return!1;let i=e.src.charCodeAt(r+1);if(i!==33&&i!==63&&i!==47&&!jc(i))return!1;let a=e.src.slice(r).match(Ia);if(!a)return!1;if(!t){let o=e.push("html_inline","",0);o.content=a[0],Qc(o.content)&&e.linkLevel++,Vc(o.content)&&e.linkLevel--}return e.pos+=a[0].length,!0}var Kc=/^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i,Zc=/^&([a-z][a-z0-9]{1,31});/i;function _r(e,t){let n=e.pos,r=e.posMax;if(e.src.charCodeAt(n)!==38||n+1>=r)return!1;if(e.src.charCodeAt(n+1)===35){let a=e.src.slice(n).match(Kc);if(a){if(!t){let o=a[1][0].toLowerCase()==="x"?parseInt(a[1].slice(1),16):parseInt(a[1],10),u=e.push("text_special","",0);u.content=on(o)?Xe(o):Xe(65533),u.markup=a[0],u.info="entity"}return e.pos+=a[0].length,!0}}else{let a=e.src.slice(n).match(Zc);if(a){let o=me(a[0]);if(o!==a[0]){if(!t){let u=e.push("text_special","",0);u.content=o,u.markup=a[0],u.info="entity"}return e.pos+=a[0].length,!0}}}return!1}function Ga(e){let t={},n=e.length;if(!n)return;let r=0,i=-2,a=[];for(let o=0;os;c-=a[c]+1){let l=e[c];if(l.marker===u.marker&&l.open&&l.end<0){let f=!1;if((l.close||u.open)&&(l.length+u.length)%3===0&&(l.length%3!==0||u.length%3!==0)&&(f=!0),!f){let g=c>0&&!e[c-1].open?a[c-1]+1:0;a[o]=o-c+g,a[c]=g,u.open=!1,l.end=o,l.close=!1,d=-1,i=-2;break}}}d!==-1&&(t[u.marker][(u.open?3:0)+(u.length||0)%3]=d)}}function Ir(e){let t=e.tokens_meta,n=e.tokens_meta.length;Ga(e.delimiters);for(let r=0;r0&&r++,i[t].type==="text"&&t+1=e.pos)throw new Error("inline rule didn't increment state.pos");break}}else e.pos=e.posMax;o||e.pos++,a[t]=e.pos};et.prototype.tokenize=function(e){let t=this.ruler.getRules(""),n=t.length,r=e.posMax,i=e.md.options.maxNesting;for(;e.pos=e.pos)throw new Error("inline rule didn't increment state.pos");break}}if(o){if(e.pos>=r)break;continue}e.pending+=e.src[e.pos++]}e.pending&&e.pushPending()};et.prototype.parse=function(e,t,n,r){let i=new this.State(e,t,n,r);this.tokenize(i);let a=this.ruler2.getRules(""),o=a.length;for(let u=0;u|$))",t.tpl_email_fuzzy="(^|"+n+'|"|\\(|'+t.src_ZCc+")("+t.src_email_name+"@"+t.tpl_host_fuzzy_strict+")",t.tpl_link_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`|\uFF5C]|"+t.src_ZPCc+"))((?![$+<=>^`|\uFF5C])"+t.tpl_host_port_fuzzy_strict+t.src_path+")",t.tpl_link_no_ip_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`|\uFF5C]|"+t.src_ZPCc+"))((?![$+<=>^`|\uFF5C])"+t.tpl_host_port_no_ip_fuzzy_strict+t.src_path+")",t}function Rr(e){return Array.prototype.slice.call(arguments,1).forEach(function(n){n&&Object.keys(n).forEach(function(r){e[r]=n[r]})}),e}function ln(e){return Object.prototype.toString.call(e)}function Yc(e){return ln(e)==="[object String]"}function Xc(e){return ln(e)==="[object Object]"}function Jc(e){return ln(e)==="[object RegExp]"}function za(e){return ln(e)==="[object Function]"}function ed(e){return e.replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}var Wa={fuzzyLink:!0,fuzzyEmail:!0,fuzzyIP:!1};function td(e){return Object.keys(e||{}).reduce(function(t,n){return t||Wa.hasOwnProperty(n)},!1)}var nd={"http:":{validate:function(e,t,n){let r=e.slice(t);return n.re.http||(n.re.http=new RegExp("^\\/\\/"+n.re.src_auth+n.re.src_host_port_strict+n.re.src_path,"i")),n.re.http.test(r)?r.match(n.re.http)[0].length:0}},"https:":"http:","ftp:":"http:","//":{validate:function(e,t,n){let r=e.slice(t);return n.re.no_http||(n.re.no_http=new RegExp("^"+n.re.src_auth+"(?:localhost|(?:(?:"+n.re.src_domain+")\\.)+"+n.re.src_domain_root+")"+n.re.src_port+n.re.src_host_terminator+n.re.src_path,"i")),n.re.no_http.test(r)?t>=3&&e[t-3]===":"||t>=3&&e[t-3]==="/"?0:r.match(n.re.no_http)[0].length:0}},"mailto:":{validate:function(e,t,n){let r=e.slice(t);return n.re.mailto||(n.re.mailto=new RegExp("^"+n.re.src_email_name+"@"+n.re.src_host_strict,"i")),n.re.mailto.test(r)?r.match(n.re.mailto)[0].length:0}}},rd="a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]",id="biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|\u0440\u0444".split("|");function ad(e){e.__index__=-1,e.__text_cache__=""}function od(e){return function(t,n){let r=t.slice(n);return e.test(r)?r.match(e)[0].length:0}}function Oa(){return function(e,t){t.normalize(e)}}function dn(e){let t=e.re=Ha(e.__opts__),n=e.__tlds__.slice();e.onCompile(),e.__tlds_replaced__||n.push(rd),n.push(t.src_xn),t.src_tlds=n.join("|");function r(u){return u.replace("%TLDS%",t.src_tlds)}t.email_fuzzy=RegExp(r(t.tpl_email_fuzzy),"i"),t.link_fuzzy=RegExp(r(t.tpl_link_fuzzy),"i"),t.link_no_ip_fuzzy=RegExp(r(t.tpl_link_no_ip_fuzzy),"i"),t.host_fuzzy_test=RegExp(r(t.tpl_host_fuzzy_test),"i");let i=[];e.__compiled__={};function a(u,s){throw new Error('(LinkifyIt) Invalid schema "'+u+'": '+s)}Object.keys(e.__schemas__).forEach(function(u){let s=e.__schemas__[u];if(s===null)return;let c={validate:null,link:null};if(e.__compiled__[u]=c,Xc(s)){Jc(s.validate)?c.validate=od(s.validate):za(s.validate)?c.validate=s.validate:a(u,s),za(s.normalize)?c.normalize=s.normalize:s.normalize?a(u,s):c.normalize=Oa();return}if(Yc(s)){i.push(u);return}a(u,s)}),i.forEach(function(u){e.__compiled__[e.__schemas__[u]]&&(e.__compiled__[u].validate=e.__compiled__[e.__schemas__[u]].validate,e.__compiled__[u].normalize=e.__compiled__[e.__schemas__[u]].normalize)}),e.__compiled__[""]={validate:null,normalize:Oa()};let o=Object.keys(e.__compiled__).filter(function(u){return u.length>0&&e.__compiled__[u]}).map(ed).join("|");e.re.schema_test=RegExp("(^|(?!_)(?:[><\uFF5C]|"+t.src_ZPCc+"))("+o+")","i"),e.re.schema_search=RegExp("(^|(?!_)(?:[><\uFF5C]|"+t.src_ZPCc+"))("+o+")","ig"),e.re.schema_at_start=RegExp("^"+e.re.schema_search.source,"i"),e.re.pretest=RegExp("("+e.re.schema_test.source+")|("+e.re.host_fuzzy_test.source+")|@","i"),ad(e)}function ud(e,t){let n=e.__index__,r=e.__last_index__,i=e.__text_cache__.slice(n,r);this.schema=e.__schema__.toLowerCase(),this.index=n+t,this.lastIndex=r+t,this.raw=i,this.text=i,this.url=i}function Br(e,t){let n=new ud(e,t);return e.__compiled__[n.schema].normalize(n,e),n}function Q(e,t){if(!(this instanceof Q))return new Q(e,t);t||td(e)&&(t=e,e={}),this.__opts__=Rr({},Wa,t),this.__index__=-1,this.__last_index__=-1,this.__schema__="",this.__text_cache__="",this.__schemas__=Rr({},nd,e),this.__compiled__={},this.__tlds__=id,this.__tlds_replaced__=!1,this.re={},dn(this)}Q.prototype.add=function(t,n){return this.__schemas__[t]=n,dn(this),this};Q.prototype.set=function(t){return this.__opts__=Rr(this.__opts__,t),this};Q.prototype.test=function(t){if(this.__text_cache__=t,this.__index__=-1,!t.length)return!1;let n,r,i,a,o,u,s,c,d;if(this.re.schema_test.test(t)){for(s=this.re.schema_search,s.lastIndex=0;(n=s.exec(t))!==null;)if(a=this.testSchemaAt(t,n[2],s.lastIndex),a){this.__schema__=n[2],this.__index__=n.index+n[1].length,this.__last_index__=n.index+n[0].length+a;break}}return this.__opts__.fuzzyLink&&this.__compiled__["http:"]&&(c=t.search(this.re.host_fuzzy_test),c>=0&&(this.__index__<0||c=0&&(i=t.match(this.re.email_fuzzy))!==null&&(o=i.index+i[1].length,u=i.index+i[0].length,(this.__index__<0||othis.__last_index__)&&(this.__schema__="mailto:",this.__index__=o,this.__last_index__=u))),this.__index__>=0};Q.prototype.pretest=function(t){return this.re.pretest.test(t)};Q.prototype.testSchemaAt=function(t,n,r){return this.__compiled__[n.toLowerCase()]?this.__compiled__[n.toLowerCase()].validate(t,r,this):0};Q.prototype.match=function(t){let n=[],r=0;this.__index__>=0&&this.__text_cache__===t&&(n.push(Br(this,r)),r=this.__last_index__);let i=r?t.slice(r):t;for(;this.test(i);)n.push(Br(this,r)),i=i.slice(this.__last_index__),r+=this.__last_index__;return n.length?n:null};Q.prototype.matchAtStart=function(t){if(this.__text_cache__=t,this.__index__=-1,!t.length)return null;let n=this.re.schema_at_start.exec(t);if(!n)return null;let r=this.testSchemaAt(t,n[2],n[0].length);return r?(this.__schema__=n[2],this.__index__=n.index+n[1].length,this.__last_index__=n.index+n[0].length+r,Br(this,0)):null};Q.prototype.tlds=function(t,n){return t=Array.isArray(t)?t:[t],n?(this.__tlds__=this.__tlds__.concat(t).sort().filter(function(r,i,a){return r!==a[i-1]}).reverse(),dn(this),this):(this.__tlds__=t.slice(),this.__tlds_replaced__=!0,dn(this),this)};Q.prototype.normalize=function(t){t.schema||(t.url="http://"+t.url),t.schema==="mailto:"&&!/^mailto:/i.test(t.url)&&(t.url="mailto:"+t.url)};Q.prototype.onCompile=function(){};var $a=Q;var sd=/^xn--/,cd=/[^\0-\x7F]/,dd=/[\x2E\u3002\uFF0E\uFF61]/g,ld={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},Gr=35,ne=Math.floor,qr=String.fromCharCode;function he(e){throw new RangeError(ld[e])}function pd(e,t){let n=[],r=e.length;for(;r--;)n[r]=t(e[r]);return n}function Qa(e,t){let n=e.split("@"),r="";n.length>1&&(r=n[0]+"@",e=n[1]),e=e.replace(dd,".");let i=e.split("."),a=pd(i,t).join(".");return r+a}function Va(e){let t=[],n=0,r=e.length;for(;n=55296&&i<=56319&&nString.fromCodePoint(...e),gd=function(e){return e>=48&&e<58?26+(e-48):e>=65&&e<91?e-65:e>=97&&e<123?e-97:36},Ua=function(e,t){return e+22+75*(e<26)-((t!=0)<<5)},ja=function(e,t,n){let r=0;for(e=n?ne(e/700):e>>1,e+=ne(e/t);e>Gr*26>>1;r+=36)e=ne(e/Gr);return ne(r+(Gr+1)*e/(e+38))},Ka=function(e){let t=[],n=e.length,r=0,i=128,a=72,o=e.lastIndexOf("-");o<0&&(o=0);for(let u=0;u=128&&he("not-basic"),t.push(e.charCodeAt(u));for(let u=o>0?o+1:0;u=n&&he("invalid-input");let f=gd(e.charCodeAt(u++));f>=36&&he("invalid-input"),f>ne((2147483647-r)/d)&&he("overflow"),r+=f*d;let g=l<=a?1:l>=a+26?26:l-a;if(fne(2147483647/p)&&he("overflow"),d*=p}let c=t.length+1;a=ja(r-s,c,s==0),ne(r/c)>2147483647-i&&he("overflow"),i+=ne(r/c),r%=c,t.splice(r++,0,i)}return String.fromCodePoint(...t)},Za=function(e){let t=[];e=Va(e);let n=e.length,r=128,i=0,a=72;for(let s of e)s<128&&t.push(qr(s));let o=t.length,u=o;for(o&&t.push("-");u=r&&dne((2147483647-i)/c)&&he("overflow"),i+=(s-r)*c,r=s;for(let d of e)if(d2147483647&&he("overflow"),d===r){let l=i;for(let f=36;;f+=36){let g=f<=a?1:f>=a+26?26:f-a;if(l=0))try{t.hostname=Hr.toASCII(t.hostname)}catch{}return Kt(Pe(t))}function Md(e){let t=Ye(e,!0);if(t.hostname&&(!t.protocol||eo.indexOf(t.protocol)>=0))try{t.hostname=Hr.toUnicode(t.hostname)}catch{}return Ze(Pe(t),Ze.defaultChars+"%")}function j(e,t){if(!(this instanceof j))return new j(e,t);t||an(e)||(t=e||{},e="default"),this.inline=new qa,this.block=new Na,this.core=new wa,this.renderer=new ba,this.linkify=new $a,this.validateLink=Sd,this.normalizeLink=Cd,this.normalizeLinkText=Md,this.utils=Vn,this.helpers=Be({},Yn),this.options={},this.configure(e),t&&this.set(t)}j.prototype.set=function(e){return Be(this.options,e),this};j.prototype.configure=function(e){let t=this;if(an(e)){let n=e;if(e=bd[n],!e)throw new Error('Wrong `markdown-it` preset "'+n+'", check name')}if(!e)throw new Error("Wrong `markdown-it` preset, can't be empty");return e.options&&t.set(e.options),e.components&&Object.keys(e.components).forEach(function(n){e.components[n].rules&&t[n].ruler.enableOnly(e.components[n].rules),e.components[n].rules2&&t[n].ruler2.enableOnly(e.components[n].rules2)}),this};j.prototype.enable=function(e,t){let n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach(function(i){n=n.concat(this[i].ruler.enable(e,!0))},this),n=n.concat(this.inline.ruler2.enable(e,!0));let r=e.filter(function(i){return n.indexOf(i)<0});if(r.length&&!t)throw new Error("MarkdownIt. Failed to enable unknown rule(s): "+r);return this};j.prototype.disable=function(e,t){let n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach(function(i){n=n.concat(this[i].ruler.disable(e,!0))},this),n=n.concat(this.inline.ruler2.disable(e,!0));let r=e.filter(function(i){return n.indexOf(i)<0});if(r.length&&!t)throw new Error("MarkdownIt. Failed to disable unknown rule(s): "+r);return this};j.prototype.use=function(e){let t=[this].concat(Array.prototype.slice.call(arguments,1));return e.apply(e,t),this};j.prototype.parse=function(e,t){if(typeof e!="string")throw new Error("Input data should be a String");let n=new this.core.State(e,this,t);return this.core.process(n),n.tokens};j.prototype.render=function(e,t){return t=t||{},this.renderer.render(this.parse(e,t),this.options,t)};j.prototype.parseInline=function(e,t){let n=new this.core.State(e,this,t);return n.inlineMode=!0,this.core.process(n),n.tokens};j.prototype.renderInline=function(e,t){return t=t||{},this.renderer.render(this.parseInline(e,t),this.options,t)};var tt=j;var wd=/^#[^\s#.,,。;;::!?!?()[\]{}<>]+(?:\/[^\s#.,,。;;::!?!?()[\]{}<>]+)*$/u;function pn(e,t){if(t||e.length===0)return e;let n=e.split(/\r?\n/),r=n.filter(i=>!vd(i));return r.length===n.length?e:Td(Fd(r)).join(` -`)}function vd(e){let t=e.trim();return t?t.split(/\s+/).every(n=>wd.test(n)):!1}function Fd(e){let t=0,n=e.length;for(;tt&&!e[n-1].trim();)n-=1;return e.slice(t,n)}function Td(e){let t=[];for(let n of e){let r=n.trim().length===0,i=t[t.length-1],a=i!==void 0&&i.trim().length===0;r&&a||t.push(r?"":n)}return t}var Ad="#[^\\s#.,\uFF0C\u3002;\uFF1B:\uFF1A!?\uFF01\uFF1F()[\\]{}<>]+(?:\\/[^\\s#.,\uFF0C\u3002;\uFF1B:\uFF1A!?\uFF01\uFF1F()[\\]{}<>]+)*";var Dd=/[\p{L}\p{N}_/#]/u,Ed=new Set(["code","pre"]),_d="ahs-ob-tag";function fn(e){if(!e||!e.includes("#"))return e;let t="",n=0,r=[];for(;nn){let s=e.slice(n,a);t+=r.length===0?to(s):s,n=a}if(n>=e.length)break;let o=e.indexOf(">",n);if(o===-1){let s=e.slice(n);t+=r.length===0?to(s):s;break}let u=e.slice(n,o+1);Nd(u,r),t+=u,n=o+1}return t}function to(e){let t=new RegExp(Ad,"gu"),n="",r=0,i;for(;(i=t.exec(e))!==null;){let a=i[0],o=i.index,u=o+a.length;if(!Id(e,o))continue;let s=Mt([a])[0];s&&(n+=e.slice(r,o),n+=Ld(a,s),r=u)}return r===0?e:n+e.slice(r)}function Id(e,t){return t===0?!0:!Dd.test(e[t-1]??"")}function Ld(e,t){return`${no(e)}`}function Nd(e,t){let n=/^<\s*(\/)?\s*([a-zA-Z0-9-]+)/.exec(e);if(!n)return;let r=!!n[1],i=n[2]?.toLowerCase();if(!(!i||!Ed.has(i))){if(r){for(let a=t.length-1;a>=0;a-=1)if(t[a]===i){t.splice(a,1);break}return}/\/\s*>$/.test(e)||t.push(i)}}function no(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var gn=class{constructor(t=new Z){this.deckNormalizationService=t}mapFilePathToDeck(t,n){if(n==="off")return{warnings:[]};let r=t.lastIndexOf("/");if(r<0)return{warnings:[]};let i=t.slice(0,r);if(!i.trim())return{warnings:[]};let a=i.split("/").filter(Boolean);if(n==="folder-and-file"){let o=t.slice(r+1).replace(/\.[^.]+$/,"").trim();o&&a.push(o)}return a.some(o=>o.includes("::"))?{warnings:[{filePath:t,code:"deck_invalid_folder_segment"}]}:{deck:this.deckNormalizationService.normalize(a.join("/")),warnings:[]}}};var ze=class{constructor(t=new gn,n=new Z){this.folderDeckMappingService=t;this.deckNormalizationService=n}resolve(t,n,r){if(t.deckHint)return{resolvedDeck:{value:this.deckNormalizationService.normalize(t.deckHint),source:t.deckHintSource??"body"},warnings:[...t.deckWarnings]};let i=this.folderDeckMappingService.mapFilePathToDeck(t.filePath,r);return i.deck?{resolvedDeck:{value:i.deck,source:"folder"},warnings:[...t.deckWarnings,...i.warnings]}:{resolvedDeck:{value:this.deckNormalizationService.normalize(n),source:"default"},warnings:[...t.deckWarnings,...i.warnings,{filePath:t.filePath,code:"deck_fallback_default"}]}}};function Oe(e){return`${e.filePath}\0${e.code}\0${zr(e.params)}`}function zr(e){return e===void 0?"":e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(n=>zr(n)).join(",")}]`:`{${Object.entries(e).sort(([n],[r])=>n.localeCompare(r)).map(([n,r])=>`${JSON.stringify(n)}:${zr(r)}`).join(",")}}`}function mn({href:e,label:t,escapeHref:n=!0}){return`${ro(t)}`}function nt(e,t,n){if(n==="question-last-line")return{title:e.title?`${e.title}
${t}`:t,body:e.body};let r=`

${t}

`;return n==="answer-first-line"?{title:e.title,body:e.body?`${r}${e.body}`:r}:{title:e.title,body:e.body?`${e.body}${r}`:r}}function ro(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var Pd=new tt({breaks:!0,html:!0,linkify:!0}),Rd=/`[^`\n]+`/g,Bd=/==(.+?)==/g,hn=class{constructor(t,n=new pe,r=new ze,i=new V,a=()=>Date.now(),o=()=>`g_${z(`${Date.now()}_${Math.random()}_${Date.now()}`).slice(0,12)}`,u=()=>(this.sequence+=1,`i_${z(`${Date.now()}_${this.sequence}_${Math.random()}`).slice(0,10)}`),s){this.ankiGateway=t;this.qaGroupFieldMappingService=n;this.deckResolutionService=r;this.groupMarkerService=i;this.now=a;this.createGroupId=o;this.createItemId=u;this.createBacklink=s;this.sequence=0}async sync(t,n,r){if(t.length===0)return{created:0,updated:0,migratedNoteTypes:0,migratedDecks:0,markerWrites:[],resolvedNoteIds:new Map,touchedSyncKeys:[],syncedGroupBlocks:[],warnings:[]};let{modelName:i,mapping:a,availableSlots:o,legacyInternalFields:u}=await this.resolveQaGroupModel(r),s=qd(n.groupBlocks??{}),c=new Set,d=new Map,l=[],f=new Map,g=new Set,p=[],M=0,b=0,k=0,S=0,x=this.buildGroupBacklinkAnchor(t[0]??null,r);for(let h of t){if(h.items.length>o.length)throw new C("errors.noteFieldMapping.qaGroupSlotCapacityExceeded",{modelName:i,capacity:o.length,itemCount:h.items.length,filePath:h.filePath,blockStartLine:h.blockStartLine});let w=await this.resolveRecoveredGroup(h,s,i,a,o),F=w.groupId??h.groupId??this.createGroupId(),_=Vd(w.items,o),A=zd(h.items,_,this.createItemId,o);if(A.length>o.length)throw new C("errors.noteFieldMapping.qaGroupSlotCapacityExceeded",{modelName:i,capacity:o.length,itemCount:A.length,filePath:h.filePath,blockStartLine:h.blockStartLine});let y=Od(A,o),T=this.deckResolutionService.resolve({filePath:h.filePath,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:h.deckWarnings},r.defaultDeck,r.folderDeckMode);for(let R of T.warnings)d.set(Oe(R),R);let D=T.resolvedDeck.value;c.has(D)||(await this.ankiGateway.ensureDeckExists(D),c.add(D));let O=A.map(R=>({...R,title:Or(R.title,!1),answer:Or(pn(R.answer,r.keepPureTagLinesInCardBody),!0)})),W=Gd(a,Or(h.stem,!1),O,this.buildGroupBacklinkAnchor(h,r)||x,r.obsidianBacklinkPlacement,u),v=w.noteId??h.noteId,I=w.loadedNote;if(v===void 0)v=await this.ankiGateway.addNote({deckName:D,modelName:i,fields:W,tags:h.tagsHint??[]}),M+=1,g.add(h.syncKey);else{if(I??(I=await this.tryLoadQaGroupNote(v,h,i)),I.kind==="missing"&&(v=await this.ankiGateway.addNote({deckName:D,modelName:i,fields:W,tags:h.tagsHint??[]}),M+=1,g.add(h.syncKey)),I.kind==="matching"){let R=I.note,re=!Ud(R.fields,W),ve=!(R.deckNames??[]).includes(D),Fe=je(h.tagsHint,R.tags),xn=Fe.addTags.length>0||Fe.removeTags.length>0;if(!re&&!ve&&!xn){f.set(h.syncKey,v);let po=this.now();p.push({groupId:F,noteId:v,filePath:h.filePath,headingText:h.headingText,backlinkHeadingText:h.backlinkHeadingText,headingLevel:h.headingLevel,stem:h.stem,src:h.src||be(h.filePath,h.backlinkHeadingText),blockStartOffset:h.blockStartOffset,blockEndOffset:h.blockEndOffset,blockStartLine:h.blockStartLine,bodyStartLine:h.bodyStartLine,blockEndLine:h.blockEndLine,contentEndLine:h.contentEndLine,markerLine:h.markerLine,markerIndent:h.markerIndent,rawBlockText:h.rawBlockText,rawBlockHash:h.rawBlockHash,deck:D,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:[...T.warnings],tagsHint:h.tagsHint?[...h.tagsHint]:[],items:A,freeSlots:y,lastSyncedAt:w.stateRecord?.lastSyncedAt??po,orphan:!1});continue}(re||ve)&&await this.ankiGateway.updateNote({noteId:v,fields:W,deckName:ve?D:void 0}),re&&(b+=1),!re&&xn&&(b+=1),ve&&(S+=1),xn&&await this.ankiGateway.syncNoteTags([{noteId:v,addTags:Fe.addTags,removeTags:Fe.removeTags}]),g.add(h.syncKey)}if(I.kind==="model-mismatch"){let R=!(I.note.deckNames??[]).includes(D),re=je(h.tagsHint,I.note.tags),ve=re.addTags.length>0||re.removeTags.length>0;try{await this.ankiGateway.updateNoteModel({noteId:v,modelName:i,fields:W})}catch(Fe){throw Nt({noteId:v,fromModel:I.actualModelName,toModel:I.expectedModelName,error:Fe,location:`${h.filePath}:${h.blockStartLine}`})}R&&I.note.cardIds.length>0&&(await this.ankiGateway.changeDecks([{deckName:D,cardIds:I.note.cardIds}]),S+=1),ve&&await this.ankiGateway.syncNoteTags([{noteId:v,addTags:re.addTags,removeTags:re.removeTags}]),b+=1,k+=1,g.add(h.syncKey)}}f.set(h.syncKey,v);let U=Object.fromEntries(A.filter(R=>R.itemId&&R.slot).map(R=>[R.itemId,R.slot]));(h.markerState!=="present-valid"||!this.groupMarkerService.isEquivalent(h.groupMarker,v,U,y)||Qd(h))&&l.push({syncKey:h.syncKey,filePath:h.filePath,blockStartLine:h.blockStartLine,contentEndLine:h.contentEndLine,blockEndLine:h.blockEndLine,markerLine:h.markerLine,markerIndent:h.markerIndent,noteId:v,groupId:F,itemToSlot:U,freeSlots:y,sourceContent:h.sourceContent??""});let $r=this.now();p.push({groupId:F,noteId:v,filePath:h.filePath,headingText:h.headingText,backlinkHeadingText:h.backlinkHeadingText,headingLevel:h.headingLevel,stem:h.stem,src:h.src||be(h.filePath,h.backlinkHeadingText),blockStartOffset:h.blockStartOffset,blockEndOffset:h.blockEndOffset,blockStartLine:h.blockStartLine,bodyStartLine:h.bodyStartLine,blockEndLine:h.blockEndLine,contentEndLine:h.contentEndLine,markerLine:h.markerLine,markerIndent:h.markerIndent,rawBlockText:h.rawBlockText,rawBlockHash:h.rawBlockHash,deck:D,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:[...T.warnings],tagsHint:h.tagsHint?[...h.tagsHint]:[],items:A,freeSlots:y,lastSyncedAt:g.has(h.syncKey)?$r:w.stateRecord?.lastSyncedAt??$r,orphan:!1})}return{created:M,updated:b,migratedNoteTypes:k,migratedDecks:S,markerWrites:l,resolvedNoteIds:f,touchedSyncKeys:[...g],syncedGroupBlocks:p,warnings:[...d.values()]}}async resolveRecoveredGroup(t,n,r,i,a){let o=(t.groupId?n.byGroupId.get(t.groupId):void 0)??(t.noteId!==void 0?n.byNoteId.get(t.noteId):void 0)??$d(n.bySrc.get(t.src));if(o)return{noteId:o.noteId,groupId:o.groupId,items:o.items.map(u=>({...u})),freeSlots:[...o.freeSlots],stateRecord:o};if(t.noteId!==void 0){let u=await this.tryLoadQaGroupNote(t.noteId,t,r);return u.kind==="matching"?{...Hd(u.note,i,a,t.groupId),loadedNote:u}:u.kind==="model-mismatch"?{noteId:u.note.noteId,groupId:t.groupId,items:[],freeSlots:[...a],loadedNote:u}:{noteId:t.noteId,groupId:t.groupId,items:[],freeSlots:[...a],loadedNote:u}}return{items:[],freeSlots:[...a]}}async tryLoadQaGroupNote(t,n,r){let i=(await this.ankiGateway.getNoteDetails([t]))[0];return i?i.modelName!==r?{kind:"model-mismatch",note:i,actualModelName:i.modelName,expectedModelName:r}:{kind:"matching",note:i}:{kind:"missing"}}buildGroupBacklinkAnchor(t,n){return!t||!n.addObsidianBacklink||!this.createBacklink?"":mn({href:this.createBacklink({filePath:t.filePath,sourceContent:t.sourceContent,headingLine:t.blockStartLine,blockStartLine:t.blockStartLine,bodyStartLine:t.bodyStartLine,blockEndLine:t.blockEndLine,contentEndLine:t.contentEndLine,markerLine:t.markerLine,headingLevel:t.headingLevel,headingText:t.backlinkHeadingText}),label:n.obsidianBacklinkLabel})}async resolveQaGroupModel(t){let n=t.cardTypeConfigs["qa-group"].noteType.trim();if(!n)throw new C("errors.noteFieldMapping.noteTypeNotSelected.qaGroup");let r=t.noteFieldMappings[L("qa-group",n)],i=await this.ankiGateway.getModelFieldNames(n),a=this.qaGroupFieldMappingService.suggest(n,i,this.now(),B(r)?r.acceptedWarnings:void 0,B(r)?r.titleField:void 0);return this.qaGroupFieldMappingService.validateMapping(a,i),this.qaGroupFieldMappingService.validateWarningsAccepted(a),{modelName:n,mapping:a,availableSlots:a.slots.map(o=>o.index),legacyInternalFields:jd(i)}}};function Gd(e,t,n,r,i,a){if(!e.titleField)throw new C("errors.noteFieldMapping.qaGroupMissingTitle",{modelName:e.modelName});let o=r&&i==="question-last-line"?nt({title:t,body:""},r,i).title:t,u={[e.titleField]:o};for(let c of e.slots)u[c.questionField]="",u[c.answerField]="";for(let c of a)u[c]="";let s=new Map(e.slots.map(c=>[c.index,c]));for(let c of n){if(c.slot===void 0)continue;let d=s.get(c.slot);if(!d)continue;let l=r&&i!=="question-last-line"?nt({title:c.title,body:c.answer},r,i).body:c.answer;u[d.questionField]=c.title,u[d.answerField]=l}return u}function qd(e){let t=new Map,n=new Map,r=new Map;for(let i of Object.values(e)){if(i.orphan)continue;t.set(i.groupId,i),n.set(i.noteId,i);let a=r.get(i.src);if(a){a.push(i);continue}r.set(i.src,[i])}return{byGroupId:t,byNoteId:n,bySrc:r}}function Hd(e,t,n,r){let i=[],a=new Set;for(let o of t.slots){let u=ao(e.fields[o.questionField]??""),s=ao(e.fields[o.answerField]??"");!u&&!s||(a.add(o.index),i.push({itemId:`recovered-slot-${String(o.index).padStart(2,"0")}`,title:u,answer:s,slot:o.index,ordinalInMarkdown:o.index}))}return{noteId:e.noteId,groupId:r,items:i,freeSlots:n.filter(o=>!a.has(o))}}function zd(e,t,n,r){let i=new Map,a=[];for(let l of t){let f=io(l.title,l.answer),g=i.get(f);g?g.push(l):i.set(f,[l]),a.push(l)}let o=[],u=[];for(let l=0;ll.ordinalInMarkdown-f.ordinalInMarkdown||(l.slot??999)-(f.slot??999));for(let l of u){let f=e[l],g=s.shift();if(g){o[l]={...f,itemId:g.itemId,slot:g.slot};continue}o[l]={...f,itemId:n()}}let c=new Set(o.map(l=>l.slot).filter(l=>typeof l=="number")),d=[...r].filter(l=>!c.has(l));for(let l of o){if(l.slot!==void 0)continue;let f=d.shift();if(f===void 0)throw new Error("No free QA Group slots are available.");l.slot=f}return o.map((l,f)=>({...l,ordinalInMarkdown:f+1}))}function Od(e,t){let n=new Set(e.map(r=>r.slot).filter(r=>typeof r=="number"));return t.filter(r=>!n.has(r))}function io(e,t){return`${e}\0${t}`}function Wd(e,t){let n=e.findIndex(r=>r.itemId===t.itemId&&r.slot===t.slot&&r.title===t.title&&r.answer===t.answer);n>=0&&e.splice(n,1)}function $d(e){if(!(!e||e.length!==1))return e[0]}function Ud(e,t){let n=Object.keys(t).sort();for(let r of n)if((e[r]??"")!==(t[r]??""))return!1;return!0}function Qd(e){if(!e.sourceContent)return!1;let t=e.sourceContent.split(/\r?\n/);for(let n=e.blockStartLine;n$1"),i=n.restore(r),a=Pd.renderInline(i).trim();return t?fn(a):a}function Vd(e,t){let n=new Set(t);return e.map(r=>({...r,slot:typeof r.slot=="number"&&n.has(r.slot)?r.slot:void 0}))}function ao(e){return e.replace(/

]*>.*?<\/a><\/p>/g,"").replace(/
]*>.*?<\/a>/g,"").trim()}function jd(e){return e.includes("GroupId")&&e.includes("Src")&&e.some(n=>/^S\d+_Id$/i.test(n))&&e.some(n=>/^S\d+_Q$/i.test(n))&&e.some(n=>/^S\d+_A$/i.test(n))?e.filter(n=>n==="GroupId"||n==="Src"||/^S\d+_Id$/i.test(n)):[]}function Kd(e){let t=[];return{text:e.replace(Rd,r=>{let i=`@@QA_GROUP_INLINE_CODE_${t.length}@@`;return t.push(r),i}),restore:r=>t.reduce((i,a,o)=>i.split(`@@QA_GROUP_INLINE_CODE_${o}@@`).join(a),r)}}var Zd="manual-render-v3",we=class{constructor(t=new ze){this.deckResolutionService=t}resolve(t,n){let r=Yd(t.cardType,n),i=this.deckResolutionService.resolve(t,n.defaultDeck,n.folderDeckMode),a=i.resolvedDeck.value,o=n.noteFieldMappings[L(t.cardType,r)]??null,u={version:Zd,cardType:t.cardType,noteModel:r,mapping:o,addObsidianBacklink:n.addObsidianBacklink,obsidianBacklinkLabel:n.obsidianBacklinkLabel,obsidianBacklinkPlacement:n.obsidianBacklinkPlacement,convertHighlightsToCloze:n.convertHighlightsToCloze,keepPureTagLinesInCardBody:n.keepPureTagLinesInCardBody},s=z(JSON.stringify(u));return{deck:a,noteModel:r,renderConfigHash:s,warnings:i.warnings}}};function Yd(e,t){if(wi(e)){if(!t.clozeNoteType.trim())throw new C("errors.noteFieldMapping.noteTypeNotSelected.cloze");return t.clozeNoteType}if(e==="semantic-qa"){if(!t.semanticQaNoteType.trim())throw new C("errors.noteFieldMapping.noteTypeNotSelected.semanticQa");return t.semanticQaNoteType}if(!t.qaNoteType.trim())throw new C("errors.noteFieldMapping.noteTypeNotSelected.basic");return t.qaNoteType}var kn=class{constructor(t=new we){this.renderConfigService=t}plan(t,n,r,i){let a=new Map,o=new Set(n.pendingWriteBack.filter(k=>k.markerKind!=="group-gi").map(k=>Ee(k.filePath,k.blockStartLine,k.rawBlockHash))),u=new Set,s=[],c=[],d=[],l=[],f=[],g=new Map,p=0;for(let k of t){if(a.has(k.syncKey))throw new Error(`Duplicate syncKey detected in current scan: ${k.syncKey}`);if(a.set(k.syncKey,k),k.noteId!==void 0){let y=N(k.noteId);if(u.has(y))throw new Error(`Duplicate noteId detected in current scan: ${k.noteId}`);u.add(y)}let S=k.noteId!==void 0?n.cards[N(k.noteId)]:void 0,x=this.renderConfigService.resolve(k,i);for(let y of x.warnings)g.set(Oe(y),y);let h=k.noteId,w=Ee(k.filePath,k.blockStartLine,k.rawBlockHash),F={card:{...k,noteId:h},noteId:h,deck:x.deck,noteModel:x.noteModel,renderConfigHash:x.renderConfigHash};if(!h){s.push(F);continue}if(d.push(F),(k.idMarkerState!=="present-valid"||k.noteIdSource!=="marker"||o.has(w))&&f.push(F),!S){c.push(F);continue}let _=S.rawBlockHash!==k.rawBlockHash||S.renderConfigHash!==x.renderConfigHash||!Ui(S.tagsHint,k.tagsHint)||S.orphan,A=S.deck!==x.deck;_&&c.push(F),A&&l.push(F),!_&&!A&&(p+=1)}let M=new Set(r),b=Object.values(n.cards).filter(k=>M.has(k.filePath)&&!u.has(N(k.noteId)));return{toCreate:s,toUpdate:c,toVerifyDeck:d,toChangeDeck:l,toRewriteMarker:f,toOrphan:b,unchangedCards:p,warnings:Array.from(g.values())}}};var oo=new tt({breaks:!0,html:!0,linkify:!0}),Xd=/`[^`\n]+`/g,Jd=/```[\s\S]*?```|~~~[\s\S]*?~~~/g,el=/(?`\\[${b.trim()}\\]`),c=c.replace(tl,(M,b)=>`\\(${b.trim()}\\)`),i&&r.convertHighlightsToCloze&&(c=c.replace(uo,"{$1}")),i&&(c=c.replace(rl,(M,b,k)=>`{{c${b?Number(b):l++}::${k}}}`)),c=c.replace(il,(M,b)=>{let k=r.resourceResolver.resolveEmbed(b,n.card.filePath);return k?(d.push({kind:k.kind,fileName:k.fileName,absolutePath:k.absolutePath,altText:k.altText}),k.kind==="audio"?`[sound:${k.fileName}]`:`${rt(k.altText??k.fileName)}`):M}),c=c.replace(al,(M,b)=>{let k=r.resourceResolver.resolveWikiLink(b,n.card.filePath);return k?`${rt(k.displayText)}`:M}),c=c.replace(uo,"$1");let f=Wr(c,nl,"MATH");c=f.text,c=s.restore(c),c=u.restore(c);let g=(a?oo.renderInline(c):oo.render(c)).trim(),p=f.restore(g,rt);return{html:a?p:fn(p),media:d}}};function Wr(e,t,n){let r=[];return{text:e.replace(t,a=>{let o=`@@${n}_${r.length}@@`;return r.push(a),o}),restore:(a,o=u=>u)=>r.reduce((u,s,c)=>u.split(`@@${n}_${c}@@`).join(o(s)),a)}}function ol(e){let t=new Set;return e.filter(n=>{let r=`${n.kind}:${n.absolutePath}:${n.fileName}`;return t.has(r)?!1:(t.add(r),!0)})}function rt(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var it=class extends C{constructor(t){super("errors.currentFileOutOfScope",{filePath:t}),this.name="CurrentFileOutOfScopeError"}},yn=class{constructor(t,n,r,i=new Ut(t),a=new kn,o=new bn,u=new Bt(r),s=new Qt(t),c=new we,d=()=>Date.now()){this.vaultGateway=t;this.pluginStateRepository=n;this.ankiGateway=r;this.fileIndexerService=i;this.diffPlannerService=a;this.renderer=o;this.ankiBatchExecutor=u;this.markdownWriteBackService=s;this.scanScopeService=new Le;if(this.qaGroupSyncService=new hn(r,void 0,void 0,void 0,void 0,void 0,void 0,this.vaultGateway.createBacklink.bind(this.vaultGateway)),this.groupMarkerService=new V,ul(c)){this.renderConfigService=c,this.now=d;return}this.renderConfigService=new we,this.now=c}async syncVault(t){oe(t);let n=await this.pluginStateRepository.load(),r=await this.fileIndexerService.indexVault(t,n);return this.syncIndexedResult(r,n,t)}async syncFile(t,n){if(oe(n),!this.scanScopeService.isPathInScope(t,n.scopeMode,n.includeFolders,n.excludeFolders))throw new it(t);let r=await this.pluginStateRepository.load(),i=await this.fileIndexerService.indexFile(t,n,r);return this.syncIndexedResult(i,r,n)}async rebuildIndex(t){oe(t);let n=await this.pluginStateRepository.load(),r=await this.fileIndexerService.indexVault(t,n,!0),i=this.diffPlannerService.plan(r.cards,n,r.scopedFilePaths,t),a=new Map(r.indexedFiles.map(l=>[l.filePath,l])),o=i.toRewriteMarker.filter(l=>l.noteId!==void 0),u=this.buildReindexedGroupStates(r.groupBlocks,n),s=await this.markdownWriteBackService.write(o,a,u.markerWrites),c=so(n,r.scopedFilePaths,u.syncedGroupBlocks),d=this.buildNextState(n,r.cards,r.indexedFiles,u.syncedGroupBlocks,t,new Set(s.writtenSyncKeys),new Map,i.toOrphan,c);if(d.pendingWriteBack=[...n.pendingWriteBack.filter(l=>!new Set(r.scopedFilePaths).has(l.filePath)),...s.pendingEntries],this.markFilesDirty(d,[...s.failureFiles.map(l=>l.filePath),...s.conflictFiles]),await this.pluginStateRepository.save(d),s.failureFiles.length>0)throw this.createWriteBackFailureError(s.failureFiles);return{scannedFiles:r.scannedFiles,scannedCards:r.cards.length+r.groupBlocks.length,created:0,updated:0,migratedNoteTypes:0,migratedDecks:0,orphaned:i.toOrphan.length+c.length,uploadedMedia:0,skippedUnchangedCards:r.skippedUnchangedCards,rewrittenMarkers:s.writtenSyncKeys.length,markerWriteConflictFiles:s.conflictFiles,warnings:co(i.warnings,u.warnings)}}async syncIndexedResult(t,n,r){let i=this.diffPlannerService.plan(t.cards,n,t.scopedFilePaths,r),a={addObsidianBacklink:r.addObsidianBacklink,obsidianBacklinkLabel:r.obsidianBacklinkLabel,obsidianBacklinkPlacement:r.obsidianBacklinkPlacement,convertHighlightsToCloze:r.convertHighlightsToCloze,keepPureTagLinesInCardBody:r.keepPureTagLinesInCardBody,resourceResolver:this.vaultGateway},o=new Map;for(let g of[...i.toCreate,...i.toUpdate])o.has(g.card.syncKey)||o.set(g.card.syncKey,this.renderer.render(g,a));let u=await this.ankiBatchExecutor.execute(i,o,async g=>this.renderer.render(g,a),r.noteFieldMappings),s=await this.qaGroupSyncService.sync(t.groupBlocks,n,r),c=new Map(t.indexedFiles.map(g=>[g.filePath,g])),d=await this.markdownWriteBackService.write(u.markerWrites,c,s.markerWrites),l=so(n,t.scopedFilePaths,s.syncedGroupBlocks),f=this.buildNextState(n,t.cards,t.indexedFiles,s.syncedGroupBlocks,r,new Set([...u.touchedSyncKeys,...s.touchedSyncKeys,...d.writtenSyncKeys]),u.resolvedNoteIds,i.toOrphan,l);if(f.pendingWriteBack=[...n.pendingWriteBack.filter(g=>!new Set(t.scopedFilePaths).has(g.filePath)),...d.pendingEntries],this.markFilesDirty(f,[...d.failureFiles.map(g=>g.filePath),...d.conflictFiles]),await this.pluginStateRepository.save(f),d.failureFiles.length>0)throw this.createWriteBackFailureError(d.failureFiles);return{scannedFiles:t.scannedFiles,scannedCards:t.cards.length+t.groupBlocks.length,created:u.created+s.created,updated:u.updated+s.updated,migratedNoteTypes:u.migratedNoteTypes+s.migratedNoteTypes,migratedDecks:u.migratedDecks+s.migratedDecks,orphaned:i.toOrphan.length+l.length,uploadedMedia:u.uploadedMedia,skippedUnchangedCards:t.skippedUnchangedCards,rewrittenMarkers:d.writtenSyncKeys.length,markerWriteConflictFiles:d.conflictFiles,warnings:co(i.warnings,s.warnings)}}buildNextState(t,n,r,i,a,o,u,s,c){let d=this.now(),l=Gn(a),f=new Set(r.filter(b=>b.content!==void 0).map(b=>b.filePath)),g=new Map;for(let b of i){let k=g.get(b.filePath);k?k.push(b):g.set(b.filePath,[b])}let p={files:{...t.files},cards:{...t.cards},groupBlocks:{...t.groupBlocks??{}},pendingWriteBack:[...t.pendingWriteBack]};for(let b of f)delete p.files[b];for(let[b,k]of Object.entries(p.cards))f.has(k.filePath)&&delete p.cards[b];for(let[b,k]of Object.entries(p.groupBlocks??{}))f.has(k.filePath)&&delete p.groupBlocks?.[b];let M=new Map;for(let b of n){let k=u.get(b.syncKey)??b.noteId;k!==void 0&&M.set(b.syncKey,k)}for(let b of r){if(b.content===void 0)continue;let k=Array.from(new Set(b.cards.map(S=>M.get(S.syncKey)).filter(S=>S!==void 0)));p.files[b.filePath]={filePath:b.filePath,fileHash:b.fileHash,fileStamp:b.fileStamp,deckRulesFingerprint:l,lastIndexedAt:d,noteIds:k,groupIds:(g.get(b.filePath)??[]).map(S=>S.groupId)}}for(let b of n){let k=M.get(b.syncKey);if(k===void 0)continue;let S=t.cards[N(k)]??(b.noteId!==void 0?t.cards[N(b.noteId)]:void 0),x=this.renderConfigService.resolve(b,a);p.cards[N(k)]={noteId:k,filePath:b.filePath,heading:b.heading,backlinkHeadingText:b.backlinkHeadingText,headingLevel:b.headingLevel,bodyMarkdown:b.bodyMarkdown,cardType:b.cardType,blockStartOffset:b.blockStartOffset,blockEndOffset:b.blockEndOffset,blockStartLine:b.blockStartLine,bodyStartLine:b.bodyStartLine,blockEndLine:b.blockEndLine,contentEndLine:b.contentEndLine,markerLine:b.markerLine,rawBlockText:b.rawBlockText,rawBlockHash:b.rawBlockHash,renderConfigHash:x.renderConfigHash,deck:x.deck,deckHint:b.deckHint,deckHintSource:b.deckHintSource,deckWarnings:[...b.deckWarnings],tagsHint:b.tagsHint,lastSyncedAt:o.has(b.syncKey)?d:S?.lastSyncedAt??0,orphan:!1}}for(let b of s)p.cards[N(b.noteId)]={...b,orphan:!0};for(let b of i)p.groupBlocks??(p.groupBlocks={}),p.groupBlocks[b.groupId]=b;for(let b of c)p.groupBlocks??(p.groupBlocks={}),p.groupBlocks[b.groupId]={...b,orphan:!0};return p}buildReindexedGroupStates(t,n){let r=[],i=[],a=[],o=new Map(Object.values(n.groupBlocks??{}).filter(s=>!s.orphan).map(s=>[s.noteId,s])),u=new Map;for(let s of Object.values(n.groupBlocks??{}).filter(c=>!c.orphan)){let c=u.get(s.src);c?c.push(s):u.set(s.src,[s])}for(let s of t){let c=(s.groupId?n.groupBlocks?.[s.groupId]:void 0)??(s.noteId!==void 0?o.get(s.noteId):void 0)??sl(u.get(s.src));if(!c)continue;let d=Object.fromEntries(c.items.filter(l=>l.itemId&&l.slot).map(l=>[l.itemId,l.slot]));r.push({...c,filePath:s.filePath,headingText:s.headingText,backlinkHeadingText:s.backlinkHeadingText,headingLevel:s.headingLevel,stem:s.stem,src:s.src,blockStartOffset:s.blockStartOffset,blockEndOffset:s.blockEndOffset,blockStartLine:s.blockStartLine,bodyStartLine:s.bodyStartLine,blockEndLine:s.blockEndLine,contentEndLine:s.contentEndLine,markerLine:s.markerLine,markerIndent:s.markerIndent,rawBlockText:s.rawBlockText,rawBlockHash:s.rawBlockHash,deckHint:s.deckHint,deckHintSource:s.deckHintSource,deckWarnings:[...s.deckWarnings],tagsHint:s.tagsHint?[...s.tagsHint]:[],orphan:!1}),a.push(...s.deckWarnings),s.sourceContent&&(s.markerState!=="present-valid"||!this.groupMarkerService.isEquivalent(s.groupMarker,c.noteId,d,c.freeSlots)||cl(s))&&i.push({syncKey:s.syncKey,filePath:s.filePath,blockStartLine:s.blockStartLine,contentEndLine:s.contentEndLine,blockEndLine:s.blockEndLine,markerLine:s.markerLine,markerIndent:s.markerIndent,noteId:c.noteId,groupId:c.groupId,itemToSlot:d,freeSlots:[...c.freeSlots],sourceContent:s.sourceContent})}return{syncedGroupBlocks:r,markerWrites:i,warnings:a}}markFilesDirty(t,n){for(let r of new Set(n))t.files[r]&&(t.files[r]={...t.files[r],fileHash:"",fileStamp:""})}createWriteBackFailureError(t){return new C("errors.writeBack.summary",{fileCount:t.length},{failures:t})}};function ul(e){return typeof e=="object"&&e!==null&&"resolve"in e}function so(e,t,n){let r=new Set(t),i=new Set(n.map(a=>a.groupId));return Object.values(e.groupBlocks??{}).filter(a=>r.has(a.filePath)&&!i.has(a.groupId)).map(a=>({...a,orphan:!0}))}function co(...e){let t=new Map;for(let n of e)for(let r of n)t.set(Oe(r),r);return[...t.values()]}function sl(e){if(!(!e||e.length!==1))return e[0]}function cl(e){if(!e.sourceContent)return!1;let t=e.sourceContent.split(/\r?\n/);for(let n=e.blockStartLine;nthis.settings.ankiConnectUrl);this.deckTemplateInsertionService=new dt}async onload(){let n=new Ct(this);this.pluginConfigRepository=new Ft(n);let r=new Tt(n),i=new vt(this.app);this.vaultGateway=i;try{this.settings=await this.pluginConfigRepository.load()}catch(o){console.error("Failed to load plugin settings, falling back to defaults.",o),this.settings=P,this.noticeService.error(m("notice.invalidSettingsRestored"))}let a=new yn(i,r,this.ankiGateway);this.syncCurrentFileUseCase=new bt(a),this.syncVaultUseCase=new xt(a),this.rebuildCardIndexUseCase=new yt(a),this.clearCurrentFileSyncedCardsUseCase=new kt(r,this.ankiGateway,i),this.cleanupEmptyDecksUseCase=new lt(this.ankiGateway),Mi(this),this.addSettingTab(new Lt(this))}async updateSettings(n){if(!this.pluginConfigRepository)return;let r=ke({...this.settings,...n});try{await this.pluginConfigRepository.save(r),this.settings=r}catch(i){this.noticeService.error(le(i,"notice.failedSavePluginSettings"))}}async listNoteModels(){return this.ankiGateway.listNoteModels()}async getModelFieldNamesByModelNames(n){return this.ankiGateway.getModelFieldNamesByModelNames(n)}async getNoteModelDetails(n){return this.ankiGateway.getModelDetails(n)}async listFolderTree(){return this.vaultGateway?this.vaultGateway.listFolderTree():[]}async runSyncCurrentFile(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(m("notice.noActiveMarkdownForSync"));return}if(!this.syncCurrentFileUseCase){this.noticeService.error(m("notice.syncUseCaseNotInitialized"));return}try{let r=await this.syncCurrentFileUseCase.execute(n.path,this.settings);this.noticeService.showSyncSummary("currentFile",r)}catch(r){if(r instanceof it){this.noticeService.info(vn(r));return}console.error("Current file sync failed.",r),this.noticeService.error(le(r,"notice.currentFileSyncFailed"))}}async runSyncVault(){if(!this.syncVaultUseCase){this.noticeService.error(m("notice.syncUseCaseNotInitialized"));return}try{let n=await this.syncVaultUseCase.execute(this.settings);this.noticeService.showSyncSummary("vault",n)}catch(n){console.error("Vault sync failed.",n),this.noticeService.error(le(n,"notice.vaultSyncFailed"))}}async runRebuildCardIndex(){if(!this.rebuildCardIndexUseCase){this.noticeService.error(m("notice.syncUseCaseNotInitialized"));return}try{let n=await this.rebuildCardIndexUseCase.execute(this.settings);this.noticeService.showRebuildSummary(n)}catch(n){console.error("Card index rebuild failed.",n),this.noticeService.error(le(n,"notice.rebuildFailed"))}}async insertDeckTemplateToCurrentFile(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(m("notice.noActiveMarkdownForDeckTemplateInsertion"));return}if(!this.vaultGateway){this.noticeService.error(m("notice.vaultGatewayNotInitialized"));return}try{let r=await this.vaultGateway.readMarkdownFile(n.path);if(!r){this.noticeService.error(m("notice.markdownFileNotFound",{filePath:n.path}));return}let i=this.deckTemplateInsertionService.insert(r,this.settings.fileDeckMarker,this.settings.fileDeckTemplate,this.settings.fileDeckInsertLocation);if(i.nextContent===i.expectedContent){this.noticeService.info(m("notice.deckTemplateAlreadyCurrent"));return}await this.vaultGateway.replaceMarkdownFile(n.path,i.expectedContent,i.nextContent),this.noticeService.info(m("notice.deckTemplateInserted",{deck:i.insertedDeck}))}catch(r){console.error("Deck template insertion failed.",r),this.noticeService.error(le(r,"notice.deckTemplateInsertionFailed"))}}async runClearCurrentFileSyncedCards(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(m("notice.noActiveMarkdownForReset"));return}if(!this.clearCurrentFileSyncedCardsUseCase){this.noticeService.error(m("notice.clearCurrentFileUseCaseNotInitialized"));return}try{if(!await this.clearCurrentFileSyncedCardsUseCase.hasTrackedCards(n.path)){this.noticeService.info(m("notice.noTrackedCardsInCurrentFile"));return}let i=await this.clearCurrentFileSyncedCardsUseCase.execute(n.path);this.noticeService.showClearCurrentFileSummary(i)}catch(r){console.error("Clear current file synced cards failed.",r),this.noticeService.error(le(r,"notice.clearCurrentFileFailed"))}}async runCleanupEmptyDecks(){if(!this.cleanupEmptyDecksUseCase){this.noticeService.error(m("notice.cleanupEmptyDecksUseCaseNotInitialized"));return}try{let n=await this.cleanupEmptyDecksUseCase.listCandidates();if(n.length===0){this.noticeService.info(m("notice.noEmptyDeckCandidates"));return}let r=await new Dt(this.app,n).openAndGetSelection();if(r===null){this.noticeService.info(m("notice.cleanupEmptyDecksCancelled"));return}let i=await this.cleanupEmptyDecksUseCase.execute(r,n);this.noticeService.showCleanupEmptyDecksSummary(i)}catch(n){console.error("Cleanup empty decks failed.",n),this.noticeService.error(le(n,"notice.cleanupEmptyDecksFailed"))}}};var dl=at; +`;break;default:}return r};Ge.prototype.render=function(e,t,n){let r="",i=this.rules;for(let a=0,o=e.length;a=0&&(r=this.attrs[n][1]),r};qe.prototype.attrJoin=function(t,n){let r=this.attrIndex(t);r<0?this.attrPush([t,n]):this.attrs[r][1]=this.attrs[r][1]+" "+n};var de=qe;function Sa(e,t,n){this.src=e,this.env=n,this.tokens=[],this.inlineMode=!1,this.md=t}Sa.prototype.Token=de;var Ca=Sa;var hc=/\r\n?|\n/g,kc=/\0/g;function tr(e){let t;t=e.src.replace(hc,` +`),t=t.replace(kc,"\uFFFD"),e.src=t}function nr(e){let t;e.inlineMode?(t=new e.Token("inline","",0),t.content=e.src,t.map=[0,1],t.children=[],e.tokens.push(t)):e.md.block.parse(e.src,e.md,e.env,e.tokens)}function rr(e){let t=e.tokens;for(let n=0,r=t.length;n\s]/i.test(e)}function yc(e){return/^<\/a\s*>/i.test(e)}function ir(e){let t=e.tokens;if(e.md.options.linkify)for(let n=0,r=t.length;n=0;o--){let u=i[o];if(u.type==="link_close"){for(o--;i[o].level!==u.level&&i[o].type!=="link_open";)o--;continue}if(u.type==="html_inline"&&(bc(u.content)&&a>0&&a--,yc(u.content)&&a++),!(a>0)&&u.type==="text"&&e.md.linkify.test(u.content)){let s=u.content,c=e.md.linkify.match(s),d=[],l=u.level,f=0;c.length>0&&c[0].index===0&&o>0&&i[o-1].type==="text_special"&&(c=c.slice(1));for(let g=0;gf){let w=new e.Token("text","",0);w.content=s.slice(f,k),w.level=l,d.push(w)}let S=new e.Token("link_open","a",1);S.attrs=[["href",M]],S.level=l++,S.markup="linkify",S.info="auto",d.push(S);let x=new e.Token("text","",0);x.content=b,x.level=l,d.push(x);let h=new e.Token("link_close","a",-1);h.level=--l,h.markup="linkify",h.info="auto",d.push(h),f=c[g].lastIndex}if(f=0;n--){let r=e[n];r.type==="text"&&!t&&(r.content=r.content.replace(Sc,Mc)),r.type==="link_open"&&r.info==="auto"&&t--,r.type==="link_close"&&r.info==="auto"&&t++}}function Fc(e){let t=0;for(let n=e.length-1;n>=0;n--){let r=e[n];r.type==="text"&&!t&&Ma.test(r.content)&&(r.content=r.content.replace(/\+-/g,"\xB1").replace(/\.{2,}/g,"\u2026").replace(/([?!])…/g,"$1..").replace(/([?!]){4,}/g,"$1$1$1").replace(/,{2,}/g,",").replace(/(^|[^-])---(?=[^-]|$)/mg,"$1\u2014").replace(/(^|\s)--(?=\s|$)/mg,"$1\u2013").replace(/(^|[^-\s])--(?=[^-\s]|$)/mg,"$1\u2013")),r.type==="link_open"&&r.info==="auto"&&t--,r.type==="link_close"&&r.info==="auto"&&t++}}function ar(e){let t;if(e.md.options.typographer)for(t=e.tokens.length-1;t>=0;t--)e.tokens[t].type==="inline"&&(xc.test(e.tokens[t].content)&&wc(e.tokens[t].children),Ma.test(e.tokens[t].content)&&Fc(e.tokens[t].children))}var vc=/['"]/,wa=/['"]/g,Fa="\u2019";function cn(e,t,n){return e.slice(0,t)+n+e.slice(t+1)}function Tc(e,t){let n,r=[];for(let i=0;i=0&&!(r[n].level<=o);n--);if(r.length=n+1,a.type!=="text")continue;let u=a.content,s=0,c=u.length;e:for(;s=0)p=u.charCodeAt(d.index-1);else for(n=i-1;n>=0&&!(e[n].type==="softbreak"||e[n].type==="hardbreak");n--)if(e[n].content){p=e[n].content.charCodeAt(e[n].content.length-1);break}let M=32;if(s=48&&p<=57&&(f=l=!1),l&&f&&(l=b,f=k),!l&&!f){g&&(a.content=cn(a.content,d.index,Fa));continue}if(f)for(n=r.length-1;n>=0;n--){let h=r[n];if(r[n].level=0;t--)e.tokens[t].type!=="inline"||!vc.test(e.tokens[t].content)||Tc(e.tokens[t].children,e)}function ur(e){let t,n,r=e.tokens,i=r.length;for(let a=0;a0&&this.level++,this.tokens.push(r),r};te.prototype.isEmpty=function(t){return this.bMarks[t]+this.tShift[t]>=this.eMarks[t]};te.prototype.skipEmptyLines=function(t){for(let n=this.lineMax;tn;)if(!E(this.src.charCodeAt(--t)))return t+1;return t};te.prototype.skipChars=function(t,n){for(let r=this.src.length;tr;)if(n!==this.src.charCodeAt(--t))return t+1;return t};te.prototype.getLines=function(t,n,r,i){if(t>=n)return"";let a=new Array(n-t);for(let o=0,u=t;ur?a[o]=new Array(s-r+1).join(" ")+this.src.slice(d,l):a[o]=this.src.slice(d,l)}return a.join("")};te.prototype.Token=de;var Ta=te;var Ac=65536;function dr(e,t){let n=e.bMarks[t]+e.tShift[t],r=e.eMarks[t];return e.src.slice(n,r)}function Aa(e){let t=[],n=e.length,r=0,i=e.charCodeAt(r),a=!1,o=0,u="";for(;rn)return!1;let i=t+1;if(e.sCount[i]=4)return!1;let a=e.bMarks[i]+e.tShift[i];if(a>=e.eMarks[i])return!1;let o=e.src.charCodeAt(a++);if(o!==124&&o!==45&&o!==58||a>=e.eMarks[i])return!1;let u=e.src.charCodeAt(a++);if(u!==124&&u!==45&&u!==58&&!E(u)||o===45&&E(u))return!1;for(;a=4)return!1;c=Aa(s),c.length&&c[0]===""&&c.shift(),c.length&&c[c.length-1]===""&&c.pop();let l=c.length;if(l===0||l!==d.length)return!1;if(r)return!0;let f=e.parentType;e.parentType="table";let g=e.md.block.ruler.getRules("blockquote"),p=e.push("table_open","table",1),M=[t,0];p.map=M;let b=e.push("thead_open","thead",1);b.map=[t,t+1];let k=e.push("tr_open","tr",1);k.map=[t,t+1];for(let h=0;h=4||(c=Aa(s),c.length&&c[0]===""&&c.shift(),c.length&&c[c.length-1]===""&&c.pop(),x+=l-c.length,x>Ac))break;if(i===t+2){let v=e.push("tbody_open","tbody",1);v.map=S=[t+2,0]}let w=e.push("tr_open","tr",1);w.map=[i,i+1];for(let v=0;v=4){r++,i=r;continue}break}e.line=i;let a=e.push("code_block","code",0);return a.content=e.getLines(t,i,4+e.blkIndent,!1)+` +`,a.map=[t,e.line],!0}function fr(e,t,n,r){let i=e.bMarks[t]+e.tShift[t],a=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4||i+3>a)return!1;let o=e.src.charCodeAt(i);if(o!==126&&o!==96)return!1;let u=i;i=e.skipChars(i,o);let s=i-u;if(s<3)return!1;let c=e.src.slice(u,i),d=e.src.slice(i,a);if(o===96&&d.indexOf(String.fromCharCode(o))>=0)return!1;if(r)return!0;let l=t,f=!1;for(;l++,!(l>=n||(i=u=e.bMarks[l]+e.tShift[l],a=e.eMarks[l],i=4)&&(i=e.skipChars(i,o),!(i-u=4||e.src.charCodeAt(i)!==62)return!1;if(r)return!0;let u=[],s=[],c=[],d=[],l=e.md.block.ruler.getRules("blockquote"),f=e.parentType;e.parentType="blockquote";let g=!1,p;for(p=t;p=a)break;if(e.src.charCodeAt(i++)===62&&!x){let w=e.sCount[p]+1,v,_;e.src.charCodeAt(i)===32?(i++,w++,_=!1,v=!0):e.src.charCodeAt(i)===9?(v=!0,(e.bsCount[p]+w)%4===3?(i++,w++,_=!1):_=!0):v=!1;let A=w;for(u.push(e.bMarks[p]),e.bMarks[p]=i;i=a,s.push(e.bsCount[p]),e.bsCount[p]=e.sCount[p]+1+(v?1:0),c.push(e.sCount[p]),e.sCount[p]=A-w,d.push(e.tShift[p]),e.tShift[p]=i-e.bMarks[p];continue}if(g)break;let h=!1;for(let w=0,v=l.length;w";let k=[t,0];b.map=k,e.md.block.tokenize(e,t,p);let S=e.push("blockquote_close","blockquote",-1);S.markup=">",e.lineMax=o,e.parentType=f,k[1]=e.line;for(let x=0;x=4)return!1;let a=e.bMarks[t]+e.tShift[t],o=e.src.charCodeAt(a++);if(o!==42&&o!==45&&o!==95)return!1;let u=1;for(;a=r)return-1;let a=e.src.charCodeAt(i++);if(a<48||a>57)return-1;for(;;){if(i>=r)return-1;if(a=e.src.charCodeAt(i++),a>=48&&a<=57){if(i-n>=10)return-1;continue}if(a===41||a===46)break;return-1}return i=4||e.listIndent>=0&&e.sCount[s]-e.listIndent>=4&&e.sCount[s]=e.blkIndent&&(d=!0);let l,f,g;if((g=Ea(e,s))>=0){if(l=!0,o=e.bMarks[s]+e.tShift[s],f=Number(e.src.slice(o,g-1)),d&&f!==1)return!1}else if((g=Da(e,s))>=0)l=!1;else return!1;if(d&&e.skipSpaces(g)>=e.eMarks[s])return!1;if(r)return!0;let p=e.src.charCodeAt(g-1),M=e.tokens.length;l?(u=e.push("ordered_list_open","ol",1),f!==1&&(u.attrs=[["start",f]])):u=e.push("bullet_list_open","ul",1);let b=[s,0];u.map=b,u.markup=String.fromCharCode(p);let k=!1,S=e.md.block.ruler.getRules("list"),x=e.parentType;for(e.parentType="list";s=i?_=1:_=w-h,_>4&&(_=1);let A=h+_;u=e.push("list_item_open","li",1),u.markup=String.fromCharCode(p);let y=[s,0];u.map=y,l&&(u.info=e.src.slice(o,g-1));let T=e.tight,D=e.tShift[s],z=e.sCount[s],O=e.listIndent;if(e.listIndent=e.blkIndent,e.blkIndent=A,e.tight=!0,e.tShift[s]=v-e.bMarks[s],e.sCount[s]=w,v>=i&&e.isEmpty(s+1)?e.line=Math.min(e.line+2,n):e.md.block.tokenize(e,s,n,!0),(!e.tight||k)&&(c=!1),k=e.line-s>1&&e.isEmpty(e.line-1),e.blkIndent=e.listIndent,e.listIndent=O,e.tShift[s]=D,e.sCount[s]=z,e.tight=T,u=e.push("list_item_close","li",-1),u.markup=String.fromCharCode(p),s=e.line,y[1]=s,s>=n||e.sCount[s]=4)break;let F=!1;for(let I=0,Q=S.length;I=4||e.src.charCodeAt(i)!==91)return!1;function u(S){let x=e.lineMax;if(S>=x||e.isEmpty(S))return null;let h=!1;if(e.sCount[S]-e.blkIndent>3&&(h=!0),e.sCount[S]<0&&(h=!0),!h){let _=e.md.block.ruler.getRules("reference"),A=e.parentType;e.parentType="reference";let y=!1;for(let T=0,D=_.length;T"u"&&(e.env.references={}),typeof e.env.references[k]>"u"&&(e.env.references[k]={title:b,href:l}),e.line=o),!0):!1}var _a=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"];var Ec="[a-zA-Z_:][a-zA-Z0-9:._-]*",_c="[^\"'=<>`\\x00-\\x20]+",Ic="'[^']*'",Lc='"[^"]*"',Nc="(?:"+_c+"|"+Ic+"|"+Lc+")",Pc="(?:\\s+"+Ec+"(?:\\s*=\\s*"+Nc+")?)",Ia="<[A-Za-z][A-Za-z0-9\\-]*"+Pc+"*\\s*\\/?>",La="<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>",Rc="",Bc="<[?][\\s\\S]*?[?]>",Gc="]*>",qc="",Na=new RegExp("^(?:"+Ia+"|"+La+"|"+Rc+"|"+Bc+"|"+Gc+"|"+qc+")"),Pa=new RegExp("^(?:"+Ia+"|"+La+")");var He=[[/^<(script|pre|style|textarea)(?=(\s|>|$))/i,/<\/(script|pre|style|textarea)>/i,!0],[/^/,!0],[/^<\?/,/\?>/,!0],[/^/,!0],[/^/,!0],[new RegExp("^|$))","i"),/^$/,!0],[new RegExp(Pa.source+"\\s*$"),/^$/,!1]];function br(e,t,n,r){let i=e.bMarks[t]+e.tShift[t],a=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4||!e.md.options.html||e.src.charCodeAt(i)!==60)return!1;let o=e.src.slice(i,a),u=0;for(;u=4)return!1;let o=e.src.charCodeAt(i);if(o!==35||i>=a)return!1;let u=1;for(o=e.src.charCodeAt(++i);o===35&&i6||ii&&E(e.src.charCodeAt(s-1))&&(a=s),e.line=t+1;let c=e.push("heading_open","h"+String(u),1);c.markup="########".slice(0,u),c.map=[t,e.line];let d=e.push("inline","",0);d.content=e.src.slice(i,a).trim(),d.map=[t,e.line],d.children=[];let l=e.push("heading_close","h"+String(u),-1);return l.markup="########".slice(0,u),!0}function xr(e,t,n){let r=e.md.block.ruler.getRules("paragraph");if(e.sCount[t]-e.blkIndent>=4)return!1;let i=e.parentType;e.parentType="paragraph";let a=0,o,u=t+1;for(;u3)continue;if(e.sCount[u]>=e.blkIndent){let g=e.bMarks[u]+e.tShift[u],p=e.eMarks[u];if(g=p))){a=o===61?1:2;break}}if(e.sCount[u]<0)continue;let f=!1;for(let g=0,p=r.length;g3||e.sCount[a]<0)continue;let c=!1;for(let d=0,l=r.length;d=n||e.sCount[o]=a){e.line=n;break}let s=e.line,c=!1;for(let d=0;d=e.line)throw new Error("block rule didn't increment state.line");break}if(!c)throw new Error("none of the block rules matched");e.tight=!u,e.isEmpty(e.line-1)&&(u=!0),o=e.line,o0&&(this.level++,this._prev_delimiters.push(this.delimiters),this.delimiters=[],i={delimiters:this.delimiters}),this.pendingLevel=this.level,this.tokens.push(r),this.tokens_meta.push(i),r};Je.prototype.scanDelims=function(e,t){let n=this.posMax,r=this.src.charCodeAt(e),i=e>0?this.src.charCodeAt(e-1):32,a=e;for(;a0)return!1;let n=e.pos,r=e.posMax;if(n+3>r||e.src.charCodeAt(n)!==58||e.src.charCodeAt(n+1)!==47||e.src.charCodeAt(n+2)!==47)return!1;let i=e.pending.match(zc);if(!i)return!1;let a=i[1],o=e.md.linkify.matchAtStart(e.src.slice(n-a.length));if(!o)return!1;let u=o.url;if(u.length<=a.length)return!1;let s=u.length;for(;s>0&&u.charCodeAt(s-1)===42;)s--;s!==u.length&&(u=u.slice(0,s));let c=e.md.normalizeLink(u);if(!e.md.validateLink(c))return!1;if(!t){e.pending=e.pending.slice(0,-a.length);let d=e.push("link_open","a",1);d.attrs=[["href",c]],d.markup="linkify",d.info="auto";let l=e.push("text","",0);l.content=e.md.normalizeLinkText(u);let f=e.push("link_close","a",-1);f.markup="linkify",f.info="auto"}return e.pos+=u.length-a.length,!0}function wr(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==10)return!1;let r=e.pending.length-1,i=e.posMax;if(!t)if(r>=0&&e.pending.charCodeAt(r)===32)if(r>=1&&e.pending.charCodeAt(r-1)===32){let a=r-1;for(;a>=1&&e.pending.charCodeAt(a-1)===32;)a--;e.pending=e.pending.slice(0,a),e.push("hardbreak","br",0)}else e.pending=e.pending.slice(0,-1),e.push("softbreak","br",0);else e.push("softbreak","br",0);for(n++;n?@[]^_`{|}~-".split("").forEach(function(e){Fr[e.charCodeAt(0)]=1});function vr(e,t){let n=e.pos,r=e.posMax;if(e.src.charCodeAt(n)!==92||(n++,n>=r))return!1;let i=e.src.charCodeAt(n);if(i===10){for(t||e.push("hardbreak","br",0),n++;n=55296&&i<=56319&&n+1=56320&&u<=57343&&(a+=e.src[n+1],n++)}let o="\\"+a;if(!t){let u=e.push("text_special","",0);i<256&&Fr[i]!==0?u.content=a:u.content=o,u.markup=o,u.info="escape"}return e.pos=n+1,!0}function Tr(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==96)return!1;let i=n;n++;let a=e.posMax;for(;n=0;r--){let i=t[r];if(i.marker!==95&&i.marker!==42||i.end===-1)continue;let a=t[i.end],o=r>0&&t[r-1].end===i.end+1&&t[r-1].marker===i.marker&&t[r-1].token===i.token-1&&t[i.end+1].token===a.token+1,u=String.fromCharCode(i.marker),s=e.tokens[i.token];s.type=o?"strong_open":"em_open",s.tag=o?"strong":"em",s.nesting=1,s.markup=o?u+u:u,s.content="";let c=e.tokens[a.token];c.type=o?"strong_close":"em_close",c.tag=o?"strong":"em",c.nesting=-1,c.markup=o?u+u:u,c.content="",o&&(e.tokens[t[r-1].token].content="",e.tokens[t[i.end+1].token].content="",r--)}}function Qc(e){let t=e.tokens_meta,n=e.tokens_meta.length;qa(e,e.delimiters);for(let r=0;r=l)return!1;if(s=p,i=e.md.helpers.parseLinkDestination(e.src,p,e.posMax),i.ok){for(o=e.md.normalizeLink(i.str),e.md.validateLink(o)?p=i.pos:o="",s=p;p=l||e.src.charCodeAt(p)!==41)&&(c=!0),p++}if(c){if(typeof e.env.references>"u")return!1;if(p=0?r=e.src.slice(s,p++):p=g+1):p=g+1,r||(r=e.src.slice(f,g)),a=e.env.references[Ce(r)],!a)return e.pos=d,!1;o=a.href,u=a.title}if(!t){e.pos=f,e.posMax=g;let M=e.push("link_open","a",1),b=[["href",o]];M.attrs=b,u&&b.push(["title",u]),e.linkLevel++,e.md.inline.tokenize(e),e.linkLevel--,e.push("link_close","a",-1)}return e.pos=p,e.posMax=l,!0}function _r(e,t){let n,r,i,a,o,u,s,c,d="",l=e.pos,f=e.posMax;if(e.src.charCodeAt(e.pos)!==33||e.src.charCodeAt(e.pos+1)!==91)return!1;let g=e.pos+2,p=e.md.helpers.parseLinkLabel(e,e.pos+1,!1);if(p<0)return!1;if(a=p+1,a=f)return!1;for(c=a,u=e.md.helpers.parseLinkDestination(e.src,a,e.posMax),u.ok&&(d=e.md.normalizeLink(u.str),e.md.validateLink(d)?a=u.pos:d=""),c=a;a=f||e.src.charCodeAt(a)!==41)return e.pos=l,!1;a++}else{if(typeof e.env.references>"u")return!1;if(a=0?i=e.src.slice(c,a++):a=p+1):a=p+1,i||(i=e.src.slice(g,p)),o=e.env.references[Ce(i)],!o)return e.pos=l,!1;d=o.href,s=o.title}if(!t){r=e.src.slice(g,p);let M=[];e.md.inline.parse(r,e.md,e.env,M);let b=e.push("image","img",0),k=[["src",d],["alt",""]];b.attrs=k,b.children=M,b.content=r,s&&k.push(["title",s])}return e.pos=a,e.posMax=f,!0}var Uc=/^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/,Vc=/^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;function Ir(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==60)return!1;let r=e.pos,i=e.posMax;for(;;){if(++n>=i)return!1;let o=e.src.charCodeAt(n);if(o===60)return!1;if(o===62)break}let a=e.src.slice(r+1,n);if(Vc.test(a)){let o=e.md.normalizeLink(a);if(!e.md.validateLink(o))return!1;if(!t){let u=e.push("link_open","a",1);u.attrs=[["href",o]],u.markup="autolink",u.info="auto";let s=e.push("text","",0);s.content=e.md.normalizeLinkText(a);let c=e.push("link_close","a",-1);c.markup="autolink",c.info="auto"}return e.pos+=a.length+2,!0}if(Uc.test(a)){let o=e.md.normalizeLink("mailto:"+a);if(!e.md.validateLink(o))return!1;if(!t){let u=e.push("link_open","a",1);u.attrs=[["href",o]],u.markup="autolink",u.info="auto";let s=e.push("text","",0);s.content=e.md.normalizeLinkText(a);let c=e.push("link_close","a",-1);c.markup="autolink",c.info="auto"}return e.pos+=a.length+2,!0}return!1}function jc(e){return/^\s]/i.test(e)}function Kc(e){return/^<\/a\s*>/i.test(e)}function Zc(e){let t=e|32;return t>=97&&t<=122}function Lr(e,t){if(!e.md.options.html)return!1;let n=e.posMax,r=e.pos;if(e.src.charCodeAt(r)!==60||r+2>=n)return!1;let i=e.src.charCodeAt(r+1);if(i!==33&&i!==63&&i!==47&&!Zc(i))return!1;let a=e.src.slice(r).match(Na);if(!a)return!1;if(!t){let o=e.push("html_inline","",0);o.content=a[0],jc(o.content)&&e.linkLevel++,Kc(o.content)&&e.linkLevel--}return e.pos+=a[0].length,!0}var Yc=/^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i,Xc=/^&([a-z][a-z0-9]{1,31});/i;function Nr(e,t){let n=e.pos,r=e.posMax;if(e.src.charCodeAt(n)!==38||n+1>=r)return!1;if(e.src.charCodeAt(n+1)===35){let a=e.src.slice(n).match(Yc);if(a){if(!t){let o=a[1][0].toLowerCase()==="x"?parseInt(a[1].slice(1),16):parseInt(a[1],10),u=e.push("text_special","",0);u.content=sn(o)?Xe(o):Xe(65533),u.markup=a[0],u.info="entity"}return e.pos+=a[0].length,!0}}else{let a=e.src.slice(n).match(Xc);if(a){let o=me(a[0]);if(o!==a[0]){if(!t){let u=e.push("text_special","",0);u.content=o,u.markup=a[0],u.info="entity"}return e.pos+=a[0].length,!0}}}return!1}function Ha(e){let t={},n=e.length;if(!n)return;let r=0,i=-2,a=[];for(let o=0;os;c-=a[c]+1){let l=e[c];if(l.marker===u.marker&&l.open&&l.end<0){let f=!1;if((l.close||u.open)&&(l.length+u.length)%3===0&&(l.length%3!==0||u.length%3!==0)&&(f=!0),!f){let g=c>0&&!e[c-1].open?a[c-1]+1:0;a[o]=o-c+g,a[c]=g,u.open=!1,l.end=o,l.close=!1,d=-1,i=-2;break}}}d!==-1&&(t[u.marker][(u.open?3:0)+(u.length||0)%3]=d)}}function Pr(e){let t=e.tokens_meta,n=e.tokens_meta.length;Ha(e.delimiters);for(let r=0;r0&&r++,i[t].type==="text"&&t+1=e.pos)throw new Error("inline rule didn't increment state.pos");break}}else e.pos=e.posMax;o||e.pos++,a[t]=e.pos};et.prototype.tokenize=function(e){let t=this.ruler.getRules(""),n=t.length,r=e.posMax,i=e.md.options.maxNesting;for(;e.pos=e.pos)throw new Error("inline rule didn't increment state.pos");break}}if(o){if(e.pos>=r)break;continue}e.pending+=e.src[e.pos++]}e.pending&&e.pushPending()};et.prototype.parse=function(e,t,n,r){let i=new this.State(e,t,n,r);this.tokenize(i);let a=this.ruler2.getRules(""),o=a.length;for(let u=0;u|$))",t.tpl_email_fuzzy="(^|"+n+'|"|\\(|'+t.src_ZCc+")("+t.src_email_name+"@"+t.tpl_host_fuzzy_strict+")",t.tpl_link_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`|\uFF5C]|"+t.src_ZPCc+"))((?![$+<=>^`|\uFF5C])"+t.tpl_host_port_fuzzy_strict+t.src_path+")",t.tpl_link_no_ip_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`|\uFF5C]|"+t.src_ZPCc+"))((?![$+<=>^`|\uFF5C])"+t.tpl_host_port_no_ip_fuzzy_strict+t.src_path+")",t}function qr(e){return Array.prototype.slice.call(arguments,1).forEach(function(n){n&&Object.keys(n).forEach(function(r){e[r]=n[r]})}),e}function fn(e){return Object.prototype.toString.call(e)}function Jc(e){return fn(e)==="[object String]"}function ed(e){return fn(e)==="[object Object]"}function td(e){return fn(e)==="[object RegExp]"}function Wa(e){return fn(e)==="[object Function]"}function nd(e){return e.replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}var Qa={fuzzyLink:!0,fuzzyEmail:!0,fuzzyIP:!1};function rd(e){return Object.keys(e||{}).reduce(function(t,n){return t||Qa.hasOwnProperty(n)},!1)}var id={"http:":{validate:function(e,t,n){let r=e.slice(t);return n.re.http||(n.re.http=new RegExp("^\\/\\/"+n.re.src_auth+n.re.src_host_port_strict+n.re.src_path,"i")),n.re.http.test(r)?r.match(n.re.http)[0].length:0}},"https:":"http:","ftp:":"http:","//":{validate:function(e,t,n){let r=e.slice(t);return n.re.no_http||(n.re.no_http=new RegExp("^"+n.re.src_auth+"(?:localhost|(?:(?:"+n.re.src_domain+")\\.)+"+n.re.src_domain_root+")"+n.re.src_port+n.re.src_host_terminator+n.re.src_path,"i")),n.re.no_http.test(r)?t>=3&&e[t-3]===":"||t>=3&&e[t-3]==="/"?0:r.match(n.re.no_http)[0].length:0}},"mailto:":{validate:function(e,t,n){let r=e.slice(t);return n.re.mailto||(n.re.mailto=new RegExp("^"+n.re.src_email_name+"@"+n.re.src_host_strict,"i")),n.re.mailto.test(r)?r.match(n.re.mailto)[0].length:0}}},ad="a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]",od="biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|\u0440\u0444".split("|");function ud(e){e.__index__=-1,e.__text_cache__=""}function sd(e){return function(t,n){let r=t.slice(n);return e.test(r)?r.match(e)[0].length:0}}function $a(){return function(e,t){t.normalize(e)}}function pn(e){let t=e.re=Oa(e.__opts__),n=e.__tlds__.slice();e.onCompile(),e.__tlds_replaced__||n.push(ad),n.push(t.src_xn),t.src_tlds=n.join("|");function r(u){return u.replace("%TLDS%",t.src_tlds)}t.email_fuzzy=RegExp(r(t.tpl_email_fuzzy),"i"),t.link_fuzzy=RegExp(r(t.tpl_link_fuzzy),"i"),t.link_no_ip_fuzzy=RegExp(r(t.tpl_link_no_ip_fuzzy),"i"),t.host_fuzzy_test=RegExp(r(t.tpl_host_fuzzy_test),"i");let i=[];e.__compiled__={};function a(u,s){throw new Error('(LinkifyIt) Invalid schema "'+u+'": '+s)}Object.keys(e.__schemas__).forEach(function(u){let s=e.__schemas__[u];if(s===null)return;let c={validate:null,link:null};if(e.__compiled__[u]=c,ed(s)){td(s.validate)?c.validate=sd(s.validate):Wa(s.validate)?c.validate=s.validate:a(u,s),Wa(s.normalize)?c.normalize=s.normalize:s.normalize?a(u,s):c.normalize=$a();return}if(Jc(s)){i.push(u);return}a(u,s)}),i.forEach(function(u){e.__compiled__[e.__schemas__[u]]&&(e.__compiled__[u].validate=e.__compiled__[e.__schemas__[u]].validate,e.__compiled__[u].normalize=e.__compiled__[e.__schemas__[u]].normalize)}),e.__compiled__[""]={validate:null,normalize:$a()};let o=Object.keys(e.__compiled__).filter(function(u){return u.length>0&&e.__compiled__[u]}).map(nd).join("|");e.re.schema_test=RegExp("(^|(?!_)(?:[><\uFF5C]|"+t.src_ZPCc+"))("+o+")","i"),e.re.schema_search=RegExp("(^|(?!_)(?:[><\uFF5C]|"+t.src_ZPCc+"))("+o+")","ig"),e.re.schema_at_start=RegExp("^"+e.re.schema_search.source,"i"),e.re.pretest=RegExp("("+e.re.schema_test.source+")|("+e.re.host_fuzzy_test.source+")|@","i"),ud(e)}function cd(e,t){let n=e.__index__,r=e.__last_index__,i=e.__text_cache__.slice(n,r);this.schema=e.__schema__.toLowerCase(),this.index=n+t,this.lastIndex=r+t,this.raw=i,this.text=i,this.url=i}function Hr(e,t){let n=new cd(e,t);return e.__compiled__[n.schema].normalize(n,e),n}function U(e,t){if(!(this instanceof U))return new U(e,t);t||rd(e)&&(t=e,e={}),this.__opts__=qr({},Qa,t),this.__index__=-1,this.__last_index__=-1,this.__schema__="",this.__text_cache__="",this.__schemas__=qr({},id,e),this.__compiled__={},this.__tlds__=od,this.__tlds_replaced__=!1,this.re={},pn(this)}U.prototype.add=function(t,n){return this.__schemas__[t]=n,pn(this),this};U.prototype.set=function(t){return this.__opts__=qr(this.__opts__,t),this};U.prototype.test=function(t){if(this.__text_cache__=t,this.__index__=-1,!t.length)return!1;let n,r,i,a,o,u,s,c,d;if(this.re.schema_test.test(t)){for(s=this.re.schema_search,s.lastIndex=0;(n=s.exec(t))!==null;)if(a=this.testSchemaAt(t,n[2],s.lastIndex),a){this.__schema__=n[2],this.__index__=n.index+n[1].length,this.__last_index__=n.index+n[0].length+a;break}}return this.__opts__.fuzzyLink&&this.__compiled__["http:"]&&(c=t.search(this.re.host_fuzzy_test),c>=0&&(this.__index__<0||c=0&&(i=t.match(this.re.email_fuzzy))!==null&&(o=i.index+i[1].length,u=i.index+i[0].length,(this.__index__<0||othis.__last_index__)&&(this.__schema__="mailto:",this.__index__=o,this.__last_index__=u))),this.__index__>=0};U.prototype.pretest=function(t){return this.re.pretest.test(t)};U.prototype.testSchemaAt=function(t,n,r){return this.__compiled__[n.toLowerCase()]?this.__compiled__[n.toLowerCase()].validate(t,r,this):0};U.prototype.match=function(t){let n=[],r=0;this.__index__>=0&&this.__text_cache__===t&&(n.push(Hr(this,r)),r=this.__last_index__);let i=r?t.slice(r):t;for(;this.test(i);)n.push(Hr(this,r)),i=i.slice(this.__last_index__),r+=this.__last_index__;return n.length?n:null};U.prototype.matchAtStart=function(t){if(this.__text_cache__=t,this.__index__=-1,!t.length)return null;let n=this.re.schema_at_start.exec(t);if(!n)return null;let r=this.testSchemaAt(t,n[2],n[0].length);return r?(this.__schema__=n[2],this.__index__=n.index+n[1].length,this.__last_index__=n.index+n[0].length+r,Hr(this,0)):null};U.prototype.tlds=function(t,n){return t=Array.isArray(t)?t:[t],n?(this.__tlds__=this.__tlds__.concat(t).sort().filter(function(r,i,a){return r!==a[i-1]}).reverse(),pn(this),this):(this.__tlds__=t.slice(),this.__tlds_replaced__=!0,pn(this),this)};U.prototype.normalize=function(t){t.schema||(t.url="http://"+t.url),t.schema==="mailto:"&&!/^mailto:/i.test(t.url)&&(t.url="mailto:"+t.url)};U.prototype.onCompile=function(){};var Ua=U;var dd=/^xn--/,ld=/[^\0-\x7F]/,pd=/[\x2E\u3002\uFF0E\uFF61]/g,fd={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},zr=35,ne=Math.floor,Or=String.fromCharCode;function he(e){throw new RangeError(fd[e])}function gd(e,t){let n=[],r=e.length;for(;r--;)n[r]=t(e[r]);return n}function ja(e,t){let n=e.split("@"),r="";n.length>1&&(r=n[0]+"@",e=n[1]),e=e.replace(pd,".");let i=e.split("."),a=gd(i,t).join(".");return r+a}function Ka(e){let t=[],n=0,r=e.length;for(;n=55296&&i<=56319&&nString.fromCodePoint(...e),hd=function(e){return e>=48&&e<58?26+(e-48):e>=65&&e<91?e-65:e>=97&&e<123?e-97:36},Va=function(e,t){return e+22+75*(e<26)-((t!=0)<<5)},Za=function(e,t,n){let r=0;for(e=n?ne(e/700):e>>1,e+=ne(e/t);e>zr*26>>1;r+=36)e=ne(e/zr);return ne(r+(zr+1)*e/(e+38))},Ya=function(e){let t=[],n=e.length,r=0,i=128,a=72,o=e.lastIndexOf("-");o<0&&(o=0);for(let u=0;u=128&&he("not-basic"),t.push(e.charCodeAt(u));for(let u=o>0?o+1:0;u=n&&he("invalid-input");let f=hd(e.charCodeAt(u++));f>=36&&he("invalid-input"),f>ne((2147483647-r)/d)&&he("overflow"),r+=f*d;let g=l<=a?1:l>=a+26?26:l-a;if(fne(2147483647/p)&&he("overflow"),d*=p}let c=t.length+1;a=Za(r-s,c,s==0),ne(r/c)>2147483647-i&&he("overflow"),i+=ne(r/c),r%=c,t.splice(r++,0,i)}return String.fromCodePoint(...t)},Xa=function(e){let t=[];e=Ka(e);let n=e.length,r=128,i=0,a=72;for(let s of e)s<128&&t.push(Or(s));let o=t.length,u=o;for(o&&t.push("-");u=r&&dne((2147483647-i)/c)&&he("overflow"),i+=(s-r)*c,r=s;for(let d of e)if(d2147483647&&he("overflow"),d===r){let l=i;for(let f=36;;f+=36){let g=f<=a?1:f>=a+26?26:f-a;if(l=0))try{t.hostname=Wr.toASCII(t.hostname)}catch{}return Yt(Pe(t))}function Fd(e){let t=Ye(e,!0);if(t.hostname&&(!t.protocol||no.indexOf(t.protocol)>=0))try{t.hostname=Wr.toUnicode(t.hostname)}catch{}return Ze(Pe(t),Ze.defaultChars+"%")}function j(e,t){if(!(this instanceof j))return new j(e,t);t||un(e)||(t=e||{},e="default"),this.inline=new za,this.block=new Ra,this.core=new va,this.renderer=new xa,this.linkify=new Ua,this.validateLink=Md,this.normalizeLink=wd,this.normalizeLinkText=Fd,this.utils=Zn,this.helpers=Be({},er),this.options={},this.configure(e),t&&this.set(t)}j.prototype.set=function(e){return Be(this.options,e),this};j.prototype.configure=function(e){let t=this;if(un(e)){let n=e;if(e=xd[n],!e)throw new Error('Wrong `markdown-it` preset "'+n+'", check name')}if(!e)throw new Error("Wrong `markdown-it` preset, can't be empty");return e.options&&t.set(e.options),e.components&&Object.keys(e.components).forEach(function(n){e.components[n].rules&&t[n].ruler.enableOnly(e.components[n].rules),e.components[n].rules2&&t[n].ruler2.enableOnly(e.components[n].rules2)}),this};j.prototype.enable=function(e,t){let n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach(function(i){n=n.concat(this[i].ruler.enable(e,!0))},this),n=n.concat(this.inline.ruler2.enable(e,!0));let r=e.filter(function(i){return n.indexOf(i)<0});if(r.length&&!t)throw new Error("MarkdownIt. Failed to enable unknown rule(s): "+r);return this};j.prototype.disable=function(e,t){let n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach(function(i){n=n.concat(this[i].ruler.disable(e,!0))},this),n=n.concat(this.inline.ruler2.disable(e,!0));let r=e.filter(function(i){return n.indexOf(i)<0});if(r.length&&!t)throw new Error("MarkdownIt. Failed to disable unknown rule(s): "+r);return this};j.prototype.use=function(e){let t=[this].concat(Array.prototype.slice.call(arguments,1));return e.apply(e,t),this};j.prototype.parse=function(e,t){if(typeof e!="string")throw new Error("Input data should be a String");let n=new this.core.State(e,this,t);return this.core.process(n),n.tokens};j.prototype.render=function(e,t){return t=t||{},this.renderer.render(this.parse(e,t),this.options,t)};j.prototype.parseInline=function(e,t){let n=new this.core.State(e,this,t);return n.inlineMode=!0,this.core.process(n),n.tokens};j.prototype.renderInline=function(e,t){return t=t||{},this.renderer.render(this.parseInline(e,t),this.options,t)};var tt=j;var vd=/^#[^\s#.,,。;;::!?!?()[\]{}<>]+(?:\/[^\s#.,,。;;::!?!?()[\]{}<>]+)*$/u;function gn(e,t){if(t||e.length===0)return e;let n=e.split(/\r?\n/),r=n.filter(i=>!Td(i));return r.length===n.length?e:Dd(Ad(r)).join(` +`)}function Td(e){let t=e.trim();return t?t.split(/\s+/).every(n=>vd.test(n)):!1}function Ad(e){let t=0,n=e.length;for(;tt&&!e[n-1].trim();)n-=1;return e.slice(t,n)}function Dd(e){let t=[];for(let n of e){let r=n.trim().length===0,i=t[t.length-1],a=i!==void 0&&i.trim().length===0;r&&a||t.push(r?"":n)}return t}var Ed="#[^\\s#.,\uFF0C\u3002;\uFF1B:\uFF1A!?\uFF01\uFF1F()[\\]{}<>]+(?:\\/[^\\s#.,\uFF0C\u3002;\uFF1B:\uFF1A!?\uFF01\uFF1F()[\\]{}<>]+)*";var _d=/[\p{L}\p{N}_/#]/u,Id=new Set(["code","pre"]),Ld="ahs-ob-tag";function mn(e){if(!e||!e.includes("#"))return e;let t="",n=0,r=[];for(;nn){let s=e.slice(n,a);t+=r.length===0?ro(s):s,n=a}if(n>=e.length)break;let o=e.indexOf(">",n);if(o===-1){let s=e.slice(n);t+=r.length===0?ro(s):s;break}let u=e.slice(n,o+1);Rd(u,r),t+=u,n=o+1}return t}function ro(e){let t=new RegExp(Ed,"gu"),n="",r=0,i;for(;(i=t.exec(e))!==null;){let a=i[0],o=i.index,u=o+a.length;if(!Nd(e,o))continue;let s=wt([a])[0];s&&(n+=e.slice(r,o),n+=Pd(a,s),r=u)}return r===0?e:n+e.slice(r)}function Nd(e,t){return t===0?!0:!_d.test(e[t-1]??"")}function Pd(e,t){return`${io(e)}`}function Rd(e,t){let n=/^<\s*(\/)?\s*([a-zA-Z0-9-]+)/.exec(e);if(!n)return;let r=!!n[1],i=n[2]?.toLowerCase();if(!(!i||!Id.has(i))){if(r){for(let a=t.length-1;a>=0;a-=1)if(t[a]===i){t.splice(a,1);break}return}/\/\s*>$/.test(e)||t.push(i)}}function io(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var hn=class{constructor(t=new Z){this.deckNormalizationService=t}mapFilePathToDeck(t,n){if(n==="off")return{warnings:[]};let r=t.lastIndexOf("/");if(r<0)return{warnings:[]};let i=t.slice(0,r);if(!i.trim())return{warnings:[]};let a=i.split("/").filter(Boolean);if(n==="folder-and-file"){let o=t.slice(r+1).replace(/\.[^.]+$/,"").trim();o&&a.push(o)}return a.some(o=>o.includes("::"))?{warnings:[{filePath:t,code:"deck_invalid_folder_segment"}]}:{deck:this.deckNormalizationService.normalize(a.join("/")),warnings:[]}}};var ze=class{constructor(t=new hn,n=new Z){this.folderDeckMappingService=t;this.deckNormalizationService=n}resolve(t,n,r){if(t.deckHint)return{resolvedDeck:{value:this.deckNormalizationService.normalize(t.deckHint),source:t.deckHintSource??"body"},warnings:[...t.deckWarnings]};let i=this.folderDeckMappingService.mapFilePathToDeck(t.filePath,r);return i.deck?{resolvedDeck:{value:i.deck,source:"folder"},warnings:[...t.deckWarnings,...i.warnings]}:{resolvedDeck:{value:this.deckNormalizationService.normalize(n),source:"default"},warnings:[...t.deckWarnings,...i.warnings,{filePath:t.filePath,code:"deck_fallback_default"}]}}};function Oe(e){return`${e.filePath}\0${e.code}\0${$r(e.params)}`}function $r(e){return e===void 0?"":e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(n=>$r(n)).join(",")}]`:`{${Object.entries(e).sort(([n],[r])=>n.localeCompare(r)).map(([n,r])=>`${JSON.stringify(n)}:${$r(r)}`).join(",")}}`}function kn({href:e,label:t,escapeHref:n=!0}){return`${ao(t)}`}function nt(e,t,n){if(n==="question-last-line")return{title:e.title?`${e.title}
${t}`:t,body:e.body};let r=`

${t}

`;return n==="answer-first-line"?{title:e.title,body:e.body?`${r}${e.body}`:r}:{title:e.title,body:e.body?`${e.body}${r}`:r}}function ao(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var Bd=new tt({breaks:!0,html:!0,linkify:!0}),Gd=/`[^`\n]+`/g,qd=/==(.+?)==/g,bn=class{constructor(t,n=new pe,r=new ze,i=new V,a=()=>Date.now(),o=()=>`g_${H(`${Date.now()}_${Math.random()}_${Date.now()}`).slice(0,12)}`,u=()=>(this.sequence+=1,`i_${H(`${Date.now()}_${this.sequence}_${Math.random()}`).slice(0,10)}`),s){this.ankiGateway=t;this.qaGroupFieldMappingService=n;this.deckResolutionService=r;this.groupMarkerService=i;this.now=a;this.createGroupId=o;this.createItemId=u;this.createBacklink=s;this.sequence=0}async sync(t,n,r){if(t.length===0)return{created:0,updated:0,migratedNoteTypes:0,migratedDecks:0,markerWrites:[],resolvedNoteIds:new Map,touchedSyncKeys:[],syncedGroupBlocks:[],warnings:[]};let{modelName:i,mapping:a,availableSlots:o,legacyInternalFields:u}=await this.resolveQaGroupModel(r),s=zd(n.groupBlocks??{}),c=new Set,d=new Map,l=[],f=new Map,g=new Set,p=[],M=0,b=0,k=0,S=0,x=this.buildGroupBacklinkAnchor(t[0]??null,r);for(let h of t){if(h.items.length>o.length)throw new C("errors.noteFieldMapping.qaGroupSlotCapacityExceeded",{modelName:i,capacity:o.length,itemCount:h.items.length,filePath:h.filePath,blockStartLine:h.blockStartLine});let w=await this.resolveRecoveredGroup(h,s,i,a,o),v=w.groupId??h.groupId??this.createGroupId(),_=Kd(w.items,o),A=Wd(h.items,_,this.createItemId,o);if(A.length>o.length)throw new C("errors.noteFieldMapping.qaGroupSlotCapacityExceeded",{modelName:i,capacity:o.length,itemCount:A.length,filePath:h.filePath,blockStartLine:h.blockStartLine});let y=$d(A,o),T=this.deckResolutionService.resolve({filePath:h.filePath,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:h.deckWarnings},r.defaultDeck,r.folderDeckMode);for(let R of T.warnings)d.set(Oe(R),R);let D=T.resolvedDeck.value;c.has(D)||(await this.ankiGateway.ensureDeckExists(D),c.add(D));let z=A.map(R=>({...R,title:Qr(R.title,!1),answer:Qr(gn(R.answer,r.keepPureTagLinesInCardBody),!0)})),O=Hd(a,Qr(h.stem,!1),z,this.buildGroupBacklinkAnchor(h,r)||x,r.obsidianBacklinkPlacement,u),F=w.noteId??h.noteId,I=w.loadedNote;if(F===void 0)F=await this.ankiGateway.addNote({deckName:D,modelName:i,fields:O,tags:h.tagsHint??[]}),M+=1,g.add(h.syncKey);else{if(I??(I=await this.tryLoadQaGroupNote(F,h,i)),I.kind==="missing"&&(F=await this.ankiGateway.addNote({deckName:D,modelName:i,fields:O,tags:h.tagsHint??[]}),M+=1,g.add(h.syncKey)),I.kind==="matching"){let R=I.note,re=!Vd(R.fields,O),Fe=!(R.deckNames??[]).includes(D),ve=je(h.tagsHint,R.tags),Cn=ve.addTags.length>0||ve.removeTags.length>0;if(!re&&!Fe&&!Cn){f.set(h.syncKey,F);let go=this.now();p.push({groupId:v,noteId:F,filePath:h.filePath,headingText:h.headingText,backlinkHeadingText:h.backlinkHeadingText,headingLevel:h.headingLevel,stem:h.stem,src:h.src||be(h.filePath,h.backlinkHeadingText),blockStartOffset:h.blockStartOffset,blockEndOffset:h.blockEndOffset,blockStartLine:h.blockStartLine,bodyStartLine:h.bodyStartLine,blockEndLine:h.blockEndLine,contentEndLine:h.contentEndLine,markerLine:h.markerLine,markerIndent:h.markerIndent,rawBlockText:h.rawBlockText,rawBlockHash:h.rawBlockHash,deck:D,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:[...T.warnings],tagsHint:h.tagsHint?[...h.tagsHint]:[],items:A,freeSlots:y,lastSyncedAt:w.stateRecord?.lastSyncedAt??go,orphan:!1});continue}(re||Fe)&&await this.ankiGateway.updateNote({noteId:F,fields:O,deckName:Fe?D:void 0}),re&&(b+=1),!re&&Cn&&(b+=1),Fe&&(S+=1),Cn&&await this.ankiGateway.syncNoteTags([{noteId:F,addTags:ve.addTags,removeTags:ve.removeTags}]),g.add(h.syncKey)}if(I.kind==="model-mismatch"){let R=!(I.note.deckNames??[]).includes(D),re=je(h.tagsHint,I.note.tags),Fe=re.addTags.length>0||re.removeTags.length>0;try{await this.ankiGateway.updateNoteModel({noteId:F,modelName:i,fields:O})}catch(ve){throw Rt({noteId:F,fromModel:I.actualModelName,toModel:I.expectedModelName,error:ve,location:`${h.filePath}:${h.blockStartLine}`})}R&&I.note.cardIds.length>0&&(await this.ankiGateway.changeDecks([{deckName:D,cardIds:I.note.cardIds}]),S+=1),Fe&&await this.ankiGateway.syncNoteTags([{noteId:F,addTags:re.addTags,removeTags:re.removeTags}]),b+=1,k+=1,g.add(h.syncKey)}}f.set(h.syncKey,F);let Q=Object.fromEntries(A.filter(R=>R.itemId&&R.slot).map(R=>[R.itemId,R.slot]));(h.markerState!=="present-valid"||!this.groupMarkerService.isEquivalent(h.groupMarker,F,Q,y)||jd(h))&&l.push({syncKey:h.syncKey,filePath:h.filePath,blockStartLine:h.blockStartLine,contentEndLine:h.contentEndLine,blockEndLine:h.blockEndLine,markerLine:h.markerLine,markerIndent:h.markerIndent,noteId:F,groupId:v,itemToSlot:Q,freeSlots:y,sourceContent:h.sourceContent??""});let Vr=this.now();p.push({groupId:v,noteId:F,filePath:h.filePath,headingText:h.headingText,backlinkHeadingText:h.backlinkHeadingText,headingLevel:h.headingLevel,stem:h.stem,src:h.src||be(h.filePath,h.backlinkHeadingText),blockStartOffset:h.blockStartOffset,blockEndOffset:h.blockEndOffset,blockStartLine:h.blockStartLine,bodyStartLine:h.bodyStartLine,blockEndLine:h.blockEndLine,contentEndLine:h.contentEndLine,markerLine:h.markerLine,markerIndent:h.markerIndent,rawBlockText:h.rawBlockText,rawBlockHash:h.rawBlockHash,deck:D,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:[...T.warnings],tagsHint:h.tagsHint?[...h.tagsHint]:[],items:A,freeSlots:y,lastSyncedAt:g.has(h.syncKey)?Vr:w.stateRecord?.lastSyncedAt??Vr,orphan:!1})}return{created:M,updated:b,migratedNoteTypes:k,migratedDecks:S,markerWrites:l,resolvedNoteIds:f,touchedSyncKeys:[...g],syncedGroupBlocks:p,warnings:[...d.values()]}}async resolveRecoveredGroup(t,n,r,i,a){let o=(t.groupId?n.byGroupId.get(t.groupId):void 0)??(t.noteId!==void 0?n.byNoteId.get(t.noteId):void 0)??Ud(n.bySrc.get(t.src));if(o)return{noteId:o.noteId,groupId:o.groupId,items:o.items.map(u=>({...u})),freeSlots:[...o.freeSlots],stateRecord:o};if(t.noteId!==void 0){let u=await this.tryLoadQaGroupNote(t.noteId,t,r);return u.kind==="matching"?{...Od(u.note,i,a,t.groupId),loadedNote:u}:u.kind==="model-mismatch"?{noteId:u.note.noteId,groupId:t.groupId,items:[],freeSlots:[...a],loadedNote:u}:{noteId:t.noteId,groupId:t.groupId,items:[],freeSlots:[...a],loadedNote:u}}return{items:[],freeSlots:[...a]}}async tryLoadQaGroupNote(t,n,r){let i=(await this.ankiGateway.getNoteDetails([t]))[0];return i?i.modelName!==r?{kind:"model-mismatch",note:i,actualModelName:i.modelName,expectedModelName:r}:{kind:"matching",note:i}:{kind:"missing"}}buildGroupBacklinkAnchor(t,n){return!t||!n.addObsidianBacklink||!this.createBacklink?"":kn({href:this.createBacklink({filePath:t.filePath,sourceContent:t.sourceContent,headingLine:t.blockStartLine,blockStartLine:t.blockStartLine,bodyStartLine:t.bodyStartLine,blockEndLine:t.blockEndLine,contentEndLine:t.contentEndLine,markerLine:t.markerLine,headingLevel:t.headingLevel,headingText:t.backlinkHeadingText}),label:n.obsidianBacklinkLabel})}async resolveQaGroupModel(t){let n=t.cardTypeConfigs["qa-group"].noteType.trim();if(!n)throw new C("errors.noteFieldMapping.noteTypeNotSelected.qaGroup");let r=t.noteFieldMappings[L("qa-group",n)];if(!W(r))throw new C("errors.noteFieldMapping.missingSavedMapping.qaGroup",{modelName:n});let i=await this.ankiGateway.getModelFieldNames(n),a={...r,modelName:n,loadedFieldNames:[...i],slots:r.slots.map(o=>({...o})),warnings:[...r.warnings],acceptedWarnings:r.acceptedWarnings?[...r.acceptedWarnings]:void 0,loadedAt:this.now()};return this.qaGroupFieldMappingService.validateMapping(a,i),{modelName:n,mapping:a,availableSlots:a.slots.map(o=>o.index),legacyInternalFields:Zd(i)}}};function Hd(e,t,n,r,i,a){if(!e.titleField)throw new C("errors.noteFieldMapping.qaGroupMissingTitle",{modelName:e.modelName});let o=r&&i==="question-last-line"?nt({title:t,body:""},r,i).title:t,u={[e.titleField]:o};for(let c of e.slots)u[c.questionField]="",u[c.answerField]="";for(let c of a)u[c]="";let s=new Map(e.slots.map(c=>[c.index,c]));for(let c of n){if(c.slot===void 0)continue;let d=s.get(c.slot);if(!d)continue;let l=r&&i!=="question-last-line"?nt({title:c.title,body:c.answer},r,i).body:c.answer;u[d.questionField]=c.title,u[d.answerField]=l}return u}function zd(e){let t=new Map,n=new Map,r=new Map;for(let i of Object.values(e)){if(i.orphan)continue;t.set(i.groupId,i),n.set(i.noteId,i);let a=r.get(i.src);if(a){a.push(i);continue}r.set(i.src,[i])}return{byGroupId:t,byNoteId:n,bySrc:r}}function Od(e,t,n,r){let i=[],a=new Set;for(let o of t.slots){let u=uo(e.fields[o.questionField]??""),s=uo(e.fields[o.answerField]??"");!u&&!s||(a.add(o.index),i.push({itemId:`recovered-slot-${String(o.index).padStart(2,"0")}`,title:u,answer:s,slot:o.index,ordinalInMarkdown:o.index}))}return{noteId:e.noteId,groupId:r,items:i,freeSlots:n.filter(o=>!a.has(o))}}function Wd(e,t,n,r){let i=new Map,a=[];for(let l of t){let f=oo(l.title,l.answer),g=i.get(f);g?g.push(l):i.set(f,[l]),a.push(l)}let o=[],u=[];for(let l=0;ll.ordinalInMarkdown-f.ordinalInMarkdown||(l.slot??999)-(f.slot??999));for(let l of u){let f=e[l],g=s.shift();if(g){o[l]={...f,itemId:g.itemId,slot:g.slot};continue}o[l]={...f,itemId:n()}}let c=new Set(o.map(l=>l.slot).filter(l=>typeof l=="number")),d=[...r].filter(l=>!c.has(l));for(let l of o){if(l.slot!==void 0)continue;let f=d.shift();if(f===void 0)throw new Error("No free QA Group slots are available.");l.slot=f}return o.map((l,f)=>({...l,ordinalInMarkdown:f+1}))}function $d(e,t){let n=new Set(e.map(r=>r.slot).filter(r=>typeof r=="number"));return t.filter(r=>!n.has(r))}function oo(e,t){return`${e}\0${t}`}function Qd(e,t){let n=e.findIndex(r=>r.itemId===t.itemId&&r.slot===t.slot&&r.title===t.title&&r.answer===t.answer);n>=0&&e.splice(n,1)}function Ud(e){if(!(!e||e.length!==1))return e[0]}function Vd(e,t){let n=Object.keys(t).sort();for(let r of n)if((e[r]??"")!==(t[r]??""))return!1;return!0}function jd(e){if(!e.sourceContent)return!1;let t=e.sourceContent.split(/\r?\n/);for(let n=e.blockStartLine;n$1"),i=n.restore(r),a=Bd.renderInline(i).trim();return t?mn(a):a}function Kd(e,t){let n=new Set(t);return e.map(r=>({...r,slot:typeof r.slot=="number"&&n.has(r.slot)?r.slot:void 0}))}function uo(e){return e.replace(/

]*>.*?<\/a><\/p>/g,"").replace(/
]*>.*?<\/a>/g,"").trim()}function Zd(e){return e.includes("GroupId")&&e.includes("Src")&&e.some(n=>/^S\d+_Id$/i.test(n))&&e.some(n=>/^S\d+_Q$/i.test(n))&&e.some(n=>/^S\d+_A$/i.test(n))?e.filter(n=>n==="GroupId"||n==="Src"||/^S\d+_Id$/i.test(n)):[]}function Yd(e){let t=[];return{text:e.replace(Gd,r=>{let i=`@@QA_GROUP_INLINE_CODE_${t.length}@@`;return t.push(r),i}),restore:r=>t.reduce((i,a,o)=>i.split(`@@QA_GROUP_INLINE_CODE_${o}@@`).join(a),r)}}var Xd="manual-render-v3",we=class{constructor(t=new ze){this.deckResolutionService=t}resolve(t,n){let r=Jd(t.cardType,n),i=this.deckResolutionService.resolve(t,n.defaultDeck,n.folderDeckMode),a=i.resolvedDeck.value,o=n.noteFieldMappings[L(t.cardType,r)]??null,u={version:Xd,cardType:t.cardType,noteModel:r,mapping:o,addObsidianBacklink:n.addObsidianBacklink,obsidianBacklinkLabel:n.obsidianBacklinkLabel,obsidianBacklinkPlacement:n.obsidianBacklinkPlacement,convertHighlightsToCloze:n.convertHighlightsToCloze,keepPureTagLinesInCardBody:n.keepPureTagLinesInCardBody},s=H(JSON.stringify(u));return{deck:a,noteModel:r,renderConfigHash:s,warnings:i.warnings}}};function Jd(e,t){if(vi(e)){if(!t.clozeNoteType.trim())throw new C("errors.noteFieldMapping.noteTypeNotSelected.cloze");return t.clozeNoteType}if(e==="semantic-qa"){if(!t.semanticQaNoteType.trim())throw new C("errors.noteFieldMapping.noteTypeNotSelected.semanticQa");return t.semanticQaNoteType}if(!t.qaNoteType.trim())throw new C("errors.noteFieldMapping.noteTypeNotSelected.basic");return t.qaNoteType}var yn=class{constructor(t=new we){this.renderConfigService=t}plan(t,n,r,i){let a=new Map,o=new Set(n.pendingWriteBack.filter(k=>k.markerKind!=="group-gi").map(k=>Ee(k.filePath,k.blockStartLine,k.rawBlockHash))),u=new Set,s=[],c=[],d=[],l=[],f=[],g=new Map,p=0;for(let k of t){if(a.has(k.syncKey))throw new Error(`Duplicate syncKey detected in current scan: ${k.syncKey}`);if(a.set(k.syncKey,k),k.noteId!==void 0){let y=N(k.noteId);if(u.has(y))throw new Error(`Duplicate noteId detected in current scan: ${k.noteId}`);u.add(y)}let S=k.noteId!==void 0?n.cards[N(k.noteId)]:void 0,x=this.renderConfigService.resolve(k,i);for(let y of x.warnings)g.set(Oe(y),y);let h=k.noteId,w=Ee(k.filePath,k.blockStartLine,k.rawBlockHash),v={card:{...k,noteId:h},noteId:h,deck:x.deck,noteModel:x.noteModel,renderConfigHash:x.renderConfigHash};if(!h){s.push(v);continue}if(d.push(v),(k.idMarkerState!=="present-valid"||k.noteIdSource!=="marker"||o.has(w))&&f.push(v),!S){c.push(v);continue}let _=S.rawBlockHash!==k.rawBlockHash||S.renderConfigHash!==x.renderConfigHash||!Vi(S.tagsHint,k.tagsHint)||S.orphan,A=S.deck!==x.deck;_&&c.push(v),A&&l.push(v),!_&&!A&&(p+=1)}let M=new Set(r),b=Object.values(n.cards).filter(k=>M.has(k.filePath)&&!u.has(N(k.noteId)));return{toCreate:s,toUpdate:c,toVerifyDeck:d,toChangeDeck:l,toRewriteMarker:f,toOrphan:b,unchangedCards:p,warnings:Array.from(g.values())}}};var so=new tt({breaks:!0,html:!0,linkify:!0}),el=/`[^`\n]+`/g,tl=/```[\s\S]*?```|~~~[\s\S]*?~~~/g,nl=/(?`\\[${b.trim()}\\]`),c=c.replace(rl,(M,b)=>`\\(${b.trim()}\\)`),i&&r.convertHighlightsToCloze&&(c=c.replace(co,"{$1}")),i&&(c=c.replace(al,(M,b,k)=>`{{c${b?Number(b):l++}::${k}}}`)),c=c.replace(ol,(M,b)=>{let k=r.resourceResolver.resolveEmbed(b,n.card.filePath);return k?(d.push({kind:k.kind,fileName:k.fileName,absolutePath:k.absolutePath,altText:k.altText}),k.kind==="audio"?`[sound:${k.fileName}]`:`${rt(k.altText??k.fileName)}`):M}),c=c.replace(ul,(M,b)=>{let k=r.resourceResolver.resolveWikiLink(b,n.card.filePath);return k?`${rt(k.displayText)}`:M}),c=c.replace(co,"$1");let f=Ur(c,il,"MATH");c=f.text,c=s.restore(c),c=u.restore(c);let g=(a?so.renderInline(c):so.render(c)).trim(),p=f.restore(g,rt);return{html:a?p:mn(p),media:d}}};function Ur(e,t,n){let r=[];return{text:e.replace(t,a=>{let o=`@@${n}_${r.length}@@`;return r.push(a),o}),restore:(a,o=u=>u)=>r.reduce((u,s,c)=>u.split(`@@${n}_${c}@@`).join(o(s)),a)}}function sl(e){let t=new Set;return e.filter(n=>{let r=`${n.kind}:${n.absolutePath}:${n.fileName}`;return t.has(r)?!1:(t.add(r),!0)})}function rt(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var it=class extends C{constructor(t){super("errors.currentFileOutOfScope",{filePath:t}),this.name="CurrentFileOutOfScopeError"}},Sn=class{constructor(t,n,r,i=new Vt(t),a=new yn,o=new xn,u=new qt(r),s=new jt(t),c=new we,d=()=>Date.now()){this.vaultGateway=t;this.pluginStateRepository=n;this.ankiGateway=r;this.fileIndexerService=i;this.diffPlannerService=a;this.renderer=o;this.ankiBatchExecutor=u;this.markdownWriteBackService=s;this.scanScopeService=new Le;if(this.qaGroupSyncService=new bn(r,void 0,void 0,void 0,void 0,void 0,void 0,this.vaultGateway.createBacklink.bind(this.vaultGateway)),this.groupMarkerService=new V,cl(c)){this.renderConfigService=c,this.now=d;return}this.renderConfigService=new we,this.now=c}async syncVault(t){oe(t);let n=await this.pluginStateRepository.load(),r=await this.fileIndexerService.indexVault(t,n);return this.syncIndexedResult(r,n,t)}async syncFile(t,n){if(oe(n),!this.scanScopeService.isPathInScope(t,n.scopeMode,n.includeFolders,n.excludeFolders))throw new it(t);let r=await this.pluginStateRepository.load(),i=await this.fileIndexerService.indexFile(t,n,r);return this.syncIndexedResult(i,r,n)}async rebuildIndex(t){oe(t);let n=await this.pluginStateRepository.load(),r=await this.fileIndexerService.indexVault(t,n,!0),i=this.diffPlannerService.plan(r.cards,n,r.scopedFilePaths,t),a=new Map(r.indexedFiles.map(l=>[l.filePath,l])),o=i.toRewriteMarker.filter(l=>l.noteId!==void 0),u=this.buildReindexedGroupStates(r.groupBlocks,n),s=await this.markdownWriteBackService.write(o,a,u.markerWrites),c=lo(n,r.scopedFilePaths,u.syncedGroupBlocks),d=this.buildNextState(n,r.cards,r.indexedFiles,u.syncedGroupBlocks,t,new Set(s.writtenSyncKeys),new Map,i.toOrphan,c);if(d.pendingWriteBack=[...n.pendingWriteBack.filter(l=>!new Set(r.scopedFilePaths).has(l.filePath)),...s.pendingEntries],this.markFilesDirty(d,[...s.failureFiles.map(l=>l.filePath),...s.conflictFiles]),await this.pluginStateRepository.save(d),s.failureFiles.length>0)throw this.createWriteBackFailureError(s.failureFiles);return{scannedFiles:r.scannedFiles,scannedCards:r.cards.length+r.groupBlocks.length,created:0,updated:0,migratedNoteTypes:0,migratedDecks:0,orphaned:i.toOrphan.length+c.length,uploadedMedia:0,skippedUnchangedCards:r.skippedUnchangedCards,rewrittenMarkers:s.writtenSyncKeys.length,markerWriteConflictFiles:s.conflictFiles,warnings:po(i.warnings,u.warnings)}}async syncIndexedResult(t,n,r){let i=this.diffPlannerService.plan(t.cards,n,t.scopedFilePaths,r),a={addObsidianBacklink:r.addObsidianBacklink,obsidianBacklinkLabel:r.obsidianBacklinkLabel,obsidianBacklinkPlacement:r.obsidianBacklinkPlacement,convertHighlightsToCloze:r.convertHighlightsToCloze,keepPureTagLinesInCardBody:r.keepPureTagLinesInCardBody,resourceResolver:this.vaultGateway},o=new Map;for(let g of[...i.toCreate,...i.toUpdate])o.has(g.card.syncKey)||o.set(g.card.syncKey,this.renderer.render(g,a));let u=await this.ankiBatchExecutor.execute(i,o,async g=>this.renderer.render(g,a),r.noteFieldMappings),s=await this.qaGroupSyncService.sync(t.groupBlocks,n,r),c=new Map(t.indexedFiles.map(g=>[g.filePath,g])),d=await this.markdownWriteBackService.write(u.markerWrites,c,s.markerWrites),l=lo(n,t.scopedFilePaths,s.syncedGroupBlocks),f=this.buildNextState(n,t.cards,t.indexedFiles,s.syncedGroupBlocks,r,new Set([...u.touchedSyncKeys,...s.touchedSyncKeys,...d.writtenSyncKeys]),u.resolvedNoteIds,i.toOrphan,l);if(f.pendingWriteBack=[...n.pendingWriteBack.filter(g=>!new Set(t.scopedFilePaths).has(g.filePath)),...d.pendingEntries],this.markFilesDirty(f,[...d.failureFiles.map(g=>g.filePath),...d.conflictFiles]),await this.pluginStateRepository.save(f),d.failureFiles.length>0)throw this.createWriteBackFailureError(d.failureFiles);return{scannedFiles:t.scannedFiles,scannedCards:t.cards.length+t.groupBlocks.length,created:u.created+s.created,updated:u.updated+s.updated,migratedNoteTypes:u.migratedNoteTypes+s.migratedNoteTypes,migratedDecks:u.migratedDecks+s.migratedDecks,orphaned:i.toOrphan.length+l.length,uploadedMedia:u.uploadedMedia,skippedUnchangedCards:t.skippedUnchangedCards,rewrittenMarkers:d.writtenSyncKeys.length,markerWriteConflictFiles:d.conflictFiles,warnings:po(i.warnings,s.warnings)}}buildNextState(t,n,r,i,a,o,u,s,c){let d=this.now(),l=zn(a),f=new Set(r.filter(b=>b.content!==void 0).map(b=>b.filePath)),g=new Map;for(let b of i){let k=g.get(b.filePath);k?k.push(b):g.set(b.filePath,[b])}let p={files:{...t.files},cards:{...t.cards},groupBlocks:{...t.groupBlocks??{}},pendingWriteBack:[...t.pendingWriteBack]};for(let b of f)delete p.files[b];for(let[b,k]of Object.entries(p.cards))f.has(k.filePath)&&delete p.cards[b];for(let[b,k]of Object.entries(p.groupBlocks??{}))f.has(k.filePath)&&delete p.groupBlocks?.[b];let M=new Map;for(let b of n){let k=u.get(b.syncKey)??b.noteId;k!==void 0&&M.set(b.syncKey,k)}for(let b of r){if(b.content===void 0)continue;let k=Array.from(new Set(b.cards.map(S=>M.get(S.syncKey)).filter(S=>S!==void 0)));p.files[b.filePath]={filePath:b.filePath,fileHash:b.fileHash,fileStamp:b.fileStamp,deckRulesFingerprint:l,lastIndexedAt:d,noteIds:k,groupIds:(g.get(b.filePath)??[]).map(S=>S.groupId)}}for(let b of n){let k=M.get(b.syncKey);if(k===void 0)continue;let S=t.cards[N(k)]??(b.noteId!==void 0?t.cards[N(b.noteId)]:void 0),x=this.renderConfigService.resolve(b,a);p.cards[N(k)]={noteId:k,filePath:b.filePath,heading:b.heading,backlinkHeadingText:b.backlinkHeadingText,headingLevel:b.headingLevel,bodyMarkdown:b.bodyMarkdown,cardType:b.cardType,blockStartOffset:b.blockStartOffset,blockEndOffset:b.blockEndOffset,blockStartLine:b.blockStartLine,bodyStartLine:b.bodyStartLine,blockEndLine:b.blockEndLine,contentEndLine:b.contentEndLine,markerLine:b.markerLine,rawBlockText:b.rawBlockText,rawBlockHash:b.rawBlockHash,renderConfigHash:x.renderConfigHash,deck:x.deck,deckHint:b.deckHint,deckHintSource:b.deckHintSource,deckWarnings:[...b.deckWarnings],tagsHint:b.tagsHint,lastSyncedAt:o.has(b.syncKey)?d:S?.lastSyncedAt??0,orphan:!1}}for(let b of s)p.cards[N(b.noteId)]={...b,orphan:!0};for(let b of i)p.groupBlocks??(p.groupBlocks={}),p.groupBlocks[b.groupId]=b;for(let b of c)p.groupBlocks??(p.groupBlocks={}),p.groupBlocks[b.groupId]={...b,orphan:!0};return p}buildReindexedGroupStates(t,n){let r=[],i=[],a=[],o=new Map(Object.values(n.groupBlocks??{}).filter(s=>!s.orphan).map(s=>[s.noteId,s])),u=new Map;for(let s of Object.values(n.groupBlocks??{}).filter(c=>!c.orphan)){let c=u.get(s.src);c?c.push(s):u.set(s.src,[s])}for(let s of t){let c=(s.groupId?n.groupBlocks?.[s.groupId]:void 0)??(s.noteId!==void 0?o.get(s.noteId):void 0)??dl(u.get(s.src));if(!c)continue;let d=Object.fromEntries(c.items.filter(l=>l.itemId&&l.slot).map(l=>[l.itemId,l.slot]));r.push({...c,filePath:s.filePath,headingText:s.headingText,backlinkHeadingText:s.backlinkHeadingText,headingLevel:s.headingLevel,stem:s.stem,src:s.src,blockStartOffset:s.blockStartOffset,blockEndOffset:s.blockEndOffset,blockStartLine:s.blockStartLine,bodyStartLine:s.bodyStartLine,blockEndLine:s.blockEndLine,contentEndLine:s.contentEndLine,markerLine:s.markerLine,markerIndent:s.markerIndent,rawBlockText:s.rawBlockText,rawBlockHash:s.rawBlockHash,deckHint:s.deckHint,deckHintSource:s.deckHintSource,deckWarnings:[...s.deckWarnings],tagsHint:s.tagsHint?[...s.tagsHint]:[],orphan:!1}),a.push(...s.deckWarnings),s.sourceContent&&(s.markerState!=="present-valid"||!this.groupMarkerService.isEquivalent(s.groupMarker,c.noteId,d,c.freeSlots)||ll(s))&&i.push({syncKey:s.syncKey,filePath:s.filePath,blockStartLine:s.blockStartLine,contentEndLine:s.contentEndLine,blockEndLine:s.blockEndLine,markerLine:s.markerLine,markerIndent:s.markerIndent,noteId:c.noteId,groupId:c.groupId,itemToSlot:d,freeSlots:[...c.freeSlots],sourceContent:s.sourceContent})}return{syncedGroupBlocks:r,markerWrites:i,warnings:a}}markFilesDirty(t,n){for(let r of new Set(n))t.files[r]&&(t.files[r]={...t.files[r],fileHash:"",fileStamp:""})}createWriteBackFailureError(t){return new C("errors.writeBack.summary",{fileCount:t.length},{failures:t})}};function cl(e){return typeof e=="object"&&e!==null&&"resolve"in e}function lo(e,t,n){let r=new Set(t),i=new Set(n.map(a=>a.groupId));return Object.values(e.groupBlocks??{}).filter(a=>r.has(a.filePath)&&!i.has(a.groupId)).map(a=>({...a,orphan:!0}))}function po(...e){let t=new Map;for(let n of e)for(let r of n)t.set(Oe(r),r);return[...t.values()]}function dl(e){if(!(!e||e.length!==1))return e[0]}function ll(e){if(!e.sourceContent)return!1;let t=e.sourceContent.split(/\r?\n/);for(let n=e.blockStartLine;nthis.settings.ankiConnectUrl);this.deckTemplateInsertionService=new lt}async onload(){let n=new Mt(this);this.pluginConfigRepository=new Tt(n);let r=new At(n),i=new vt(this.app);this.vaultGateway=i;try{this.settings=await this.pluginConfigRepository.load()}catch(o){console.error("Failed to load plugin settings, falling back to defaults.",o),this.settings=P,this.noticeService.error(m("notice.invalidSettingsRestored"))}let a=new Sn(i,r,this.ankiGateway);this.syncCurrentFileUseCase=new yt(a),this.syncVaultUseCase=new St(a),this.rebuildCardIndexUseCase=new xt(a),this.clearCurrentFileSyncedCardsUseCase=new bt(r,this.ankiGateway,i),this.cleanupEmptyDecksUseCase=new pt(this.ankiGateway),Fi(this),this.addSettingTab(new Pt(this))}async updateSettings(n){if(!this.pluginConfigRepository)return;let r=ke({...this.settings,...n});try{await this.pluginConfigRepository.save(r),this.settings=r}catch(i){this.noticeService.error(le(i,"notice.failedSavePluginSettings"))}}async listNoteModels(){return this.ankiGateway.listNoteModels()}async getModelFieldNamesByModelNames(n){return this.ankiGateway.getModelFieldNamesByModelNames(n)}async getNoteModelDetails(n){return this.ankiGateway.getModelDetails(n)}async listFolderTree(){return this.vaultGateway?this.vaultGateway.listFolderTree():[]}async runSyncCurrentFile(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(m("notice.noActiveMarkdownForSync"));return}if(!this.syncCurrentFileUseCase){this.noticeService.error(m("notice.syncUseCaseNotInitialized"));return}try{let r=await this.syncCurrentFileUseCase.execute(n.path,this.settings);this.noticeService.showSyncSummary("currentFile",r)}catch(r){if(r instanceof it){this.noticeService.info(Tn(r));return}console.error("Current file sync failed.",r),this.noticeService.error(le(r,"notice.currentFileSyncFailed"))}}async runSyncVault(){if(!this.syncVaultUseCase){this.noticeService.error(m("notice.syncUseCaseNotInitialized"));return}try{let n=await this.syncVaultUseCase.execute(this.settings);this.noticeService.showSyncSummary("vault",n)}catch(n){console.error("Vault sync failed.",n),this.noticeService.error(le(n,"notice.vaultSyncFailed"))}}async runRebuildCardIndex(){if(!this.rebuildCardIndexUseCase){this.noticeService.error(m("notice.syncUseCaseNotInitialized"));return}try{let n=await this.rebuildCardIndexUseCase.execute(this.settings);this.noticeService.showRebuildSummary(n)}catch(n){console.error("Card index rebuild failed.",n),this.noticeService.error(le(n,"notice.rebuildFailed"))}}async insertDeckTemplateToCurrentFile(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(m("notice.noActiveMarkdownForDeckTemplateInsertion"));return}if(!this.vaultGateway){this.noticeService.error(m("notice.vaultGatewayNotInitialized"));return}try{let r=await this.vaultGateway.readMarkdownFile(n.path);if(!r){this.noticeService.error(m("notice.markdownFileNotFound",{filePath:n.path}));return}let i=this.deckTemplateInsertionService.insert(r,this.settings.fileDeckMarker,this.settings.fileDeckTemplate,this.settings.fileDeckInsertLocation);if(i.nextContent===i.expectedContent){this.noticeService.info(m("notice.deckTemplateAlreadyCurrent"));return}await this.vaultGateway.replaceMarkdownFile(n.path,i.expectedContent,i.nextContent),this.noticeService.info(m("notice.deckTemplateInserted",{deck:i.insertedDeck}))}catch(r){console.error("Deck template insertion failed.",r),this.noticeService.error(le(r,"notice.deckTemplateInsertionFailed"))}}async runClearCurrentFileSyncedCards(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(m("notice.noActiveMarkdownForReset"));return}if(!this.clearCurrentFileSyncedCardsUseCase){this.noticeService.error(m("notice.clearCurrentFileUseCaseNotInitialized"));return}try{if(!await this.clearCurrentFileSyncedCardsUseCase.hasTrackedCards(n.path)){this.noticeService.info(m("notice.noTrackedCardsInCurrentFile"));return}let i=await this.clearCurrentFileSyncedCardsUseCase.execute(n.path);this.noticeService.showClearCurrentFileSummary(i)}catch(r){console.error("Clear current file synced cards failed.",r),this.noticeService.error(le(r,"notice.clearCurrentFileFailed"))}}async runCleanupEmptyDecks(){if(!this.cleanupEmptyDecksUseCase){this.noticeService.error(m("notice.cleanupEmptyDecksUseCaseNotInitialized"));return}try{let n=await this.cleanupEmptyDecksUseCase.listCandidates();if(n.length===0){this.noticeService.info(m("notice.noEmptyDeckCandidates"));return}let r=await new Et(this.app,n).openAndGetSelection();if(r===null){this.noticeService.info(m("notice.cleanupEmptyDecksCancelled"));return}let i=await this.cleanupEmptyDecksUseCase.execute(r,n);this.noticeService.showCleanupEmptyDecksSummary(i)}catch(n){console.error("Cleanup empty decks failed.",n),this.noticeService.error(le(n,"notice.cleanupEmptyDecksFailed"))}}};var pl=at; diff --git a/src/application/config/PluginSettings.test.ts b/src/application/config/PluginSettings.test.ts index bd93877..44aa7bd 100644 --- a/src/application/config/PluginSettings.test.ts +++ b/src/application/config/PluginSettings.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "vitest"; import { PluginUserError } from "@/application/errors/PluginUserError"; +import { createNoteFieldMappingKey } from "@/application/config/NoteModelFieldMapping"; import { DEFAULT_OBSIDIAN_BACKLINK_LABEL, @@ -174,6 +175,43 @@ describe("PluginSettings", () => { }); }); + it("hydrates missing enabled basic and cloze field mappings from cached Anki fields", () => { + const settings = mergePluginSettings({ + ankiModelFieldCache: { + "问答题": { + fieldNames: ["正面", "背面"], + loadedAt: 10, + }, + "填空题": { + fieldNames: ["文字", "背面额外"], + loadedAt: 20, + }, + }, + cardTypeConfigs: { + ...DEFAULT_SETTINGS.cardTypeConfigs, + basic: { + ...DEFAULT_SETTINGS.cardTypeConfigs.basic, + noteType: "问答题", + }, + cloze: { + ...DEFAULT_SETTINGS.cardTypeConfigs.cloze, + noteType: "填空题", + }, + }, + noteFieldMappings: {}, + }); + + expect(settings.noteFieldMappings[createNoteFieldMappingKey("basic", "问答题")]).toEqual(expect.objectContaining({ + titleField: "正面", + bodyField: "背面", + loadedAt: 10, + })); + expect(settings.noteFieldMappings[createNoteFieldMappingKey("cloze", "填空题")]).toEqual(expect.objectContaining({ + mainField: "文字", + loadedAt: 20, + })); + }); + it("migrates the old default cloze recognition to H4 + #anki-cloze", () => { const settings = mergePluginSettings({ cardTypeConfigs: { diff --git a/src/application/config/PluginSettings.ts b/src/application/config/PluginSettings.ts index 0f06677..637514b 100644 --- a/src/application/config/PluginSettings.ts +++ b/src/application/config/PluginSettings.ts @@ -125,8 +125,7 @@ export function normalizeObsidianBacklinkLabel(value: string | null | undefined) export function normalizePluginSettings(settings: PluginSettings): PluginSettings { const cardTypeConfigs = mergeCardTypeConfigs(settings.cardTypeConfigs, settings); const legacySettings = deriveLegacySettings(cardTypeConfigs); - - return { + const normalizedSettings = { ...settings, ...legacySettings, cardTypeConfigs, @@ -135,6 +134,11 @@ export function normalizePluginSettings(settings: PluginSettings): PluginSetting ankiModelFieldCache: normalizeAnkiModelFieldCache(settings.ankiModelFieldCache), obsidianBacklinkLabel: normalizeObsidianBacklinkLabel(settings.obsidianBacklinkLabel), }; + + return { + ...normalizedSettings, + noteFieldMappings: hydrateMissingNoteFieldMappingsFromCache(normalizedSettings), + }; } export function mergePluginSettings(settings?: Partial | null): PluginSettings { @@ -568,6 +572,61 @@ function normalizeNoteFieldMappings(value: unknown): Record { + const hydratedMappings = { ...settings.noteFieldMappings }; + + for (const configId of CARD_TYPE_CONFIG_IDS) { + if (configId === "qa-group") { + continue; + } + + const config = settings.cardTypeConfigs[configId]; + if (!config.enabled) { + continue; + } + + const modelName = config.noteType.trim(); + if (modelName.length === 0) { + continue; + } + + const cardType = configId === "cloze" ? "cloze" : configId === "semantic-qa" ? "semantic-qa" : "basic"; + const mappingKey = createNoteFieldMappingKey(cardType, modelName); + if (hydratedMappings[mappingKey]) { + continue; + } + + const cacheEntry = settings.ankiModelFieldCache[modelName]; + if (!cacheEntry || cacheEntry.fieldNames.length === 0) { + continue; + } + + const fieldNames = [...cacheEntry.fieldNames]; + hydratedMappings[mappingKey] = cardType === "cloze" + ? { + cardType, + modelName, + loadedFieldNames: fieldNames, + mainField: findPreferredFieldName(fieldNames, ["Text", "Body", "Content"]) ?? fieldNames[0], + loadedAt: cacheEntry.loadedAt, + } + : { + cardType, + modelName, + loadedFieldNames: fieldNames, + titleField: findPreferredFieldName(fieldNames, ["Front", "Title"]) ?? fieldNames[0], + bodyField: findPreferredFieldName(fieldNames, ["Back", "Body", "Answer"]) ?? fieldNames.find((fieldName) => fieldName !== (findPreferredFieldName(fieldNames, ["Front", "Title"]) ?? fieldNames[0])), + loadedAt: cacheEntry.loadedAt, + }; + } + + return hydratedMappings; +} + +function findPreferredFieldName(fieldNames: string[], preferredNames: string[]): string | undefined { + return fieldNames.find((fieldName) => preferredNames.some((preferredName) => preferredName.toLowerCase() === fieldName.toLowerCase())); +} + function normalizeQaGroupFieldMapping( mapping: Record, modelName: string, diff --git a/src/application/services/NoteFieldMappingService.test.ts b/src/application/services/NoteFieldMappingService.test.ts index ed3e8e1..015d3c2 100644 --- a/src/application/services/NoteFieldMappingService.test.ts +++ b/src/application/services/NoteFieldMappingService.test.ts @@ -76,7 +76,7 @@ describe("NoteFieldMappingService", () => { }), { fieldNames: ["Text", "Extra"], - isCloze: true, + isCloze: false, }, { [createNoteFieldMappingKey("cloze", "Cloze")]: { @@ -92,6 +92,61 @@ describe("NoteFieldMappingService", () => { expect(fields).toEqual({ Text: "Context

{{c1::answer}}" }); }); + it("throws when a cloze main field is missing from the saved mapping", () => { + const service = new NoteFieldMappingService(); + + const error = expectPluginUserError(() => + service.map( + createCard({ + type: "cloze", + noteModel: "Cloze", + }), + { fieldNames: ["Text", "Extra"], isCloze: false }, + { + [createNoteFieldMappingKey("cloze", "Cloze")]: { + cardType: "cloze", + modelName: "Cloze", + loadedFieldNames: ["Text", "Extra"], + mainField: undefined, + loadedAt: 1, + }, + }, + ), + ); + + expect(error.userMessage.key).toBe("errors.noteFieldMapping.incompleteSavedMapping.cloze"); + expect(error.userMessage.params).toEqual({ modelName: "Cloze" }); + }); + + it("throws when a cloze main field is stale even if isCloze is false", () => { + const service = new NoteFieldMappingService(); + + const error = expectPluginUserError(() => + service.map( + createCard({ + type: "cloze", + noteModel: "Cloze", + }), + { fieldNames: ["Body", "Extra"], isCloze: false }, + { + [createNoteFieldMappingKey("cloze", "Cloze")]: { + cardType: "cloze", + modelName: "Cloze", + loadedFieldNames: ["Text", "Extra"], + mainField: "Text", + loadedAt: 1, + }, + }, + ), + ); + + expect(error.userMessage.key).toBe("errors.noteFieldMapping.stale"); + expect(error.userMessage.params).toEqual({ + modelName: "Cloze", + fields: ["\"Text\""], + }); + }); + it("throws when a mapping is missing", () => { const service = new NoteFieldMappingService(); diff --git a/src/application/services/NoteFieldMappingService.ts b/src/application/services/NoteFieldMappingService.ts index f8b142d..d5cb355 100644 --- a/src/application/services/NoteFieldMappingService.ts +++ b/src/application/services/NoteFieldMappingService.ts @@ -38,7 +38,7 @@ export class NoteFieldMappingService { return this.mapBasic(card, mapping as BasicLikeNoteModelFieldMapping); } - return this.mapCloze(card, noteModelDetails, mapping as ClozeNoteModelFieldMapping); + return this.mapCloze(card, mapping as ClozeNoteModelFieldMapping); } suggest(cardType: NoteModelFieldMappingCardType, modelName: string, fieldNames: string[], loadedAt = Date.now()): NoteModelFieldMapping { @@ -103,12 +103,6 @@ export class NoteFieldMappingService { }); } - if (!noteModelDetails.isCloze) { - throw new PluginUserError("errors.noteFieldMapping.clozeIncompatible", { - modelName: mapping.modelName, - }); - } - if (!availableFields.has(mapping.mainField)) { throw new PluginUserError("errors.noteFieldMapping.stale", { modelName: mapping.modelName, @@ -133,13 +127,7 @@ export class NoteFieldMappingService { }; } - private mapCloze(card: RenderedCardInput, noteModelDetails: NoteModelDetails, mapping: ClozeNoteModelFieldMapping): Record { - if (!noteModelDetails.isCloze) { - throw new PluginUserError("errors.noteFieldMapping.clozeIncompatible", { - modelName: card.noteModel, - }); - } - + private mapCloze(card: RenderedCardInput, mapping: ClozeNoteModelFieldMapping): Record { if (!mapping.mainField) { throw new PluginUserError("errors.noteFieldMapping.incompleteSavedMapping.cloze", { modelName: card.noteModel, diff --git a/src/application/services/QaGroupSyncService.test.ts b/src/application/services/QaGroupSyncService.test.ts index c7734ba..7643493 100644 --- a/src/application/services/QaGroupSyncService.test.ts +++ b/src/application/services/QaGroupSyncService.test.ts @@ -76,6 +76,85 @@ describe("QaGroupSyncService", () => { expect(ankiGateway.addedNotes[0]?.fields).not.toHaveProperty("题目"); }); + it("uses the saved QA Group slots as sync authority instead of re-detecting field names", async () => { + const ankiGateway = new FakeManualSyncAnkiGateway(); + ankiGateway.modelDetailsByName[QA_GROUP_USER_NOTE_TYPE] = { + fieldNames: ["题目", "问题01", "答案01", "Titre", "QPerso", "APerso"], + isCloze: false, + }; + const service = new QaGroupSyncService(ankiGateway); + const baseSettings = createModule3Settings(); + + await service.sync([ + createIndexedGroupBlock({ + items: [{ title: "Alpha", answer: "First answer", ordinalInMarkdown: 1 }], + }), + ], createEmptyPluginState(), { + ...baseSettings, + noteFieldMappings: { + ...baseSettings.noteFieldMappings, + [`qa-group:${QA_GROUP_USER_NOTE_TYPE}`]: { + cardType: "qa-group", + modelName: QA_GROUP_USER_NOTE_TYPE, + loadedFieldNames: ["题目", "问题01", "答案01", "Titre", "QPerso", "APerso"], + titleField: "Titre", + slots: [ + { index: 1, questionField: "QPerso", answerField: "APerso" }, + ], + warnings: [], + loadedAt: 1, + }, + }, + }); + + expect(ankiGateway.addedNotes[0]?.fields).toMatchObject({ + Titre: "Concepts", + QPerso: "Alpha", + }); + expect(ankiGateway.addedNotes[0]?.fields.APerso).toContain("First answer"); + expect(ankiGateway.addedNotes[0]?.fields).not.toHaveProperty("题目"); + expect(ankiGateway.addedNotes[0]?.fields).not.toHaveProperty("问题01", "Alpha"); + }); + + it("syncs QA Group notes with saved arbitrary field names when the fields still exist", async () => { + const ankiGateway = new FakeManualSyncAnkiGateway(); + ankiGateway.modelDetailsByName[QA_GROUP_USER_NOTE_TYPE] = { + fieldNames: ["Titre", "QuestionLibre", "ReponseLibre"], + isCloze: false, + }; + const service = new QaGroupSyncService(ankiGateway); + const baseSettings = createModule3Settings(); + + const result = await service.sync([ + createIndexedGroupBlock({ + items: [{ title: "Alpha", answer: "Premiere reponse", ordinalInMarkdown: 1 }], + }), + ], createEmptyPluginState(), { + ...baseSettings, + noteFieldMappings: { + ...baseSettings.noteFieldMappings, + [`qa-group:${QA_GROUP_USER_NOTE_TYPE}`]: { + cardType: "qa-group", + modelName: QA_GROUP_USER_NOTE_TYPE, + loadedFieldNames: ["Titre", "QuestionLibre", "ReponseLibre"], + titleField: "Titre", + slots: [ + { index: 1, questionField: "QuestionLibre", answerField: "ReponseLibre" }, + ], + warnings: [], + loadedAt: 1, + }, + }, + }); + + expect(result.created).toBe(1); + expect(ankiGateway.addedNotes[0]?.fields).toMatchObject({ + Titre: "Concepts", + QuestionLibre: "Alpha", + }); + expect(ankiGateway.addedNotes[0]?.fields.ReponseLibre).toContain("Premiere reponse"); + }); + it("renders QA Group stem, questions, and answers as inline Markdown HTML", async () => { const ankiGateway = new FakeManualSyncAnkiGateway(); const vaultGateway = new FakeManualSyncVaultGateway(); @@ -628,10 +707,10 @@ describe("QaGroupSyncService", () => { }); }); - it("blocks sync when the selected QA Group template still has unconfirmed field warnings", async () => { + it("fails clearly when a saved QA Group field mapping points to fields that no longer exist", async () => { const ankiGateway = new FakeManualSyncAnkiGateway(); ankiGateway.modelDetailsByName[QA_GROUP_USER_NOTE_TYPE] = { - fieldNames: ["题目", "问题01", "答案01", "问题02"], + fieldNames: ["题目", "问题01"], isCloze: false, }; const service = new QaGroupSyncService(ankiGateway); @@ -639,6 +718,40 @@ describe("QaGroupSyncService", () => { await expect(service.sync([ createIndexedGroupBlock(), + ], createEmptyPluginState(), { + ...baseSettings, + noteFieldMappings: { + ...baseSettings.noteFieldMappings, + [`qa-group:${QA_GROUP_USER_NOTE_TYPE}`]: { + cardType: "qa-group", + modelName: QA_GROUP_USER_NOTE_TYPE, + loadedFieldNames: ["题目", "问题01", "答案01"], + titleField: "题目", + slots: [{ index: 1, questionField: "问题01", answerField: "答案01" }], + warnings: [], + loadedAt: 1, + }, + }, + })).rejects.toMatchObject({ + userMessage: { + key: "errors.noteFieldMapping.stale", + }, + }); + }); + + it("does not block sync when a saved QA Group mapping still carries unconfirmed auto-detection warnings", async () => { + const ankiGateway = new FakeManualSyncAnkiGateway(); + ankiGateway.modelDetailsByName[QA_GROUP_USER_NOTE_TYPE] = { + fieldNames: ["题目", "问题01", "答案01", "问题02"], + isCloze: false, + }; + const service = new QaGroupSyncService(ankiGateway); + const baseSettings = createModule3Settings(); + + const result = await service.sync([ + createIndexedGroupBlock({ + items: [{ title: "Alpha", answer: "First answer", ordinalInMarkdown: 1 }], + }), ], createEmptyPluginState(), { ...baseSettings, noteFieldMappings: { @@ -653,9 +766,30 @@ describe("QaGroupSyncService", () => { loadedAt: 1, }, }, + }); + + expect(result.created).toBe(1); + expect(ankiGateway.addedNotes[0]?.fields).toMatchObject({ + 题目: "Concepts", + 问题01: "Alpha", + }); + }); + + it("fails clearly when QA Group sync starts without a saved field mapping", async () => { + const ankiGateway = new FakeManualSyncAnkiGateway(); + const service = new QaGroupSyncService(ankiGateway); + const baseSettings = createModule3Settings(); + const nextMappings = { ...baseSettings.noteFieldMappings }; + delete nextMappings[`qa-group:${QA_GROUP_USER_NOTE_TYPE}`]; + + await expect(service.sync([ + createIndexedGroupBlock(), + ], createEmptyPluginState(), { + ...baseSettings, + noteFieldMappings: nextMappings, })).rejects.toMatchObject({ userMessage: { - key: "errors.noteFieldMapping.qaGroupWarningsUnaccepted", + key: "errors.noteFieldMapping.missingSavedMapping.qaGroup", }, }); }); diff --git a/src/application/services/QaGroupSyncService.ts b/src/application/services/QaGroupSyncService.ts index bfbb19d..cad2b33 100644 --- a/src/application/services/QaGroupSyncService.ts +++ b/src/application/services/QaGroupSyncService.ts @@ -482,16 +482,23 @@ export class QaGroupSyncService { } const storedMapping = settings.noteFieldMappings[createNoteFieldMappingKey("qa-group", modelName)]; + if (!isQaGroupFieldMapping(storedMapping)) { + throw new PluginUserError("errors.noteFieldMapping.missingSavedMapping.qaGroup", { + modelName, + }); + } + const fieldNames = await this.ankiGateway.getModelFieldNames(modelName); - const mapping = this.qaGroupFieldMappingService.suggest( + const mapping: QaGroupFieldMapping = { + ...storedMapping, modelName, - fieldNames, - this.now(), - isQaGroupFieldMapping(storedMapping) ? storedMapping.acceptedWarnings : undefined, - isQaGroupFieldMapping(storedMapping) ? storedMapping.titleField : undefined, - ); + loadedFieldNames: [...fieldNames], + slots: storedMapping.slots.map((slot) => ({ ...slot })), + warnings: [...storedMapping.warnings], + acceptedWarnings: storedMapping.acceptedWarnings ? [...storedMapping.acceptedWarnings] : undefined, + loadedAt: this.now(), + }; this.qaGroupFieldMappingService.validateMapping(mapping, fieldNames); - this.qaGroupFieldMappingService.validateWarningsAccepted(mapping); return { modelName, diff --git a/src/infrastructure/anki/AnkiConnectGateway.test.ts b/src/infrastructure/anki/AnkiConnectGateway.test.ts index 34c4ca4..cfca8fb 100644 --- a/src/infrastructure/anki/AnkiConnectGateway.test.ts +++ b/src/infrastructure/anki/AnkiConnectGateway.test.ts @@ -125,29 +125,20 @@ describe("AnkiConnectGateway", () => { }); }); - it("loads model fields and detects cloze templates", async () => { - requestUrlMock - .mockResolvedValueOnce({ - json: { - error: null, - result: ["Text", "Extra"], - }, - }) - .mockResolvedValueOnce({ - json: { - error: null, - result: { - "Cloze Card": {}, - }, - }, - }); + it("loads model fields without inferring cloze compatibility from names", async () => { + requestUrlMock.mockResolvedValueOnce({ + json: { + error: null, + result: ["Text", "Extra"], + }, + }); const gateway = new AnkiConnectGateway(() => "http://127.0.0.1:8765"); const details = await gateway.getModelDetails("My Cloze"); expect(details).toEqual({ fieldNames: ["Text", "Extra"], - isCloze: true, + isCloze: false, }); }); diff --git a/src/infrastructure/anki/AnkiConnectGateway.ts b/src/infrastructure/anki/AnkiConnectGateway.ts index 024d3e7..38799ac 100644 --- a/src/infrastructure/anki/AnkiConnectGateway.ts +++ b/src/infrastructure/anki/AnkiConnectGateway.ts @@ -217,19 +217,9 @@ export class AnkiConnectGateway implements AnkiGroupGateway { } async getModelDetails(modelName: string): Promise { - const fieldNames = await this.getModelFieldNames(modelName); - let isCloze = modelName.toLowerCase().includes("cloze"); - - try { - const templates = await this.getModelTemplates(modelName); - isCloze = isCloze || Object.keys(templates).some((templateName) => templateName.toLowerCase().includes("cloze")); - } catch { - isCloze = isCloze || fieldNames.some((fieldName) => fieldName.toLowerCase() === "text"); - } - return { - fieldNames, - isCloze, + fieldNames: await this.getModelFieldNames(modelName), + isCloze: false, }; } diff --git a/src/presentation/i18n/messages/en.ts b/src/presentation/i18n/messages/en.ts index 13520c9..57be811 100644 --- a/src/presentation/i18n/messages/en.ts +++ b/src/presentation/i18n/messages/en.ts @@ -428,6 +428,7 @@ export const en = { basic: "No saved field mapping found for basic note type \"{{modelName}}\". Open plugin settings and read fields from Anki first.", cloze: "No saved field mapping found for cloze note type \"{{modelName}}\". Open plugin settings and read fields from Anki first.", semanticQa: "No saved field mapping found for semantic QA note type \"{{modelName}}\". Open plugin settings and read fields from Anki first.", + qaGroup: "No saved field mapping found for QA Group note type \"{{modelName}}\". Open plugin settings, read fields from Anki, and save the mapping first.", }, incompleteSavedMapping: { basic: "Saved field mapping for basic note type \"{{modelName}}\" is incomplete. Open plugin settings and save both title and body fields.", @@ -440,11 +441,11 @@ export const en = { }, stale: "Saved field mapping for note type \"{{modelName}}\" is stale because these fields no longer exist in Anki: {{fields}}. Open plugin settings and read fields from Anki again.", clozeIncompatible: "Cloze note type \"{{modelName}}\" is not cloze-compatible in Anki.", - qaGroupMissingTitle: "QA Group note type \"{{modelName}}\" does not expose a recognizable title field. Use one of 题目, 标题, 正面, Stem, or Title.", - qaGroupNoCompleteSlots: "QA Group note type \"{{modelName}}\" does not expose any complete question/answer slot pairs.", + qaGroupMissingTitle: "Saved field mapping for QA Group note type \"{{modelName}}\" is incomplete because the title field is missing. Save the mapping again in settings.", + qaGroupNoCompleteSlots: "Saved field mapping for QA Group note type \"{{modelName}}\" is incomplete because it has no saved question/answer slot pairs. Save the mapping again in settings.", qaGroupNonContinuousSlots: "QA Group note type \"{{modelName}}\" must start its question/answer slots at pair {{firstIndex}} = 1. Renumber the first pair to 1.", qaGroupWarningsUnaccepted: "QA Group note type \"{{modelName}}\" still has unconfirmed field warnings. Confirm them in settings before syncing.", - qaGroupSlotCapacityExceeded: "QA Group note type \"{{modelName}}\" only exposes {{capacity}} question/answer pair(s), but the current block has {{itemCount}} item(s): {{filePath}}:{{blockStartLine}}.", + qaGroupSlotCapacityExceeded: "Saved field mapping for QA Group note type \"{{modelName}}\" only includes {{capacity}} question/answer pair(s), but the current block has {{itemCount}} item(s): {{filePath}}:{{blockStartLine}}.", }, noteTypeMigration: { failed: "Failed to migrate Anki note {{noteId}} from \"{{fromModel}}\" to \"{{toModel}}\"{{location}}: {{reason}}", diff --git a/src/presentation/i18n/messages/zh.ts b/src/presentation/i18n/messages/zh.ts index d4eb49c..7a58ca8 100644 --- a/src/presentation/i18n/messages/zh.ts +++ b/src/presentation/i18n/messages/zh.ts @@ -426,6 +426,7 @@ export const zh = { basic: "找不到基础卡笔记类型 \"{{modelName}}\" 的已保存字段映射。请打开插件设置并先从 Anki 读取字段。", cloze: "找不到填空题笔记类型 \"{{modelName}}\" 的已保存字段映射。请打开插件设置并先从 Anki 读取字段。", semanticQa: "找不到语义 QA 笔记类型 \"{{modelName}}\" 的已保存字段映射。请打开插件设置并先从 Anki 读取字段。", + qaGroup: "找不到问答题(多级列表)笔记模板 \"{{modelName}}\" 的已保存字段映射。请先在设置页从 Anki 读取字段并保存映射。", }, incompleteSavedMapping: { basic: "基础卡笔记类型 \"{{modelName}}\" 的已保存字段映射不完整。请打开插件设置并保存标题字段和正文字段。", @@ -438,11 +439,11 @@ export const zh = { }, stale: "笔记类型 \"{{modelName}}\" 的已保存字段映射已过期,因为这些字段在 Anki 中已不存在:{{fields}}。请重新从 Anki 读取字段。", clozeIncompatible: "填空题笔记类型 \"{{modelName}}\" 在 Anki 中不是填空题兼容模型。", - qaGroupMissingTitle: "问答题(多级列表)笔记模板 \"{{modelName}}\" 缺少可识别的题目字段。请使用 题目、标题、正面、Stem 或 Title 之一。", - qaGroupNoCompleteSlots: "问答题(多级列表)笔记模板 \"{{modelName}}\" 没有可用的完整问题/答案字段组。", + qaGroupMissingTitle: "问答题(多级列表)笔记模板 \"{{modelName}}\" 的已保存字段映射不完整,缺少标题字段。请在设置页重新保存字段映射。", + qaGroupNoCompleteSlots: "问答题(多级列表)笔记模板 \"{{modelName}}\" 的已保存字段映射不完整,至少需要一组问题/答案字段。请在设置页重新保存字段映射。", qaGroupNonContinuousSlots: "问答题(多级列表)笔记模板 \"{{modelName}}\" 的第一组问题/答案字段不是从第 {{firstIndex}} 组开始连续编号。请从第 1 组开始。", qaGroupWarningsUnaccepted: "问答题(多级列表)笔记模板 \"{{modelName}}\" 仍有未确认的字段警告。请先在设置页确认后再同步。", - qaGroupSlotCapacityExceeded: "问答题(多级列表)笔记模板 \"{{modelName}}\" 只识别到 {{capacity}} 组问题/答案字段,但当前块有 {{itemCount}} 项:{{filePath}}:{{blockStartLine}}。", + qaGroupSlotCapacityExceeded: "问答题(多级列表)笔记模板 \"{{modelName}}\" 的已保存字段映射只包含 {{capacity}} 组问题/答案字段,但当前块有 {{itemCount}} 项:{{filePath}}:{{blockStartLine}}。", }, noteTypeMigration: { failed: "无法将 Anki 笔记 {{noteId}} 从“{{fromModel}}”迁移到“{{toModel}}”{{location}}:{{reason}}", diff --git a/src/presentation/settings/PluginSettingTab.test.ts b/src/presentation/settings/PluginSettingTab.test.ts index cfcd992..e5978d8 100644 --- a/src/presentation/settings/PluginSettingTab.test.ts +++ b/src/presentation/settings/PluginSettingTab.test.ts @@ -1255,6 +1255,11 @@ describe("PluginSettingTab", () => { const basicAnswerFieldSelect = queryByDataset(tab.containerEl, "cardTypeAnswerField", "basic"); expect(collectOptionValues(basicQuestionFieldSelect)).toEqual(["", "Front", "Back", "Extra"]); expect(collectOptionValues(basicAnswerFieldSelect)).toEqual(["", "Front", "Back", "Extra"]); + expect(plugin.settings.noteFieldMappings[createNoteFieldMappingKey("basic", "Basic")]).toEqual(expect.objectContaining({ + titleField: "Front", + bodyField: "Back", + loadedFieldNames: ["Front", "Back", "Extra"], + })); expect(plugin.getNoteModelDetailsCalls).toBe(0); }); @@ -1299,9 +1304,62 @@ describe("PluginSettingTab", () => { expect(plugin.settings.noteFieldMappings[mappingKey]).toEqual(expect.objectContaining({ warnings: expect.any(Array), - acceptedWarnings: undefined, + acceptedWarnings: expect.any(Array), })); - expect(queryByDataset(tab.containerEl, "qaGroupWarning", "qa-group").textContent).toContain("第 03 组缺少答案字段"); + expect(queryByDataset(tab.containerEl, "qaGroupWarning", "qa-group").textContent).toContain("第 02 组缺少答案字段"); + }); + + it("keeps the saved qa-group title field and slots when reading Anki fields again", async () => { + const plugin = new FakePlugin(); + plugin.settings = normalizePluginSettings({ + ...plugin.settings, + ankiNoteTypeCache: [QA_GROUP_USER_MODEL_NAME], + ankiModelFieldCache: { + [QA_GROUP_USER_MODEL_NAME]: { + fieldNames: ["题目", "问题01", "答案01", "Titre", "QPerso", "APerso"], + loadedAt: 100, + }, + }, + cardTypeConfigs: { + ...plugin.settings.cardTypeConfigs, + "qa-group": { + ...plugin.settings.cardTypeConfigs["qa-group"], + noteType: QA_GROUP_USER_MODEL_NAME, + }, + }, + noteFieldMappings: { + ...plugin.settings.noteFieldMappings, + [createNoteFieldMappingKey("qa-group", QA_GROUP_USER_MODEL_NAME)]: { + cardType: "qa-group", + modelName: QA_GROUP_USER_MODEL_NAME, + loadedFieldNames: ["Titre", "QPerso", "APerso"], + titleField: "Titre", + slots: [ + { index: 1, questionField: "QPerso", answerField: "APerso" }, + ], + warnings: [], + loadedAt: 1, + }, + }, + }); + plugin.fieldNamesByModelName[QA_GROUP_USER_MODEL_NAME] = ["题目", "问题01", "答案01", "Titre", "QPerso", "APerso"]; + const tab = new AnkiHeadingSyncSettingTab(plugin as never); + + tab.display(); + await expandCard(tab, "card-types"); + await queryByDataset(tab.containerEl, "cardTypesRefresh", "true").trigger("click"); + await flushPromises(); + + const mappingKey = createNoteFieldMappingKey("qa-group", QA_GROUP_USER_MODEL_NAME); + expect(plugin.settings.noteFieldMappings[mappingKey]).toEqual(expect.objectContaining({ + titleField: "Titre", + slots: [ + { index: 1, questionField: "QPerso", answerField: "APerso" }, + ], + loadedFieldNames: ["题目", "问题01", "答案01", "Titre", "QPerso", "APerso"], + })); + expect(queryByDataset(tab.containerEl, "qaGroupTitleField", "qa-group").value).toBe("Titre"); + expect(queryByDataset(tab.containerEl, "qaGroupSlotSummary", "qa-group").textContent).toBe("已识别 1 组"); }); it("renders the scope card with renamed copy and aligned folder tree rows", async () => { diff --git a/src/presentation/settings/PluginSettingTab.ts b/src/presentation/settings/PluginSettingTab.ts index d989927..0d43562 100644 --- a/src/presentation/settings/PluginSettingTab.ts +++ b/src/presentation/settings/PluginSettingTab.ts @@ -880,6 +880,10 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { } } + if ((configId === "basic" || configId === "cloze") && typeof partialConfig.noteType === "string") { + await this.syncFieldMappingFromCache(configId); + } + this.renderCard("card-types"); return true; } @@ -937,6 +941,7 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { }); this.hydrateVisibleCardTypeCaches(ankiModelFieldCache); + await this.syncVisibleFieldMappingsFromCache(ankiModelFieldCache); await this.syncQaGroupMappingFromCache(this.plugin.settings.cardTypeConfigs["qa-group"].noteType, ankiModelFieldCache); const configuredCount = this.countConfiguredCardTypes(ankiModelFieldCache); @@ -1080,10 +1085,56 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { this.seedDraftMapping(runtimeCardType, modelName, modelDetails, cacheEntry.loadedAt); } + private async syncVisibleFieldMappingsFromCache( + ankiModelFieldCache: AnkiHeadingSyncPlugin["settings"]["ankiModelFieldCache"] = this.plugin.settings.ankiModelFieldCache, + ): Promise { + for (const configId of VISIBLE_CARD_TYPE_CONFIG_IDS) { + if (configId === "qa-group") { + continue; + } + + await this.syncFieldMappingFromCache(configId, ankiModelFieldCache); + } + } + + private async syncFieldMappingFromCache( + configId: Extract, + ankiModelFieldCache: AnkiHeadingSyncPlugin["settings"]["ankiModelFieldCache"] = this.plugin.settings.ankiModelFieldCache, + ): Promise { + const runtimeCardType = this.getRuntimeCardType(configId); + const modelName = this.plugin.settings.cardTypeConfigs[configId].noteType.trim(); + const cacheEntry = ankiModelFieldCache[modelName]; + if (!cacheEntry) { + return; + } + + const mappingKey = createNoteFieldMappingKey(runtimeCardType, modelName); + const currentMapping = this.plugin.settings.noteFieldMappings[mappingKey] ?? this.draftMappings[mappingKey]; + const nextMapping = currentMapping + ? { + ...currentMapping, + loadedFieldNames: [...cacheEntry.fieldNames], + loadedAt: cacheEntry.loadedAt, + } as NoteModelFieldMapping + : this.noteFieldMappingService.suggest(runtimeCardType, modelName, cacheEntry.fieldNames, cacheEntry.loadedAt); + + this.draftMappings[mappingKey] = nextMapping; + if (areMappingsEqual(this.plugin.settings.noteFieldMappings[mappingKey], nextMapping)) { + return; + } + + await this.plugin.updateSettings({ + noteFieldMappings: { + ...this.plugin.settings.noteFieldMappings, + [mappingKey]: nextMapping, + }, + }); + } + private createCachedModelDetails(modelName: string, fieldNames: string[]): NoteModelDetails { return { fieldNames: [...fieldNames], - isCloze: modelName.toLowerCase().includes("cloze"), + isCloze: false, }; } @@ -1103,13 +1154,18 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { const currentMapping = this.plugin.settings.noteFieldMappings[mappingKey] ?? this.draftMappings[mappingKey]; if (runtimeCardType === "qa-group") { + if (isQaGroupFieldMapping(currentMapping)) { + this.draftMappings[mappingKey] = this.refreshSavedQaGroupMapping(currentMapping, modelDetails.fieldNames, loadedAt); + return; + } + try { this.draftMappings[mappingKey] = this.qaGroupFieldMappingService.suggest( modelName, modelDetails.fieldNames, loadedAt, - isQaGroupFieldMapping(currentMapping) ? currentMapping.acceptedWarnings : undefined, - isQaGroupFieldMapping(currentMapping) ? currentMapping.titleField : undefined, + undefined, + undefined, ); } catch { delete this.draftMappings[mappingKey]; @@ -1277,13 +1333,27 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { const mappingKey = createNoteFieldMappingKey("qa-group", trimmedModelName); const currentMapping = this.plugin.settings.noteFieldMappings[mappingKey] ?? this.draftMappings[mappingKey]; + if (isQaGroupFieldMapping(currentMapping)) { + const nextMapping = this.refreshSavedQaGroupMapping(currentMapping, cacheEntry.fieldNames, cacheEntry.loadedAt); + this.draftMappings[mappingKey] = nextMapping; + if (!areMappingsEqual(this.plugin.settings.noteFieldMappings[mappingKey], nextMapping)) { + await this.plugin.updateSettings({ + noteFieldMappings: { + ...this.plugin.settings.noteFieldMappings, + [mappingKey]: nextMapping, + }, + }); + } + return; + } + try { const nextMapping = this.qaGroupFieldMappingService.suggest( trimmedModelName, cacheEntry.fieldNames, cacheEntry.loadedAt, - isQaGroupFieldMapping(currentMapping) ? currentMapping.acceptedWarnings : undefined, - isQaGroupFieldMapping(currentMapping) ? currentMapping.titleField : undefined, + undefined, + undefined, ); this.draftMappings[mappingKey] = nextMapping; @@ -1344,6 +1414,17 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { } } + private refreshSavedQaGroupMapping(mapping: QaGroupFieldMapping, fieldNames: string[], loadedAt: number): QaGroupFieldMapping { + return { + ...mapping, + loadedFieldNames: [...fieldNames], + slots: mapping.slots.map((slot) => ({ ...slot })), + warnings: [...mapping.warnings], + acceptedWarnings: mapping.acceptedWarnings ? [...mapping.acceptedWarnings] : undefined, + loadedAt, + }; + } + private renderQaGroupWarning(warning: string): string { const parsedWarning = parseQaGroupFieldWarning(warning); if (!parsedWarning) {