From 488bd3d91f4cfad5461c271da5ae71643d9e99ad Mon Sep 17 00:00:00 2001 From: Dusk Date: Thu, 30 Apr 2026 19:18:15 +0800 Subject: [PATCH] feat(deck): add folder-level deck mode overrides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 include 模式下允许选中文件夹改用与全局 folderDeckMode 相反的映射规则 Add include-scope folder overrides that apply the opposite global folderDeckMode mapping 取消勾选文件夹时会清理该路径及其子树的覆盖记录,并把规则接入设置页与 deck fingerprint Clears override records for deselected folders and descendants, and wires the rules into the settings UI and deck fingerprint --- docs/folder-deck-mode-overrides-decisions.md | 67 ++++++++++++++ docs/folder-deck-mode-overrides-gap-report.md | 65 +++++++++++++ main.js | 48 +++++----- src/application/config/PluginSettings.test.ts | 35 +++++++ src/application/config/PluginSettings.ts | 26 +++++- .../services/FileIndexerService.test.ts | 69 ++++++++++++++ .../services/FileIndexerService.ts | 3 +- .../services/QaGroupSyncService.ts | 2 +- .../services/RenderConfigService.ts | 2 +- .../services/DeckResolutionService.test.ts | 41 +++++++-- .../services/DeckResolutionService.ts | 12 ++- .../services/FolderDeckMappingService.test.ts | 20 ++++ .../services/FolderDeckMappingService.ts | 45 +++++++-- .../DataJsonPluginConfigRepository.test.ts | 14 +++ src/presentation/i18n/messages/en.ts | 13 +++ src/presentation/i18n/messages/zh.ts | 13 +++ .../settings/PluginSettingTab.test.ts | 92 +++++++++++++++++++ src/presentation/settings/PluginSettingTab.ts | 84 ++++++++++++++++- styles.css | 40 +++++++- 19 files changed, 642 insertions(+), 49 deletions(-) create mode 100644 docs/folder-deck-mode-overrides-decisions.md create mode 100644 docs/folder-deck-mode-overrides-gap-report.md diff --git a/docs/folder-deck-mode-overrides-decisions.md b/docs/folder-deck-mode-overrides-decisions.md new file mode 100644 index 0000000..d3b9b90 --- /dev/null +++ b/docs/folder-deck-mode-overrides-decisions.md @@ -0,0 +1,67 @@ +# 文件夹级牌组模式覆盖决策 + +## 设置结构 + +- 新增 `PluginSettings.alternateFolderDeckModeFolders: string[]`。 +- 默认值为 `[]`。 +- 缺失字段按旧数据迁移到 `[]`。 +- 校验规则与 `includeFolders` / `excludeFolders` 保持一致:必须是数组,且成员必须是字符串。 +- 不额外引入全局路径规范化或去重 helper;保持与现有配置层行为一致。 + +## UI 放置位置 + +- 在 `PluginSettingTab.renderFolderNode()` 内,仅对 include 模式且当前行已选中的文件夹渲染覆盖控件。 +- 新控件追加在文件夹标签后,不替换现有运行范围 checkbox。 +- 保留现有 dataset:`folderRow`、`folderToggle`、`folderPath`、`folderPathLabel`。 +- 新增 dataset 供测试使用: + - `folderDeckModeOverride` + - `folderDeckModeOverrideHint` + +## 圆形 checkbox 行为 + +- 控件只读写 `alternateFolderDeckModeFolders`。 +- 不改动 include 勾选状态。 +- 点击时阻止冒泡,避免触发展开按钮或运行范围 checkbox 的副作用。 +- 使用原生 checkbox,CSS 改成圆形外观并保留 `aria-label` / `title`。 + +## 提示文案 + +- 全局 `folder-and-file` 时,启用提示显示:`本文件夹单独采用「文件夹」作为牌组名`。 +- 全局 `folder` 时,启用提示显示:`本文件夹单独采用「文件夹及文件名」作为牌组名`。 +- 全局 `off` 时不显示控件和提示,但保留已保存的覆盖列表。 + +## 路径匹配规则 + +- 覆盖匹配使用规范:`filePath === folderPath || filePath.startsWith(folderPath + "/")`。 +- 父文件夹覆盖对子孙路径全部生效。 +- 不支持“子文件夹反向恢复全局模式”的三态语义,本次仍是二元开关。 + +## 覆盖模式解析 + +- 全局 `folder-and-file` 时,命中覆盖文件夹改用 `folder`。 +- 全局 `folder` 时,命中覆盖文件夹改用 `folder-and-file`。 +- 全局 `off` 时,忽略覆盖列表。 + +## include 取消勾选清理 + +- 当 include 模式取消勾选某个文件夹时,清理该路径及所有后代路径在 `alternateFolderDeckModeFolders` 中的记录。 +- 该清理仅影响覆盖列表,不影响其他 include 选择。 +- exclude/all 模式下不显示控件,也不触发这套清理逻辑。 + +## 牌组解析接入点 + +- 在 `FolderDeckMappingService` 中增加“基于覆盖列表求实际 mode”的能力。 +- `DeckResolutionService.resolve()` 接收完整 `PluginSettings`,从而统一处理默认 deck、全局 mode 与覆盖列表。 +- 普通卡片通过 `RenderConfigService` 传入完整 settings。 +- QA Group 继续复用同一个 `DeckResolutionService`,保持优先级一致。 + +## 指纹变更 + +- `createDeckRulesFingerprint()` 纳入 `alternateFolderDeckModeFolders`。 +- 指纹版本升级到下一版。 +- 为减少纯顺序变动引起的无意义重算,指纹内部对覆盖文件夹列表做排序后再哈希;这只影响 fingerprint,不改变实际设置保存顺序。 + +## 与原计划的偏差 + +- 偏差 1:配置层不新增全局路径规范化/去重。原因:现有 `includeFolders` / `excludeFolders` 没有这样做,新字段若单独增强会造成配置行为不一致。 +- 偏差 2:DeckResolution 直接改为接收完整 `settings`。原因:当前普通卡片和 QA Group 都通过该服务决策 deck,把覆盖规则聚合在这里最小且一致,避免在多个调用点重复计算“反向 mode”。 \ No newline at end of file diff --git a/docs/folder-deck-mode-overrides-gap-report.md b/docs/folder-deck-mode-overrides-gap-report.md new file mode 100644 index 0000000..7f00b63 --- /dev/null +++ b/docs/folder-deck-mode-overrides-gap-report.md @@ -0,0 +1,65 @@ +# 文件夹级牌组模式覆盖 gap report + +## 当前运行范围文件树结构 + +- 运行范围卡片由 `src/presentation/settings/PluginSettingTab.ts` 的 `renderScopeCard()` 渲染。 +- scope 模式切换保存在 `PluginSettings.scopeMode`,文件夹选择保存在 `includeFolders` / `excludeFolders`。 +- 文件树数据来自插件接口 `listFolderTree()`,在设置页内通过 `ensureFolderTreeLoaded()` 懒加载。 +- 文件树选择状态由 `src/presentation/settings/FolderScopeTree.ts` 的 `buildFolderTreeSelection()` 与 `toggleFolderTreeSelection()` 计算。 +- 单行 UI 由 `renderFolderNode()` 负责,现有 dataset 包括:`folderRow`、`folderToggle`、`folderPath`、`folderPathLabel`、`folderChildren`。 +- 现有文件夹行是三列 grid:展开按钮、运行范围 checkbox、文件夹标签。 + +## 当前文件夹牌组映射流程 + +- 全局设置字段是 `PluginSettings.folderDeckMode`,取值 `off | folder | folder-and-file`。 +- 普通卡片路径在 `src/application/services/RenderConfigService.ts` 中通过 `DeckResolutionService.resolve(card, defaultDeck, folderDeckMode)` 决定最终 deck。 +- QA Group 路径在 `src/application/services/QaGroupSyncService.ts` 中也直接调用同一个 `DeckResolutionService.resolve(...)`。 +- `src/domain/manual-sync/services/DeckResolutionService.ts` 当前优先顺序是: + 1. `card.deckHint` + 2. `FolderDeckMappingService.mapFilePathToDeck(filePath, folderDeckMode)` + 3. `defaultDeck` +- `src/domain/manual-sync/services/FolderDeckMappingService.ts` 只按 `filePath` 和 `mode` 计算 deck,不知道运行范围或文件夹覆盖。 + +## 当前牌组优先级实现 + +- 文件级显式 deck hint 仍然是最高优先级,这一层已经在 `DeckResolutionService.resolve()` 最前面短路返回。 +- 文件夹映射层完全依赖 `FolderDeckMappingService`。 +- 只有当前两层都没有产出 deck 时才回退到默认牌组并附加 `deck_fallback_default` warning。 + +## 覆盖设置应存放的位置 + +- 新字段应加入 `src/application/config/PluginSettings.ts` 的 `PluginSettings` 接口与 `DEFAULT_SETTINGS`。 +- 加载/保存路径通过 `mergePluginSettings()` 与 `normalizePluginSettings()` 进入 `DataJsonPluginConfigRepository`。 +- 现有 include/exclude 文件夹列表只做“数组 + 字符串”校验,没有统一去重或路径规范化 helper;新字段应沿用同样约定,避免引入与仓库现状不一致的新归一化语义。 + +## UI 应插入的位置 + +- 只应插入到 `renderFolderNode()` 的 include 模式行内。 +- 行内现有顺序是 toggle、scope checkbox、label;新增控件应追加在 label 后侧,并保持现有 dataset 不变。 +- 仅当 `scopeMode === "include"`、当前行已选中、且全局 `folderDeckMode !== "off"` 时显示。 +- 取消 include 勾选的清理逻辑不应放在 UI 层分散处理,而应合并进 `updateFolderSelection()`,这样任何同一路径的取消动作都能统一清理子树覆盖记录。 + +## 指纹更新位置 + +- deck 规则指纹在 `src/application/services/FileIndexerService.ts` 的 `createDeckRulesFingerprint()` 中生成。 +- `indexVault()` 通过比较 `existingFileState.deckRulesFingerprint !== deckRulesFingerprint` 强制重读;因此覆盖规则必须进入该指纹。 +- 当前版本号为 `deck-rules-v4`,实现覆盖后需要升级版本。 + +## 预计修改的测试文件 + +- `src/application/config/PluginSettings.test.ts` +- `src/infrastructure/persistence/DataJsonPluginConfigRepository.test.ts` +- `src/presentation/settings/PluginSettingTab.test.ts` +- `src/domain/manual-sync/services/FolderDeckMappingService.test.ts` +- `src/domain/manual-sync/services/DeckResolutionService.test.ts` +- `src/application/services/FileIndexerService.test.ts` +- 可能还要更新 `src/test-support/manualSyncFakes.ts` 的默认设置工厂,以便新字段默认值在各类测试夹具中可用。 + +## 风险点 + +- `toggleFolderTreeSelection()` 会压缩选择结果;覆盖清理必须基于“被取消的目标路径及其后代”,不能误删其他分支。 +- 父文件夹覆盖应对子孙路径生效,但不能把 `notes` 误匹配到 `notes2`;应复用仓库里现有的 `path === folder || path.startsWith(folder + "/")` 规则。 +- `DeckResolutionService.resolve()` 当前签名被多处调用,若扩展参数需要同步更新 `RenderConfigService`、`QaGroupSyncService` 和直接单测。 +- 作用范围树的测试大量依赖现有 dataset;新增控件不能破坏 `folderRow`、`folderToggle`、`folderPath`、`folderPathLabel` 的查找方式。 +- 设置页行布局当前是固定 grid,新增圆形 checkbox 后需要补 CSS,避免标签挤压或破坏缩进对齐。 +- 当全局 `folderDeckMode` 为 `off` 时必须忽略覆盖列表,但不能清空已保存数据。 \ No newline at end of file diff --git a/main.js b/main.js index 3dcfef7..9976f6f 100644 --- a/main.js +++ b/main.js @@ -1,38 +1,38 @@ /* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD */ -"use strict";var Tn=Object.defineProperty;var ho=Object.getOwnPropertyDescriptor;var ko=Object.getOwnPropertyNames;var bo=Object.prototype.hasOwnProperty;var Qe=(e,t)=>{for(var n in t)Tn(e,n,{get:t[n],enumerable:!0})},yo=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ko(t))!bo.call(e,i)&&i!==n&&Tn(e,i,{get:()=>t[i],enumerable:!(r=ho(t,i))||r.enumerable});return e};var xo=e=>yo(Tn({},"__esModule",{value:!0}),e);var bl={};Qe(bl,{default:()=>kl});module.exports=xo(bl);var go=require("obsidian");function B(e,t){return`${e}:${t}`}function Dn(e){return e?.cardType==="basic"}function ei(e){return e?.cardType==="cloze"}function H(e){return e?.cardType==="qa-group"}var ti=require("obsidian");function se(e=(0,ti.getLanguage)()){let t=e.toLowerCase();return t==="zh"||t.startsWith("zh-")?"zh":"en"}function ce(e,t){return t.join(e==="zh"?"\u3001":", ")}var An={commands:{syncCurrentFileToAnki:"Sync current file to Anki",syncVaultToAnki:"Sync vault to Anki",clearCurrentFileSyncedCards:"Clear synced cards in current file",cleanupEmptyDecks:"Clean up empty decks"},settings:{pluginTitle:"Anki heading sync",ankiConnectUrl:{name:"AnkiConnect URL",desc:"Default: http://127.0.0.1:8765",placeholder:"Example: http://127.0.0.1:8765"},qaHeadingLevel:{name:"Heading level for question-and-answer cards",desc:"Default: H4"},clozeHeadingLevel:{name:"Cloze heading level",desc:"Default: 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:"List notes for question-and-answer groups",marker:{name:"Marker for question-and-answer groups",desc:"When a question-and-answer heading ends with this hashtag marker, the whole heading block syncs as one list note for that group.",placeholder:"Hashtag marker"},managedNoteType:"Current note type: {{modelName}}. This route syncs QA Group list notes using the field mapping shown below.",managedModelContract:"Current note type summary: {{fieldCount}} fields and {{templateCount}} templates are available for this route."},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 uses the default backlink label.",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 "#example #tag/case". Inline tags like "this is a #tag example" and lines with ordinary text like "tag label: #project" 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:"Basic and question-and-answer",description:"Choose the note type for question-and-answer cards, read its fields from Anki, then confirm the title and body mapping."},cloze:{title:"Cloze",description:"Choose the cloze note type, read its fields from Anki, then confirm the main field mapping."}},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. By default, use the built-in target deck marker."},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"},unconfiguredWarning:"Run scope is not configured yet. Include mode requires at least one selected folder before sync can run.",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:"Written automatically",autoComposedAnswer:"Auto composed",qaGroupManagedNoteType:"{{modelName}} (for QA Group list notes)",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:",qaGroupFirstQuestionField:"First question field:",qaGroupFirstAnswerField:"First answer field:",qaGroupConfiguredSlots:"Configured pairs:",qaGroupSlotFields:"Question/answer fields:",qaGroupWarnings:"Warnings:"},qaGroup:{noModel:"Select an Anki note type first",unavailable:"Read fields from Anki first",detectedSlots:"Configured {{count}} pair(s)",configuredSlots:"Configured {{count}} pair(s)",configuredSlotExample:"First {{firstQuestionField}} / {{firstAnswerField}}, last {{lastQuestionField}} / {{lastAnswerField}}",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."}},sharedClozeMappingHint:"Reuse the current Anki note type and main field from the sequential cloze row. No separate setup is needed.",rows:{basic:"Question and answer (regular paragraph)",qaGroup:"Question and answer (nested list)",cloze:"Cloze (sequential deletions)",clozeAll:"Cloze (all deletions)"}},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.",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.",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}}, rebuilt {{rebuilt}}, 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}}, rebuilt {{rebuilt}}, updated {{updated}}, migrated note types {{migratedNoteTypes}}, migrated decks {{migratedDecks}}, orphaned {{orphaned}}, media {{uploadedMedia}}, 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:{runScopeNotConfigured:"Run scope is not configured. In include mode, select at least one folder before syncing.",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:"The question-and-answer 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:"A question-and-answer note type is required.",qaGroupMarkerRequired:"A question-and-answer group marker is required.",qaGroupMarkerInvalid:"The question-and-answer group marker must be a hashtag-style token.",clozeNoteTypeRequired:"Cloze 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:"Question-and-answer group field mapping slots must be an array.",noteFieldMappingsQaGroupSlotObject:"Each question-and-answer group field mapping slot must be an object.",noteFieldMappingsQaGroupSlotIndex:"Each question-and-answer group field mapping slot.index must be an integer greater than 0.",noteFieldMappingsQaGroupSlotQuestionField:"Each question-and-answer group field mapping slot.questionField must be a string.",noteFieldMappingsQaGroupSlotAnswerField:"Each question-and-answer group field mapping slot.answerField must be a string.",noteFieldMappingsQaGroupWarningsArray:"Question-and-answer group field mapping warnings must be an array.",noteFieldMappingsQaGroupWarningsStrings:"Question-and-answer group field mapping warnings can only contain strings.",noteFieldMappingsQaGroupAcceptedWarningsArray:"Question-and-answer group field mapping acceptedWarnings must be an array.",noteFieldMappingsQaGroupAcceptedWarningsStrings:"Question-and-answer group field mapping acceptedWarnings can only contain strings.",noteFieldMappingsQaGroupDerivationObject:"Question-and-answer group field mapping derivation must be an object.",noteFieldMappingsQaGroupDerivationMode:"QA Group field mapping derivation.mode must be first-pair.",noteFieldMappingsQaGroupDerivationFirstQuestionField:"Question-and-answer group field mapping derivation.firstQuestionField must be a string.",noteFieldMappingsQaGroupDerivationFirstAnswerField:"Question-and-answer group field mapping derivation.firstAnswerField must be a string."},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.",qaGroup:"No Anki note type is selected for question-and-answer 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.',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.',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.'},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.',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.',qaGroupSelectedFieldMissing:'The selected field "{{field}}" for QA Group note type "{{modelName}}" is no longer present in Anki. Read fields again and save the mapping again.',qaGroupDuplicateFields:'QA Group note type "{{modelName}}" cannot reuse the same title, question, or answer field.',qaGroupFirstPairNumberMismatch:'The first question field "{{questionField}}" and first answer field "{{answerField}}" for QA Group note type "{{modelName}}" do not use the same pair number.',qaGroupFirstPairMustStartAtOne:'QA Group note type "{{modelName}}" must start its first selected pair at 1, but the current pair starts at {{firstIndex}}.',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 ni={commands:{syncCurrentFileToAnki:"\u540C\u6B65\u5F53\u524D\u6587\u4EF6\u5230 Anki",syncVaultToAnki:"\u540C\u6B65\u5168\u5E93\u5230 Anki",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:"\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\u5F62\u5F0F\uFF09",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\u540C\u6B65\u4E3A\u4E00\u6761\u591A\u7EA7\u5217\u8868\u95EE\u7B54\u7B14\u8BB0\u3002",placeholder:"#anki-list"},managedNoteType:"\u5F53\u524D\u7B14\u8BB0\u7C7B\u578B\uFF1A{{modelName}}\u3002\u8FD9\u6761\u8DEF\u7EBF\u4F1A\u6309\u4E0B\u65B9\u5B57\u6BB5\u6620\u5C04\u540C\u6B65\u591A\u7EA7\u5217\u8868\u95EE\u7B54\u5185\u5BB9\u3002",managedModelContract:"\u5F53\u524D\u7B14\u8BB0\u7C7B\u578B\u6458\u8981\uFF1A\u8FD9\u6761\u8DEF\u7EBF\u53EF\u7528 {{fieldCount}} \u4E2A\u5B57\u6BB5\u548C {{templateCount}} \u4E2A\u6A21\u677F\u3002"},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"}},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"},unconfiguredWarning:"\u8FD0\u884C\u8303\u56F4\u5C1A\u672A\u914D\u7F6E\u3002\u5F53\u524D\u662F include \u6A21\u5F0F\uFF0C\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u6587\u4EF6\u5939\u540E\u624D\u80FD\u540C\u6B65\u3002",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\u5199\u5165",autoComposedAnswer:"\u81EA\u52A8\u62FC\u63A5",qaGroupManagedNoteType:"{{modelName}}\uFF08\u7528\u4E8E\u591A\u7EA7\u5217\u8868\u95EE\u7B54\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",qaGroupFirstQuestionField:"\u9996\u4E2A\u95EE\u9898\u5B57\u6BB5\uFF1A",qaGroupFirstAnswerField:"\u9996\u4E2A\u7B54\u6848\u5B57\u6BB5\uFF1A",qaGroupConfiguredSlots:"\u5DF2\u914D\u7F6E\u7EC4\u6570\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\u914D\u7F6E{{count}}\u7EC4",configuredSlots:"\u5DF2\u914D\u7F6E{{count}}\u7EC4",configuredSlotExample:"\u9996\u7EC4 {{firstQuestionField}} / {{firstAnswerField}}\uFF0C\u672B\u7EC4 {{lastQuestionField}} / {{lastAnswerField}}",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"}},sharedClozeMappingHint:"\u590D\u7528\u201C\u586B\u7A7A\u9898\uFF08\u9010\u4E2A\u6316\u7A7A\uFF09\u201D\u5F53\u524D\u9009\u62E9\u7684 Anki \u7B14\u8BB0\u6A21\u677F\u548C\u4E3B\u5B57\u6BB5\uFF0C\u65E0\u9700\u5355\u72EC\u8BBE\u7F6E\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\uFF08\u9010\u4E2A\u6316\u7A7A\uFF09",clozeAll:"\u586B\u7A7A\u9898\uFF08\u5168\u90E8\u6316\u7A7A\uFF09"}},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",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",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\u91CD\u5EFA {{rebuilt}}\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\u91CD\u5EFA {{rebuilt}}\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",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:{runScopeNotConfigured:"\u8FD0\u884C\u8303\u56F4\u5C1A\u672A\u914D\u7F6E\u3002\u5F53\u524D\u662F include \u6A21\u5F0F\uFF0C\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u6587\u4EF6\u5939\u540E\u518D\u540C\u6B65\u3002",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",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",noteFieldMappingsQaGroupDerivationObject:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 derivation \u5FC5\u987B\u662F\u5BF9\u8C61\u3002",noteFieldMappingsQaGroupDerivationMode:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 derivation.mode \u53EA\u80FD\u662F first-pair\u3002",noteFieldMappingsQaGroupDerivationFirstQuestionField:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 derivation.firstQuestionField \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",noteFieldMappingsQaGroupDerivationFirstAnswerField:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 derivation.firstAnswerField \u5FC5\u987B\u662F\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",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',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',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'},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',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',qaGroupSelectedFieldMissing:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u4E2D\u5DF2\u9009\u62E9\u5B57\u6BB5 "{{field}}"\uFF0C\u4F46\u5B83\u5F53\u524D\u4E0D\u5728 Anki \u5B57\u6BB5\u5217\u8868\u91CC\u3002\u8BF7\u91CD\u65B0\u8BFB\u53D6\u5B57\u6BB5\u540E\u518D\u4FDD\u5B58\u3002',qaGroupDuplicateFields:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u9898\u76EE\u5B57\u6BB5\u3001\u95EE\u9898\u5B57\u6BB5\u548C\u7B54\u6848\u5B57\u6BB5\u4E0D\u80FD\u91CD\u590D\u3002',qaGroupFirstPairNumberMismatch:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u9996\u4E2A\u95EE\u9898\u5B57\u6BB5 "{{questionField}}" \u4E0E\u9996\u4E2A\u7B54\u6848\u5B57\u6BB5 "{{answerField}}" \u7F16\u53F7\u4E0D\u4E00\u81F4\u3002\u8BF7\u9009\u62E9\u540C\u4E00\u7EC4\u5B57\u6BB5\u3002',qaGroupFirstPairMustStartAtOne:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u9996\u7EC4\u5B57\u6BB5\u5FC5\u987B\u4ECE\u7B2C 1 \u7EC4\u5F00\u59CB\uFF0C\u5F53\u524D\u662F\u7B2C {{firstIndex}} \u7EC4\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 ri(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 Co(e,t,n){return t?e.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(r,i)=>{let a=t[i];return a===void 0?"":Array.isArray(a)?ce(n,a.filter(o=>o!==void 0).map(o=>String(o))):String(a)}):e}function g(e,t){let n=se(),i=ri(n==="zh"?ni:An,e)??ri(An,e)??e;return Co(i,t,n)}var S=class extends Error{constructor(t,n,r){super(t),this.name="PluginUserError",this.userMessage={key:t,params:n},this.details=r}};function En(e){return e instanceof S}function Ie(e){return"rawMessage"in e?e.rawMessage:g(e.key,e.params)}function ii(e){return"rawMessage"in e?e.rawMessage:g(e.key,e.params)}function lt(e){let t=Ie(e.userMessage);if(!e.details?.failures?.length)return t;let n=e.details.failures.map(r=>`${r.filePath}: ${ii(r)}`).join(` +"use strict";var Tn=Object.defineProperty;var bo=Object.getOwnPropertyDescriptor;var yo=Object.getOwnPropertyNames;var xo=Object.prototype.hasOwnProperty;var Qe=(e,t)=>{for(var n in t)Tn(e,n,{get:t[n],enumerable:!0})},Co=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of yo(t))!xo.call(e,i)&&i!==n&&Tn(e,i,{get:()=>t[i],enumerable:!(r=bo(t,i))||r.enumerable});return e};var So=e=>Co(Tn({},"__esModule",{value:!0}),e);var Ml={};Qe(Ml,{default:()=>Fl});module.exports=So(Ml);var ho=require("obsidian");function B(e,t){return`${e}:${t}`}function Dn(e){return e?.cardType==="basic"}function ti(e){return e?.cardType==="cloze"}function O(e){return e?.cardType==="qa-group"}var ni=require("obsidian");function se(e=(0,ni.getLanguage)()){let t=e.toLowerCase();return t==="zh"||t.startsWith("zh-")?"zh":"en"}function de(e,t){return t.join(e==="zh"?"\u3001":", ")}var An={commands:{syncCurrentFileToAnki:"Sync current file to Anki",syncVaultToAnki:"Sync vault to Anki",clearCurrentFileSyncedCards:"Clear synced cards in current file",cleanupEmptyDecks:"Clean up empty decks"},settings:{pluginTitle:"Anki heading sync",ankiConnectUrl:{name:"AnkiConnect URL",desc:"Default: http://127.0.0.1:8765",placeholder:"Example: http://127.0.0.1:8765"},qaHeadingLevel:{name:"Heading level for question-and-answer cards",desc:"Default: H4"},clozeHeadingLevel:{name:"Cloze heading level",desc:"Default: 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:"List notes for question-and-answer groups",marker:{name:"Marker for question-and-answer groups",desc:"When a question-and-answer heading ends with this hashtag marker, the whole heading block syncs as one list note for that group.",placeholder:"Hashtag marker"},managedNoteType:"Current note type: {{modelName}}. This route syncs QA Group list notes using the field mapping shown below.",managedModelContract:"Current note type summary: {{fieldCount}} fields and {{templateCount}} templates are available for this route."},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 uses the default backlink label.",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 "#example #tag/case". Inline tags like "this is a #tag example" and lines with ordinary text like "tag label: #project" 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:"Basic and question-and-answer",description:"Choose the note type for question-and-answer cards, read its fields from Anki, then confirm the title and body mapping."},cloze:{title:"Cloze",description:"Choose the cloze note type, read its fields from Anki, then confirm the main field mapping."}},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. By default, use the built-in target deck marker."},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"},unconfiguredWarning:"Run scope is not configured yet. Include mode requires at least one selected folder before sync can run.",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}}",folderDeckModeOverride:{ariaLabel:"Toggle the alternate folder deck mapping mode for {{name}}",hint:{folder:"This folder uses the folder-only deck name by itself",folderAndFile:"This folder uses the folder-and-file deck name by itself"},title:{folder:"Global mode is folder-and-file; enable this to use folder-only deck names for this folder",folderAndFile:"Global mode is folder-only; enable this to use folder-and-file deck names for this folder"}}},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:"Written automatically",autoComposedAnswer:"Auto composed",qaGroupManagedNoteType:"{{modelName}} (for QA Group list notes)",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:",qaGroupFirstQuestionField:"First question field:",qaGroupFirstAnswerField:"First answer field:",qaGroupConfiguredSlots:"Configured pairs:",qaGroupSlotFields:"Question/answer fields:",qaGroupWarnings:"Warnings:"},qaGroup:{noModel:"Select an Anki note type first",unavailable:"Read fields from Anki first",detectedSlots:"Configured {{count}} pair(s)",configuredSlots:"Configured {{count}} pair(s)",configuredSlotExample:"First {{firstQuestionField}} / {{firstAnswerField}}, last {{lastQuestionField}} / {{lastAnswerField}}",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."}},sharedClozeMappingHint:"Reuse the current Anki note type and main field from the sequential cloze row. No separate setup is needed.",rows:{basic:"Question and answer (regular paragraph)",qaGroup:"Question and answer (nested list)",cloze:"Cloze (sequential deletions)",clozeAll:"Cloze (all deletions)"}},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.",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.",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}}, rebuilt {{rebuilt}}, 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}}, rebuilt {{rebuilt}}, updated {{updated}}, migrated note types {{migratedNoteTypes}}, migrated decks {{migratedDecks}}, orphaned {{orphaned}}, media {{uploadedMedia}}, 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:{runScopeNotConfigured:"Run scope is not configured. In include mode, select at least one folder before syncing.",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:"The question-and-answer 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:"A question-and-answer note type is required.",qaGroupMarkerRequired:"A question-and-answer group marker is required.",qaGroupMarkerInvalid:"The question-and-answer group marker must be a hashtag-style token.",clozeNoteTypeRequired:"Cloze 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.",alternateFolderDeckModeFoldersArray:"Alternate folder deck mode folders must be an array.",alternateFolderDeckModeFoldersStrings:"Alternate folder deck mode 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:"Question-and-answer group field mapping slots must be an array.",noteFieldMappingsQaGroupSlotObject:"Each question-and-answer group field mapping slot must be an object.",noteFieldMappingsQaGroupSlotIndex:"Each question-and-answer group field mapping slot.index must be an integer greater than 0.",noteFieldMappingsQaGroupSlotQuestionField:"Each question-and-answer group field mapping slot.questionField must be a string.",noteFieldMappingsQaGroupSlotAnswerField:"Each question-and-answer group field mapping slot.answerField must be a string.",noteFieldMappingsQaGroupWarningsArray:"Question-and-answer group field mapping warnings must be an array.",noteFieldMappingsQaGroupWarningsStrings:"Question-and-answer group field mapping warnings can only contain strings.",noteFieldMappingsQaGroupAcceptedWarningsArray:"Question-and-answer group field mapping acceptedWarnings must be an array.",noteFieldMappingsQaGroupAcceptedWarningsStrings:"Question-and-answer group field mapping acceptedWarnings can only contain strings.",noteFieldMappingsQaGroupDerivationObject:"Question-and-answer group field mapping derivation must be an object.",noteFieldMappingsQaGroupDerivationMode:"QA Group field mapping derivation.mode must be first-pair.",noteFieldMappingsQaGroupDerivationFirstQuestionField:"Question-and-answer group field mapping derivation.firstQuestionField must be a string.",noteFieldMappingsQaGroupDerivationFirstAnswerField:"Question-and-answer group field mapping derivation.firstAnswerField must be a string."},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.",qaGroup:"No Anki note type is selected for question-and-answer 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.',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.',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.'},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.',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.',qaGroupSelectedFieldMissing:'The selected field "{{field}}" for QA Group note type "{{modelName}}" is no longer present in Anki. Read fields again and save the mapping again.',qaGroupDuplicateFields:'QA Group note type "{{modelName}}" cannot reuse the same title, question, or answer field.',qaGroupFirstPairNumberMismatch:'The first question field "{{questionField}}" and first answer field "{{answerField}}" for QA Group note type "{{modelName}}" do not use the same pair number.',qaGroupFirstPairMustStartAtOne:'QA Group note type "{{modelName}}" must start its first selected pair at 1, but the current pair starts at {{firstIndex}}.',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 ri={commands:{syncCurrentFileToAnki:"\u540C\u6B65\u5F53\u524D\u6587\u4EF6\u5230 Anki",syncVaultToAnki:"\u540C\u6B65\u5168\u5E93\u5230 Anki",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:"\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\u5F62\u5F0F\uFF09",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\u540C\u6B65\u4E3A\u4E00\u6761\u591A\u7EA7\u5217\u8868\u95EE\u7B54\u7B14\u8BB0\u3002",placeholder:"#anki-list"},managedNoteType:"\u5F53\u524D\u7B14\u8BB0\u7C7B\u578B\uFF1A{{modelName}}\u3002\u8FD9\u6761\u8DEF\u7EBF\u4F1A\u6309\u4E0B\u65B9\u5B57\u6BB5\u6620\u5C04\u540C\u6B65\u591A\u7EA7\u5217\u8868\u95EE\u7B54\u5185\u5BB9\u3002",managedModelContract:"\u5F53\u524D\u7B14\u8BB0\u7C7B\u578B\u6458\u8981\uFF1A\u8FD9\u6761\u8DEF\u7EBF\u53EF\u7528 {{fieldCount}} \u4E2A\u5B57\u6BB5\u548C {{templateCount}} \u4E2A\u6A21\u677F\u3002"},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"}},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"},unconfiguredWarning:"\u8FD0\u884C\u8303\u56F4\u5C1A\u672A\u914D\u7F6E\u3002\u5F53\u524D\u662F include \u6A21\u5F0F\uFF0C\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u6587\u4EF6\u5939\u540E\u624D\u80FD\u540C\u6B65\u3002",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}}",folderDeckModeOverride:{ariaLabel:"\u5207\u6362 {{name}} \u7684\u6587\u4EF6\u5939\u724C\u7EC4\u6620\u5C04\u6A21\u5F0F",hint:{folder:"\u672C\u6587\u4EF6\u5939\u5355\u72EC\u91C7\u7528\u300C\u6587\u4EF6\u5939\u300D\u4F5C\u4E3A\u724C\u7EC4\u540D",folderAndFile:"\u672C\u6587\u4EF6\u5939\u5355\u72EC\u91C7\u7528\u300C\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u300D\u4F5C\u4E3A\u724C\u7EC4\u540D"},title:{folder:"\u5F53\u524D\u5168\u5C40\u4E3A\u300C\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u300D\uFF0C\u52FE\u9009\u540E\u6B64\u6587\u4EF6\u5939\u6539\u7528\u300C\u6587\u4EF6\u5939\u300D\u4F5C\u4E3A\u724C\u7EC4\u540D",folderAndFile:"\u5F53\u524D\u5168\u5C40\u4E3A\u300C\u6587\u4EF6\u5939\u300D\uFF0C\u52FE\u9009\u540E\u6B64\u6587\u4EF6\u5939\u6539\u7528\u300C\u6587\u4EF6\u5939\u53CA\u6587\u4EF6\u540D\u300D\u4F5C\u4E3A\u724C\u7EC4\u540D"}}},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\u5199\u5165",autoComposedAnswer:"\u81EA\u52A8\u62FC\u63A5",qaGroupManagedNoteType:"{{modelName}}\uFF08\u7528\u4E8E\u591A\u7EA7\u5217\u8868\u95EE\u7B54\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",qaGroupFirstQuestionField:"\u9996\u4E2A\u95EE\u9898\u5B57\u6BB5\uFF1A",qaGroupFirstAnswerField:"\u9996\u4E2A\u7B54\u6848\u5B57\u6BB5\uFF1A",qaGroupConfiguredSlots:"\u5DF2\u914D\u7F6E\u7EC4\u6570\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\u914D\u7F6E{{count}}\u7EC4",configuredSlots:"\u5DF2\u914D\u7F6E{{count}}\u7EC4",configuredSlotExample:"\u9996\u7EC4 {{firstQuestionField}} / {{firstAnswerField}}\uFF0C\u672B\u7EC4 {{lastQuestionField}} / {{lastAnswerField}}",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"}},sharedClozeMappingHint:"\u590D\u7528\u201C\u586B\u7A7A\u9898\uFF08\u9010\u4E2A\u6316\u7A7A\uFF09\u201D\u5F53\u524D\u9009\u62E9\u7684 Anki \u7B14\u8BB0\u6A21\u677F\u548C\u4E3B\u5B57\u6BB5\uFF0C\u65E0\u9700\u5355\u72EC\u8BBE\u7F6E\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\uFF08\u9010\u4E2A\u6316\u7A7A\uFF09",clozeAll:"\u586B\u7A7A\u9898\uFF08\u5168\u90E8\u6316\u7A7A\uFF09"}},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",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",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\u91CD\u5EFA {{rebuilt}}\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\u91CD\u5EFA {{rebuilt}}\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",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:{runScopeNotConfigured:"\u8FD0\u884C\u8303\u56F4\u5C1A\u672A\u914D\u7F6E\u3002\u5F53\u524D\u662F include \u6A21\u5F0F\uFF0C\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u6587\u4EF6\u5939\u540E\u518D\u540C\u6B65\u3002",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",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",alternateFolderDeckModeFoldersArray:"\u6587\u4EF6\u5939\u724C\u7EC4\u6A21\u5F0F\u8986\u76D6\u5217\u8868\u5FC5\u987B\u662F\u6570\u7EC4\u3002",alternateFolderDeckModeFoldersStrings:"\u6587\u4EF6\u5939\u724C\u7EC4\u6A21\u5F0F\u8986\u76D6\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",noteFieldMappingsQaGroupDerivationObject:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 derivation \u5FC5\u987B\u662F\u5BF9\u8C61\u3002",noteFieldMappingsQaGroupDerivationMode:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 derivation.mode \u53EA\u80FD\u662F first-pair\u3002",noteFieldMappingsQaGroupDerivationFirstQuestionField:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 derivation.firstQuestionField \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002",noteFieldMappingsQaGroupDerivationFirstAnswerField:"QA Group \u5B57\u6BB5\u6620\u5C04\u4E2D\u7684 derivation.firstAnswerField \u5FC5\u987B\u662F\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",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',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',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'},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',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',qaGroupSelectedFieldMissing:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u4E2D\u5DF2\u9009\u62E9\u5B57\u6BB5 "{{field}}"\uFF0C\u4F46\u5B83\u5F53\u524D\u4E0D\u5728 Anki \u5B57\u6BB5\u5217\u8868\u91CC\u3002\u8BF7\u91CD\u65B0\u8BFB\u53D6\u5B57\u6BB5\u540E\u518D\u4FDD\u5B58\u3002',qaGroupDuplicateFields:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u9898\u76EE\u5B57\u6BB5\u3001\u95EE\u9898\u5B57\u6BB5\u548C\u7B54\u6848\u5B57\u6BB5\u4E0D\u80FD\u91CD\u590D\u3002',qaGroupFirstPairNumberMismatch:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u9996\u4E2A\u95EE\u9898\u5B57\u6BB5 "{{questionField}}" \u4E0E\u9996\u4E2A\u7B54\u6848\u5B57\u6BB5 "{{answerField}}" \u7F16\u53F7\u4E0D\u4E00\u81F4\u3002\u8BF7\u9009\u62E9\u540C\u4E00\u7EC4\u5B57\u6BB5\u3002',qaGroupFirstPairMustStartAtOne:'\u95EE\u7B54\u9898\uFF08\u591A\u7EA7\u5217\u8868\uFF09\u7B14\u8BB0\u6A21\u677F "{{modelName}}" \u7684\u9996\u7EC4\u5B57\u6BB5\u5FC5\u987B\u4ECE\u7B2C 1 \u7EC4\u5F00\u59CB\uFF0C\u5F53\u524D\u662F\u7B2C {{firstIndex}} \u7EC4\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 ii(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 Fo(e,t,n){return t?e.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(r,i)=>{let a=t[i];return a===void 0?"":Array.isArray(a)?de(n,a.filter(o=>o!==void 0).map(o=>String(o))):String(a)}):e}function g(e,t){let n=se(),i=ii(n==="zh"?ri:An,e)??ii(An,e)??e;return Fo(i,t,n)}var S=class extends Error{constructor(t,n,r){super(t),this.name="PluginUserError",this.userMessage={key:t,params:n},this.details=r}};function En(e){return e instanceof S}function Le(e){return"rawMessage"in e?e.rawMessage:g(e.key,e.params)}function ai(e){return"rawMessage"in e?e.rawMessage:g(e.key,e.params)}function lt(e){let t=Le(e.userMessage);if(!e.details?.failures?.length)return t;let n=e.details.failures.map(r=>`${r.filePath}: ${ai(r)}`).join(` `);return`${t} -${n}`}function ye(e,t,n){return En(e)?e.userMessage:e instanceof Error?{rawMessage:e.message}:{key:t,params:n}}function xe(e,t){return En(e)?lt(e):Ie(ye(e,t))}function pt(e,t){return En(t)?{filePath:e,...t.userMessage}:t instanceof Error?{filePath:e,rawMessage:t.message}:{filePath:e,rawMessage:String(t)}}function ai(e){let t=se();return ce(t,e.map(n=>`${n.filePath} (${ii(n)})`))}var So=["\u9898\u76EE","\u6807\u9898","\u6B63\u9762","Stem","Title"],Fo=[/^问题0*(\d+)$/i,/^Q0*(\d+)$/i,/^S0*(\d+)_Q$/i],Mo=[/^答案0*(\d+)$/i,/^A0*(\d+)$/i,/^S0*(\d+)_A$/i],de=class{suggest(t,n,r=Date.now(),i,a){let o=a&&n.includes(a)?a:vo(n,So),u=wo(n,t);return this.createMappingFromSelection(t,n,{titleField:o,firstQuestionField:u.questionField,firstAnswerField:u.answerField},r)}createMappingFromSelection(t,n,r,i=Date.now()){let a=[...n],o=_n(r.titleField),u=_n(r.firstQuestionField),s=_n(r.firstAnswerField),c=Do(u,s),d=new Set(a);for(let l of[o,u,s])if(l&&!d.has(l))throw new S("errors.noteFieldMapping.qaGroupSelectedFieldMissing",{modelName:t,field:l});return{cardType:"qa-group",modelName:t,loadedFieldNames:a,titleField:o,slots:To(t,a,o,u,s),warnings:[],acceptedWarnings:void 0,derivation:c,loadedAt:i}}validateMapping(t,n){if(!t.titleField)throw new S("errors.noteFieldMapping.qaGroupMissingTitle",{modelName:t.modelName});if(t.slots.length===0)throw new S("errors.noteFieldMapping.qaGroupNoCompleteSlots",{modelName:t.modelName});let r=new Set(n),i=new Set,a=new Set([t.titleField]);r.has(t.titleField)||i.add(t.titleField);for(let o of t.slots){if(r.has(o.questionField)||i.add(o.questionField),r.has(o.answerField)||i.add(o.answerField),a.has(o.questionField)||a.has(o.answerField)||o.questionField===o.answerField)throw new S("errors.noteFieldMapping.qaGroupDuplicateFields",{modelName:t.modelName});a.add(o.questionField),a.add(o.answerField)}if(i.size>0)throw new S("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:[...i].map(o=>`"${o}"`)})}validateWarningsAccepted(t){if(!(!t.warnings.length||In(t.warnings,t.acceptedWarnings)))throw new S("errors.noteFieldMapping.qaGroupWarningsUnaccepted",{modelName:t.modelName})}};function In(e,t){return e.length===0?!0:!t||e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function ci(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=oi(u,Fo);if(s&&!n.has(s)){n.set(s,u);continue}let c=oi(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 S("errors.noteFieldMapping.qaGroupNonContinuousSlots",{modelName:t,firstIndex:i[0]});let a=n.get(1),o=r.get(1);if(!a||!o)throw new S("errors.noteFieldMapping.qaGroupNoCompleteSlots",{modelName:t});return{questionField:a,answerField:o}}function oi(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>=1)return i}}function vo(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function To(e,t,n,r,i){if(!r||!i)return[];let a=new Set;if(n&&a.add(n),a.has(r)||a.has(i)||r===i)throw new S("errors.noteFieldMapping.qaGroupDuplicateFields",{modelName:e});let o=ui(r),u=ui(i);if(!o||!u)return[{index:1,questionField:r,answerField:i}];if(o.index!==u.index)throw new S("errors.noteFieldMapping.qaGroupFirstPairNumberMismatch",{modelName:e,questionField:r,answerField:i});if(o.index!==1)throw new S("errors.noteFieldMapping.qaGroupFirstPairMustStartAtOne",{modelName:e,firstIndex:o.index});let s=new Set(t),c=[];for(let d=1;;d+=1){let l=d===1?r:si(o,d),f=d===1?i:si(u,d);if(!s.has(l)||!s.has(f))break;if(a.has(l)||a.has(f)||l===f)throw new S("errors.noteFieldMapping.qaGroupDuplicateFields",{modelName:e});a.add(l),a.add(f),c.push({index:d,questionField:l,answerField:f})}return c}function Do(e,t){if(!(!e&&!t))return{mode:"first-pair",firstQuestionField:e,firstAnswerField:t}}function _n(e){let t=e?.trim();return t||void 0}function ui(e){let t=[...e.matchAll(/\d+/g)],n=t[t.length-1];if(!(!n||n.index===void 0))return{prefix:e.slice(0,n.index),digits:n[0],suffix:e.slice(n.index+n[0].length),index:Number.parseInt(n[0],10)}}function si(e,t){return`${e.prefix}${String(t).padStart(e.digits.length,"0")}${e.suffix}`}var Rn=["basic","qa-group","cloze","cloze-all"],Ke="Open in Obsidian",Ln=4,di=5,Ze=4,gi="",Nn="",Ao="",Pn="#anki-cloze",Eo="#anki-cloze-all",mi="#anki-list",_o=new de,O={qaHeadingLevel:Ln,clozeHeadingLevel:Ze,cardAnswerCutoffMode:"heading-block",qaGroupMarker:mi,qaNoteType:gi,clozeNoteType:Nn,cardTypeConfigs:ki(),noteFieldMappings:{},ankiNoteTypeCache:[],ankiModelFieldCache:{},defaultDeck:"Obsidian",fileDeckEnabled:!1,fileDeckMarker:"TARGET DECK",fileDeckTemplate:"obsidian::filename",fileDeckInsertLocation:"body",folderDeckMode:"folder-and-file",scopeMode:"include",includeFolders:[],excludeFolders:[],addObsidianBacklink:!0,obsidianBacklinkLabel:Ke,obsidianBacklinkPlacement:"answer-last-line",convertHighlightsToCloze:!0,syncObsidianTagsToAnki:!0,keepPureTagLinesInCardBody:!0,ankiConnectUrl:"http://127.0.0.1:8765"};function Io(e){if(typeof e!="string")return Ke;let t=e.trim();return t.length>0?t:Ke}function Ce(e){let t=bi(e.cardTypeConfigs,e),n=zo(t),r={...e,...n,cardTypeConfigs:t,noteFieldMappings:xi(e.noteFieldMappings),ankiNoteTypeCache:$o(e.ankiNoteTypeCache),ankiModelFieldCache:Uo(e.ankiModelFieldCache),obsidianBacklinkLabel:Io(e.obsidianBacklinkLabel)};return{...r,noteFieldMappings:Ho(r)}}function hi(e){let t=e??{},n=bi(t.cardTypeConfigs,t);return Ce({...O,...t,cardTypeConfigs:n,noteFieldMappings:xi(t.noteFieldMappings??O.noteFieldMappings),ankiModelFieldCache:t.ankiModelFieldCache??O.ankiModelFieldCache,includeFolders:t.includeFolders??O.includeFolders,excludeFolders:t.excludeFolders??O.excludeFolders})}function pe(e){if(Po(e.cardTypeConfigs),e.cardAnswerCutoffMode!=="heading-block"&&e.cardAnswerCutoffMode!=="double-blank-lines")throw new S("errors.settings.cardAnswerCutoffModeInvalid");if(Ro(e.noteFieldMappings),Lo(e.ankiNoteTypeCache),No(e.ankiModelFieldCache),!e.defaultDeck.trim())throw new S("errors.settings.defaultDeckRequired");if(typeof e.fileDeckEnabled!="boolean")throw new S("errors.settings.fileDeckEnabledBoolean");if(typeof e.syncObsidianTagsToAnki!="boolean")throw new S("errors.settings.syncObsidianTagsToAnkiBoolean");if(typeof e.keepPureTagLinesInCardBody!="boolean")throw new S("errors.settings.keepPureTagLinesInCardBodyBoolean");if(typeof e.fileDeckMarker!="string")throw new S("errors.settings.fileDeckMarkerString");if(typeof e.fileDeckTemplate!="string")throw new S("errors.settings.fileDeckTemplateString");if(e.fileDeckInsertLocation!=="yaml"&&e.fileDeckInsertLocation!=="body")throw new S("errors.settings.fileDeckInsertLocationInvalid");if(e.folderDeckMode!=="off"&&e.folderDeckMode!=="folder"&&e.folderDeckMode!=="folder-and-file")throw new S("errors.settings.folderDeckModeInvalid");if(e.scopeMode!=="all"&&e.scopeMode!=="include"&&e.scopeMode!=="exclude")throw new S("errors.settings.scopeModeInvalid");if(e.obsidianBacklinkPlacement!=="question-last-line"&&e.obsidianBacklinkPlacement!=="answer-first-line"&&e.obsidianBacklinkPlacement!=="answer-last-line")throw new S("errors.settings.obsidianBacklinkPlacementInvalid");if(li(e.includeFolders,"include"),li(e.excludeFolders,"exclude"),!e.ankiConnectUrl.trim())throw new S("errors.settings.ankiConnectUrlRequired")}function gt(e,t){return e!=="include"?!0:t.some(n=>n.trim().length>0)}function Lo(e){if(!Array.isArray(e))throw new S("errors.settings.ankiNoteTypeCacheArray");for(let t of e)if(typeof t!="string")throw new S("errors.settings.ankiNoteTypeCacheStrings")}function No(e){if(!e||typeof e!="object"||Array.isArray(e))throw new S("errors.settings.ankiModelFieldCacheObject");for(let t of Object.values(e)){if(!t||typeof t!="object"||Array.isArray(t))throw new S("errors.settings.ankiModelFieldCacheEntryObject");if(!Array.isArray(t.fieldNames))throw new S("errors.settings.ankiModelFieldCacheFieldNamesArray");for(let n of t.fieldNames)if(typeof n!="string")throw new S("errors.settings.ankiModelFieldCacheFieldNamesStrings");if(!Number.isFinite(t.loadedAt))throw new S("errors.settings.ankiModelFieldCacheLoadedAt")}}function li(e,t){if(!Array.isArray(e))throw new S(t==="include"?"errors.settings.includeFoldersArray":"errors.settings.excludeFoldersArray");for(let n of e)if(typeof n!="string")throw new S(t==="include"?"errors.settings.includeFoldersStrings":"errors.settings.excludeFoldersStrings")}function Po(e){if(!e||typeof e!="object"||Array.isArray(e))throw new S("errors.settings.cardTypeConfigsObject");let t=new Map;for(let n of Rn){let r=e[n];if(!r||typeof r!="object"||Array.isArray(r))throw new S("errors.settings.cardTypeConfigsObject");if(typeof r.enabled!="boolean")throw new S("errors.settings.cardTypeEnabledBoolean");if(!Number.isInteger(r.headingLevel)||r.headingLevel<1||r.headingLevel>6)throw new S("errors.settings.headingLevelsRange");if(typeof r.extraMarker!="string")throw new S("errors.settings.cardTypeExtraMarkerString");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 S("errors.settings.cardTypeDefaultConflict",{headingLevel:n})}function Ro(e){if(!e||typeof e!="object"||Array.isArray(e))throw new S("errors.settings.noteFieldMappingsObject");for(let t of Object.values(e)){if(t.cardType!=="basic"&&t.cardType!=="qa-group"&&t.cardType!=="cloze")throw new S("errors.settings.noteFieldMappingsCardType");if(!t.modelName.trim())throw new S("errors.settings.noteFieldMappingsModelName");if(!Array.isArray(t.loadedFieldNames))throw new S("errors.settings.noteFieldMappingsLoadedFieldNames");if(!Number.isFinite(t.loadedAt))throw new S("errors.settings.noteFieldMappingsLoadedAt");if(H(t)){if(!Array.isArray(t.slots))throw new S("errors.settings.noteFieldMappingsQaGroupSlotsArray");for(let n of t.slots){if(!n||typeof n!="object"||Array.isArray(n))throw new S("errors.settings.noteFieldMappingsQaGroupSlotObject");if(!Number.isInteger(n.index)||n.index<1)throw new S("errors.settings.noteFieldMappingsQaGroupSlotIndex");if(typeof n.questionField!="string")throw new S("errors.settings.noteFieldMappingsQaGroupSlotQuestionField");if(typeof n.answerField!="string")throw new S("errors.settings.noteFieldMappingsQaGroupSlotAnswerField")}if(fi(t.warnings,"errors.settings.noteFieldMappingsQaGroupWarningsArray","errors.settings.noteFieldMappingsQaGroupWarningsStrings"),fi(t.acceptedWarnings,"errors.settings.noteFieldMappingsQaGroupAcceptedWarningsArray","errors.settings.noteFieldMappingsQaGroupAcceptedWarningsStrings",!0),t.derivation!==void 0){if(!t.derivation||typeof t.derivation!="object"||Array.isArray(t.derivation))throw new S("errors.settings.noteFieldMappingsQaGroupDerivationObject");if(t.derivation.mode!=="first-pair")throw new S("errors.settings.noteFieldMappingsQaGroupDerivationMode");if(t.derivation.firstQuestionField!==void 0&&typeof t.derivation.firstQuestionField!="string")throw new S("errors.settings.noteFieldMappingsQaGroupDerivationFirstQuestionField");if(t.derivation.firstAnswerField!==void 0&&typeof t.derivation.firstAnswerField!="string")throw new S("errors.settings.noteFieldMappingsQaGroupDerivationFirstAnswerField")}}}}function ki(){return{basic:{enabled:!0,headingLevel:Ln,extraMarker:"",noteType:gi},"qa-group":{enabled:!0,headingLevel:Ln,extraMarker:mi,noteType:""},cloze:{enabled:!0,headingLevel:Ze,extraMarker:Pn,noteType:Nn},"cloze-all":{enabled:!0,headingLevel:Ze,extraMarker:Eo,noteType:Nn}}}function Bo(e){let t=ki();return{basic:{...t.basic,headingLevel:Ve(e.qaHeadingLevel,t.basic.headingLevel),noteType:je(e.qaNoteType,t.basic.noteType)},"qa-group":{...t["qa-group"],headingLevel:Ve(e.qaHeadingLevel,t["qa-group"].headingLevel),extraMarker:yi(e.qaGroupMarker,t["qa-group"].extraMarker),noteType:je(e.cardTypeConfigs?.["qa-group"]?.noteType,t["qa-group"].noteType)},cloze:{...t.cloze,headingLevel:Ve(e.clozeHeadingLevel,t.cloze.headingLevel),noteType:je(e.clozeNoteType,t.cloze.noteType)},"cloze-all":{...t["cloze-all"],headingLevel:Ve(e.clozeHeadingLevel,t["cloze-all"].headingLevel),noteType:je(e.clozeNoteType,t["cloze-all"].noteType)}}}function bi(e,t){let n=Bo(t),r={};for(let i of Rn){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:Ve(u.headingLevel,o.headingLevel),extraMarker:yi(u.extraMarker,o.extraMarker),noteType:je(u.noteType,o.noteType)};r[i]=i==="cloze"?Go(s,a,t):s}return r["cloze-all"]={...r["cloze-all"],noteType:r.cloze.noteType},r}function Go(e,t,n){return e.headingLevel===di&&e.extraMarker===Ao?{...e,headingLevel:Ze,extraMarker:Pn}:!qo(t)&&n.clozeHeadingLevel===di?{...e,headingLevel:Ze,extraMarker:Pn}:e}function qo(e){return!e||typeof e!="object"||Array.isArray(e)?!1:"headingLevel"in e||"extraMarker"in e}function zo(e){return{qaHeadingLevel:e.basic.headingLevel,clozeHeadingLevel:e.cloze.headingLevel,qaGroupMarker:e["qa-group"].extraMarker,qaNoteType:e.basic.noteType,clozeNoteType:e.cloze.noteType}}function Ve(e,t){return typeof e=="number"&&Number.isInteger(e)&&e>=1&&e<=6?e:t}function yi(e,t){return typeof e!="string"?t:e.trim()}function je(e,t){if(typeof e!="string")return t;let n=e.trim();return n.length>0?n:t}function xi(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")continue;let i=typeof r.modelName=="string"?r.modelName.trim():"";if(i.length===0)continue;let a=Ci(r.loadedFieldNames),o=typeof r.loadedAt=="number"&&Number.isFinite(r.loadedAt)?r.loadedAt:0;if(r.cardType==="qa-group"){let u=Oo(r,i,a,o);t[B(u.cardType,u.modelName)]=u;continue}if(r.cardType==="cloze"){t[B(r.cardType,i)]={cardType:r.cardType,modelName:i,loadedFieldNames:a,mainField:le(r.mainField),loadedAt:o};continue}t[B(r.cardType,i)]={cardType:r.cardType,modelName:i,loadedFieldNames:a,titleField:le(r.titleField),bodyField:le(r.bodyField),loadedAt:o}}return t}function Ho(e){let t={...e.noteFieldMappings};for(let n of Rn){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"||n==="cloze-all"?"cloze":"basic",o=B(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:ft(s,["Text","Body","Content"])??s[0],loadedAt:u.loadedAt}:{cardType:a,modelName:i,loadedFieldNames:s,titleField:ft(s,["Front","Title"])??s[0],bodyField:ft(s,["Back","Body","Answer"])??s.find(c=>c!==(ft(s,["Front","Title"])??s[0])),loadedAt:u.loadedAt}}return t}function ft(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function Oo(e,t,n,r){let i=pi(e.acceptedWarnings),a=Qo(e.slots),o=pi(e.warnings),u=le(e.titleField),s=Wo(e.derivation);if(a.length>0||o.length>0||i.length>0||s!==void 0)return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:a,warnings:o,acceptedWarnings:i.length>0?i:void 0,derivation:s,loadedAt:r};if(n.length>0)try{return _o.suggest(t,n,r,i,u)}catch{return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:[],warnings:[],acceptedWarnings:void 0,derivation:s,loadedAt:r}}return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:[],warnings:[],acceptedWarnings:void 0,derivation:s,loadedAt:r}}function Wo(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e;if(t.mode==="first-pair")return{mode:"first-pair",firstQuestionField:le(t.firstQuestionField),firstAnswerField:le(t.firstAnswerField)}}function $o(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 Uo(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:Ci(a.fieldNames),loadedAt:o}]]});return t.sort(([n],[r])=>n.localeCompare(r)),Object.fromEntries(t)}function Ci(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=le(r.questionField),a=le(r.answerField);!i||!a||t.push({index:r.index,questionField:i,answerField:a})}return t}function le(e){if(typeof e!="string")return;let t=e.trim();return t.length>0?t:void 0}function pi(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 fi(e,t,n,r=!1){if(!(typeof e>"u"&&r)){if(!Array.isArray(e))throw new S(t);for(let i of e)if(typeof i!="string")throw new S(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 S("errors.deck.emptyName");return r.join("::")}};var mt=class{constructor(t=new Z){this.deckNormalizationService=t}insert(t,n,r,i){let a=this.expandTemplate(r,t.basename),o=i==="yaml"?Vo(t.content,n,a):jo(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 Vo(e,t,n){let r=e.split(/\r?\n/),i=Si(r),a=`${t}: ${n}`;if(!i)return["---",a,"---","",...r].join(` -`);let o=[...r],u=Xo(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 jo(e,t,n){let r=e.split(/\r?\n/),i=Si(r),a=i?i.end+1:0,o=r.slice(0,a),u=r.slice(a),s=Ko(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=Yo(u),f=l.length>0?[c,"",...l]:[c];return i?[...o,"",...f].join(` +${n}`}function ye(e,t,n){return En(e)?e.userMessage:e instanceof Error?{rawMessage:e.message}:{key:t,params:n}}function xe(e,t){return En(e)?lt(e):Le(ye(e,t))}function pt(e,t){return En(t)?{filePath:e,...t.userMessage}:t instanceof Error?{filePath:e,rawMessage:t.message}:{filePath:e,rawMessage:String(t)}}function oi(e){let t=se();return de(t,e.map(n=>`${n.filePath} (${ai(n)})`))}var Mo=["\u9898\u76EE","\u6807\u9898","\u6B63\u9762","Stem","Title"],wo=[/^问题0*(\d+)$/i,/^Q0*(\d+)$/i,/^S0*(\d+)_Q$/i],vo=[/^答案0*(\d+)$/i,/^A0*(\d+)$/i,/^S0*(\d+)_A$/i],ce=class{suggest(t,n,r=Date.now(),i,a){let o=a&&n.includes(a)?a:Do(n,Mo),u=To(n,t);return this.createMappingFromSelection(t,n,{titleField:o,firstQuestionField:u.questionField,firstAnswerField:u.answerField},r)}createMappingFromSelection(t,n,r,i=Date.now()){let a=[...n],o=_n(r.titleField),u=_n(r.firstQuestionField),s=_n(r.firstAnswerField),d=Eo(u,s),c=new Set(a);for(let l of[o,u,s])if(l&&!c.has(l))throw new S("errors.noteFieldMapping.qaGroupSelectedFieldMissing",{modelName:t,field:l});return{cardType:"qa-group",modelName:t,loadedFieldNames:a,titleField:o,slots:Ao(t,a,o,u,s),warnings:[],acceptedWarnings:void 0,derivation:d,loadedAt:i}}validateMapping(t,n){if(!t.titleField)throw new S("errors.noteFieldMapping.qaGroupMissingTitle",{modelName:t.modelName});if(t.slots.length===0)throw new S("errors.noteFieldMapping.qaGroupNoCompleteSlots",{modelName:t.modelName});let r=new Set(n),i=new Set,a=new Set([t.titleField]);r.has(t.titleField)||i.add(t.titleField);for(let o of t.slots){if(r.has(o.questionField)||i.add(o.questionField),r.has(o.answerField)||i.add(o.answerField),a.has(o.questionField)||a.has(o.answerField)||o.questionField===o.answerField)throw new S("errors.noteFieldMapping.qaGroupDuplicateFields",{modelName:t.modelName});a.add(o.questionField),a.add(o.answerField)}if(i.size>0)throw new S("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:[...i].map(o=>`"${o}"`)})}validateWarningsAccepted(t){if(!(!t.warnings.length||Ln(t.warnings,t.acceptedWarnings)))throw new S("errors.noteFieldMapping.qaGroupWarningsUnaccepted",{modelName:t.modelName})}};function Ln(e,t){return e.length===0?!0:!t||e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function ci(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 To(e,t){let n=new Map,r=new Map;for(let u of e){let s=ui(u,wo);if(s&&!n.has(s)){n.set(s,u);continue}let d=ui(u,vo);d&&!r.has(d)&&r.set(d,u)}let i=[...new Set([...n.keys(),...r.keys()])].sort((u,s)=>u-s);if(i.length>0&&i[0]!==1)throw new S("errors.noteFieldMapping.qaGroupNonContinuousSlots",{modelName:t,firstIndex:i[0]});let a=n.get(1),o=r.get(1);if(!a||!o)throw new S("errors.noteFieldMapping.qaGroupNoCompleteSlots",{modelName:t});return{questionField:a,answerField:o}}function ui(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>=1)return i}}function Do(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function Ao(e,t,n,r,i){if(!r||!i)return[];let a=new Set;if(n&&a.add(n),a.has(r)||a.has(i)||r===i)throw new S("errors.noteFieldMapping.qaGroupDuplicateFields",{modelName:e});let o=si(r),u=si(i);if(!o||!u)return[{index:1,questionField:r,answerField:i}];if(o.index!==u.index)throw new S("errors.noteFieldMapping.qaGroupFirstPairNumberMismatch",{modelName:e,questionField:r,answerField:i});if(o.index!==1)throw new S("errors.noteFieldMapping.qaGroupFirstPairMustStartAtOne",{modelName:e,firstIndex:o.index});let s=new Set(t),d=[];for(let c=1;;c+=1){let l=c===1?r:di(o,c),f=c===1?i:di(u,c);if(!s.has(l)||!s.has(f))break;if(a.has(l)||a.has(f)||l===f)throw new S("errors.noteFieldMapping.qaGroupDuplicateFields",{modelName:e});a.add(l),a.add(f),d.push({index:c,questionField:l,answerField:f})}return d}function Eo(e,t){if(!(!e&&!t))return{mode:"first-pair",firstQuestionField:e,firstAnswerField:t}}function _n(e){let t=e?.trim();return t||void 0}function si(e){let t=[...e.matchAll(/\d+/g)],n=t[t.length-1];if(!(!n||n.index===void 0))return{prefix:e.slice(0,n.index),digits:n[0],suffix:e.slice(n.index+n[0].length),index:Number.parseInt(n[0],10)}}function di(e,t){return`${e.prefix}${String(t).padStart(e.digits.length,"0")}${e.suffix}`}var Bn=["basic","qa-group","cloze","cloze-all"],Ke="Open in Obsidian",Nn=4,li=5,Ze=4,gi="",Pn="",_o="",Rn="#anki-cloze",Lo="#anki-cloze-all",mi="#anki-list",Io=new ce,H={qaHeadingLevel:Nn,clozeHeadingLevel:Ze,cardAnswerCutoffMode:"heading-block",qaGroupMarker:mi,qaNoteType:gi,clozeNoteType:Pn,cardTypeConfigs:ki(),noteFieldMappings:{},ankiNoteTypeCache:[],ankiModelFieldCache:{},defaultDeck:"Obsidian",fileDeckEnabled:!1,fileDeckMarker:"TARGET DECK",fileDeckTemplate:"obsidian::filename",fileDeckInsertLocation:"body",folderDeckMode:"folder-and-file",scopeMode:"include",includeFolders:[],excludeFolders:[],alternateFolderDeckModeFolders:[],addObsidianBacklink:!0,obsidianBacklinkLabel:Ke,obsidianBacklinkPlacement:"answer-last-line",convertHighlightsToCloze:!0,syncObsidianTagsToAnki:!0,keepPureTagLinesInCardBody:!0,ankiConnectUrl:"http://127.0.0.1:8765"};function No(e){if(typeof e!="string")return Ke;let t=e.trim();return t.length>0?t:Ke}function Ce(e){let t=bi(e.cardTypeConfigs,e),n=Oo(t),r={...e,...n,cardTypeConfigs:t,noteFieldMappings:xi(e.noteFieldMappings),ankiNoteTypeCache:Qo(e.ankiNoteTypeCache),ankiModelFieldCache:Vo(e.ankiModelFieldCache),obsidianBacklinkLabel:No(e.obsidianBacklinkLabel)};return{...r,noteFieldMappings:Wo(r)}}function hi(e){let t=e??{},n=bi(t.cardTypeConfigs,t);return Ce({...H,...t,cardTypeConfigs:n,noteFieldMappings:xi(t.noteFieldMappings??H.noteFieldMappings),ankiModelFieldCache:t.ankiModelFieldCache??H.ankiModelFieldCache,includeFolders:t.includeFolders??H.includeFolders,excludeFolders:t.excludeFolders??H.excludeFolders,alternateFolderDeckModeFolders:t.alternateFolderDeckModeFolders??H.alternateFolderDeckModeFolders})}function pe(e){if(Bo(e.cardTypeConfigs),e.cardAnswerCutoffMode!=="heading-block"&&e.cardAnswerCutoffMode!=="double-blank-lines")throw new S("errors.settings.cardAnswerCutoffModeInvalid");if(Go(e.noteFieldMappings),Po(e.ankiNoteTypeCache),Ro(e.ankiModelFieldCache),!e.defaultDeck.trim())throw new S("errors.settings.defaultDeckRequired");if(typeof e.fileDeckEnabled!="boolean")throw new S("errors.settings.fileDeckEnabledBoolean");if(typeof e.syncObsidianTagsToAnki!="boolean")throw new S("errors.settings.syncObsidianTagsToAnkiBoolean");if(typeof e.keepPureTagLinesInCardBody!="boolean")throw new S("errors.settings.keepPureTagLinesInCardBodyBoolean");if(typeof e.fileDeckMarker!="string")throw new S("errors.settings.fileDeckMarkerString");if(typeof e.fileDeckTemplate!="string")throw new S("errors.settings.fileDeckTemplateString");if(e.fileDeckInsertLocation!=="yaml"&&e.fileDeckInsertLocation!=="body")throw new S("errors.settings.fileDeckInsertLocationInvalid");if(e.folderDeckMode!=="off"&&e.folderDeckMode!=="folder"&&e.folderDeckMode!=="folder-and-file")throw new S("errors.settings.folderDeckModeInvalid");if(e.scopeMode!=="all"&&e.scopeMode!=="include"&&e.scopeMode!=="exclude")throw new S("errors.settings.scopeModeInvalid");if(e.obsidianBacklinkPlacement!=="question-last-line"&&e.obsidianBacklinkPlacement!=="answer-first-line"&&e.obsidianBacklinkPlacement!=="answer-last-line")throw new S("errors.settings.obsidianBacklinkPlacementInvalid");if(In(e.includeFolders,"include"),In(e.excludeFolders,"exclude"),In(e.alternateFolderDeckModeFolders,"alternateFolderDeckMode"),!e.ankiConnectUrl.trim())throw new S("errors.settings.ankiConnectUrlRequired")}function gt(e,t){return e!=="include"?!0:t.some(n=>n.trim().length>0)}function Po(e){if(!Array.isArray(e))throw new S("errors.settings.ankiNoteTypeCacheArray");for(let t of e)if(typeof t!="string")throw new S("errors.settings.ankiNoteTypeCacheStrings")}function Ro(e){if(!e||typeof e!="object"||Array.isArray(e))throw new S("errors.settings.ankiModelFieldCacheObject");for(let t of Object.values(e)){if(!t||typeof t!="object"||Array.isArray(t))throw new S("errors.settings.ankiModelFieldCacheEntryObject");if(!Array.isArray(t.fieldNames))throw new S("errors.settings.ankiModelFieldCacheFieldNamesArray");for(let n of t.fieldNames)if(typeof n!="string")throw new S("errors.settings.ankiModelFieldCacheFieldNamesStrings");if(!Number.isFinite(t.loadedAt))throw new S("errors.settings.ankiModelFieldCacheLoadedAt")}}function In(e,t){if(!Array.isArray(e))throw t==="include"?new S("errors.settings.includeFoldersArray"):t==="exclude"?new S("errors.settings.excludeFoldersArray"):new S("errors.settings.alternateFolderDeckModeFoldersArray");for(let n of e)if(typeof n!="string")throw t==="include"?new S("errors.settings.includeFoldersStrings"):t==="exclude"?new S("errors.settings.excludeFoldersStrings"):new S("errors.settings.alternateFolderDeckModeFoldersStrings")}function Bo(e){if(!e||typeof e!="object"||Array.isArray(e))throw new S("errors.settings.cardTypeConfigsObject");let t=new Map;for(let n of Bn){let r=e[n];if(!r||typeof r!="object"||Array.isArray(r))throw new S("errors.settings.cardTypeConfigsObject");if(typeof r.enabled!="boolean")throw new S("errors.settings.cardTypeEnabledBoolean");if(!Number.isInteger(r.headingLevel)||r.headingLevel<1||r.headingLevel>6)throw new S("errors.settings.headingLevelsRange");if(typeof r.extraMarker!="string")throw new S("errors.settings.cardTypeExtraMarkerString");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 S("errors.settings.cardTypeDefaultConflict",{headingLevel:n})}function Go(e){if(!e||typeof e!="object"||Array.isArray(e))throw new S("errors.settings.noteFieldMappingsObject");for(let t of Object.values(e)){if(t.cardType!=="basic"&&t.cardType!=="qa-group"&&t.cardType!=="cloze")throw new S("errors.settings.noteFieldMappingsCardType");if(!t.modelName.trim())throw new S("errors.settings.noteFieldMappingsModelName");if(!Array.isArray(t.loadedFieldNames))throw new S("errors.settings.noteFieldMappingsLoadedFieldNames");if(!Number.isFinite(t.loadedAt))throw new S("errors.settings.noteFieldMappingsLoadedAt");if(O(t)){if(!Array.isArray(t.slots))throw new S("errors.settings.noteFieldMappingsQaGroupSlotsArray");for(let n of t.slots){if(!n||typeof n!="object"||Array.isArray(n))throw new S("errors.settings.noteFieldMappingsQaGroupSlotObject");if(!Number.isInteger(n.index)||n.index<1)throw new S("errors.settings.noteFieldMappingsQaGroupSlotIndex");if(typeof n.questionField!="string")throw new S("errors.settings.noteFieldMappingsQaGroupSlotQuestionField");if(typeof n.answerField!="string")throw new S("errors.settings.noteFieldMappingsQaGroupSlotAnswerField")}if(fi(t.warnings,"errors.settings.noteFieldMappingsQaGroupWarningsArray","errors.settings.noteFieldMappingsQaGroupWarningsStrings"),fi(t.acceptedWarnings,"errors.settings.noteFieldMappingsQaGroupAcceptedWarningsArray","errors.settings.noteFieldMappingsQaGroupAcceptedWarningsStrings",!0),t.derivation!==void 0){if(!t.derivation||typeof t.derivation!="object"||Array.isArray(t.derivation))throw new S("errors.settings.noteFieldMappingsQaGroupDerivationObject");if(t.derivation.mode!=="first-pair")throw new S("errors.settings.noteFieldMappingsQaGroupDerivationMode");if(t.derivation.firstQuestionField!==void 0&&typeof t.derivation.firstQuestionField!="string")throw new S("errors.settings.noteFieldMappingsQaGroupDerivationFirstQuestionField");if(t.derivation.firstAnswerField!==void 0&&typeof t.derivation.firstAnswerField!="string")throw new S("errors.settings.noteFieldMappingsQaGroupDerivationFirstAnswerField")}}}}function ki(){return{basic:{enabled:!0,headingLevel:Nn,extraMarker:"",noteType:gi},"qa-group":{enabled:!0,headingLevel:Nn,extraMarker:mi,noteType:""},cloze:{enabled:!0,headingLevel:Ze,extraMarker:Rn,noteType:Pn},"cloze-all":{enabled:!0,headingLevel:Ze,extraMarker:Lo,noteType:Pn}}}function qo(e){let t=ki();return{basic:{...t.basic,headingLevel:Ve(e.qaHeadingLevel,t.basic.headingLevel),noteType:je(e.qaNoteType,t.basic.noteType)},"qa-group":{...t["qa-group"],headingLevel:Ve(e.qaHeadingLevel,t["qa-group"].headingLevel),extraMarker:yi(e.qaGroupMarker,t["qa-group"].extraMarker),noteType:je(e.cardTypeConfigs?.["qa-group"]?.noteType,t["qa-group"].noteType)},cloze:{...t.cloze,headingLevel:Ve(e.clozeHeadingLevel,t.cloze.headingLevel),noteType:je(e.clozeNoteType,t.cloze.noteType)},"cloze-all":{...t["cloze-all"],headingLevel:Ve(e.clozeHeadingLevel,t["cloze-all"].headingLevel),noteType:je(e.clozeNoteType,t["cloze-all"].noteType)}}}function bi(e,t){let n=qo(t),r={};for(let i of Bn){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:Ve(u.headingLevel,o.headingLevel),extraMarker:yi(u.extraMarker,o.extraMarker),noteType:je(u.noteType,o.noteType)};r[i]=i==="cloze"?zo(s,a,t):s}return r["cloze-all"]={...r["cloze-all"],noteType:r.cloze.noteType},r}function zo(e,t,n){return e.headingLevel===li&&e.extraMarker===_o?{...e,headingLevel:Ze,extraMarker:Rn}:!Ho(t)&&n.clozeHeadingLevel===li?{...e,headingLevel:Ze,extraMarker:Rn}:e}function Ho(e){return!e||typeof e!="object"||Array.isArray(e)?!1:"headingLevel"in e||"extraMarker"in e}function Oo(e){return{qaHeadingLevel:e.basic.headingLevel,clozeHeadingLevel:e.cloze.headingLevel,qaGroupMarker:e["qa-group"].extraMarker,qaNoteType:e.basic.noteType,clozeNoteType:e.cloze.noteType}}function Ve(e,t){return typeof e=="number"&&Number.isInteger(e)&&e>=1&&e<=6?e:t}function yi(e,t){return typeof e!="string"?t:e.trim()}function je(e,t){if(typeof e!="string")return t;let n=e.trim();return n.length>0?n:t}function xi(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")continue;let i=typeof r.modelName=="string"?r.modelName.trim():"";if(i.length===0)continue;let a=Ci(r.loadedFieldNames),o=typeof r.loadedAt=="number"&&Number.isFinite(r.loadedAt)?r.loadedAt:0;if(r.cardType==="qa-group"){let u=$o(r,i,a,o);t[B(u.cardType,u.modelName)]=u;continue}if(r.cardType==="cloze"){t[B(r.cardType,i)]={cardType:r.cardType,modelName:i,loadedFieldNames:a,mainField:le(r.mainField),loadedAt:o};continue}t[B(r.cardType,i)]={cardType:r.cardType,modelName:i,loadedFieldNames:a,titleField:le(r.titleField),bodyField:le(r.bodyField),loadedAt:o}}return t}function Wo(e){let t={...e.noteFieldMappings};for(let n of Bn){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"||n==="cloze-all"?"cloze":"basic",o=B(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:ft(s,["Text","Body","Content"])??s[0],loadedAt:u.loadedAt}:{cardType:a,modelName:i,loadedFieldNames:s,titleField:ft(s,["Front","Title"])??s[0],bodyField:ft(s,["Back","Body","Answer"])??s.find(d=>d!==(ft(s,["Front","Title"])??s[0])),loadedAt:u.loadedAt}}return t}function ft(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function $o(e,t,n,r){let i=pi(e.acceptedWarnings),a=jo(e.slots),o=pi(e.warnings),u=le(e.titleField),s=Uo(e.derivation);if(a.length>0||o.length>0||i.length>0||s!==void 0)return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:a,warnings:o,acceptedWarnings:i.length>0?i:void 0,derivation:s,loadedAt:r};if(n.length>0)try{return Io.suggest(t,n,r,i,u)}catch{return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:[],warnings:[],acceptedWarnings:void 0,derivation:s,loadedAt:r}}return{cardType:"qa-group",modelName:t,loadedFieldNames:n,titleField:u,slots:[],warnings:[],acceptedWarnings:void 0,derivation:s,loadedAt:r}}function Uo(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e;if(t.mode==="first-pair")return{mode:"first-pair",firstQuestionField:le(t.firstQuestionField),firstAnswerField:le(t.firstAnswerField)}}function Qo(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 Vo(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:Ci(a.fieldNames),loadedAt:o}]]});return t.sort(([n],[r])=>n.localeCompare(r)),Object.fromEntries(t)}function Ci(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 jo(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=le(r.questionField),a=le(r.answerField);!i||!a||t.push({index:r.index,questionField:i,answerField:a})}return t}function le(e){if(typeof e!="string")return;let t=e.trim();return t.length>0?t:void 0}function pi(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 fi(e,t,n,r=!1){if(!(typeof e>"u"&&r)){if(!Array.isArray(e))throw new S(t);for(let i of e)if(typeof i!="string")throw new S(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 S("errors.deck.emptyName");return r.join("::")}};var mt=class{constructor(t=new Z){this.deckNormalizationService=t}insert(t,n,r,i){let a=this.expandTemplate(r,t.basename),o=i==="yaml"?Ko(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 Ko(e,t,n){let r=e.split(/\r?\n/),i=Si(r),a=`${t}: ${n}`;if(!i)return["---",a,"---","",...r].join(` +`);let o=[...r],u=eu(t),s=i.start+1,d=i.end,c=o.slice(s,d).findIndex(l=>u.test(l));return c>=0?(o[s+c]=a,o.join(` +`)):(o.splice(d,0,a),o.join(` +`))}function Zo(e,t,n){let r=e.split(/\r?\n/),i=Si(r),a=i?i.end+1:0,o=r.slice(0,a),u=r.slice(a),s=Yo(u,t),d=`${t}: ${n}`,c=[...u];if(s)return c.splice(s.start,s.end-s.start+1,d),[...o,...c].join(` +`);let l=Jo(u),f=l.length>0?[d,"",...l]:[d];return i?[...o,"",...f].join(` `):f.join(` -`)}function Si(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(Fi(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 Fi(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"}},kt=class extends Error{constructor(t){super(`Markdown file not found: ${t}`),this.name="MarkdownFileNotFoundError"}};function bt(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*$/,ge=class{isCandidate(t){return Jo.test(t)}parse(t,n){let r=t.match(eu);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 Si(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(Fi(i)),u=new Map(a.map(l=>[l.deckName,l.noteCount])),s=r.filter(l=>o.has(l)&&u.get(l)===0),d=r.filter(l=>!o.has(l)||u.get(l)!==0),c=[];for(let l of s)try{await this.ankiGateway.deleteDecks([l]),c.push(l)}catch{d.push(l)}return{candidateCount:n.length,selectedCount:r.length,deletedCount:c.length,deletedDeckNames:c,skippedDeckNames:d}}};function Fi(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"}},kt=class extends Error{constructor(t){super(`Markdown file not found: ${t}`),this.name="MarkdownFileNotFoundError"}};function bt(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*$/,ge=class{isCandidate(t){return tu.test(t)}parse(t,n){let r=t.match(nu);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}.`);bt(t,{contentEndLine:n.contentEndLine,blockEndLine:n.blockEndLine,markerLine:n.markerLine,markerIndent:n.markerIndent,renderedMarker:this.create(n.noteId).raw})}};var U=class extends Error{constructor(t){super(t),this.name="GroupMarkerError"}},tu=/\s*$/,ru=/^[A-Za-z][A-Za-z0-9_-]*$/,X=class{isCandidate(t){return tu.test(t)}parse(t,n){let r=t.match(nu);if(!r)return null;let i=Number(r[1]),a=iu(r[2]),o=au(r[3]);return Gn(a,o),{noteId:i,itemToSlot:a,freeSlots:o,raw:r[0].trim(),lineIndex:n}}create(t,n,r){return Gn(n,r),{noteId:t,itemToSlot:{...n},freeSlots:[...new Set(r)].sort((i,a)=>i-a),raw:yt(t,n,r),lineIndex:-1}}isEquivalent(t,n,r,i){if(!t||t.noteId!==n)return!1;let a=Object.entries(t.itemToSlot).sort(Mi),o=Object.entries(r).sort(Mi);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 U("Batch GI marker writes must belong to the same Markdown file.");if(a.sourceContent!==t)throw new U(`GI marker writes for ${a.filePath} must share the scanned source content.`);if(a.markerLine!==void 0&&a.markerLinea.blockEndLine)throw new U(`Cannot place GI marker outside the content range in ${a.filePath}.`);if(i.has(a.blockStartLine))throw new U(`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}.`);bt(t,{contentEndLine:n.contentEndLine,blockEndLine:n.blockEndLine,markerLine:n.markerLine,markerIndent:n.markerIndent,renderedMarker:this.create(n.noteId).raw})}};var U=class extends Error{constructor(t){super(t),this.name="GroupMarkerError"}},ru=/\s*$/,au=/^[A-Za-z][A-Za-z0-9_-]*$/,X=class{isCandidate(t){return ru.test(t)}parse(t,n){let r=t.match(iu);if(!r)return null;let i=Number(r[1]),a=ou(r[2]),o=uu(r[3]);return qn(a,o),{noteId:i,itemToSlot:a,freeSlots:o,raw:r[0].trim(),lineIndex:n}}create(t,n,r){return qn(n,r),{noteId:t,itemToSlot:{...n},freeSlots:[...new Set(r)].sort((i,a)=>i-a),raw:yt(t,n,r),lineIndex:-1}}isEquivalent(t,n,r,i){if(!t||t.noteId!==n)return!1;let a=Object.entries(t.itemToSlot).sort(Mi),o=Object.entries(r).sort(Mi);if(a.length!==o.length)return!1;for(let d=0;dd-c),s=[...i].sort((d,c)=>d-c);return u.length!==s.length?!1:u.every((d,c)=>d===s[c])}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 U("Batch GI marker writes must belong to the same Markdown file.");if(a.sourceContent!==t)throw new U(`GI marker writes for ${a.filePath} must share the scanned source content.`);if(a.markerLine!==void 0&&a.markerLinea.blockEndLine)throw new U(`Cannot place GI marker outside the content range in ${a.filePath}.`);if(i.has(a.blockStartLine))throw new U(`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){bt(t,{contentEndLine:n.contentEndLine,blockEndLine:n.blockEndLine,markerLine:n.markerLine,markerIndent:n.markerIndent,renderedMarker:yt(n.noteId,n.itemToSlot,n.freeSlots),additionalRemovalLineIndexes:ou(t,n.blockStartLine,n.blockEndLine)})}};function yt(e,t,n){Gn(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 iu(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||!ru.test(a))throw new U(`Invalid GI item mapping entry: ${r}`);let u=Number(o);if(!Number.isInteger(u)||u<1)throw new U(`Invalid GI slot value: ${o}`);if(t[a]!==void 0||n.has(u))throw new U(`Duplicate GI mapping entry detected: ${r}`);t[a]=u,n.add(u)}return t}function au(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 U(`Invalid GI free slot value: ${i}`);if(n.has(a))throw new U(`Duplicate GI free slot detected: ${i}`);n.add(a),t.push(a)}return t.sort((r,i)=>r-i)}function Gn(e,t){let n=new Set;for(let r of Object.values(e)){if(!Number.isInteger(r)||r<1)throw new U(`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 U(`GI free slot must be a positive integer. Received: ${r}`);if(n.has(r))throw new U(`GI free slot ${r} overlaps with an occupied slot.`)}}function ou(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?{...xt(),conflictFiles:[t]}:{...xt(),failureFiles:[pt(t,o)]}}}};function uu(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){bt(t,{contentEndLine:n.contentEndLine,blockEndLine:n.blockEndLine,markerLine:n.markerLine,markerIndent:n.markerIndent,renderedMarker:yt(n.noteId,n.itemToSlot,n.freeSlots),additionalRemovalLineIndexes:su(t,n.blockStartLine,n.blockEndLine)})}};function yt(e,t,n){qn(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 ou(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||!au.test(a))throw new U(`Invalid GI item mapping entry: ${r}`);let u=Number(o);if(!Number.isInteger(u)||u<1)throw new U(`Invalid GI slot value: ${o}`);if(t[a]!==void 0||n.has(u))throw new U(`Duplicate GI mapping entry detected: ${r}`);t[a]=u,n.add(u)}return t}function uu(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 U(`Invalid GI free slot value: ${i}`);if(n.has(a))throw new U(`Duplicate GI free slot detected: ${i}`);n.add(a),t.push(a)}return t.sort((r,i)=>r-i)}function qn(e,t){let n=new Set;for(let r of Object.values(e)){if(!Number.isInteger(r)||r<1)throw new U(`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 U(`GI free slot must be a positive integer. Received: ${r}`);if(n.has(r))throw new U(`GI free slot ${r} overlaps with an occupied slot.`)}}function su(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?{...xt(),conflictFiles:[t]}:{...xt(),failureFiles:[pt(t,o)]}}}};function du(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=vi(n,t);if(r.trackedCards.length===0&&r.trackedGroups.length===0)return cu();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=su(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 vi(e,t){let n=new Set,r=new Set,i=e.groupBlocks??{};for(let u of e.files[t]?.noteIds??[]){let s=z(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(z(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 su(e,t,n){let r={...e.cards},i={...e.groupBlocks??{}};for(let o of n.trackedCards)delete r[z(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 cu(){return{trackedCards:0,trackedGroups:0,deletedNotes:0,removedMarkers:0,removedCardMarkers:0,removedGroupMarkers:0,deletedLocalRecords:0,conflictFiles:[],failureFiles:[]}}var Ft=class{constructor(t){this.manualSyncService=t}async execute(t,n){return this.manualSyncService.syncFile(t,n)}};var Mt=class{constructor(t){this.manualSyncService=t}async execute(t){return this.manualSyncService.syncVault(t)}};var Ti=require("obsidian"),wt=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=du(r[o]);return u&&(i[a]=u),i},{})}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)}}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:lu(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(pu("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,Ti.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 du(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 lu(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 pu(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}: ${fu(n)}`}function fu(e){return e instanceof Error&&e.message.trim().length>0?e.message.trim():String(e)}var vt=class{constructor(t){this.plugin=t}async load(){let t=await this.plugin.loadData();return t!==null&&typeof t=="object"?t:null}async save(t){await this.plugin.saveData(t)}};var ie=require("obsidian");function Q(e){let t=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}function Tt(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 gu=new Set(["png","jpg","jpeg","gif","bmp","svg","webp","tiff"]),mu=new Set(["wav","m4a","flac","mp3","wma","aac","webm","ogg"]),At=class{constructor(t){this.app=t}listFolderTree(){return Promise.resolve(this.app.vault.getRoot().children.filter(t=>t instanceof ie.TFolder).map(t=>this.toFolderTreeNode(t)))}listMarkdownFileRefs(){return Promise.resolve(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 ie.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 ie.TFile)||i.extension.toLowerCase()!=="md")throw new kt(t);await this.app.vault.process(i,a=>{if(a!==n)throw new fe(t);return r})}resolveWikiLink(t,n){let{alias:r,linkPath:i}=Di(t),o=this.app.metadataCache.getFirstLinkpathDest(Dt(i),n)?.path??Dt(i),u=r||hu(i);return{url:this.createObsidianUrl(i.includes("#")?`${o}${i.slice(i.indexOf("#"))}`:o),displayText:u}}resolveEmbed(t,n){let{alias:r,linkPath:i}=Di(t),a=this.app.metadataCache.getFirstLinkpathDest(Dt(i),n);if(!(a instanceof ie.TFile))return null;let o=a.extension.toLowerCase(),u=gu.has(o)?"image":mu.has(o)?"audio":null;if(!u)return null;let s=ku(this.app,a.path),c=`${Q(a.path)}-${a.name}`;return{kind:u,fileName:c,absolutePath:s,altText:r||a.name}}createBacklink(t){return this.createObsidianUrl(`${t.filePath}#${bu(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:yu(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 ie.TFolder).map(n=>this.toFolderTreeNode(n))}}};function Di(e){let[t,n]=e.split("|",2).map(r=>r.trim());return{linkPath:t,alias:n||void 0}}function Dt(e){return e.split("#",1)[0]}function hu(e){let t=Dt(e);return(t.split("/").pop()??t).replace(/\.[^.]+$/,"")||e}function ku(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 bu(e){return e.replace(/(?:\s+#\S+)+$/g,t=>t.replace(/(^|\s)#(\S+)/g,"$1$2"))}function yu(e){return e?Tt((0,ie.getAllTags)(e)):[]}var Et=class{constructor(t){this.pluginDataStore=t}async load(){let t=await this.pluginDataStore.load()??{},n=hi(t.settings);return pe(n),n}async save(t){let n=Ce(t);pe(n);let r=await this.pluginDataStore.load()??{};await this.pluginDataStore.save({...r,settings:n})}};function Se(e,t){if(e==="cloze")return t==="all"?"all":"sequential"}function _t(e,t,n){return`${e}\0${t}\0${n}`}var It=class{constructor(t){this.pluginDataStore=t}async load(){let t=await this.pluginDataStore.load()??{};return xu(t.pluginState)}async save(t){let n=await this.pluginDataStore.load()??{};await this.pluginDataStore.save({...n,pluginState:t})}};function xu(e){if(!e)return wi();let t=Au(e.cards),n=Eu(e.files),r=_u(e.groupBlocks),i={};for(let u of Object.values(t)){let s=Xe(u.noteId);if(s===void 0)continue;let c=Cu(u,s);if(!c)continue;let d=z(s),l=i[d];(!l||l.lastSyncedAt<=c.lastSyncedAt)&&(i[d]=c)}let a={};for(let[u,s]of Object.entries(n))a[u]={filePath:u,fileHash:typeof s.fileHash=="string"?s.fileHash:"",fileStamp:typeof s.fileStamp=="string"?s.fileStamp:"",deckRulesFingerprint:typeof s.deckRulesFingerprint=="string"?s.deckRulesFingerprint:void 0,lastIndexedAt:typeof s.lastIndexedAt=="number"?s.lastIndexedAt:0,noteIds:wu(s,t,i),groupIds:Du(s,r)};let o={};for(let[u,s]of Object.entries(r)){let c=Mu(s,u);if(!c)continue;let d=o[u];(!d||d.lastSyncedAt<=c.lastSyncedAt)&&(o[u]=c)}return{files:a,cards:i,groupBlocks:o,pendingWriteBack:vu(e.pendingWriteBack)}}function Cu(e,t){let n=Su(e.cardType);return n?{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:n,clozeMode:Se(n,Fu(e.clozeMode)),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(r=>typeof r=="string"):[],lastSyncedAt:typeof e.lastSyncedAt=="number"?e.lastSyncedAt:0,orphan:!!e.orphan}:null}function Su(e){if(e==="basic"||e==="cloze")return e}function Fu(e){if(e==="sequential"||e==="all")return e}function Mu(e,t){let n=Xe(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 wu(e,t,n){let r=new Set;if(Array.isArray(e.noteIds))for(let i of e.noteIds){let a=Xe(i);a!==void 0&&n[z(a)]&&r.add(a)}if(Array.isArray(e.cardIds))for(let i of e.cardIds){let a=Xe(t[i]?.noteId);a!==void 0&&n[z(a)]&&r.add(a)}return Array.from(r)}function vu(e){return Array.isArray(e)?e.flatMap(t=>{let n=Tu(t);return n?[n]:[]}):[]}function Tu(e){let t=Ye(e.filePath),n=Iu(e.blockStartLine),r=Ye(e.expectedFileHash),i=Ye(e.targetMarker),a=Ye(e.rawBlockHash),o=Xe(e.targetNoteId);if(!t||!n||!r||!i||!a||!o)return null;let u=Lu(e.markerKind);if(e.markerKind!==void 0&&!u)return null;let s=e.targetGroupId===void 0?void 0:Ye(e.targetGroupId);return e.targetGroupId!==void 0&&!s?null:{filePath:t,blockStartLine:n,expectedFileHash:r,targetMarker:i,rawBlockHash:a,targetNoteId:o,markerKind:u,targetGroupId:s}}function Du(e,t){return Array.isArray(e.groupIds)?e.groupIds.filter(n=>typeof n=="string"&&!!t[n]):[]}function Au(e){let t={},n=e??{};for(let r in n){let i=n[r];t[r]=i}return t}function Eu(e){let t={},n=e??{};for(let r in n){let i=n[r];t[r]=i}return t}function _u(e){let t={},n=e??{};for(let r in n){let i=n[r];t[r]=i}return t}function Xe(e){return typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0}function Iu(e){return typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0}function Ye(e){return typeof e=="string"&&e.trim().length>0?e:void 0}function Lu(e){return e==="card-id"||e==="group-gi"?e:void 0}function Ai(e){e.addCommand({id:"sync-current-file-to-anki",name:g("commands.syncCurrentFileToAnki"),callback:()=>{e.runSyncCurrentFile()}}),e.addCommand({id:"sync-vault-to-anki",name:g("commands.syncVaultToAnki"),callback:()=>{e.runSyncVault()}}),e.addCommand({id:"clear-current-file-synced-cards",name:g("commands.clearCurrentFileSyncedCards"),callback:()=>{e.runClearCurrentFileSyncedCards()}}),e.addCommand({id:"cleanup-empty-decks",name:g("commands.cleanupEmptyDecks"),callback:()=>{e.runCleanupEmptyDecks()}})}var Je=require("obsidian");var Lt=class extends Je.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:g("modal.emptyDeck.title")}),n.createEl("p",{text:g("modal.emptyDeck.description")});for(let i of this.candidateDeckNames)new Je.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 Je.Setting(n).addButton(i=>{i.setButtonText(g("modal.emptyDeck.selectAll")).onClick(()=>{this.selectAllDecks()})}).addButton(i=>{i.setButtonText(g("modal.emptyDeck.clearAll")).onClick(()=>{this.clearSelectedDecks()})}).addButton(i=>{i.setButtonText(g("modal.emptyDeck.invert")).onClick(()=>{this.invertSelectedDecks()})}).addButton(i=>{i.setButtonText(g("modal.emptyDeck.cancel")).onClick(()=>{this.finish(null)})}).addButton(i=>{this.deleteButton=i,i.setButtonText(g("modal.emptyDeck.deleteSelected")).setCta().onClick(()=>{this.finish(Array.from(this.selectedDeckNames))})});this.selectionCountEl=r.settingEl.createSpan({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 g("modal.emptyDeck.selectionCount",{selected:this.selectedDeckNames.size,total:this.candidateDeckNames.length})}};var qn=require("obsidian");var Nt=class{info(t){new qn.Notice(t,5e3)}error(t){new qn.Notice(t,8e3)}showSyncSummary(t,n){let r=se(),o=[g(t==="currentFile"?"notice.summary.currentFileSync":"notice.summary.vaultSync",{scannedFiles:n.scannedFiles,scannedCards:n.scannedCards,created:n.created,rebuilt:n.rebuilt,updated:n.updated,migratedNoteTypes:n.migratedNoteTypes,migratedDecks:n.migratedDecks,orphaned:n.orphaned,uploadedMedia:n.uploadedMedia,skippedUnchangedCards:n.skippedUnchangedCards})];n.markerWriteConflictFiles.length>0&&o.push(g("notice.summary.markerWriteConflicts",{files:ce(r,n.markerWriteConflictFiles)})),n.warnings.length>0&&o.push(g("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))}showClearCurrentFileSummary(t){let n=se(),r=[g("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(g("notice.summary.markerRemovalConflicts",{files:ce(n,t.conflictFiles)})),t.failureFiles.length>0&&r.push(g("notice.summary.failures",{items:ai(t.failureFiles)})),this.info(r.join(" "))}showCleanupEmptyDecksSummary(t){let n=se(),r=[g("notice.summary.cleanupEmptyDecks",{candidateCount:t.candidateCount,selectedCount:t.selectedCount,deletedCount:t.deletedCount,skippedCount:t.skippedDeckNames.length})];t.skippedDeckNames.length>0&&r.push(g("notice.summary.skippedDecks",{decks:ce(n,t.skippedDeckNames)})),this.info(r.join(" "))}renderDeckWarning(t){return g(Nu(t.code),t.params)}};function Nu(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 Ei(e){return e==="cloze"}function _i(e){return e==="basic"}var Ne=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),_i(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 Pu(t)?{cardType:t,modelName:n,loadedFieldNames:[...r],titleField:Pt(r,["Front","Title"])??r[0],bodyField:Pt(r,["Back","Body","Answer"])??r.find(a=>a!==(Pt(r,["Front","Title"])??r[0])),loadedAt:i}:{cardType:t,modelName:n,loadedFieldNames:[...r],mainField:Pt(r,["Text","Body","Content"])??r[0],loadedAt:i}}validateMapping(t,n){if(!Dn(t)&&!ei(t))throw new Error("QaGroupFieldMappingService validates qa-group mappings.");let r=new Set(n.fieldNames);if(Dn(t)){if(!t.titleField||!t.bodyField)throw new S(Ii(t.cardType),{modelName:t.modelName});if(t.titleField===t.bodyField)throw new S(Bu(),{modelName:t.modelName});let i=[t.titleField,t.bodyField].filter(a=>!r.has(a));if(i.length>0)throw new S("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:i.map(a=>`"${a}"`)});return}if(!t.mainField)throw new S("errors.noteFieldMapping.incompleteSavedMapping.cloze",{modelName:t.modelName});if(!r.has(t.mainField))throw new S("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:[`"${t.mainField}"`]})}mapBasic(t,n){let r=n.titleField,i=n.bodyField;if(!r||!i)throw new S(Ii(t.type),{modelName:t.noteModel});return{[r]:t.renderedFields.title,[i]:t.renderedFields.body}}mapCloze(t,n){if(!n.mainField)throw new S("errors.noteFieldMapping.incompleteSavedMapping.cloze",{modelName:t.noteModel});return{[n.mainField]:`${t.renderedFields.title}

${t.renderedFields.body}`}}getRequiredMapping(t,n){let r=n[B(t.type,t.noteModel)];if(!r)throw new S(Ru(t.type),{modelName:t.noteModel});return r}};function Pu(e){return e==="basic"}function Ru(e){return e==="cloze"?"errors.noteFieldMapping.missingSavedMapping.cloze":"errors.noteFieldMapping.missingSavedMapping.basic"}function Ii(e){return e==="cloze"?"errors.noteFieldMapping.incompleteSavedMapping.cloze":"errors.noteFieldMapping.incompleteSavedMapping.basic"}function Bu(){return"errors.noteFieldMapping.titleBodyMustDiffer.basic"}function Pt(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function Pi(e,t){let n=new Set(zn(t));return e.map(r=>Bi(r,n,!1))}function Ri(e,t,n,r){let i=Gu(e),a=new Set(zn(t).filter(u=>i.nodeByPath.has(u)));if(!i.nodeByPath.has(n))return Rt(e,Array.from(a));if(r)return Li(n,a,i.parentByPath)||(Ni(a,n),a.add(n)),Rt(e,Array.from(a));let o=Li(n,a,i.parentByPath);if(o&&(a.delete(o),o!==n)){let u=i.nodeByPath.get(o);if(u)for(let s of qi(u,n))a.add(s)}return Ni(a,n),Rt(e,Array.from(a))}function Rt(e,t){let n=new Set(zn(t));return e.flatMap(r=>Gi(r,n).paths)}function Bi(e,t,n){let r=n||t.has(e.path),i=e.children.map(o=>Bi(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 Gi(e,t){return t.has(e.path)?{paths:[e.path]}:e.children.length===0?{paths:[]}:{paths:e.children.map(r=>Gi(r,t)).flatMap(r=>r.paths)}}function Gu(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 Li(e,t,n){let r=e;for(;r;){if(t.has(r))return r;r=n.get(r)}}function Ni(e,t){for(let n of Array.from(e))(n===t||zi(n,t))&&e.delete(n)}function qi(e,t){if(e.path===t)return[];let n=e.children.find(i=>i.path===t||zi(t,i.path));if(!n)return[e.path];let r=[];for(let i of e.children){if(i.path===n.path){r.push(...qi(i,t));continue}r.push(i.path)}return r}function zn(e){return Array.from(new Set(e.map(t=>qu(t)).filter(Boolean)))}function qu(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function zi(e,t){return e===t||e.startsWith(`${t}/`)}var Hi={key:"settings.scope.loading"},zu=500,Oi=["card-types","sync-content","deck","scope","commands"],Bt=["basic","qa-group","cloze","cloze-all"],Hu=8,Ou=64,Wi="--ahs-settings-page-header-height",Wu="--ahs-settings-sticky-card-gap",$u=`${Ou}px`,Uu=`${Hu}px`,Qu="anki-heading-sync-settings",$i="ahs-is-hidden";function v(e,...t){e.classList.add(...t)}function Vu(e,t,n){if(n){e.classList.add(t);return}e.classList.remove(t)}var Gt=class extends G.PluginSettingTab{constructor(n){super(n.app,n);this.noteFieldMappingService=new Ne;this.qaGroupFieldMappingService=new de;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=Hi;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.flushDebouncedTextSaves(),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(n.classList.add(Qu),!this.displayInitialized){n.style.setProperty(Wi,$u),n.style.setProperty(Wu,Uu),n.empty();let i=n.createDiv();i.dataset.settingsPageHeader="true",v(i,"ahs-settings-page-header");let a=i.createDiv();a.dataset.settingsPageHeaderMask="true",v(a,"ahs-settings-page-header-mask");let o=new G.Setting(i).setName(g("settings.pluginTitle")).setHeading();v(o.settingEl,"ahs-settings-page-title-setting"),v(o.nameEl,"ahs-settings-page-title"),this.observePageHeaderHeight(i);let u=n.createDiv();u.dataset.settingsCardsContainer="true",this.initializeCards(u),this.displayInitialized=!0}for(let i of Oi)this.renderCard(i);n.scrollTop=r}markActionButton(n){n.setCta()}initializeCards(n){this.cardShells.clear();for(let r of Oi){let i=n.createDiv();i.dataset.settingsCard=r;let a=i.createEl("button");a.type="button",a.dataset.settingsCardToggle=r,v(a,"ahs-settings-card-toggle"),a.addEventListener("click",()=>{this.toggleCard(r)});let o=i.createDiv();o.dataset.settingsCardBody=r,v(o,"ahs-settings-card-body",$i),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)),Vu(r.bodyEl,$i,!i),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(Wi,`${Math.round(r)}px`)}disconnectPageHeaderResizeObserver(){this.pageHeaderResizeObserver?.disconnect(),this.pageHeaderResizeObserver=null}renderCardTypesCard(n){this.hydrateVisibleCardTypeCaches(),this.maybeStartNoteTypeCacheCheck();let r=n.createDiv();v(r,"ahs-settings-action-row");let i=new G.ButtonComponent(r).setButtonText(this.ankiConfigLoading?g("settings.cards.cardTypes.loadAnki.loading"):g("settings.cards.cardTypes.loadAnki.button")).setCta().setDisabled(this.ankiConfigLoading).onClick(()=>this.loadAnkiCardTypeConfig());i.buttonEl.dataset.cardTypesRefresh="true",r.createSpan({text:`${g("settings.cards.cardTypes.statusLabel")}${Ie(this.getCardTypeStatusMessage())}`});let a=n.createDiv();a.dataset.cardTypeList="true",v(a,"ahs-settings-card-list");for(let o of Bt)this.renderCardTypeBlock(a,o)}renderCardTypeBlock(n,r){let i=this.plugin.settings.cardTypeConfigs[r],a=n.createDiv();a.dataset.cardTypeConfig=r,v(a,"ahs-settings-card-type-block");let o=a.createDiv();v(o,"ahs-settings-card-type-header");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)});v(s,"ahs-settings-card-type-title");let c=a.createDiv();v(c,"ahs-settings-recognition-row");let d=this.createInlineControlGroup(c,g("settings.cards.cardTypes.labels.headingLevel")),l=this.createSelect(d,`card-type-heading:${r}`);l.dataset.cardTypeHeading=r,v(l,"ahs-settings-heading-select");for(let b=1;b<=6;b+=1)this.appendOption(l,String(b),`H${b}`);l.value=String(i.headingLevel),l.addEventListener("change",()=>{this.saveCardTypeConfig(r,{headingLevel:Number(l.value)})});let m=this.createInlineControlGroup(c,g("settings.cards.cardTypes.labels.extraMarker")).createEl("input");if(m.type="text",m.dataset.cardTypeMarker=r,m.placeholder=g("settings.cards.cardTypes.markerPlaceholder"),v(m,"ahs-settings-marker-input"),m.value=this.getDraftValue(`card-type-marker:${r}`,i.extraMarker),m.addEventListener("input",()=>{this.scheduleDebouncedTextSave(`card-type-marker:${r}`,m.value,async b=>{await this.saveCardTypeConfig(r,{extraMarker:b})&&this.textDraftValues.delete(`card-type-marker:${r}`)})}),r==="cloze-all"){let b=a.createEl("p",{text:g("settings.cards.cardTypes.sharedClozeMappingHint")});b.dataset.cardTypeSharedHint=r,v(b,"ahs-settings-muted-text");return}let p=a.createDiv();v(p,"ahs-settings-grid-row");let F=this.createGridControlSlot(p,g("settings.cards.cardTypes.labels.noteType")),k=this.createSelect(F,`card-type-note-type:${r}`);k.dataset.cardTypeNoteType=r,this.applyFluidEllipsis(k);for(let b of this.getSelectableNoteModels(i.noteType))this.appendOption(k,b,b);k.value=i.noteType,k.disabled=this.ankiConfigLoading,k.addEventListener("change",()=>{this.saveCardTypeConfig(r,{noteType:k.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,g("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,g("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,g("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=a.mapping?this.getQaGroupSelectedFields(a.mapping):void 0,u=this.createGridControlSlot(n,g("settings.cards.cardTypes.labels.qaGroupTitleField"));if(a.mapping){let l=this.createFieldSelect(u,`card-type-qa-group-title-field:${r}`);l.dataset.qaGroupTitleField=r,this.applyFluidEllipsis(l),this.populateFieldSelect(l,a.mapping.loadedFieldNames,a.mapping.titleField);let f=n.createDiv();f.dataset.qaGroupPairRow=r,v(f,"ahs-settings-qa-group-pair-row");let m=this.createGridControlSlot(f,g("settings.cards.cardTypes.labels.qaGroupFirstQuestionField")),p=this.createFieldSelect(m,`card-type-qa-group-first-question-field:${r}`);p.dataset.qaGroupFirstQuestionField=r,this.applyFluidEllipsis(p),this.populateFieldSelect(p,a.mapping.loadedFieldNames,o?.firstQuestionField);let F=this.createGridControlSlot(f,g("settings.cards.cardTypes.labels.qaGroupFirstAnswerField")),k=this.createFieldSelect(F,`card-type-qa-group-first-answer-field:${r}`);k.dataset.qaGroupFirstAnswerField=r,this.applyFluidEllipsis(k),this.populateFieldSelect(k,a.mapping.loadedFieldNames,o?.firstAnswerField);let b=()=>{this.saveQaGroupFieldSelection(r,{titleField:l.value||void 0,firstQuestionField:p.value||void 0,firstAnswerField:k.value||void 0})};l.addEventListener("change",b),p.addEventListener("change",b),k.addEventListener("change",b);let x=f.createSpan({text:g("settings.cards.cardTypes.qaGroup.configuredSlots",{count:a.mapping.slots.length})});x.dataset.qaGroupSlotSummary=r,v(x,"ahs-settings-nowrap-start"),this.applyFluidEllipsis(x)}else{u.createSpan({text:i.length>0?g("settings.cards.cardTypes.qaGroup.unavailable"):g("settings.cards.cardTypes.qaGroup.noModel")}).dataset.qaGroupTitleField=r;let l=n.createDiv();l.dataset.qaGroupPairRow=r,v(l,"ahs-settings-qa-group-pair-row");let f=this.createGridControlSlot(l,g("settings.cards.cardTypes.labels.qaGroupFirstQuestionField"));f.createSpan({text:i.length>0?g("settings.cards.cardTypes.qaGroup.unavailable"):g("settings.cards.cardTypes.qaGroup.noModel")}).dataset.qaGroupFirstQuestionField=r;let m=this.createGridControlSlot(l,g("settings.cards.cardTypes.labels.qaGroupFirstAnswerField"));m.createSpan({text:i.length>0?g("settings.cards.cardTypes.qaGroup.unavailable"):g("settings.cards.cardTypes.qaGroup.noModel")}).dataset.qaGroupFirstAnswerField=r;let p=l.createSpan({text:i.length>0?g("settings.cards.cardTypes.qaGroup.unavailable"):g("settings.cards.cardTypes.qaGroup.noModel")});p.dataset.qaGroupSlotSummary=r,v(p,"ahs-settings-nowrap-start"),this.applyFluidEllipsis(p)}if(a.error){let l=n.createDiv({text:Ie(a.error)});l.dataset.qaGroupError=r,v(l,"ahs-settings-grid-full");return}if(!a.mapping||a.mapping.warnings.length===0)return;let s=n.createDiv();s.dataset.qaGroupWarnings=r,v(s,"ahs-settings-grid-full","ahs-settings-warnings"),s.createEl("strong",{text:g("settings.cards.cardTypes.labels.qaGroupWarnings")});for(let l of a.mapping.warnings)s.createDiv({text:this.renderQaGroupWarning(l)}).dataset.qaGroupWarning=r;let c=s.createEl("label");v(c,"ahs-settings-inline-check");let d=c.createEl("input");d.type="checkbox",d.checked=In(a.mapping.warnings,a.mapping.acceptedWarnings),d.dataset.qaGroupWarningAccept=r,d.addEventListener("change",()=>{this.saveQaGroupWarningAcceptance(r,d.checked)}),c.createSpan({text:g("settings.cards.cardTypes.qaGroup.acceptWarnings")})}renderSyncContentCard(n){let r=this.createSyncContentSection(n,"body-range",g("settings.cards.syncContent.sections.bodyRange"));new G.Setting(r).setName(g("settings.cardAnswerCutoffMode.name")).setDesc(g("settings.cardAnswerCutoffMode.desc")).addDropdown(u=>{u.addOption("heading-block",g("settings.cardAnswerCutoffMode.options.headingBlock")),u.addOption("double-blank-lines",g("settings.cardAnswerCutoffMode.options.doubleBlankLines")),u.setValue(this.plugin.settings.cardAnswerCutoffMode).onChange(s=>{this.plugin.updateSettings({cardAnswerCutoffMode:s})})});let i=this.createSyncContentSection(n,"backlink",g("settings.cards.syncContent.sections.backlink"));new G.Setting(i).setName(g("settings.syncOptions.addObsidianBacklink.name")).setDesc(g("settings.syncOptions.addObsidianBacklink.desc")).addToggle(u=>{u.setValue(this.plugin.settings.addObsidianBacklink).onChange(s=>{this.plugin.updateSettings({addObsidianBacklink:s})})}),new G.Setting(i).setName(g("settings.syncOptions.obsidianBacklinkLabel.name")).setDesc(g("settings.syncOptions.obsidianBacklinkLabel.desc")).addText(u=>{u.setPlaceholder(g("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||Ke}),this.textDraftValues.delete("obsidian-backlink-label")})})}),new G.Setting(i).setName(g("settings.syncOptions.obsidianBacklinkPlacement.name")).setDesc(g("settings.syncOptions.obsidianBacklinkPlacement.desc")).addDropdown(u=>{u.addOption("question-last-line",g("settings.syncOptions.obsidianBacklinkPlacement.options.questionLastLine")),u.addOption("answer-first-line",g("settings.syncOptions.obsidianBacklinkPlacement.options.answerFirstLine")),u.addOption("answer-last-line",g("settings.syncOptions.obsidianBacklinkPlacement.options.answerLastLine")),u.setValue(this.plugin.settings.obsidianBacklinkPlacement).onChange(s=>{this.plugin.updateSettings({obsidianBacklinkPlacement:s})})});let a=this.createSyncContentSection(n,"tags",g("settings.cards.syncContent.sections.tags"));new G.Setting(a).setName(g("settings.syncOptions.syncObsidianTagsToAnki.name")).setDesc(g("settings.syncOptions.syncObsidianTagsToAnki.desc")).addToggle(u=>{u.setValue(this.plugin.settings.syncObsidianTagsToAnki).onChange(s=>{this.plugin.updateSettings({syncObsidianTagsToAnki:s})})}),new G.Setting(a).setName(g("settings.syncOptions.keepPureTagLinesInCardBody.name")).setDesc(g("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",g("settings.cards.syncContent.sections.clozeSpecial"));new G.Setting(o).setName(g("settings.syncOptions.highlightsToCloze.name")).setDesc(g("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();return a.dataset.syncContentSection=r,v(a,"ahs-settings-section"),this.createSectionHeading(a,"syncContentSectionTitle",r,i),a}renderScopeCard(n){if(new G.Setting(n).setName(g("settings.scope.name")).setDesc(ju(this.plugin.settings.scopeMode)).addDropdown(s=>{s.addOption("all",g("settings.scope.option.all")).addOption("include",g("settings.scope.option.include")).addOption("exclude",g("settings.scope.option.exclude")).setValue(this.plugin.settings.scopeMode).onChange(c=>{c!=="all"&&c!=="include"&&c!=="exclude"||this.updateScopeMode(c)})}),!gt(this.plugin.settings.scopeMode,this.plugin.settings.includeFolders)){let s=n.createEl("p",{text:g("settings.scope.unconfiguredWarning")});s.dataset.scopeWarning="unconfigured",v(s,"ahs-settings-warning-text")}if(this.plugin.settings.scopeMode==="all")return;let r=n.createDiv(),i=new G.ButtonComponent(r).setButtonText(g("settings.cards.scope.refreshFolders")).setCta().setDisabled(!!this.folderTreeLoadPromise).onClick(()=>{this.refreshFolderTree()});if(i.buttonEl.dataset.scopeRefreshFolders="true",this.ensureFolderTreeLoaded(),n.createEl("p",{text:Zu(this.plugin.settings.scopeMode)}),this.folderTreeLoadPromise||this.folderTree.length===0){n.createEl("p",{text:Ie(this.folderTreeStatus)});return}this.expandSelectedFolderAncestorsIfNeeded(this.plugin.settings.scopeMode);let a=this.getSelectedFoldersForScopeMode(this.plugin.settings.scopeMode),o=Pi(this.folderTree,a),u=n.createDiv();u.dataset.scopeTree="true",v(u,"ahs-settings-folder-tree");for(let s of o)this.renderFolderNode(u,s,this.plugin.settings.scopeMode,0)}renderDeckCard(n){let r=this.createDeckSection(n,"folder-mapping",g("settings.cards.deck.sections.folderMapping"));new G.Setting(r).setName(g("settings.deck.folderDeckMode.name")).setDesc(g("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",g("settings.cards.deck.sections.fileDeck"));new G.Setting(i).setName(g("settings.deck.fileDeckEnabled.name")).setDesc(g("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(g("settings.deck.marker.name")).setDesc(g("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(g("settings.deck.template.name")).setDesc(g("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(g("settings.deck.insertLocation.name")).setDesc(g("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(g("settings.deck.insertTemplate.name")).setDesc(g("settings.deck.insertTemplate.desc")).addButton(o=>{this.markActionButton(o),o.setButtonText(g("settings.deck.insertTemplate.button")).onClick(()=>{this.plugin.insertDeckTemplateToCurrentFile()})}));let a=this.createDeckSection(n,"default-deck",g("settings.cards.deck.sections.defaultDeck"));new G.Setting(a).setName(g("settings.deck.defaultDeck.name")).setDesc(g("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,g("settings.deck.fallbackDesc"),"fallback"),this.createDeckPriorityFooter(n)}renderDeckExampleBlock(n){let r=n.createDiv();r.dataset.deckExampleBlock="true",v(r,"ahs-settings-deck-example-block");let i=r.createEl("strong",{text:g("settings.deck.examplesTitle")});v(i,"ahs-settings-small-title");for(let a of[g("settings.deck.folderExample"),g("settings.deck.folderAndFileExample")]){let o=r.createDiv({text:a});o.dataset.deckExampleRow="true",v(o,"ahs-settings-helper-text")}}createDeckHelperText(n,r,i){let a=n.createDiv({text:r});return a.dataset.deckHelperText=i,v(a,"ahs-settings-helper-text"),a}createDeckPriorityFooter(n){let r=this.createDeckHelperText(n,g("settings.deck.priorityDesc"),"priority");r.dataset.deckPriorityFooter="true",v(r,"ahs-settings-helper-text-priority")}createDeckSection(n,r,i){let a=n.createDiv();return a.dataset.deckSection=r,v(a,"ahs-settings-section"),this.createSectionHeading(a,"deckSectionTitle",r,i),a}renderCommandsCard(n){n.createEl("p",{text:g("settings.cards.commands.desc")});let r=n.createEl("ul");for(let[i,a]of[[g("commands.syncCurrentFileToAnki"),g("settings.cards.commands.items.syncCurrentFile")],[g("commands.syncVaultToAnki"),g("settings.cards.commands.items.syncVault")],[g("commands.clearCurrentFileSyncedCards"),g("settings.cards.commands.items.clearCurrentFile")],[g("commands.cleanupEmptyDecks"),g("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{pe(Ce({...this.plugin.settings,cardTypeConfigs:i}))}catch(a){return this.cardTypeStatusOverride=ye(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=B("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=B(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=Ui(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=ye(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=Ui(await this.plugin.listNoteModels());if(n!==this.noteTypeCacheCheckToken)return;this.detectedAnkiNoteTypeCache=r,this.noteTypeCacheCheckStatus=Ku(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 Bt)this.hydrateCardTypeCache(r,n)}hydrateCardTypeCache(n,r){let i=this.getRuntimeCardType(n),a=this.plugin.settings.cardTypeConfigs[n].noteType,o=B(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 Bt)r==="qa-group"||r==="cloze-all"||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=B(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,!Hn(this.plugin.settings.noteFieldMappings[u],c)&&await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[u]:c}})}createCachedModelDetails(n,r){return{fieldNames:[...r]}}countConfiguredCardTypes(n){return Bt.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=B(n,r),u=this.plugin.settings.noteFieldMappings[o]??this.draftMappings[o];if(n==="qa-group"){if(H(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=B(r,i),o=this.draftMappings[a]??this.plugin.settings.noteFieldMappings[a];if(o)return H(o)?this.cloneQaGroupFieldMapping(o):{...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(),H(c)?c.acceptedWarnings:void 0,H(c)?c.titleField:void 0);return this.draftMappings[a]=d,this.cloneQaGroupFieldMapping(d)}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=B(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(),H(o)?o.acceptedWarnings:void 0,H(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,derivation: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||!H(i))return;let a=this.getRuntimeCardType(n),o=B(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 saveQaGroupFieldSelection(n,r){let i=this.plugin.settings.cardTypeConfigs[n].noteType.trim();if(i.length===0)return;let a=B("qa-group",i),o=this.getCurrentMappingForConfig(n),u=o&&H(o)?o.loadedFieldNames:this.loadedModelDetails[a]?.fieldNames??[],s=o&&H(o)?o.loadedAt:Date.now(),c=this.createQaGroupSelectionDraft(i,u,s,r);this.draftMappings[a]=c;try{let d=this.qaGroupFieldMappingService.createMappingFromSelection(i,u,r,s);this.cardTypeStatusOverride=null,this.draftMappings[a]=d,await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[a]:d}})}catch{this.cardTypeStatusOverride=null,this.renderCard("card-types");return}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=B("qa-group",i),u=this.plugin.settings.noteFieldMappings[o]??this.draftMappings[o];if(H(u)){let s=this.refreshSavedQaGroupMapping(u,a.fieldNames,a.loadedAt);this.draftMappings[o]=s,Hn(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,Hn(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=B("qa-group",r),a=this.draftMappings[i]??this.plugin.settings.noteFieldMappings[i];if(a&&H(a)){if(a.derivation?.mode==="first-pair"){let u=this.getQaGroupSelectedFields(a);try{return{mapping:this.qaGroupFieldMappingService.createMappingFromSelection(r,a.loadedFieldNames,u,a.loadedAt)}}catch(s){return{mapping:this.cloneQaGroupFieldMapping(a),error:ye(s,"settings.cards.cardTypes.failedSave")}}}return{mapping:this.cloneQaGroupFieldMapping(a)}}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(),H(u)?u.acceptedWarnings:void 0,H(u)?u.titleField:void 0)}}catch(u){return{error:ye(u,"settings.cards.cardTypes.failedSave")}}}refreshSavedQaGroupMapping(n,r,i){if(n.derivation?.mode==="first-pair")try{return this.qaGroupFieldMappingService.createMappingFromSelection(n.modelName,r,this.getQaGroupSelectedFields(n),i)}catch{return{...this.cloneQaGroupFieldMapping(n),loadedFieldNames:[...r],loadedAt:i}}return{...n,loadedFieldNames:[...r],slots:n.slots.map(a=>({...a})),warnings:[...n.warnings],acceptedWarnings:n.acceptedWarnings?[...n.acceptedWarnings]:void 0,derivation:n.derivation?{...n.derivation}:void 0,loadedAt:i}}cloneQaGroupFieldMapping(n){return{...n,derivation:n.derivation?{...n.derivation}:void 0,loadedFieldNames:[...n.loadedFieldNames],slots:n.slots.map(r=>({...r})),warnings:[...n.warnings],acceptedWarnings:n.acceptedWarnings?[...n.acceptedWarnings]:void 0}}getQaGroupSelectedFields(n){return{titleField:n.titleField,firstQuestionField:n.derivation?.firstQuestionField??n.slots[0]?.questionField,firstAnswerField:n.derivation?.firstAnswerField??n.slots[0]?.answerField}}createQaGroupSelectionDraft(n,r,i,a){let o=a.titleField?.trim()||void 0,u=a.firstQuestionField?.trim()||void 0,s=a.firstAnswerField?.trim()||void 0;return{cardType:"qa-group",modelName:n,titleField:o,slots:[],warnings:[],acceptedWarnings:void 0,derivation:u||s?{mode:"first-pair",firstQuestionField:u,firstAnswerField:s}:void 0,loadedFieldNames:[...r],loadedAt:i}}renderQaGroupWarning(n){let r=ci(n);if(!r)return n;let i=String(r.index).padStart(2,"0");return r.kind==="missing-answer"?g("settings.cards.cardTypes.qaGroup.warning.missingAnswer",{index:i,questionField:r.questionField,answerField:r.answerField}):g("settings.cards.cardTypes.qaGroup.warning.missingQuestion",{index:i,questionField:r.questionField,answerField:r.answerField})}getRuntimeCardType(n){return n==="qa-group"?"qa-group":n==="cloze"||n==="cloze-all"?"cloze":"basic"}ensureFolderTreeLoaded(n=!1){n&&(this.hasLoadedFolderTree=!1,this.folderTree=[]),!(this.hasLoadedFolderTree||this.folderTreeLoadPromise)&&(this.folderTreeStatus=Hi,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=ye(r,"settings.scope.failedLoad")}).finally(()=>{this.hasLoadedFolderTree=!0,this.folderTreeLoadPromise=null,this.renderCard("scope")}))}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=Ri(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,v(o,"ahs-settings-folder-row"),o.style.setProperty("--ahs-folder-depth-indent",`${a*18}px`);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":"",v(c,"ahs-settings-folder-toggle"),u?(v(c,"ahs-settings-folder-toggle-button"),c.setAttr("aria-label",s?g("settings.scope.collapseFolder",{name:r.name}):g("settings.scope.expandFolder",{name:r.name})),c.setAttr("title",s?g("settings.scope.collapseFolder",{name:r.name}):g("settings.scope.expandFolder",{name:r.name})),c.addEventListener("click",()=>{this.expandedFolderPaths.has(r.path)?this.expandedFolderPaths.delete(r.path):this.expandedFolderPaths.add(r.path),this.renderCard("scope")})):v(c,"ahs-settings-folder-toggle-spacer");let d=o.createEl("input");d.type="checkbox",d.checked=r.checked,d.indeterminate=r.indeterminate,d.dataset.folderPath=r.path,v(d,"ahs-settings-folder-checkbox"),d.addEventListener("change",()=>{this.updateFolderSelection(i,r.path,d.checked)});let l=o.createSpan({text:r.name});if(l.dataset.folderPathLabel=r.path,v(l,"ahs-settings-folder-label"),this.applyFluidEllipsis(l),!u||!s)return;let f=n.createDiv();f.dataset.folderChildren=r.path,v(f,"ahs-settings-folder-children");for(let m of r.children)this.renderFolderNode(f,m,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 Yu(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");v(i,"ahs-settings-inline-control-group");let a=i.createSpan({text:r});return v(a,"ahs-settings-inline-control-label"),i}createGridControlSlot(n,r){let i=n.createEl("label");v(i,"ahs-settings-grid-control-slot");let a=i.createSpan({text:r});v(a,"ahs-settings-grid-control-label");let o=i.createDiv();return v(o,"ahs-settings-grid-control-content"),o}applyFluidEllipsis(n){let r=(n.tagName||n.tag||"").toLowerCase(),i=r==="select"||r==="input";v(n,"ahs-settings-fluid-ellipsis"),i&&v(n,"ahs-settings-fluid-control")}createSectionHeading(n,r,i,a){let o=n.createDiv(),u=new G.Setting(o).setName(a).setHeading();u.settingEl.dataset[r]=i,u.nameEl.dataset[r]=i,v(u.settingEl,"ahs-settings-section-heading")}scheduleDebouncedTextSave(n,r,i){let a=window.activeWindow;this.textDraftValues.set(n,r);let o=this.debouncedTextSaves.get(n);o&&a.clearTimeout(o.timer);let u=a.setTimeout(()=>{this.flushDebouncedTextSave(n)},zu);this.debouncedTextSaves.set(n,{timer:u,saveAction:i})}async flushDebouncedTextSave(n){let r=window.activeWindow,i=this.debouncedTextSaves.get(n);i&&(r.clearTimeout(i.timer),this.debouncedTextSaves.delete(n),await i.saveAction(this.textDraftValues.get(n)??""))}async flushDebouncedTextSaves(){let n=[...this.debouncedTextSaves.keys()];await Promise.allSettled(n.map(r=>this.flushDebouncedTextSave(r)))}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?g("settings.mapping.selectFieldPlaceholder"):g("settings.cards.cardTypes.fieldsUnavailable"));for(let a of r)this.appendOption(n,a,a);n.value=i??""}populateFileDeckInsertLocationDropdown(n,r){n.addOption("body",g("settings.deck.insertLocation.options.body")),n.addOption("yaml",g("settings.deck.insertLocation.options.yaml")),n.setValue(r)}populateFolderDeckModeDropdown(n,r){n.addOption("off",g("settings.deck.folderDeckMode.options.off")),n.addOption("folder",g("settings.deck.folderDeckMode.options.folder")),n.addOption("folder-and-file",g("settings.deck.folderDeckMode.options.folderAndFile")),n.setValue(r)}getCardTitle(n){return n==="card-types"?g("settings.cards.cardTypes.title"):n==="sync-content"?g("settings.cards.syncContent.title"):n==="scope"?g("settings.cards.scope.title"):n==="deck"?g("settings.cards.deck.title"):g("settings.cards.commands.title")}getCardTypeLabel(n){return n==="basic"?g("settings.cards.cardTypes.rows.basic"):n==="qa-group"?g("settings.cards.cardTypes.rows.qaGroup"):n==="cloze"?g("settings.cards.cardTypes.rows.cloze"):n==="cloze-all"?g("settings.cards.cardTypes.rows.clozeAll"):g("settings.cards.cardTypes.rows.qaGroup")}};function ju(e){return e==="include"?g("settings.scope.summary.include"):e==="exclude"?g("settings.scope.summary.exclude"):g("settings.scope.summary.all")}function Hn(e,t){return JSON.stringify(e)===JSON.stringify(t)}function Ui(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 Ku(e,t){return e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function Zu(e){return e==="include"?g("settings.scope.treeDescription.include"):g("settings.scope.treeDescription.exclude")}function Yu(e){let t=e.split("/").filter(r=>r.length>0),n=[];for(let r=1;r0?e.message.trim():String(e)}var zt=class{async runCollectBatches(t,n,r,i){if(t.length===0)return[];let a=es(t,n),o=[],u=0;return await Promise.all(Array.from({length:Math.min(r,a.length)},async()=>{for(;u(await i(a),[]))}};function es(e,t){let n=[];for(let r=0;ri.has(a))}function et(e,t){let n=Ht(e),r=Ht(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 Ot=class{constructor(t,n=new Ne,r=new zt){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,m=0,p=Array.from(new Set([...t.toRebuild,...t.toUpdate,...t.toVerifyDeck,...t.toRewriteMarker,...t.toChangeDeck].flatMap(y=>y.noteId?[y.noteId]:[]))),F=await this.batchScheduler.runCollectBatches(p,100,1,y=>this.ankiGateway.getNoteSummaries(y)),k=new Map(F.map(y=>[y.noteId,y])),b=[],x=[],C=[],h=[],M=[],T=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.toRebuild){if(y.noteId&&k.has(y.noteId)){x.push({plannedCard:y,renderedCard:await this.requireRenderedCard(y,n,r)});continue}b.push(await this.requireRenderedCard(y,n,r)),s.set(y.card.syncKey,y)}for(let y of t.toUpdate){if(y.noteId&&k.has(y.noteId)){let w=await this.requireRenderedCard(y,n,r),_=k.get(y.noteId);_&&_.modelName!==w.noteModel?h.push({plannedCard:y,renderedCard:w,summary:_}):C.push({plannedCard:y,renderedCard:w});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&&k.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 w=k.get(y.noteId);w&&ts(w,y.deck,T.has(y.card.syncKey))&&(M.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.renderedCard.deck),...M.map(y=>y.deck)])),50,1,y=>this.ankiGateway.ensureDecks(y));let D=await this.uploadMedia([...b,...x.map(y=>y.renderedCard),...C.map(y=>y.renderedCard),...h.map(y=>y.renderedCard)]),L=await this.batchScheduler.runCollectBatches(b,50,1,async y=>this.ankiGateway.addNotes(await Promise.all(y.map(async w=>({deckName:w.deck,modelName:w.noteModel,fields:await this.mapFields(w,i,a),tags:w.card.tagsHint})))));for(let y=0;y{await this.ankiGateway.updateNotes(await Promise.all(y.map(async({plannedCard:w,renderedCard:_})=>({noteId:w.noteId??0,fields:await this.mapFields(_,i,a)}))))}),await this.batchScheduler.runVoidBatches(h,25,1,async y=>{for(let{plannedCard:w,renderedCard:_,summary:I}of y){let P=await this.mapFields(_,i,a);try{await this.ankiGateway.updateNoteModel({noteId:w.noteId??0,modelName:_.noteModel,fields:P})}catch(q){throw qt({noteId:w.noteId??0,fromModel:I.modelName,toModel:_.noteModel,error:q,location:`${w.card.filePath}:${w.card.blockStartLine}`})}}});let A=[...C,...h].flatMap(({plannedCard:y})=>{if(!y.noteId)return[];let w=k.get(y.noteId);if(!w)return[];let _=et(y.card.tagsHint,w.tags);return _.addTags.length===0&&_.removeTags.length===0?[]:[{noteId:y.noteId,addTags:_.addTags,removeTags:_.removeTags}]});await this.batchScheduler.runVoidBatches(A,50,1,y=>this.ankiGateway.syncNoteTags(y)),l+=C.length+h.length,f=h.length;for(let{plannedCard:y}of[...C,...h])y.noteId&&(u.add(y.card.syncKey),o.set(y.card.syncKey,y.noteId));let R=new Map;for(let y of M){let w=y.noteId;if(!w)continue;let _=k.get(w);if(!_||_.cardIds.length===0)continue;let I=R.get(y.deck)??new Set;for(let P of _.cardIds)I.add(P);R.set(y.deck,I)}await this.batchScheduler.runVoidBatches(Array.from(R.entries()).map(([y,w])=>({deckName:y,cardIds:Array.from(w)})),25,1,y=>this.ankiGateway.changeDecks(y)),m=M.length;for(let y of M)u.add(y.card.syncKey);return{created:c,rebuilt:d,updated:l,migratedNoteTypes:f,migratedDecks:m,uploadedMedia:D,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 ji(e){return e instanceof Error?e:new Error(String(e))}function ts(e,t,n){let r=e.deckNames?.filter(i=>i.length>0)??[];return r.length===0?n:r.some(i=>i!==t)}var Pe=class{filter(t,n,r,i){let a=Wt(r),o=Wt(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=rs(t),o=Wt(r),u=Wt(i);return n==="include"?o.some(s=>Ki(a,s)):n==="exclude"?!u.some(s=>Ki(a,s)):!0}};function Wt(e){return e.map(ns).filter(Boolean)}function ns(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function rs(e){return e.trim().replace(/\\/g,"/").replace(/^\/+/,"")}function Ki(e,t){return e===t||e.startsWith(`${t}/`)}function $t(e,t,n){return`${e}\0group\0${t}\0${n}`}function Fe(e,t){return`${e}#${t}`}function Qt(e){let t=is(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:us(e.lines.slice(n.index+1)),contentEndLine:Ut(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"?as(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:Ut(u,e.startLine,e.fallbackLine),markerLine:o?e.startLine+o.index:void 0,markerIndent:o?.indent,markerState:o?"present-invalid":"missing"}}let i=os(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:Ut(o,e.startLine,e.fallbackLine),markerLine:e.startLine+a.index,markerIndent:a.indent,markerState:"present-invalid"}}return{contentLines:e.lines,trailingLines:[],contentEndLine:Ut(e.lines,e.startLine,e.fallbackLine),markerState:"missing"}}function is(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 Ut(e,t,n){for(let r=e.length-1;r>=0;r-=1)if(e[r].trim())return t+r;return n}function os(e){for(let t=e.length-1;t>=0;t-=1)if(e[t].trim())return t}function us(e){let t=0;for(;t1&&a.push({filePath:r,code:"deck_multiple_body_declarations",params:{marker:i}}),{bodyDeck:o[0],warnings:a}}};function cs(e){if(e[0]?.trim()==="---"){for(let t=1;t!ys(s))),u=[`qa-group:${n}`,...a.map(s=>`${s.title} +`,o=e.split(/\r?\n/),u=[],s=0,d=0;for(let c=0;c0||r.trackedGroups.length>0}async execute(t){let n=await this.pluginStateRepository.load(),r=vi(n,t);if(r.trackedCards.length===0&&r.trackedGroups.length===0)return lu();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=cu(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 vi(e,t){let n=new Set,r=new Set,i=e.groupBlocks??{};for(let u of e.files[t]?.noteIds??[]){let s=z(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(z(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 cu(e,t,n){let r={...e.cards},i={...e.groupBlocks??{}};for(let o of n.trackedCards)delete r[z(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 lu(){return{trackedCards:0,trackedGroups:0,deletedNotes:0,removedMarkers:0,removedCardMarkers:0,removedGroupMarkers:0,deletedLocalRecords:0,conflictFiles:[],failureFiles:[]}}var Ft=class{constructor(t){this.manualSyncService=t}async execute(t,n){return this.manualSyncService.syncFile(t,n)}};var Mt=class{constructor(t){this.manualSyncService=t}async execute(t){return this.manualSyncService.syncVault(t)}};var Ti=require("obsidian"),wt=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=pu(r[o]);return u&&(i[a]=u),i},{})}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,d])=>[s,d?.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)}}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:fu(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(gu("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,Ti.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 pu(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 fu(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 gu(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}: ${mu(n)}`}function mu(e){return e instanceof Error&&e.message.trim().length>0?e.message.trim():String(e)}var vt=class{constructor(t){this.plugin=t}async load(){let t=await this.plugin.loadData();return t!==null&&typeof t=="object"?t:null}async save(t){await this.plugin.saveData(t)}};var ie=require("obsidian");function Q(e){let t=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}function Tt(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 hu=new Set(["png","jpg","jpeg","gif","bmp","svg","webp","tiff"]),ku=new Set(["wav","m4a","flac","mp3","wma","aac","webm","ogg"]),At=class{constructor(t){this.app=t}listFolderTree(){return Promise.resolve(this.app.vault.getRoot().children.filter(t=>t instanceof ie.TFolder).map(t=>this.toFolderTreeNode(t)))}listMarkdownFileRefs(){return Promise.resolve(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 ie.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 ie.TFile)||i.extension.toLowerCase()!=="md")throw new kt(t);await this.app.vault.process(i,a=>{if(a!==n)throw new fe(t);return r})}resolveWikiLink(t,n){let{alias:r,linkPath:i}=Di(t),o=this.app.metadataCache.getFirstLinkpathDest(Dt(i),n)?.path??Dt(i),u=r||bu(i);return{url:this.createObsidianUrl(i.includes("#")?`${o}${i.slice(i.indexOf("#"))}`:o),displayText:u}}resolveEmbed(t,n){let{alias:r,linkPath:i}=Di(t),a=this.app.metadataCache.getFirstLinkpathDest(Dt(i),n);if(!(a instanceof ie.TFile))return null;let o=a.extension.toLowerCase(),u=hu.has(o)?"image":ku.has(o)?"audio":null;if(!u)return null;let s=yu(this.app,a.path),d=`${Q(a.path)}-${a.name}`;return{kind:u,fileName:d,absolutePath:s,altText:r||a.name}}createBacklink(t){return this.createObsidianUrl(`${t.filePath}#${xu(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:Cu(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 ie.TFolder).map(n=>this.toFolderTreeNode(n))}}};function Di(e){let[t,n]=e.split("|",2).map(r=>r.trim());return{linkPath:t,alias:n||void 0}}function Dt(e){return e.split("#",1)[0]}function bu(e){let t=Dt(e);return(t.split("/").pop()??t).replace(/\.[^.]+$/,"")||e}function yu(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 xu(e){return e.replace(/(?:\s+#\S+)+$/g,t=>t.replace(/(^|\s)#(\S+)/g,"$1$2"))}function Cu(e){return e?Tt((0,ie.getAllTags)(e)):[]}var Et=class{constructor(t){this.pluginDataStore=t}async load(){let t=await this.pluginDataStore.load()??{},n=hi(t.settings);return pe(n),n}async save(t){let n=Ce(t);pe(n);let r=await this.pluginDataStore.load()??{};await this.pluginDataStore.save({...r,settings:n})}};function Se(e,t){if(e==="cloze")return t==="all"?"all":"sequential"}function _t(e,t,n){return`${e}\0${t}\0${n}`}var Lt=class{constructor(t){this.pluginDataStore=t}async load(){let t=await this.pluginDataStore.load()??{};return Su(t.pluginState)}async save(t){let n=await this.pluginDataStore.load()??{};await this.pluginDataStore.save({...n,pluginState:t})}};function Su(e){if(!e)return wi();let t=_u(e.cards),n=Lu(e.files),r=Iu(e.groupBlocks),i={};for(let u of Object.values(t)){let s=Xe(u.noteId);if(s===void 0)continue;let d=Fu(u,s);if(!d)continue;let c=z(s),l=i[c];(!l||l.lastSyncedAt<=d.lastSyncedAt)&&(i[c]=d)}let a={};for(let[u,s]of Object.entries(n))a[u]={filePath:u,fileHash:typeof s.fileHash=="string"?s.fileHash:"",fileStamp:typeof s.fileStamp=="string"?s.fileStamp:"",deckRulesFingerprint:typeof s.deckRulesFingerprint=="string"?s.deckRulesFingerprint:void 0,lastIndexedAt:typeof s.lastIndexedAt=="number"?s.lastIndexedAt:0,noteIds:Tu(s,t,i),groupIds:Eu(s,r)};let o={};for(let[u,s]of Object.entries(r)){let d=vu(s,u);if(!d)continue;let c=o[u];(!c||c.lastSyncedAt<=d.lastSyncedAt)&&(o[u]=d)}return{files:a,cards:i,groupBlocks:o,pendingWriteBack:Du(e.pendingWriteBack)}}function Fu(e,t){let n=Mu(e.cardType);return n?{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:n,clozeMode:Se(n,wu(e.clozeMode)),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(r=>typeof r=="string"):[],lastSyncedAt:typeof e.lastSyncedAt=="number"?e.lastSyncedAt:0,orphan:!!e.orphan}:null}function Mu(e){if(e==="basic"||e==="cloze")return e}function wu(e){if(e==="sequential"||e==="all")return e}function vu(e,t){let n=Xe(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 Tu(e,t,n){let r=new Set;if(Array.isArray(e.noteIds))for(let i of e.noteIds){let a=Xe(i);a!==void 0&&n[z(a)]&&r.add(a)}if(Array.isArray(e.cardIds))for(let i of e.cardIds){let a=Xe(t[i]?.noteId);a!==void 0&&n[z(a)]&&r.add(a)}return Array.from(r)}function Du(e){return Array.isArray(e)?e.flatMap(t=>{let n=Au(t);return n?[n]:[]}):[]}function Au(e){let t=Ye(e.filePath),n=Nu(e.blockStartLine),r=Ye(e.expectedFileHash),i=Ye(e.targetMarker),a=Ye(e.rawBlockHash),o=Xe(e.targetNoteId);if(!t||!n||!r||!i||!a||!o)return null;let u=Pu(e.markerKind);if(e.markerKind!==void 0&&!u)return null;let s=e.targetGroupId===void 0?void 0:Ye(e.targetGroupId);return e.targetGroupId!==void 0&&!s?null:{filePath:t,blockStartLine:n,expectedFileHash:r,targetMarker:i,rawBlockHash:a,targetNoteId:o,markerKind:u,targetGroupId:s}}function Eu(e,t){return Array.isArray(e.groupIds)?e.groupIds.filter(n=>typeof n=="string"&&!!t[n]):[]}function _u(e){let t={},n=e??{};for(let r in n){let i=n[r];t[r]=i}return t}function Lu(e){let t={},n=e??{};for(let r in n){let i=n[r];t[r]=i}return t}function Iu(e){let t={},n=e??{};for(let r in n){let i=n[r];t[r]=i}return t}function Xe(e){return typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0}function Nu(e){return typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0}function Ye(e){return typeof e=="string"&&e.trim().length>0?e:void 0}function Pu(e){return e==="card-id"||e==="group-gi"?e:void 0}function Ai(e){e.addCommand({id:"sync-current-file-to-anki",name:g("commands.syncCurrentFileToAnki"),callback:()=>{e.runSyncCurrentFile()}}),e.addCommand({id:"sync-vault-to-anki",name:g("commands.syncVaultToAnki"),callback:()=>{e.runSyncVault()}}),e.addCommand({id:"clear-current-file-synced-cards",name:g("commands.clearCurrentFileSyncedCards"),callback:()=>{e.runClearCurrentFileSyncedCards()}}),e.addCommand({id:"cleanup-empty-decks",name:g("commands.cleanupEmptyDecks"),callback:()=>{e.runCleanupEmptyDecks()}})}var Je=require("obsidian");var It=class extends Je.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:g("modal.emptyDeck.title")}),n.createEl("p",{text:g("modal.emptyDeck.description")});for(let i of this.candidateDeckNames)new Je.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 Je.Setting(n).addButton(i=>{i.setButtonText(g("modal.emptyDeck.selectAll")).onClick(()=>{this.selectAllDecks()})}).addButton(i=>{i.setButtonText(g("modal.emptyDeck.clearAll")).onClick(()=>{this.clearSelectedDecks()})}).addButton(i=>{i.setButtonText(g("modal.emptyDeck.invert")).onClick(()=>{this.invertSelectedDecks()})}).addButton(i=>{i.setButtonText(g("modal.emptyDeck.cancel")).onClick(()=>{this.finish(null)})}).addButton(i=>{this.deleteButton=i,i.setButtonText(g("modal.emptyDeck.deleteSelected")).setCta().onClick(()=>{this.finish(Array.from(this.selectedDeckNames))})});this.selectionCountEl=r.settingEl.createSpan({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 g("modal.emptyDeck.selectionCount",{selected:this.selectedDeckNames.size,total:this.candidateDeckNames.length})}};var zn=require("obsidian");var Nt=class{info(t){new zn.Notice(t,5e3)}error(t){new zn.Notice(t,8e3)}showSyncSummary(t,n){let r=se(),o=[g(t==="currentFile"?"notice.summary.currentFileSync":"notice.summary.vaultSync",{scannedFiles:n.scannedFiles,scannedCards:n.scannedCards,created:n.created,rebuilt:n.rebuilt,updated:n.updated,migratedNoteTypes:n.migratedNoteTypes,migratedDecks:n.migratedDecks,orphaned:n.orphaned,uploadedMedia:n.uploadedMedia,skippedUnchangedCards:n.skippedUnchangedCards})];n.markerWriteConflictFiles.length>0&&o.push(g("notice.summary.markerWriteConflicts",{files:de(r,n.markerWriteConflictFiles)})),n.warnings.length>0&&o.push(g("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))}showClearCurrentFileSummary(t){let n=se(),r=[g("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(g("notice.summary.markerRemovalConflicts",{files:de(n,t.conflictFiles)})),t.failureFiles.length>0&&r.push(g("notice.summary.failures",{items:oi(t.failureFiles)})),this.info(r.join(" "))}showCleanupEmptyDecksSummary(t){let n=se(),r=[g("notice.summary.cleanupEmptyDecks",{candidateCount:t.candidateCount,selectedCount:t.selectedCount,deletedCount:t.deletedCount,skippedCount:t.skippedDeckNames.length})];t.skippedDeckNames.length>0&&r.push(g("notice.summary.skippedDecks",{decks:de(n,t.skippedDeckNames)})),this.info(r.join(" "))}renderDeckWarning(t){return g(Ru(t.code),t.params)}};function Ru(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 Ei(e){return e==="cloze"}function _i(e){return e==="basic"}var Ne=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),_i(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 Bu(t)?{cardType:t,modelName:n,loadedFieldNames:[...r],titleField:Pt(r,["Front","Title"])??r[0],bodyField:Pt(r,["Back","Body","Answer"])??r.find(a=>a!==(Pt(r,["Front","Title"])??r[0])),loadedAt:i}:{cardType:t,modelName:n,loadedFieldNames:[...r],mainField:Pt(r,["Text","Body","Content"])??r[0],loadedAt:i}}validateMapping(t,n){if(!Dn(t)&&!ti(t))throw new Error("QaGroupFieldMappingService validates qa-group mappings.");let r=new Set(n.fieldNames);if(Dn(t)){if(!t.titleField||!t.bodyField)throw new S(Li(t.cardType),{modelName:t.modelName});if(t.titleField===t.bodyField)throw new S(qu(),{modelName:t.modelName});let i=[t.titleField,t.bodyField].filter(a=>!r.has(a));if(i.length>0)throw new S("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:i.map(a=>`"${a}"`)});return}if(!t.mainField)throw new S("errors.noteFieldMapping.incompleteSavedMapping.cloze",{modelName:t.modelName});if(!r.has(t.mainField))throw new S("errors.noteFieldMapping.stale",{modelName:t.modelName,fields:[`"${t.mainField}"`]})}mapBasic(t,n){let r=n.titleField,i=n.bodyField;if(!r||!i)throw new S(Li(t.type),{modelName:t.noteModel});return{[r]:t.renderedFields.title,[i]:t.renderedFields.body}}mapCloze(t,n){if(!n.mainField)throw new S("errors.noteFieldMapping.incompleteSavedMapping.cloze",{modelName:t.noteModel});return{[n.mainField]:`${t.renderedFields.title}

${t.renderedFields.body}`}}getRequiredMapping(t,n){let r=n[B(t.type,t.noteModel)];if(!r)throw new S(Gu(t.type),{modelName:t.noteModel});return r}};function Bu(e){return e==="basic"}function Gu(e){return e==="cloze"?"errors.noteFieldMapping.missingSavedMapping.cloze":"errors.noteFieldMapping.missingSavedMapping.basic"}function Li(e){return e==="cloze"?"errors.noteFieldMapping.incompleteSavedMapping.cloze":"errors.noteFieldMapping.incompleteSavedMapping.basic"}function qu(){return"errors.noteFieldMapping.titleBodyMustDiffer.basic"}function Pt(e,t){return e.find(n=>t.some(r=>r.toLowerCase()===n.toLowerCase()))}function Pi(e,t){let n=new Set(Hn(t));return e.map(r=>Bi(r,n,!1))}function Ri(e,t,n,r){let i=zu(e),a=new Set(Hn(t).filter(u=>i.nodeByPath.has(u)));if(!i.nodeByPath.has(n))return Rt(e,Array.from(a));if(r)return Ii(n,a,i.parentByPath)||(Ni(a,n),a.add(n)),Rt(e,Array.from(a));let o=Ii(n,a,i.parentByPath);if(o&&(a.delete(o),o!==n)){let u=i.nodeByPath.get(o);if(u)for(let s of qi(u,n))a.add(s)}return Ni(a,n),Rt(e,Array.from(a))}function Rt(e,t){let n=new Set(Hn(t));return e.flatMap(r=>Gi(r,n).paths)}function Bi(e,t,n){let r=n||t.has(e.path),i=e.children.map(o=>Bi(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 Gi(e,t){return t.has(e.path)?{paths:[e.path]}:e.children.length===0?{paths:[]}:{paths:e.children.map(r=>Gi(r,t)).flatMap(r=>r.paths)}}function zu(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 Ii(e,t,n){let r=e;for(;r;){if(t.has(r))return r;r=n.get(r)}}function Ni(e,t){for(let n of Array.from(e))(n===t||zi(n,t))&&e.delete(n)}function qi(e,t){if(e.path===t)return[];let n=e.children.find(i=>i.path===t||zi(t,i.path));if(!n)return[e.path];let r=[];for(let i of e.children){if(i.path===n.path){r.push(...qi(i,t));continue}r.push(i.path)}return r}function Hn(e){return Array.from(new Set(e.map(t=>Hu(t)).filter(Boolean)))}function Hu(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function zi(e,t){return e===t||e.startsWith(`${t}/`)}var Hi={key:"settings.scope.loading"},Ou=500,Oi=["card-types","sync-content","deck","scope","commands"],Bt=["basic","qa-group","cloze","cloze-all"],Wu=8,$u=64,Wi="--ahs-settings-page-header-height",Uu="--ahs-settings-sticky-card-gap",Qu=`${$u}px`,Vu=`${Wu}px`,ju="anki-heading-sync-settings",$i="ahs-is-hidden";function v(e,...t){e.classList.add(...t)}function Ku(e,t,n){if(n){e.classList.add(t);return}e.classList.remove(t)}var Gt=class extends G.PluginSettingTab{constructor(n){super(n.app,n);this.noteFieldMappingService=new Ne;this.qaGroupFieldMappingService=new ce;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=Hi;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.flushDebouncedTextSaves(),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(n.classList.add(ju),!this.displayInitialized){n.style.setProperty(Wi,Qu),n.style.setProperty(Uu,Vu),n.empty();let i=n.createDiv();i.dataset.settingsPageHeader="true",v(i,"ahs-settings-page-header");let a=i.createDiv();a.dataset.settingsPageHeaderMask="true",v(a,"ahs-settings-page-header-mask");let o=new G.Setting(i).setName(g("settings.pluginTitle")).setHeading();v(o.settingEl,"ahs-settings-page-title-setting"),v(o.nameEl,"ahs-settings-page-title"),this.observePageHeaderHeight(i);let u=n.createDiv();u.dataset.settingsCardsContainer="true",this.initializeCards(u),this.displayInitialized=!0}for(let i of Oi)this.renderCard(i);n.scrollTop=r}markActionButton(n){n.setCta()}initializeCards(n){this.cardShells.clear();for(let r of Oi){let i=n.createDiv();i.dataset.settingsCard=r;let a=i.createEl("button");a.type="button",a.dataset.settingsCardToggle=r,v(a,"ahs-settings-card-toggle"),a.addEventListener("click",()=>{this.toggleCard(r)});let o=i.createDiv();o.dataset.settingsCardBody=r,v(o,"ahs-settings-card-body",$i),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)),Ku(r.bodyEl,$i,!i),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(Wi,`${Math.round(r)}px`)}disconnectPageHeaderResizeObserver(){this.pageHeaderResizeObserver?.disconnect(),this.pageHeaderResizeObserver=null}renderCardTypesCard(n){this.hydrateVisibleCardTypeCaches(),this.maybeStartNoteTypeCacheCheck();let r=n.createDiv();v(r,"ahs-settings-action-row");let i=new G.ButtonComponent(r).setButtonText(this.ankiConfigLoading?g("settings.cards.cardTypes.loadAnki.loading"):g("settings.cards.cardTypes.loadAnki.button")).setCta().setDisabled(this.ankiConfigLoading).onClick(()=>this.loadAnkiCardTypeConfig());i.buttonEl.dataset.cardTypesRefresh="true",r.createSpan({text:`${g("settings.cards.cardTypes.statusLabel")}${Le(this.getCardTypeStatusMessage())}`});let a=n.createDiv();a.dataset.cardTypeList="true",v(a,"ahs-settings-card-list");for(let o of Bt)this.renderCardTypeBlock(a,o)}renderCardTypeBlock(n,r){let i=this.plugin.settings.cardTypeConfigs[r],a=n.createDiv();a.dataset.cardTypeConfig=r,v(a,"ahs-settings-card-type-block");let o=a.createDiv();v(o,"ahs-settings-card-type-header");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)});v(s,"ahs-settings-card-type-title");let d=a.createDiv();v(d,"ahs-settings-recognition-row");let c=this.createInlineControlGroup(d,g("settings.cards.cardTypes.labels.headingLevel")),l=this.createSelect(c,`card-type-heading:${r}`);l.dataset.cardTypeHeading=r,v(l,"ahs-settings-heading-select");for(let b=1;b<=6;b+=1)this.appendOption(l,String(b),`H${b}`);l.value=String(i.headingLevel),l.addEventListener("change",()=>{this.saveCardTypeConfig(r,{headingLevel:Number(l.value)})});let m=this.createInlineControlGroup(d,g("settings.cards.cardTypes.labels.extraMarker")).createEl("input");if(m.type="text",m.dataset.cardTypeMarker=r,m.placeholder=g("settings.cards.cardTypes.markerPlaceholder"),v(m,"ahs-settings-marker-input"),m.value=this.getDraftValue(`card-type-marker:${r}`,i.extraMarker),m.addEventListener("input",()=>{this.scheduleDebouncedTextSave(`card-type-marker:${r}`,m.value,async b=>{await this.saveCardTypeConfig(r,{extraMarker:b})&&this.textDraftValues.delete(`card-type-marker:${r}`)})}),r==="cloze-all"){let b=a.createEl("p",{text:g("settings.cards.cardTypes.sharedClozeMappingHint")});b.dataset.cardTypeSharedHint=r,v(b,"ahs-settings-muted-text");return}let p=a.createDiv();v(p,"ahs-settings-grid-row");let F=this.createGridControlSlot(p,g("settings.cards.cardTypes.labels.noteType")),k=this.createSelect(F,`card-type-note-type:${r}`);k.dataset.cardTypeNoteType=r,this.applyFluidEllipsis(k);for(let b of this.getSelectableNoteModels(i.noteType))this.appendOption(k,b,b);k.value=i.noteType,k.disabled=this.ankiConfigLoading,k.addEventListener("change",()=>{this.saveCardTypeConfig(r,{noteType:k.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 c=this.createGridControlSlot(n,g("settings.cards.cardTypes.labels.mainField")),l=this.createFieldSelect(c,`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,g("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,g("settings.cards.cardTypes.labels.answerField")),d=this.createFieldSelect(s,`card-type-answer-field:${r}`);d.dataset.cardTypeAnswerField=r,this.applyFluidEllipsis(d),this.populateFieldSelect(d,u?.loadedFieldNames??[],u?.bodyField),d.addEventListener("change",()=>{this.saveFieldMapping(r,{bodyField:d.value||void 0})})}renderQaGroupFieldControls(n,r){let i=this.plugin.settings.cardTypeConfigs[r].noteType.trim(),a=this.getQaGroupFieldState(r),o=a.mapping?this.getQaGroupSelectedFields(a.mapping):void 0,u=this.createGridControlSlot(n,g("settings.cards.cardTypes.labels.qaGroupTitleField"));if(a.mapping){let l=this.createFieldSelect(u,`card-type-qa-group-title-field:${r}`);l.dataset.qaGroupTitleField=r,this.applyFluidEllipsis(l),this.populateFieldSelect(l,a.mapping.loadedFieldNames,a.mapping.titleField);let f=n.createDiv();f.dataset.qaGroupPairRow=r,v(f,"ahs-settings-qa-group-pair-row");let m=this.createGridControlSlot(f,g("settings.cards.cardTypes.labels.qaGroupFirstQuestionField")),p=this.createFieldSelect(m,`card-type-qa-group-first-question-field:${r}`);p.dataset.qaGroupFirstQuestionField=r,this.applyFluidEllipsis(p),this.populateFieldSelect(p,a.mapping.loadedFieldNames,o?.firstQuestionField);let F=this.createGridControlSlot(f,g("settings.cards.cardTypes.labels.qaGroupFirstAnswerField")),k=this.createFieldSelect(F,`card-type-qa-group-first-answer-field:${r}`);k.dataset.qaGroupFirstAnswerField=r,this.applyFluidEllipsis(k),this.populateFieldSelect(k,a.mapping.loadedFieldNames,o?.firstAnswerField);let b=()=>{this.saveQaGroupFieldSelection(r,{titleField:l.value||void 0,firstQuestionField:p.value||void 0,firstAnswerField:k.value||void 0})};l.addEventListener("change",b),p.addEventListener("change",b),k.addEventListener("change",b);let x=f.createSpan({text:g("settings.cards.cardTypes.qaGroup.configuredSlots",{count:a.mapping.slots.length})});x.dataset.qaGroupSlotSummary=r,v(x,"ahs-settings-nowrap-start"),this.applyFluidEllipsis(x)}else{u.createSpan({text:i.length>0?g("settings.cards.cardTypes.qaGroup.unavailable"):g("settings.cards.cardTypes.qaGroup.noModel")}).dataset.qaGroupTitleField=r;let l=n.createDiv();l.dataset.qaGroupPairRow=r,v(l,"ahs-settings-qa-group-pair-row");let f=this.createGridControlSlot(l,g("settings.cards.cardTypes.labels.qaGroupFirstQuestionField"));f.createSpan({text:i.length>0?g("settings.cards.cardTypes.qaGroup.unavailable"):g("settings.cards.cardTypes.qaGroup.noModel")}).dataset.qaGroupFirstQuestionField=r;let m=this.createGridControlSlot(l,g("settings.cards.cardTypes.labels.qaGroupFirstAnswerField"));m.createSpan({text:i.length>0?g("settings.cards.cardTypes.qaGroup.unavailable"):g("settings.cards.cardTypes.qaGroup.noModel")}).dataset.qaGroupFirstAnswerField=r;let p=l.createSpan({text:i.length>0?g("settings.cards.cardTypes.qaGroup.unavailable"):g("settings.cards.cardTypes.qaGroup.noModel")});p.dataset.qaGroupSlotSummary=r,v(p,"ahs-settings-nowrap-start"),this.applyFluidEllipsis(p)}if(a.error){let l=n.createDiv({text:Le(a.error)});l.dataset.qaGroupError=r,v(l,"ahs-settings-grid-full");return}if(!a.mapping||a.mapping.warnings.length===0)return;let s=n.createDiv();s.dataset.qaGroupWarnings=r,v(s,"ahs-settings-grid-full","ahs-settings-warnings"),s.createEl("strong",{text:g("settings.cards.cardTypes.labels.qaGroupWarnings")});for(let l of a.mapping.warnings)s.createDiv({text:this.renderQaGroupWarning(l)}).dataset.qaGroupWarning=r;let d=s.createEl("label");v(d,"ahs-settings-inline-check");let c=d.createEl("input");c.type="checkbox",c.checked=Ln(a.mapping.warnings,a.mapping.acceptedWarnings),c.dataset.qaGroupWarningAccept=r,c.addEventListener("change",()=>{this.saveQaGroupWarningAcceptance(r,c.checked)}),d.createSpan({text:g("settings.cards.cardTypes.qaGroup.acceptWarnings")})}renderSyncContentCard(n){let r=this.createSyncContentSection(n,"body-range",g("settings.cards.syncContent.sections.bodyRange"));new G.Setting(r).setName(g("settings.cardAnswerCutoffMode.name")).setDesc(g("settings.cardAnswerCutoffMode.desc")).addDropdown(u=>{u.addOption("heading-block",g("settings.cardAnswerCutoffMode.options.headingBlock")),u.addOption("double-blank-lines",g("settings.cardAnswerCutoffMode.options.doubleBlankLines")),u.setValue(this.plugin.settings.cardAnswerCutoffMode).onChange(s=>{this.plugin.updateSettings({cardAnswerCutoffMode:s})})});let i=this.createSyncContentSection(n,"backlink",g("settings.cards.syncContent.sections.backlink"));new G.Setting(i).setName(g("settings.syncOptions.addObsidianBacklink.name")).setDesc(g("settings.syncOptions.addObsidianBacklink.desc")).addToggle(u=>{u.setValue(this.plugin.settings.addObsidianBacklink).onChange(s=>{this.plugin.updateSettings({addObsidianBacklink:s})})}),new G.Setting(i).setName(g("settings.syncOptions.obsidianBacklinkLabel.name")).setDesc(g("settings.syncOptions.obsidianBacklinkLabel.desc")).addText(u=>{u.setPlaceholder(g("settings.syncOptions.obsidianBacklinkLabel.placeholder")).setValue(this.getDraftValue("obsidian-backlink-label",this.plugin.settings.obsidianBacklinkLabel)).onChange(s=>{this.scheduleDebouncedTextSave("obsidian-backlink-label",s,async d=>{let c=d.trim();await this.plugin.updateSettings({obsidianBacklinkLabel:c||Ke}),this.textDraftValues.delete("obsidian-backlink-label")})})}),new G.Setting(i).setName(g("settings.syncOptions.obsidianBacklinkPlacement.name")).setDesc(g("settings.syncOptions.obsidianBacklinkPlacement.desc")).addDropdown(u=>{u.addOption("question-last-line",g("settings.syncOptions.obsidianBacklinkPlacement.options.questionLastLine")),u.addOption("answer-first-line",g("settings.syncOptions.obsidianBacklinkPlacement.options.answerFirstLine")),u.addOption("answer-last-line",g("settings.syncOptions.obsidianBacklinkPlacement.options.answerLastLine")),u.setValue(this.plugin.settings.obsidianBacklinkPlacement).onChange(s=>{this.plugin.updateSettings({obsidianBacklinkPlacement:s})})});let a=this.createSyncContentSection(n,"tags",g("settings.cards.syncContent.sections.tags"));new G.Setting(a).setName(g("settings.syncOptions.syncObsidianTagsToAnki.name")).setDesc(g("settings.syncOptions.syncObsidianTagsToAnki.desc")).addToggle(u=>{u.setValue(this.plugin.settings.syncObsidianTagsToAnki).onChange(s=>{this.plugin.updateSettings({syncObsidianTagsToAnki:s})})}),new G.Setting(a).setName(g("settings.syncOptions.keepPureTagLinesInCardBody.name")).setDesc(g("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",g("settings.cards.syncContent.sections.clozeSpecial"));new G.Setting(o).setName(g("settings.syncOptions.highlightsToCloze.name")).setDesc(g("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();return a.dataset.syncContentSection=r,v(a,"ahs-settings-section"),this.createSectionHeading(a,"syncContentSectionTitle",r,i),a}renderScopeCard(n){if(new G.Setting(n).setName(g("settings.scope.name")).setDesc(Yu(this.plugin.settings.scopeMode)).addDropdown(s=>{s.addOption("all",g("settings.scope.option.all")).addOption("include",g("settings.scope.option.include")).addOption("exclude",g("settings.scope.option.exclude")).setValue(this.plugin.settings.scopeMode).onChange(d=>{d!=="all"&&d!=="include"&&d!=="exclude"||this.updateScopeMode(d)})}),!gt(this.plugin.settings.scopeMode,this.plugin.settings.includeFolders)){let s=n.createEl("p",{text:g("settings.scope.unconfiguredWarning")});s.dataset.scopeWarning="unconfigured",v(s,"ahs-settings-warning-text")}if(this.plugin.settings.scopeMode==="all")return;let r=n.createDiv(),i=new G.ButtonComponent(r).setButtonText(g("settings.cards.scope.refreshFolders")).setCta().setDisabled(!!this.folderTreeLoadPromise).onClick(()=>{this.refreshFolderTree()});if(i.buttonEl.dataset.scopeRefreshFolders="true",this.ensureFolderTreeLoaded(),n.createEl("p",{text:Ju(this.plugin.settings.scopeMode)}),this.folderTreeLoadPromise||this.folderTree.length===0){n.createEl("p",{text:Le(this.folderTreeStatus)});return}this.expandSelectedFolderAncestorsIfNeeded(this.plugin.settings.scopeMode);let a=this.getSelectedFoldersForScopeMode(this.plugin.settings.scopeMode),o=Pi(this.folderTree,a),u=n.createDiv();u.dataset.scopeTree="true",v(u,"ahs-settings-folder-tree");for(let s of o)this.renderFolderNode(u,s,this.plugin.settings.scopeMode,0)}renderDeckCard(n){let r=this.createDeckSection(n,"folder-mapping",g("settings.cards.deck.sections.folderMapping"));new G.Setting(r).setName(g("settings.deck.folderDeckMode.name")).setDesc(g("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",g("settings.cards.deck.sections.fileDeck"));new G.Setting(i).setName(g("settings.deck.fileDeckEnabled.name")).setDesc(g("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(g("settings.deck.marker.name")).setDesc(g("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 d=s.trim();if(!d){this.textDraftValues.delete("file-deck-marker"),this.renderCard("deck");return}await this.plugin.updateSettings({fileDeckMarker:d}),this.textDraftValues.delete("file-deck-marker")})})}),new G.Setting(i).setName(g("settings.deck.template.name")).setDesc(g("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 d=s.trim();if(!d){this.textDraftValues.delete("file-deck-template"),this.renderCard("deck");return}await this.plugin.updateSettings({fileDeckTemplate:d}),this.textDraftValues.delete("file-deck-template")})})}),new G.Setting(i).setName(g("settings.deck.insertLocation.name")).setDesc(g("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(g("settings.deck.insertTemplate.name")).setDesc(g("settings.deck.insertTemplate.desc")).addButton(o=>{this.markActionButton(o),o.setButtonText(g("settings.deck.insertTemplate.button")).onClick(()=>{this.plugin.insertDeckTemplateToCurrentFile()})}));let a=this.createDeckSection(n,"default-deck",g("settings.cards.deck.sections.defaultDeck"));new G.Setting(a).setName(g("settings.deck.defaultDeck.name")).setDesc(g("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 d=s.trim();if(!d){this.textDraftValues.delete("default-deck"),this.renderCard("deck");return}await this.plugin.updateSettings({defaultDeck:d}),this.textDraftValues.delete("default-deck")})})}),this.createDeckHelperText(a,g("settings.deck.fallbackDesc"),"fallback"),this.createDeckPriorityFooter(n)}renderDeckExampleBlock(n){let r=n.createDiv();r.dataset.deckExampleBlock="true",v(r,"ahs-settings-deck-example-block");let i=r.createEl("strong",{text:g("settings.deck.examplesTitle")});v(i,"ahs-settings-small-title");for(let a of[g("settings.deck.folderExample"),g("settings.deck.folderAndFileExample")]){let o=r.createDiv({text:a});o.dataset.deckExampleRow="true",v(o,"ahs-settings-helper-text")}}createDeckHelperText(n,r,i){let a=n.createDiv({text:r});return a.dataset.deckHelperText=i,v(a,"ahs-settings-helper-text"),a}createDeckPriorityFooter(n){let r=this.createDeckHelperText(n,g("settings.deck.priorityDesc"),"priority");r.dataset.deckPriorityFooter="true",v(r,"ahs-settings-helper-text-priority")}createDeckSection(n,r,i){let a=n.createDiv();return a.dataset.deckSection=r,v(a,"ahs-settings-section"),this.createSectionHeading(a,"deckSectionTitle",r,i),a}renderCommandsCard(n){n.createEl("p",{text:g("settings.cards.commands.desc")});let r=n.createEl("ul");for(let[i,a]of[[g("commands.syncCurrentFileToAnki"),g("settings.cards.commands.items.syncCurrentFile")],[g("commands.syncVaultToAnki"),g("settings.cards.commands.items.syncVault")],[g("commands.clearCurrentFileSyncedCards"),g("settings.cards.commands.items.clearCurrentFile")],[g("commands.cleanupEmptyDecks"),g("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{pe(Ce({...this.plugin.settings,cardTypeConfigs:i}))}catch(a){return this.cardTypeStatusOverride=ye(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=B("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=B(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=Qi(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,[d,c])=>(s[d]={fieldNames:[...c],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=ye(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=Qi(await this.plugin.listNoteModels());if(n!==this.noteTypeCacheCheckToken)return;this.detectedAnkiNoteTypeCache=r,this.noteTypeCacheCheckStatus=Xu(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 Bt)this.hydrateCardTypeCache(r,n)}hydrateCardTypeCache(n,r){let i=this.getRuntimeCardType(n),a=this.plugin.settings.cardTypeConfigs[n].noteType,o=B(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 Bt)r==="qa-group"||r==="cloze-all"||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=B(i,a),s=this.plugin.settings.noteFieldMappings[u]??this.draftMappings[u],d=s?{...s,loadedFieldNames:[...o.fieldNames],loadedAt:o.loadedAt}:this.noteFieldMappingService.suggest(i,a,o.fieldNames,o.loadedAt);this.draftMappings[u]=d,!On(this.plugin.settings.noteFieldMappings[u],d)&&await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[u]:d}})}createCachedModelDetails(n,r){return{fieldNames:[...r]}}countConfiguredCardTypes(n){return Bt.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=B(n,r),u=this.plugin.settings.noteFieldMappings[o]??this.draftMappings[o];if(n==="qa-group"){if(O(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=B(r,i),o=this.draftMappings[a]??this.plugin.settings.noteFieldMappings[a];if(o)return O(o)?this.cloneQaGroupFieldMapping(o):{...o,loadedFieldNames:[...o.loadedFieldNames]};let u=this.loadedModelDetails[a];if(!u)return;if(r==="qa-group")try{let d=this.plugin.settings.noteFieldMappings[a]??this.draftMappings[a],c=this.qaGroupFieldMappingService.suggest(i,u.fieldNames,Date.now(),O(d)?d.acceptedWarnings:void 0,O(d)?d.titleField:void 0);return this.draftMappings[a]=c,this.cloneQaGroupFieldMapping(c)}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=B(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(),O(o)?o.acceptedWarnings:void 0,O(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,derivation: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||!O(i))return;let a=this.getRuntimeCardType(n),o=B(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 saveQaGroupFieldSelection(n,r){let i=this.plugin.settings.cardTypeConfigs[n].noteType.trim();if(i.length===0)return;let a=B("qa-group",i),o=this.getCurrentMappingForConfig(n),u=o&&O(o)?o.loadedFieldNames:this.loadedModelDetails[a]?.fieldNames??[],s=o&&O(o)?o.loadedAt:Date.now(),d=this.createQaGroupSelectionDraft(i,u,s,r);this.draftMappings[a]=d;try{let c=this.qaGroupFieldMappingService.createMappingFromSelection(i,u,r,s);this.cardTypeStatusOverride=null,this.draftMappings[a]=c,await this.plugin.updateSettings({noteFieldMappings:{...this.plugin.settings.noteFieldMappings,[a]:c}})}catch{this.cardTypeStatusOverride=null,this.renderCard("card-types");return}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=B("qa-group",i),u=this.plugin.settings.noteFieldMappings[o]??this.draftMappings[o];if(O(u)){let s=this.refreshSavedQaGroupMapping(u,a.fieldNames,a.loadedAt);this.draftMappings[o]=s,On(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,On(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=B("qa-group",r),a=this.draftMappings[i]??this.plugin.settings.noteFieldMappings[i];if(a&&O(a)){if(a.derivation?.mode==="first-pair"){let u=this.getQaGroupSelectedFields(a);try{return{mapping:this.qaGroupFieldMappingService.createMappingFromSelection(r,a.loadedFieldNames,u,a.loadedAt)}}catch(s){return{mapping:this.cloneQaGroupFieldMapping(a),error:ye(s,"settings.cards.cardTypes.failedSave")}}}return{mapping:this.cloneQaGroupFieldMapping(a)}}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(),O(u)?u.acceptedWarnings:void 0,O(u)?u.titleField:void 0)}}catch(u){return{error:ye(u,"settings.cards.cardTypes.failedSave")}}}refreshSavedQaGroupMapping(n,r,i){if(n.derivation?.mode==="first-pair")try{return this.qaGroupFieldMappingService.createMappingFromSelection(n.modelName,r,this.getQaGroupSelectedFields(n),i)}catch{return{...this.cloneQaGroupFieldMapping(n),loadedFieldNames:[...r],loadedAt:i}}return{...n,loadedFieldNames:[...r],slots:n.slots.map(a=>({...a})),warnings:[...n.warnings],acceptedWarnings:n.acceptedWarnings?[...n.acceptedWarnings]:void 0,derivation:n.derivation?{...n.derivation}:void 0,loadedAt:i}}cloneQaGroupFieldMapping(n){return{...n,derivation:n.derivation?{...n.derivation}:void 0,loadedFieldNames:[...n.loadedFieldNames],slots:n.slots.map(r=>({...r})),warnings:[...n.warnings],acceptedWarnings:n.acceptedWarnings?[...n.acceptedWarnings]:void 0}}getQaGroupSelectedFields(n){return{titleField:n.titleField,firstQuestionField:n.derivation?.firstQuestionField??n.slots[0]?.questionField,firstAnswerField:n.derivation?.firstAnswerField??n.slots[0]?.answerField}}createQaGroupSelectionDraft(n,r,i,a){let o=a.titleField?.trim()||void 0,u=a.firstQuestionField?.trim()||void 0,s=a.firstAnswerField?.trim()||void 0;return{cardType:"qa-group",modelName:n,titleField:o,slots:[],warnings:[],acceptedWarnings:void 0,derivation:u||s?{mode:"first-pair",firstQuestionField:u,firstAnswerField:s}:void 0,loadedFieldNames:[...r],loadedAt:i}}renderQaGroupWarning(n){let r=ci(n);if(!r)return n;let i=String(r.index).padStart(2,"0");return r.kind==="missing-answer"?g("settings.cards.cardTypes.qaGroup.warning.missingAnswer",{index:i,questionField:r.questionField,answerField:r.answerField}):g("settings.cards.cardTypes.qaGroup.warning.missingQuestion",{index:i,questionField:r.questionField,answerField:r.answerField})}getRuntimeCardType(n){return n==="qa-group"?"qa-group":n==="cloze"||n==="cloze-all"?"cloze":"basic"}ensureFolderTreeLoaded(n=!1){n&&(this.hasLoadedFolderTree=!1,this.folderTree=[]),!(this.hasLoadedFolderTree||this.folderTreeLoadPromise)&&(this.folderTreeStatus=Hi,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=ye(r,"settings.scope.failedLoad")}).finally(()=>{this.hasLoadedFolderTree=!0,this.folderTreeLoadPromise=null,this.renderCard("scope")}))}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=Ri(this.folderTree,a,r,i);if(n==="include"){let u=i?this.plugin.settings.alternateFolderDeckModeFolders:this.plugin.settings.alternateFolderDeckModeFolders.filter(s=>!Zu(s,r));await this.plugin.updateSettings({includeFolders:o,alternateFolderDeckModeFolders:u})}else await this.plugin.updateSettings({excludeFolders:o});this.renderCard("scope")}async updateAlternateFolderDeckModeFolder(n,r){let i=r?this.plugin.settings.alternateFolderDeckModeFolders.includes(n)?[...this.plugin.settings.alternateFolderDeckModeFolders]:[...this.plugin.settings.alternateFolderDeckModeFolders,n]:this.plugin.settings.alternateFolderDeckModeFolders.filter(a=>a!==n);await this.plugin.updateSettings({alternateFolderDeckModeFolders:i}),this.renderCard("scope")}renderFolderNode(n,r,i,a){let o=n.createDiv();o.dataset.folderRow=r.path,v(o,"ahs-settings-folder-row"),o.style.setProperty("--ahs-folder-depth-indent",`${a*18}px`);let u=r.children.length>0,s=u&&this.expandedFolderPaths.has(r.path),d=o.createEl(u?"button":"span");d.dataset.folderToggle=r.path,d.textContent=u?s?"\u25BE":"\u25B8":"",v(d,"ahs-settings-folder-toggle"),u?(v(d,"ahs-settings-folder-toggle-button"),d.setAttr("aria-label",s?g("settings.scope.collapseFolder",{name:r.name}):g("settings.scope.expandFolder",{name:r.name})),d.setAttr("title",s?g("settings.scope.collapseFolder",{name:r.name}):g("settings.scope.expandFolder",{name:r.name})),d.addEventListener("click",()=>{this.expandedFolderPaths.has(r.path)?this.expandedFolderPaths.delete(r.path):this.expandedFolderPaths.add(r.path),this.renderCard("scope")})):v(d,"ahs-settings-folder-toggle-spacer");let c=o.createEl("input");c.type="checkbox",c.checked=r.checked,c.indeterminate=r.indeterminate,c.dataset.folderPath=r.path,v(c,"ahs-settings-folder-checkbox"),c.addEventListener("change",()=>{this.updateFolderSelection(i,r.path,c.checked)});let l=o.createDiv();v(l,"ahs-settings-folder-label-stack");let f=l.createSpan({text:r.name});if(f.dataset.folderPathLabel=r.path,v(f,"ahs-settings-folder-label"),this.applyFluidEllipsis(f),i==="include"&&r.checked&&this.plugin.settings.folderDeckMode!=="off"){let p=o.createEl("input"),F=g("settings.scope.folderDeckModeOverride.ariaLabel",{name:r.name}),k=this.getFolderDeckModeOverrideTitle(),b=this.plugin.settings.alternateFolderDeckModeFolders.includes(r.path);if(p.type="checkbox",p.checked=b,p.dataset.folderDeckModeOverride=r.path,p.setAttr("aria-label",F),p.setAttr("title",k),v(p,"ahs-settings-folder-override-checkbox"),p.addEventListener("click",x=>{x?.stopPropagation()}),p.addEventListener("change",()=>{this.updateAlternateFolderDeckModeFolder(r.path,p.checked)}),b){let x=l.createDiv({text:this.getFolderDeckModeOverrideHint()});x.dataset.folderDeckModeOverrideHint=r.path,v(x,"ahs-settings-folder-override-hint")}}if(!u||!s)return;let m=n.createDiv();m.dataset.folderChildren=r.path,v(m,"ahs-settings-folder-children");for(let p of r.children)this.renderFolderNode(m,p,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 es(r))this.expandedFolderPaths.add(i)}}getSelectedFoldersForScopeMode(n){return n==="include"?this.plugin.settings.includeFolders:this.plugin.settings.excludeFolders}getFolderDeckModeOverrideHint(){return this.plugin.settings.folderDeckMode==="folder"?g("settings.scope.folderDeckModeOverride.hint.folderAndFile"):g("settings.scope.folderDeckModeOverride.hint.folder")}getFolderDeckModeOverrideTitle(){return this.plugin.settings.folderDeckMode==="folder"?g("settings.scope.folderDeckModeOverride.title.folderAndFile"):g("settings.scope.folderDeckModeOverride.title.folder")}createInlineControlGroup(n,r){let i=n.createEl("label");v(i,"ahs-settings-inline-control-group");let a=i.createSpan({text:r});return v(a,"ahs-settings-inline-control-label"),i}createGridControlSlot(n,r){let i=n.createEl("label");v(i,"ahs-settings-grid-control-slot");let a=i.createSpan({text:r});v(a,"ahs-settings-grid-control-label");let o=i.createDiv();return v(o,"ahs-settings-grid-control-content"),o}applyFluidEllipsis(n){let r=(n.tagName||n.tag||"").toLowerCase(),i=r==="select"||r==="input";v(n,"ahs-settings-fluid-ellipsis"),i&&v(n,"ahs-settings-fluid-control")}createSectionHeading(n,r,i,a){let o=n.createDiv(),u=new G.Setting(o).setName(a).setHeading();u.settingEl.dataset[r]=i,u.nameEl.dataset[r]=i,v(u.settingEl,"ahs-settings-section-heading")}scheduleDebouncedTextSave(n,r,i){let a=window.activeWindow;this.textDraftValues.set(n,r);let o=this.debouncedTextSaves.get(n);o&&a.clearTimeout(o.timer);let u=a.setTimeout(()=>{this.flushDebouncedTextSave(n)},Ou);this.debouncedTextSaves.set(n,{timer:u,saveAction:i})}async flushDebouncedTextSave(n){let r=window.activeWindow,i=this.debouncedTextSaves.get(n);i&&(r.clearTimeout(i.timer),this.debouncedTextSaves.delete(n),await i.saveAction(this.textDraftValues.get(n)??""))}async flushDebouncedTextSaves(){let n=[...this.debouncedTextSaves.keys()];await Promise.allSettled(n.map(r=>this.flushDebouncedTextSave(r)))}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?g("settings.mapping.selectFieldPlaceholder"):g("settings.cards.cardTypes.fieldsUnavailable"));for(let a of r)this.appendOption(n,a,a);n.value=i??""}populateFileDeckInsertLocationDropdown(n,r){n.addOption("body",g("settings.deck.insertLocation.options.body")),n.addOption("yaml",g("settings.deck.insertLocation.options.yaml")),n.setValue(r)}populateFolderDeckModeDropdown(n,r){n.addOption("off",g("settings.deck.folderDeckMode.options.off")),n.addOption("folder",g("settings.deck.folderDeckMode.options.folder")),n.addOption("folder-and-file",g("settings.deck.folderDeckMode.options.folderAndFile")),n.setValue(r)}getCardTitle(n){return n==="card-types"?g("settings.cards.cardTypes.title"):n==="sync-content"?g("settings.cards.syncContent.title"):n==="scope"?g("settings.cards.scope.title"):n==="deck"?g("settings.cards.deck.title"):g("settings.cards.commands.title")}getCardTypeLabel(n){return n==="basic"?g("settings.cards.cardTypes.rows.basic"):n==="qa-group"?g("settings.cards.cardTypes.rows.qaGroup"):n==="cloze"?g("settings.cards.cardTypes.rows.cloze"):n==="cloze-all"?g("settings.cards.cardTypes.rows.clozeAll"):g("settings.cards.cardTypes.rows.qaGroup")}};function Ui(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function Zu(e,t){let n=Ui(e),r=Ui(t);return n===r||n.startsWith(`${r}/`)}function Yu(e){return e==="include"?g("settings.scope.summary.include"):e==="exclude"?g("settings.scope.summary.exclude"):g("settings.scope.summary.all")}function On(e,t){return JSON.stringify(e)===JSON.stringify(t)}function Qi(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 Xu(e,t){return e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function Ju(e){return e==="include"?g("settings.scope.treeDescription.include"):g("settings.scope.treeDescription.exclude")}function es(e){let t=e.split("/").filter(r=>r.length>0),n=[];for(let r=1;r0?e.message.trim():String(e)}var zt=class{async runCollectBatches(t,n,r,i){if(t.length===0)return[];let a=rs(t,n),o=[],u=0;return await Promise.all(Array.from({length:Math.min(r,a.length)},async()=>{for(;u(await i(a),[]))}};function rs(e,t){let n=[];for(let r=0;ri.has(a))}function et(e,t){let n=Ht(e),r=Ht(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 Ot=class{constructor(t,n=new Ne,r=new zt){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,d=0,c=0,l=0,f=0,m=0,p=Array.from(new Set([...t.toRebuild,...t.toUpdate,...t.toVerifyDeck,...t.toRewriteMarker,...t.toChangeDeck].flatMap(y=>y.noteId?[y.noteId]:[]))),F=await this.batchScheduler.runCollectBatches(p,100,1,y=>this.ankiGateway.getNoteSummaries(y)),k=new Map(F.map(y=>[y.noteId,y])),b=[],x=[],C=[],h=[],M=[],T=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.toRebuild){if(y.noteId&&k.has(y.noteId)){x.push({plannedCard:y,renderedCard:await this.requireRenderedCard(y,n,r)});continue}b.push(await this.requireRenderedCard(y,n,r)),s.set(y.card.syncKey,y)}for(let y of t.toUpdate){if(y.noteId&&k.has(y.noteId)){let w=await this.requireRenderedCard(y,n,r),_=k.get(y.noteId);_&&_.modelName!==w.noteModel?h.push({plannedCard:y,renderedCard:w,summary:_}):C.push({plannedCard:y,renderedCard:w});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&&k.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 w=k.get(y.noteId);w&&is(w,y.deck,T.has(y.card.syncKey))&&(M.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.renderedCard.deck),...M.map(y=>y.deck)])),50,1,y=>this.ankiGateway.ensureDecks(y));let D=await this.uploadMedia([...b,...x.map(y=>y.renderedCard),...C.map(y=>y.renderedCard),...h.map(y=>y.renderedCard)]),I=await this.batchScheduler.runCollectBatches(b,50,1,async y=>this.ankiGateway.addNotes(await Promise.all(y.map(async w=>({deckName:w.deck,modelName:w.noteModel,fields:await this.mapFields(w,i,a),tags:w.card.tagsHint})))));for(let y=0;y{await this.ankiGateway.updateNotes(await Promise.all(y.map(async({plannedCard:w,renderedCard:_})=>({noteId:w.noteId??0,fields:await this.mapFields(_,i,a)}))))}),await this.batchScheduler.runVoidBatches(h,25,1,async y=>{for(let{plannedCard:w,renderedCard:_,summary:L}of y){let P=await this.mapFields(_,i,a);try{await this.ankiGateway.updateNoteModel({noteId:w.noteId??0,modelName:_.noteModel,fields:P})}catch(q){throw qt({noteId:w.noteId??0,fromModel:L.modelName,toModel:_.noteModel,error:q,location:`${w.card.filePath}:${w.card.blockStartLine}`})}}});let A=[...C,...h].flatMap(({plannedCard:y})=>{if(!y.noteId)return[];let w=k.get(y.noteId);if(!w)return[];let _=et(y.card.tagsHint,w.tags);return _.addTags.length===0&&_.removeTags.length===0?[]:[{noteId:y.noteId,addTags:_.addTags,removeTags:_.removeTags}]});await this.batchScheduler.runVoidBatches(A,50,1,y=>this.ankiGateway.syncNoteTags(y)),l+=C.length+h.length,f=h.length;for(let{plannedCard:y}of[...C,...h])y.noteId&&(u.add(y.card.syncKey),o.set(y.card.syncKey,y.noteId));let R=new Map;for(let y of M){let w=y.noteId;if(!w)continue;let _=k.get(w);if(!_||_.cardIds.length===0)continue;let L=R.get(y.deck)??new Set;for(let P of _.cardIds)L.add(P);R.set(y.deck,L)}await this.batchScheduler.runVoidBatches(Array.from(R.entries()).map(([y,w])=>({deckName:y,cardIds:Array.from(w)})),25,1,y=>this.ankiGateway.changeDecks(y)),m=M.length;for(let y of M)u.add(y.card.syncKey);return{created:d,rebuilt:c,updated:l,migratedNoteTypes:f,migratedDecks:m,uploadedMedia:D,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 Ki(e){return e instanceof Error?e:new Error(String(e))}function is(e,t,n){let r=e.deckNames?.filter(i=>i.length>0)??[];return r.length===0?n:r.some(i=>i!==t)}var Pe=class{filter(t,n,r,i){let a=Wt(r),o=Wt(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=os(t),o=Wt(r),u=Wt(i);return n==="include"?o.some(s=>Zi(a,s)):n==="exclude"?!u.some(s=>Zi(a,s)):!0}};function Wt(e){return e.map(as).filter(Boolean)}function as(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function os(e){return e.trim().replace(/\\/g,"/").replace(/^\/+/,"")}function Zi(e,t){return e===t||e.startsWith(`${t}/`)}function $t(e,t,n){return`${e}\0group\0${t}\0${n}`}function Fe(e,t){return`${e}#${t}`}function Qt(e){let t=us(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:cs(e.lines.slice(n.index+1)),contentEndLine:Ut(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"?ss(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:Ut(u,e.startLine,e.fallbackLine),markerLine:o?e.startLine+o.index:void 0,markerIndent:o?.indent,markerState:o?"present-invalid":"missing"}}let i=ds(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:Ut(o,e.startLine,e.fallbackLine),markerLine:e.startLine+a.index,markerIndent:a.indent,markerState:"present-invalid"}}return{contentLines:e.lines,trailingLines:[],contentEndLine:Ut(e.lines,e.startLine,e.fallbackLine),markerState:"missing"}}function us(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 Ut(e,t,n){for(let r=e.length-1;r>=0;r-=1)if(e[r].trim())return t+r;return n}function ds(e){for(let t=e.length-1;t>=0;t-=1)if(e[t].trim())return t}function cs(e){let t=0;for(;t1&&a.push({filePath:r,code:"deck_multiple_body_declarations",params:{marker:i}}),{bodyDeck:o[0],warnings:a}}};function ps(e){if(e[0]?.trim()==="---"){for(let t=1;t!Ss(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:Q(u)}}};function hs(e,t){let n=e.trimEnd();return n.endsWith(t)?n.slice(0,n.length-t.length).trimEnd():n}function Yi(e){let t=[],n=null;for(let i=0;ii.indent.length));return t.filter(i=>i.indent.length===r)}function Xi(e,t,n,r){let i,a=t-1,o=null;for(let u=t;ut&&!e[n-1].trim();)n-=1;return e.slice(t,n)}function Ji(e){let t=e.filter(r=>r.trim().length>0).map(r=>ea(r).length),n=t.length>0?Math.min(...t):0;return e.map(r=>r.slice(Math.min(n,r.length)))}function ea(e){return e.match(/^[ \t]*/)?.[0]??""}function ta(e){return e.startsWith("```")||e.startsWith("~~~")}function ys(e){return/^\s*",Wc="<[?][\\s\\S]*?[?]>",$c="]*>",Uc="",Ga=new RegExp("^(?:"+Ra+"|"+Ba+"|"+Oc+"|"+Wc+"|"+$c+"|"+Uc+")"),qa=new RegExp("^(?:"+Ra+"|"+Ba+")");var He=[[/^<(script|pre|style|textarea)(?=(\s|>|$))/i,/<\/(script|pre|style|textarea)>/i,!0],[/^/,!0],[/^<\?/,/\?>/,!0],[/^/,!0],[/^/,!0],[new RegExp("^|$))","i"),/^$/,!0],[new RegExp(qa.source+"\\s*$"),/^$/,!1]];function Sr(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 Mr(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 m=e.bMarks[u]+e.tShift[u],p=e.eMarks[u];if(m=p))){a=o===61?1:2;break}}if(e.sCount[u]<0)continue;let f=!1;for(let m=0,p=r.length;m3||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};it.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(Vc);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 Dr(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){Ar[e.charCodeAt(0)]=1});function Er(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&&Ar[i]!==0?u.content=a:u.content=o,u.markup=o,u.info="escape"}return e.pos=n+1,!0}function _r(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 Yc(e){let t=e.tokens_meta,n=e.tokens_meta.length;Wa(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=m+1):p=m+1,r||(r=e.src.slice(f,m)),a=e.env.references[Te(r)],!a)return e.pos=d,!1;o=a.href,u=a.title}if(!t){e.pos=f,e.posMax=m;let F=e.push("link_open","a",1),k=[["href",o]];F.attrs=k,u&&k.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 Pr(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 m=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(m,p)),o=e.env.references[Te(i)],!o)return e.pos=l,!1;d=o.href,s=o.title}if(!t){r=e.src.slice(m,p);let F=[];e.md.inline.parse(r,e.md,e.env,F);let k=e.push("image","img",0),b=[["src",d],["alt",""]];k.attrs=b,k.children=F,k.content=r,s&&b.push(["title",s])}return e.pos=a,e.posMax=f,!0}var Xc=/^([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])?)*)$/,Jc=/^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;function Rr(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(Jc.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(Xc.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 ed(e){return/^\s]/i.test(e)}function td(e){return/^<\/a\s*>/i.test(e)}function nd(e){let t=e|32;return t>=97&&t<=122}function Br(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&&!nd(i))return!1;let a=e.src.slice(r).match(Ga);if(!a)return!1;if(!t){let o=e.push("html_inline","",0);o.content=a[0],ed(o.content)&&e.linkLevel++,td(o.content)&&e.linkLevel--}return e.pos+=a[0].length,!0}var rd=/^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i,id=/^&([a-z][a-z0-9]{1,31});/i;function Gr(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(rd);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=ln(o)?rt(o):rt(65533),u.markup=a[0],u.info="entity"}return e.pos+=a[0].length,!0}}else{let a=e.src.slice(n).match(id);if(a){let o=he(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 $a(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 m=c>0&&!e[c-1].open?a[c-1]+1:0;a[o]=o-c+m,a[c]=m,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 qr(e){let t=e.tokens_meta,n=e.tokens_meta.length;$a(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};at.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()};at.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 Wr(e){return Array.prototype.slice.call(arguments,1).forEach(function(n){n&&Object.keys(n).forEach(function(r){e[r]=n[r]})}),e}function hn(e){return Object.prototype.toString.call(e)}function ad(e){return hn(e)==="[object String]"}function od(e){return hn(e)==="[object Object]"}function ud(e){return hn(e)==="[object RegExp]"}function Va(e){return hn(e)==="[object Function]"}function sd(e){return e.replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}var Ka={fuzzyLink:!0,fuzzyEmail:!0,fuzzyIP:!1};function cd(e){return Object.keys(e||{}).reduce(function(t,n){return t||Ka.hasOwnProperty(n)},!1)}var dd={"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}}},ld="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]",pd="biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|\u0440\u0444".split("|");function fd(e){e.__index__=-1,e.__text_cache__=""}function gd(e){return function(t,n){let r=t.slice(n);return e.test(r)?r.match(e)[0].length:0}}function ja(){return function(e,t){t.normalize(e)}}function mn(e){let t=e.re=Qa(e.__opts__),n=e.__tlds__.slice();e.onCompile(),e.__tlds_replaced__||n.push(ld),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,od(s)){ud(s.validate)?c.validate=gd(s.validate):Va(s.validate)?c.validate=s.validate:a(u,s),Va(s.normalize)?c.normalize=s.normalize:s.normalize?a(u,s):c.normalize=ja();return}if(ad(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:ja()};let o=Object.keys(e.__compiled__).filter(function(u){return u.length>0&&e.__compiled__[u]}).map(sd).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"),fd(e)}function md(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 $r(e,t){let n=new md(e,t);return e.__compiled__[n.schema].normalize(n,e),n}function V(e,t){if(!(this instanceof V))return new V(e,t);t||cd(e)&&(t=e,e={}),this.__opts__=Wr({},Ka,t),this.__index__=-1,this.__last_index__=-1,this.__schema__="",this.__text_cache__="",this.__schemas__=Wr({},dd,e),this.__compiled__={},this.__tlds__=pd,this.__tlds_replaced__=!1,this.re={},mn(this)}V.prototype.add=function(t,n){return this.__schemas__[t]=n,mn(this),this};V.prototype.set=function(t){return this.__opts__=Wr(this.__opts__,t),this};V.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};V.prototype.pretest=function(t){return this.re.pretest.test(t)};V.prototype.testSchemaAt=function(t,n,r){return this.__compiled__[n.toLowerCase()]?this.__compiled__[n.toLowerCase()].validate(t,r,this):0};V.prototype.match=function(t){let n=[],r=0;this.__index__>=0&&this.__text_cache__===t&&(n.push($r(this,r)),r=this.__last_index__);let i=r?t.slice(r):t;for(;this.test(i);)n.push($r(this,r)),i=i.slice(this.__last_index__),r+=this.__last_index__;return n.length?n:null};V.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,$r(this,0)):null};V.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(),mn(this),this):(this.__tlds__=t.slice(),this.__tlds_replaced__=!0,mn(this),this)};V.prototype.normalize=function(t){t.schema||(t.url="http://"+t.url),t.schema==="mailto:"&&!/^mailto:/i.test(t.url)&&(t.url="mailto:"+t.url)};V.prototype.onCompile=function(){};var Za=V;var hd=/^xn--/,kd=/[^\0-\x7F]/,bd=/[\x2E\u3002\uFF0E\uFF61]/g,yd={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},Ur=35,ne=Math.floor,Qr=String.fromCharCode;function ke(e){throw new RangeError(yd[e])}function xd(e,t){let n=[],r=e.length;for(;r--;)n[r]=t(e[r]);return n}function Xa(e,t){let n=e.split("@"),r="";n.length>1&&(r=n[0]+"@",e=n[1]),e=e.replace(bd,".");let i=e.split("."),a=xd(i,t).join(".");return r+a}function Ja(e){let t=[],n=0,r=e.length;for(;n=55296&&i<=56319&&nString.fromCodePoint(...e),Sd=function(e){return e>=48&&e<58?26+(e-48):e>=65&&e<91?e-65:e>=97&&e<123?e-97:36},Ya=function(e,t){return e+22+75*(e<26)-((t!=0)<<5)},eo=function(e,t,n){let r=0;for(e=n?ne(e/700):e>>1,e+=ne(e/t);e>Ur*26>>1;r+=36)e=ne(e/Ur);return ne(r+(Ur+1)*e/(e+38))},to=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&&ke("not-basic"),t.push(e.charCodeAt(u));for(let u=o>0?o+1:0;u=n&&ke("invalid-input");let f=Sd(e.charCodeAt(u++));f>=36&&ke("invalid-input"),f>ne((2147483647-r)/d)&&ke("overflow"),r+=f*d;let m=l<=a?1:l>=a+26?26:l-a;if(fne(2147483647/p)&&ke("overflow"),d*=p}let c=t.length+1;a=eo(r-s,c,s==0),ne(r/c)>2147483647-i&&ke("overflow"),i+=ne(r/c),r%=c,t.splice(r++,0,i)}return String.fromCodePoint(...t)},no=function(e){let t=[];e=Ja(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)&&ke("overflow"),i+=(s-r)*c,r=s;for(let d of e)if(d2147483647&&ke("overflow"),d===r){let l=i;for(let f=36;;f+=36){let m=f<=a?1:f>=a+26?26:f-a;if(l=0))try{t.hostname=Vr.toASCII(t.hostname)}catch{}return en(Re(t))}function _d(e){let t=nt(e,!0);if(t.hostname&&(!t.protocol||oo.indexOf(t.protocol)>=0))try{t.hostname=Vr.toUnicode(t.hostname)}catch{}return tt(Re(t),tt.defaultChars+"%")}function j(e,t){if(!(this instanceof j))return new j(e,t);t||dn(e)||(t=e||{},e="default"),this.inline=new Ua,this.block=new za,this.core=new Ea,this.renderer=new Ma,this.linkify=new Za,this.validateLink=Ad,this.normalizeLink=Ed,this.normalizeLinkText=_d,this.utils=er,this.helpers=Ge({},ir),this.options={},this.configure(e),t&&this.set(t)}j.prototype.set=function(e){return Ge(this.options,e),this};j.prototype.configure=function(e){let t=this;if(dn(e)){let n=e;if(e=vd[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 ot=j;var Id=/^#[^\s#.,,。;;::!?!?()[\]{}<>]+(?:\/[^\s#.,,。;;::!?!?()[\]{}<>]+)*$/u;function kn(e,t){if(t||e.length===0)return e;let n=e.split(/\r?\n/),r=n.filter(i=>!Ld(i));return r.length===n.length?e:Pd(Nd(r)).join(` -`)}function Ld(e){let t=e.trim();return t?t.split(/\s+/).every(n=>Id.test(n)):!1}function Nd(e){let t=0,n=e.length;for(;tt&&!e[n-1].trim();)n-=1;return e.slice(t,n)}function Pd(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 Rd="#[^\\s#.,\uFF0C\u3002;\uFF1B:\uFF1A!?\uFF01\uFF1F()[\\]{}<>]+(?:\\/[^\\s#.,\uFF0C\u3002;\uFF1B:\uFF1A!?\uFF01\uFF1F()[\\]{}<>]+)*";var Bd=/[\p{L}\p{N}_/#]/u,Gd=new Set(["code","pre"]),qd="ahs-ob-tag";function bn(e){if(!e||!e.includes("#"))return e;let t="",n=0,r=[];for(;nn){let s=e.slice(n,a);t+=r.length===0?uo(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?uo(s):s;break}let u=e.slice(n,o+1);Od(u,r),t+=u,n=o+1}return t}function uo(e){let t=new RegExp(Rd,"gu"),n="",r=0,i;for(;(i=t.exec(e))!==null;){let a=i[0],o=i.index,u=o+a.length;if(!zd(e,o))continue;let s=Tt([a])[0];s&&(n+=e.slice(r,o),n+=Hd(a,s),r=u)}return r===0?e:n+e.slice(r)}function zd(e,t){return t===0?!0:!Bd.test(e[t-1]??"")}function Hd(e,t){return`${so(e)}`}function Od(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||!Gd.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 so(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var yn=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 Oe=class{constructor(t=new yn,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 We(e){return`${e.filePath}\0${e.code}\0${jr(e.params)}`}function jr(e){return e===void 0?"":e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(n=>jr(n)).join(",")}]`:`{${Object.entries(e).sort(([n],[r])=>n.localeCompare(r)).map(([n,r])=>`${JSON.stringify(n)}:${jr(r)}`).join(",")}}`}function xn({href:e,label:t,escapeHref:n=!0}){return`${co(t)}`}function ut(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 co(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var Wd=new ot({breaks:!0,html:!0,linkify:!0}),$d=/`[^`\n]+`/g,Ud=/==(.+?)==/g,Cn=class{constructor(t,n=new de,r=new Oe,i=new X,a=()=>Date.now(),o=()=>`g_${Q(`${Date.now()}_${Math.random()}_${Date.now()}`).slice(0,12)}`,u=()=>(this.sequence+=1,`i_${Q(`${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=Vd(n.groupBlocks??{}),c=new Set,d=new Map,l=[],f=new Map,m=new Set,p=[],F=0,k=0,b=0,x=0,C=this.buildGroupBacklinkAnchor(t[0]??null,r);for(let h of t){if(h.items.length>o.length)throw new S("errors.noteFieldMapping.qaGroupSlotCapacityExceeded",{modelName:i,capacity:o.length,itemCount:h.items.length,filePath:h.filePath,blockStartLine:h.blockStartLine});let M=await this.resolveRecoveredGroup(h,s,i,a,o),T=M.groupId??h.groupId??this.createGroupId(),D=tl(M.items,o),L=Kd(h.items,D,this.createItemId,o);if(L.length>o.length)throw new S("errors.noteFieldMapping.qaGroupSlotCapacityExceeded",{modelName:i,capacity:o.length,itemCount:L.length,filePath:h.filePath,blockStartLine:h.blockStartLine});let A=Zd(L,o),R=this.deckResolutionService.resolve({filePath:h.filePath,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:h.deckWarnings},r.defaultDeck,r.folderDeckMode);for(let N of R.warnings)d.set(We(N),N);let y=R.resolvedDeck.value;c.has(y)||(await this.ankiGateway.ensureDeckExists(y),c.add(y));let w=L.map(N=>({...N,title:Kr(N.title,!1),answer:Kr(kn(N.answer,r.keepPureTagLinesInCardBody),!0)})),_=Qd(a,Kr(h.stem,!1),w,this.buildGroupBacklinkAnchor(h,r)||C,r.obsidianBacklinkPlacement,u),I=M.noteId??h.noteId,P=M.loadedNote;if(I===void 0)I=await this.ankiGateway.addNote({deckName:y,modelName:i,fields:_,tags:h.tagsHint??[]}),F+=1,m.add(h.syncKey);else{if(P??(P=await this.tryLoadQaGroupNote(I,h,i)),P.kind==="missing"&&(I=await this.ankiGateway.addNote({deckName:y,modelName:i,fields:_,tags:h.tagsHint??[]}),F+=1,m.add(h.syncKey)),P.kind==="matching"){let N=P.note,re=!Jd(N.fields,_),Ee=!(N.deckNames??[]).includes(y),_e=et(h.tagsHint,N.tags),vn=_e.addTags.length>0||_e.removeTags.length>0;if(!re&&!Ee&&!vn){f.set(h.syncKey,I);let mo=this.now();p.push({groupId:T,noteId:I,filePath:h.filePath,headingText:h.headingText,backlinkHeadingText:h.backlinkHeadingText,headingLevel:h.headingLevel,stem:h.stem,src:h.src||Fe(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:y,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:[...R.warnings],tagsHint:h.tagsHint?[...h.tagsHint]:[],items:L,freeSlots:A,lastSyncedAt:M.stateRecord?.lastSyncedAt??mo,orphan:!1});continue}(re||Ee)&&await this.ankiGateway.updateNote({noteId:I,fields:_,deckName:Ee?y:void 0}),re&&(k+=1),!re&&vn&&(k+=1),Ee&&(x+=1),vn&&await this.ankiGateway.syncNoteTags([{noteId:I,addTags:_e.addTags,removeTags:_e.removeTags}]),m.add(h.syncKey)}if(P.kind==="model-mismatch"){let N=!(P.note.deckNames??[]).includes(y),re=et(h.tagsHint,P.note.tags),Ee=re.addTags.length>0||re.removeTags.length>0;try{await this.ankiGateway.updateNoteModel({noteId:I,modelName:i,fields:_})}catch(_e){throw qt({noteId:I,fromModel:P.actualModelName,toModel:P.expectedModelName,error:_e,location:`${h.filePath}:${h.blockStartLine}`})}N&&P.note.cardIds.length>0&&(await this.ankiGateway.changeDecks([{deckName:y,cardIds:P.note.cardIds}]),x+=1),Ee&&await this.ankiGateway.syncNoteTags([{noteId:I,addTags:re.addTags,removeTags:re.removeTags}]),k+=1,b+=1,m.add(h.syncKey)}}f.set(h.syncKey,I);let q=Object.fromEntries(L.filter(N=>N.itemId&&N.slot).map(N=>[N.itemId,N.slot]));(h.markerState!=="present-valid"||!this.groupMarkerService.isEquivalent(h.groupMarker,I,q,A)||el(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:I,groupId:T,itemToSlot:q,freeSlots:A,sourceContent:h.sourceContent??""});let be=this.now();p.push({groupId:T,noteId:I,filePath:h.filePath,headingText:h.headingText,backlinkHeadingText:h.backlinkHeadingText,headingLevel:h.headingLevel,stem:h.stem,src:h.src||Fe(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:y,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:[...R.warnings],tagsHint:h.tagsHint?[...h.tagsHint]:[],items:L,freeSlots:A,lastSyncedAt:m.has(h.syncKey)?be:M.stateRecord?.lastSyncedAt??be,orphan:!1})}return{created:F,updated:k,migratedNoteTypes:b,migratedDecks:x,markerWrites:l,resolvedNoteIds:f,touchedSyncKeys:[...m],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)??Xd(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"?{...jd(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?"":xn({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 S("errors.noteFieldMapping.noteTypeNotSelected.qaGroup");let r=t.noteFieldMappings[B("qa-group",n)];if(!H(r))throw new S("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:nl(i)}}};function Qd(e,t,n,r,i,a){if(!e.titleField)throw new S("errors.noteFieldMapping.qaGroupMissingTitle",{modelName:e.modelName});let o=r&&i==="question-last-line"?ut({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"?ut({title:c.title,body:c.answer},r,i).body:c.answer;u[d.questionField]=c.title,u[d.answerField]=l}return u}function Vd(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 jd(e,t,n,r){let i=[],a=new Set;for(let o of t.slots){let u=po(e.fields[o.questionField]??""),s=po(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 Kd(e,t,n,r){let i=new Map,a=[];for(let l of t){let f=lo(l.title,l.answer),m=i.get(f);m?m.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],m=s.shift();if(m){o[l]={...f,itemId:m.itemId,slot:m.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 Zd(e,t){let n=new Set(e.map(r=>r.slot).filter(r=>typeof r=="number"));return t.filter(r=>!n.has(r))}function lo(e,t){return`${e}\0${t}`}function Yd(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 Xd(e){if(!(!e||e.length!==1))return e[0]}function Jd(e,t){let n=Object.keys(t).sort();for(let r of n)if((e[r]??"")!==(t[r]??""))return!1;return!0}function el(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=Wd.renderInline(i).trim();return t?bn(a):a}function tl(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 po(e){return e.replace(/

]*>.*?<\/a><\/p>/g,"").replace(/
]*>.*?<\/a>/g,"").trim()}function nl(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 rl(e){let t=[];return{text:e.replace($d,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 il="manual-render-v3",Ae=class{constructor(t=new Oe){this.deckResolutionService=t}resolve(t,n){let r=al(t.cardType,n),i=this.deckResolutionService.resolve(t,n.defaultDeck,n.folderDeckMode),a=i.resolvedDeck.value,o=n.noteFieldMappings[B(t.cardType,r)]??null,u=t.cardType==="cloze"&&t.clozeMode==="all"?"all":void 0,s={version:il,cardType:t.cardType,clozeMode:u,noteModel:r,mapping:o,addObsidianBacklink:n.addObsidianBacklink,obsidianBacklinkLabel:n.obsidianBacklinkLabel,obsidianBacklinkPlacement:n.obsidianBacklinkPlacement,convertHighlightsToCloze:n.convertHighlightsToCloze,keepPureTagLinesInCardBody:n.keepPureTagLinesInCardBody},c=Q(JSON.stringify(s));return{deck:a,noteModel:r,renderConfigHash:c,warnings:i.warnings}}};function al(e,t){if(Ei(e)){if(!t.clozeNoteType.trim())throw new S("errors.noteFieldMapping.noteTypeNotSelected.cloze");return t.clozeNoteType}if(!t.qaNoteType.trim())throw new S("errors.noteFieldMapping.noteTypeNotSelected.basic");return t.qaNoteType}var Zr=/`[^`\n]+`/g,Yr=/```[\s\S]*?```|~~~[\s\S]*?~~~/g,Sn=/==(.+?)==/g,Xr=/(?:(?0&&i.add(u)}for(let o of r.text.matchAll(Xr)){let u=o[1],s=u?Number(u):e.clozeMode==="all"?1:a++;Number.isInteger(s)&&s>0&&i.add(s)}return i}function $e(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)}}var Fn=class{constructor(t=new Ae){this.renderConfigService=t}plan(t,n,r,i){let a=new Map,o=new Set(n.pendingWriteBack.filter(x=>x.markerKind!=="group-gi").map(x=>Le(x.filePath,x.blockStartLine,x.rawBlockHash))),u=new Set,s=[],c=[],d=[],l=[],f=[],m=[],p=new Map,F=0;for(let x of t){if(a.has(x.syncKey))throw new Error(`Duplicate syncKey detected in current scan: ${x.syncKey}`);if(a.set(x.syncKey,x),x.noteId!==void 0){let R=z(x.noteId);if(u.has(R))throw new Error(`Duplicate noteId detected in current scan: ${x.noteId}`);u.add(R)}let C=x.noteId!==void 0?n.cards[z(x.noteId)]:void 0,h=this.renderConfigService.resolve(x,i);for(let R of h.warnings)p.set(We(R),R);let M=x.noteId,T=Le(x.filePath,x.blockStartLine,x.rawBlockHash),D={card:{...x,noteId:M},noteId:M,deck:h.deck,noteModel:h.noteModel,renderConfigHash:h.renderConfigHash};if(!M){s.push(D);continue}if(ul(C,x,i)){c.push(D);continue}if(l.push(D),(x.idMarkerState!=="present-valid"||x.noteIdSource!=="marker"||o.has(T))&&m.push(D),!C){d.push(D);continue}let L=C.rawBlockHash!==x.rawBlockHash||C.renderConfigHash!==h.renderConfigHash||!Vi(C.tagsHint,x.tagsHint)||C.orphan,A=C.deck!==h.deck;L&&d.push(D),A&&f.push(D),!L&&!A&&(F+=1)}let k=new Set(r),b=Object.values(n.cards).filter(x=>k.has(x.filePath)&&!u.has(z(x.noteId)));return{toCreate:s,toRebuild:c,toUpdate:d,toVerifyDeck:l,toChangeDeck:f,toRewriteMarker:m,toOrphan:b,unchangedCards:F,warnings:Array.from(p.values())}}};function ul(e,t,n){if(!e||e.cardType!=="cloze"||t.cardType!=="cloze")return!1;let r=Se(e.cardType,e.clozeMode);if(r!=="sequential"||t.clozeMode!=="all")return!1;let i=Jr({bodyMarkdown:e.bodyMarkdown,clozeMode:r,convertHighlightsToCloze:n.convertHighlightsToCloze}),a=Jr({bodyMarkdown:t.bodyMarkdown,clozeMode:t.clozeMode,convertHighlightsToCloze:n.convertHighlightsToCloze});return i.size>a.size}var fo=new ot({breaks:!0,html:!0,linkify:!0}),sl=/(?`\\[${k.trim()}\\]`),c=c.replace(cl,(F,k)=>`\\(${k.trim()}\\)`),i&&r.convertHighlightsToCloze&&(c=c.replace(Sn,"{$1}")),i&&(c=c.replace(Xr,(F,k,b)=>`{{c${k?Number(k):n.card.clozeMode==="all"?1:l++}::${b}}}`)),c=c.replace(ll,(F,k)=>{let b=r.resourceResolver.resolveEmbed(k,n.card.filePath);return b?(d.push({kind:b.kind,fileName:b.fileName,absolutePath:b.absolutePath,altText:b.altText}),b.kind==="audio"?`[sound:${b.fileName}]`:`${st(b.altText??b.fileName)}`):F}),c=c.replace(pl,(F,k)=>{let b=r.resourceResolver.resolveWikiLink(k,n.card.filePath);return b?`${st(b.displayText)}`:F}),c=c.replace(Sn,"$1");let f=$e(c,dl,"MATH");c=f.text,c=s.restore(c),c=u.restore(c);let m=(a?fo.renderInline(c):fo.render(c)).trim(),p=f.restore(m,st);return{html:a?p:bn(p),media:d}}};function fl(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 st(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var ct=class extends S{constructor(t){super("errors.currentFileOutOfScope",{filePath:t}),this.name="CurrentFileOutOfScopeError"}},Ue=class extends S{constructor(){super("errors.runScopeNotConfigured"),this.name="RunScopeNotConfiguredError"}},wn=class{constructor(t,n,r,i=new Zt(t),a=new Fn,o=new Mn,u=new Ot(r),s=new Yt(t),c=new Ae,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 Pe;if(this.qaGroupSyncService=new Cn(r,void 0,void 0,void 0,void 0,void 0,void 0,this.vaultGateway.createBacklink.bind(this.vaultGateway)),gl(c)){this.renderConfigService=c,this.now=d;return}this.renderConfigService=new Ae,this.now=c}async syncVault(t){pe(t),this.assertRunScopeConfigured(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(pe(n),this.assertRunScopeConfigured(n),!this.scanScopeService.isPathInScope(t,n.scopeMode,n.includeFolders,n.excludeFolders))throw new ct(t);let r=await this.pluginStateRepository.load(),i=await this.fileIndexerService.indexFile(t,n,r);return this.syncIndexedResult(i,r,n)}assertRunScopeConfigured(t){if(!gt(t.scopeMode,t.includeFolders))throw new Ue}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 m of[...i.toCreate,...i.toRebuild,...i.toUpdate])o.has(m.card.syncKey)||o.set(m.card.syncKey,this.renderer.render(m,a));let u=await this.ankiBatchExecutor.execute(i,o,m=>Promise.resolve(this.renderer.render(m,a)),r.noteFieldMappings),s=await this.qaGroupSyncService.sync(t.groupBlocks,n,r),c=new Map(t.indexedFiles.map(m=>[m.filePath,m])),d=await this.markdownWriteBackService.write(u.markerWrites,c,s.markerWrites),l=ml(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(m=>!new Set(t.scopedFilePaths).has(m.filePath)),...d.pendingEntries],this.markFilesDirty(f,[...d.failureFiles.map(m=>m.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,rebuilt:u.rebuilt,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:hl(i.warnings,s.warnings)}}buildNextState(t,n,r,i,a,o,u,s,c){let d=this.now(),l=Un(a),f=new Set(r.filter(k=>k.content!==void 0).map(k=>k.filePath)),m=new Map;for(let k of i){let b=m.get(k.filePath);b?b.push(k):m.set(k.filePath,[k])}let p={files:{...t.files},cards:{...t.cards},groupBlocks:{...t.groupBlocks??{}},pendingWriteBack:[...t.pendingWriteBack]};for(let k of f)delete p.files[k];for(let[k,b]of Object.entries(p.cards))f.has(b.filePath)&&delete p.cards[k];for(let[k,b]of Object.entries(p.groupBlocks??{}))f.has(b.filePath)&&delete p.groupBlocks?.[k];let F=new Map;for(let k of n){let b=u.get(k.syncKey)??k.noteId;b!==void 0&&F.set(k.syncKey,b)}for(let k of r){if(k.content===void 0)continue;let b=Array.from(new Set(k.cards.map(x=>F.get(x.syncKey)).filter(x=>x!==void 0)));p.files[k.filePath]={filePath:k.filePath,fileHash:k.fileHash,fileStamp:k.fileStamp,deckRulesFingerprint:l,lastIndexedAt:d,noteIds:b,groupIds:(m.get(k.filePath)??[]).map(x=>x.groupId)}}for(let k of n){let b=F.get(k.syncKey);if(b===void 0)continue;let x=t.cards[z(b)]??(k.noteId!==void 0?t.cards[z(k.noteId)]:void 0),C=this.renderConfigService.resolve(k,a);p.cards[z(b)]={noteId:b,filePath:k.filePath,heading:k.heading,backlinkHeadingText:k.backlinkHeadingText,headingLevel:k.headingLevel,bodyMarkdown:k.bodyMarkdown,cardType:k.cardType,clozeMode:k.clozeMode,blockStartOffset:k.blockStartOffset,blockEndOffset:k.blockEndOffset,blockStartLine:k.blockStartLine,bodyStartLine:k.bodyStartLine,blockEndLine:k.blockEndLine,contentEndLine:k.contentEndLine,markerLine:k.markerLine,rawBlockText:k.rawBlockText,rawBlockHash:k.rawBlockHash,renderConfigHash:C.renderConfigHash,deck:C.deck,deckHint:k.deckHint,deckHintSource:k.deckHintSource,deckWarnings:[...k.deckWarnings],tagsHint:k.tagsHint,lastSyncedAt:o.has(k.syncKey)?d:x?.lastSyncedAt??0,orphan:!1}}for(let k of s)p.cards[z(k.noteId)]={...k,orphan:!0};for(let k of i)p.groupBlocks??(p.groupBlocks={}),p.groupBlocks[k.groupId]=k;for(let k of c)p.groupBlocks??(p.groupBlocks={}),p.groupBlocks[k.groupId]={...k,orphan:!0};return p}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 S("errors.writeBack.summary",{fileCount:t.length},{failures:t})}};function gl(e){return typeof e=="object"&&e!==null&&"resolve"in e}function ml(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 hl(...e){let t=new Map;for(let n of e)for(let r of n)t.set(We(r),r);return[...t.values()]}var dt=class extends go.Plugin{constructor(){super(...arguments);this.settings=O;this.noticeService=new Nt;this.ankiGateway=new wt(()=>this.settings.ankiConnectUrl);this.deckTemplateInsertionService=new mt}async onload(){let n=new vt(this);this.pluginConfigRepository=new Et(n);let r=new It(n),i=new At(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=O,this.noticeService.error(g("notice.invalidSettingsRestored"))}let a=new wn(i,r,this.ankiGateway);this.syncCurrentFileUseCase=new Ft(a),this.syncVaultUseCase=new Mt(a),this.clearCurrentFileSyncedCardsUseCase=new St(r,this.ankiGateway,i),this.cleanupEmptyDecksUseCase=new ht(this.ankiGateway),Ai(this),this.addSettingTab(new Gt(this))}async updateSettings(n){if(!this.pluginConfigRepository)return;let r=Ce({...this.settings,...n});try{await this.pluginConfigRepository.save(r),this.settings=r}catch(i){this.noticeService.error(xe(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(g("notice.noActiveMarkdownForSync"));return}if(!this.syncCurrentFileUseCase){this.noticeService.error(g("notice.syncUseCaseNotInitialized"));return}try{let r=await this.syncCurrentFileUseCase.execute(n.path,this.settings);this.noticeService.showSyncSummary("currentFile",r)}catch(r){if(r instanceof ct||r instanceof Ue){this.noticeService.info(lt(r));return}console.error("Current file sync failed.",r),this.noticeService.error(xe(r,"notice.currentFileSyncFailed"))}}async runSyncVault(){if(!this.syncVaultUseCase){this.noticeService.error(g("notice.syncUseCaseNotInitialized"));return}try{let n=await this.syncVaultUseCase.execute(this.settings);this.noticeService.showSyncSummary("vault",n)}catch(n){if(n instanceof Ue){this.noticeService.info(lt(n));return}console.error("Vault sync failed.",n),this.noticeService.error(xe(n,"notice.vaultSyncFailed"))}}async insertDeckTemplateToCurrentFile(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(g("notice.noActiveMarkdownForDeckTemplateInsertion"));return}if(!this.vaultGateway){this.noticeService.error(g("notice.vaultGatewayNotInitialized"));return}try{let r=await this.vaultGateway.readMarkdownFile(n.path);if(!r){this.noticeService.error(g("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(g("notice.deckTemplateAlreadyCurrent"));return}await this.vaultGateway.replaceMarkdownFile(n.path,i.expectedContent,i.nextContent),this.noticeService.info(g("notice.deckTemplateInserted",{deck:i.insertedDeck}))}catch(r){console.error("Deck template insertion failed.",r),this.noticeService.error(xe(r,"notice.deckTemplateInsertionFailed"))}}async runClearCurrentFileSyncedCards(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(g("notice.noActiveMarkdownForReset"));return}if(!this.clearCurrentFileSyncedCardsUseCase){this.noticeService.error(g("notice.clearCurrentFileUseCaseNotInitialized"));return}try{if(!await this.clearCurrentFileSyncedCardsUseCase.hasTrackedCards(n.path)){this.noticeService.info(g("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(xe(r,"notice.clearCurrentFileFailed"))}}async runCleanupEmptyDecks(){if(!this.cleanupEmptyDecksUseCase){this.noticeService.error(g("notice.cleanupEmptyDecksUseCaseNotInitialized"));return}try{let n=await this.cleanupEmptyDecksUseCase.listCandidates();if(n.length===0){this.noticeService.info(g("notice.noEmptyDeckCandidates"));return}let r=await new Lt(this.app,n).openAndGetSelection();if(r===null){this.noticeService.info(g("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(xe(n,"notice.cleanupEmptyDecksFailed"))}}};var kl=dt; +`;break;default:}return r};qe.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};ze.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 ue=ze;function va(e,t,n){this.src=e,this.env=n,this.tokens=[],this.inlineMode=!1,this.md=t}va.prototype.Token=ue;var Ta=va;var wd=/\r\n?|\n/g,vd=/\0/g;function or(e){let t;t=e.src.replace(wd,` +`),t=t.replace(vd,"\uFFFD"),e.src=t}function ur(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 sr(e){let t=e.tokens;for(let n=0,r=t.length;n\s]/i.test(e)}function Dd(e){return/^<\/a\s*>/i.test(e)}function dr(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"&&(Td(u.content)&&a>0&&a--,Dd(u.content)&&a++),!(a>0)&&u.type==="text"&&e.md.linkify.test(u.content)){let s=u.content,d=e.md.linkify.match(s),c=[],l=u.level,f=0;d.length>0&&d[0].index===0&&o>0&&i[o-1].type==="text_special"&&(d=d.slice(1));for(let m=0;mf){let M=new e.Token("text","",0);M.content=s.slice(f,b),M.level=l,c.push(M)}let x=new e.Token("link_open","a",1);x.attrs=[["href",F]],x.level=l++,x.markup="linkify",x.info="auto",c.push(x);let C=new e.Token("text","",0);C.content=k,C.level=l,c.push(C);let h=new e.Token("link_close","a",-1);h.level=--l,h.markup="linkify",h.info="auto",c.push(h),f=d[m].lastIndex}if(f=0;n--){let r=e[n];r.type==="text"&&!t&&(r.content=r.content.replace(Ed,Ld)),r.type==="link_open"&&r.info==="auto"&&t--,r.type==="link_close"&&r.info==="auto"&&t++}}function Nd(e){let t=0;for(let n=e.length-1;n>=0;n--){let r=e[n];r.type==="text"&&!t&&Da.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 cr(e){let t;if(e.md.options.typographer)for(t=e.tokens.length-1;t>=0;t--)e.tokens[t].type==="inline"&&(Ad.test(e.tokens[t].content)&&Id(e.tokens[t].children),Da.test(e.tokens[t].content)&&Nd(e.tokens[t].children))}var Pd=/['"]/,Aa=/['"]/g,Ea="\u2019";function pn(e,t,n){return e.slice(0,t)+n+e.slice(t+1)}function Rd(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,d=u.length;e:for(;s=0)p=u.charCodeAt(c.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 F=32;if(s=48&&p<=57&&(f=l=!1),l&&f&&(l=k,f=b),!l&&!f){m&&(a.content=pn(a.content,c.index,Ea));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"||!Pd.test(e.tokens[t].content)||Rd(e.tokens[t].children,e)}function pr(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(c,l):a[o]=this.src.slice(c,l)}return a.join("")};te.prototype.Token=ue;var La=te;var Bd=65536;function mr(e,t){let n=e.bMarks[t]+e.tShift[t],r=e.eMarks[t];return e.src.slice(n,r)}function Ia(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;d=Ia(s),d.length&&d[0]===""&&d.shift(),d.length&&d[d.length-1]===""&&d.pop();let l=d.length;if(l===0||l!==c.length)return!1;if(r)return!0;let f=e.parentType;e.parentType="table";let m=e.md.block.ruler.getRules("blockquote"),p=e.push("table_open","table",1),F=[t,0];p.map=F;let k=e.push("thead_open","thead",1);k.map=[t,t+1];let b=e.push("tr_open","tr",1);b.map=[t,t+1];for(let h=0;h=4||(d=Ia(s),d.length&&d[0]===""&&d.shift(),d.length&&d[d.length-1]===""&&d.pop(),C+=l-d.length,C>Bd))break;if(i===t+2){let T=e.push("tbody_open","tbody",1);T.map=x=[t+2,0]}let M=e.push("tr_open","tr",1);M.map=[i,i+1];for(let T=0;T=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 br(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 d=e.src.slice(u,i),c=e.src.slice(i,a);if(o===96&&c.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=[],d=[],c=[],l=e.md.block.ruler.getRules("blockquote"),f=e.parentType;e.parentType="blockquote";let m=!1,p;for(p=t;p=a)break;if(e.src.charCodeAt(i++)===62&&!C){let M=e.sCount[p]+1,T,D;e.src.charCodeAt(i)===32?(i++,M++,D=!1,T=!0):e.src.charCodeAt(i)===9?(T=!0,(e.bsCount[p]+M)%4===3?(i++,M++,D=!1):D=!0):T=!1;let I=M;for(u.push(e.bMarks[p]),e.bMarks[p]=i;i=a,s.push(e.bsCount[p]),e.bsCount[p]=e.sCount[p]+1+(T?1:0),d.push(e.sCount[p]),e.sCount[p]=I-M,c.push(e.tShift[p]),e.tShift[p]=i-e.bMarks[p];continue}if(m)break;let h=!1;for(let M=0,T=l.length;M";let b=[t,0];k.map=b,e.md.block.tokenize(e,t,p);let x=e.push("blockquote_close","blockquote",-1);x.markup=">",e.lineMax=o,e.parentType=f,b[1]=e.line;for(let C=0;C=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&&(c=!0);let l,f,m;if((m=Pa(e,s))>=0){if(l=!0,o=e.bMarks[s]+e.tShift[s],f=Number(e.src.slice(o,m-1)),c&&f!==1)return!1}else if((m=Na(e,s))>=0)l=!1;else return!1;if(c&&e.skipSpaces(m)>=e.eMarks[s])return!1;if(r)return!0;let p=e.src.charCodeAt(m-1),F=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 k=[s,0];u.map=k,u.markup=String.fromCharCode(p);let b=!1,x=e.md.block.ruler.getRules("list"),C=e.parentType;for(e.parentType="list";s=i?D=1:D=M-h,D>4&&(D=1);let I=h+D;u=e.push("list_item_open","li",1),u.markup=String.fromCharCode(p);let A=[s,0];u.map=A,l&&(u.info=e.src.slice(o,m-1));let R=e.tight,y=e.tShift[s],w=e.sCount[s],_=e.listIndent;if(e.listIndent=e.blkIndent,e.blkIndent=I,e.tight=!0,e.tShift[s]=T-e.bMarks[s],e.sCount[s]=M,T>=i&&e.isEmpty(s+1)?e.line=Math.min(e.line+2,n):e.md.block.tokenize(e,s,n,!0),(!e.tight||b)&&(d=!1),b=e.line-s>1&&e.isEmpty(e.line-1),e.blkIndent=e.listIndent,e.listIndent=_,e.tShift[s]=y,e.sCount[s]=w,e.tight=R,u=e.push("list_item_close","li",-1),u.markup=String.fromCharCode(p),s=e.line,A[1]=s,s>=n||e.sCount[s]=4)break;let L=!1;for(let P=0,q=x.length;P=4||e.src.charCodeAt(i)!==91)return!1;function u(x){let C=e.lineMax;if(x>=C||e.isEmpty(x))return null;let h=!1;if(e.sCount[x]-e.blkIndent>3&&(h=!0),e.sCount[x]<0&&(h=!0),!h){let D=e.md.block.ruler.getRules("reference"),I=e.parentType;e.parentType="reference";let A=!1;for(let R=0,y=D.length;R"u"&&(e.env.references={}),typeof e.env.references[b]>"u"&&(e.env.references[b]={title:k,href:l}),e.line=o),!0):!1}var Ra=["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 qd="[a-zA-Z_:][a-zA-Z0-9:._-]*",zd="[^\"'=<>`\\x00-\\x20]+",Hd="'[^']*'",Od='"[^"]*"',Wd="(?:"+zd+"|"+Hd+"|"+Od+")",$d="(?:\\s+"+qd+"(?:\\s*=\\s*"+Wd+")?)",Ba="<[A-Za-z][A-Za-z0-9\\-]*"+$d+"*\\s*\\/?>",Ga="<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>",Ud="",Qd="<[?][\\s\\S]*?[?]>",Vd="]*>",jd="",qa=new RegExp("^(?:"+Ba+"|"+Ga+"|"+Ud+"|"+Qd+"|"+Vd+"|"+jd+")"),za=new RegExp("^(?:"+Ba+"|"+Ga+")");var He=[[/^<(script|pre|style|textarea)(?=(\s|>|$))/i,/<\/(script|pre|style|textarea)>/i,!0],[/^/,!0],[/^<\?/,/\?>/,!0],[/^/,!0],[/^/,!0],[new RegExp("^|$))","i"),/^$/,!0],[new RegExp(za.source+"\\s*$"),/^$/,!1]];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||!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 d=e.push("heading_open","h"+String(u),1);d.markup="########".slice(0,u),d.map=[t,e.line];let c=e.push("inline","",0);c.content=e.src.slice(i,a).trim(),c.map=[t,e.line],c.children=[];let l=e.push("heading_close","h"+String(u),-1);return l.markup="########".slice(0,u),!0}function wr(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 m=e.bMarks[u]+e.tShift[u],p=e.eMarks[u];if(m=p))){a=o===61?1:2;break}}if(e.sCount[u]<0)continue;let f=!1;for(let m=0,p=r.length;m3||e.sCount[a]<0)continue;let d=!1;for(let c=0,l=r.length;c=n||e.sCount[o]=a){e.line=n;break}let s=e.line,d=!1;for(let c=0;c=e.line)throw new Error("block rule didn't increment state.line");break}if(!d)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};it.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(Zd);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 d=e.md.normalizeLink(u);if(!e.md.validateLink(d))return!1;if(!t){e.pending=e.pending.slice(0,-a.length);let c=e.push("link_open","a",1);c.attrs=[["href",d]],c.markup="linkify",c.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 Ar(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){Er[e.charCodeAt(0)]=1});function _r(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&&Er[i]!==0?u.content=a:u.content=o,u.markup=o,u.info="escape"}return e.pos=n+1,!0}function Lr(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 d=e.tokens[a.token];d.type=o?"strong_close":"em_close",d.tag=o?"strong":"em",d.nesting=-1,d.markup=o?u+u:u,d.content="",o&&(e.tokens[t[r-1].token].content="",e.tokens[t[i.end+1].token].content="",r--)}}function ec(e){let t=e.tokens_meta,n=e.tokens_meta.length;$a(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)&&(d=!0),p++}if(d){if(typeof e.env.references>"u")return!1;if(p=0?r=e.src.slice(s,p++):p=m+1):p=m+1,r||(r=e.src.slice(f,m)),a=e.env.references[Te(r)],!a)return e.pos=c,!1;o=a.href,u=a.title}if(!t){e.pos=f,e.posMax=m;let F=e.push("link_open","a",1),k=[["href",o]];F.attrs=k,u&&k.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 Rr(e,t){let n,r,i,a,o,u,s,d,c="",l=e.pos,f=e.posMax;if(e.src.charCodeAt(e.pos)!==33||e.src.charCodeAt(e.pos+1)!==91)return!1;let m=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(d=a,u=e.md.helpers.parseLinkDestination(e.src,a,e.posMax),u.ok&&(c=e.md.normalizeLink(u.str),e.md.validateLink(c)?a=u.pos:c=""),d=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(d,a++):a=p+1):a=p+1,i||(i=e.src.slice(m,p)),o=e.env.references[Te(i)],!o)return e.pos=l,!1;c=o.href,s=o.title}if(!t){r=e.src.slice(m,p);let F=[];e.md.inline.parse(r,e.md,e.env,F);let k=e.push("image","img",0),b=[["src",c],["alt",""]];k.attrs=b,k.children=F,k.content=r,s&&b.push(["title",s])}return e.pos=a,e.posMax=f,!0}var tc=/^([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])?)*)$/,nc=/^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;function Br(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(nc.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 d=e.push("link_close","a",-1);d.markup="autolink",d.info="auto"}return e.pos+=a.length+2,!0}if(tc.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 d=e.push("link_close","a",-1);d.markup="autolink",d.info="auto"}return e.pos+=a.length+2,!0}return!1}function rc(e){return/^\s]/i.test(e)}function ic(e){return/^<\/a\s*>/i.test(e)}function ac(e){let t=e|32;return t>=97&&t<=122}function Gr(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&&!ac(i))return!1;let a=e.src.slice(r).match(qa);if(!a)return!1;if(!t){let o=e.push("html_inline","",0);o.content=a[0],rc(o.content)&&e.linkLevel++,ic(o.content)&&e.linkLevel--}return e.pos+=a[0].length,!0}var oc=/^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i,uc=/^&([a-z][a-z0-9]{1,31});/i;function qr(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(oc);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=ln(o)?rt(o):rt(65533),u.markup=a[0],u.info="entity"}return e.pos+=a[0].length,!0}}else{let a=e.src.slice(n).match(uc);if(a){let o=he(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 Ua(e){let t={},n=e.length;if(!n)return;let r=0,i=-2,a=[];for(let o=0;os;d-=a[d]+1){let l=e[d];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 m=d>0&&!e[d-1].open?a[d-1]+1:0;a[o]=o-d+m,a[d]=m,u.open=!1,l.end=o,l.close=!1,c=-1,i=-2;break}}}c!==-1&&(t[u.marker][(u.open?3:0)+(u.length||0)%3]=c)}}function zr(e){let t=e.tokens_meta,n=e.tokens_meta.length;Ua(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};at.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()};at.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 $r(e){return Array.prototype.slice.call(arguments,1).forEach(function(n){n&&Object.keys(n).forEach(function(r){e[r]=n[r]})}),e}function hn(e){return Object.prototype.toString.call(e)}function sc(e){return hn(e)==="[object String]"}function dc(e){return hn(e)==="[object Object]"}function cc(e){return hn(e)==="[object RegExp]"}function ja(e){return hn(e)==="[object Function]"}function lc(e){return e.replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}var Za={fuzzyLink:!0,fuzzyEmail:!0,fuzzyIP:!1};function pc(e){return Object.keys(e||{}).reduce(function(t,n){return t||Za.hasOwnProperty(n)},!1)}var fc={"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}}},gc="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]",mc="biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|\u0440\u0444".split("|");function hc(e){e.__index__=-1,e.__text_cache__=""}function kc(e){return function(t,n){let r=t.slice(n);return e.test(r)?r.match(e)[0].length:0}}function Ka(){return function(e,t){t.normalize(e)}}function mn(e){let t=e.re=Va(e.__opts__),n=e.__tlds__.slice();e.onCompile(),e.__tlds_replaced__||n.push(gc),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 d={validate:null,link:null};if(e.__compiled__[u]=d,dc(s)){cc(s.validate)?d.validate=kc(s.validate):ja(s.validate)?d.validate=s.validate:a(u,s),ja(s.normalize)?d.normalize=s.normalize:s.normalize?a(u,s):d.normalize=Ka();return}if(sc(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:Ka()};let o=Object.keys(e.__compiled__).filter(function(u){return u.length>0&&e.__compiled__[u]}).map(lc).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"),hc(e)}function bc(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 Ur(e,t){let n=new bc(e,t);return e.__compiled__[n.schema].normalize(n,e),n}function V(e,t){if(!(this instanceof V))return new V(e,t);t||pc(e)&&(t=e,e={}),this.__opts__=$r({},Za,t),this.__index__=-1,this.__last_index__=-1,this.__schema__="",this.__text_cache__="",this.__schemas__=$r({},fc,e),this.__compiled__={},this.__tlds__=mc,this.__tlds_replaced__=!1,this.re={},mn(this)}V.prototype.add=function(t,n){return this.__schemas__[t]=n,mn(this),this};V.prototype.set=function(t){return this.__opts__=$r(this.__opts__,t),this};V.prototype.test=function(t){if(this.__text_cache__=t,this.__index__=-1,!t.length)return!1;let n,r,i,a,o,u,s,d,c;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:"]&&(d=t.search(this.re.host_fuzzy_test),d>=0&&(this.__index__<0||d=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};V.prototype.pretest=function(t){return this.re.pretest.test(t)};V.prototype.testSchemaAt=function(t,n,r){return this.__compiled__[n.toLowerCase()]?this.__compiled__[n.toLowerCase()].validate(t,r,this):0};V.prototype.match=function(t){let n=[],r=0;this.__index__>=0&&this.__text_cache__===t&&(n.push(Ur(this,r)),r=this.__last_index__);let i=r?t.slice(r):t;for(;this.test(i);)n.push(Ur(this,r)),i=i.slice(this.__last_index__),r+=this.__last_index__;return n.length?n:null};V.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,Ur(this,0)):null};V.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(),mn(this),this):(this.__tlds__=t.slice(),this.__tlds_replaced__=!0,mn(this),this)};V.prototype.normalize=function(t){t.schema||(t.url="http://"+t.url),t.schema==="mailto:"&&!/^mailto:/i.test(t.url)&&(t.url="mailto:"+t.url)};V.prototype.onCompile=function(){};var Ya=V;var yc=/^xn--/,xc=/[^\0-\x7F]/,Cc=/[\x2E\u3002\uFF0E\uFF61]/g,Sc={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},Qr=35,ne=Math.floor,Vr=String.fromCharCode;function ke(e){throw new RangeError(Sc[e])}function Fc(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(Cc,".");let i=e.split("."),a=Fc(i,t).join(".");return r+a}function eo(e){let t=[],n=0,r=e.length;for(;n=55296&&i<=56319&&nString.fromCodePoint(...e),wc=function(e){return e>=48&&e<58?26+(e-48):e>=65&&e<91?e-65:e>=97&&e<123?e-97:36},Xa=function(e,t){return e+22+75*(e<26)-((t!=0)<<5)},to=function(e,t,n){let r=0;for(e=n?ne(e/700):e>>1,e+=ne(e/t);e>Qr*26>>1;r+=36)e=ne(e/Qr);return ne(r+(Qr+1)*e/(e+38))},no=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&&ke("not-basic"),t.push(e.charCodeAt(u));for(let u=o>0?o+1:0;u=n&&ke("invalid-input");let f=wc(e.charCodeAt(u++));f>=36&&ke("invalid-input"),f>ne((2147483647-r)/c)&&ke("overflow"),r+=f*c;let m=l<=a?1:l>=a+26?26:l-a;if(fne(2147483647/p)&&ke("overflow"),c*=p}let d=t.length+1;a=to(r-s,d,s==0),ne(r/d)>2147483647-i&&ke("overflow"),i+=ne(r/d),r%=d,t.splice(r++,0,i)}return String.fromCodePoint(...t)},ro=function(e){let t=[];e=eo(e);let n=e.length,r=128,i=0,a=72;for(let s of e)s<128&&t.push(Vr(s));let o=t.length,u=o;for(o&&t.push("-");u=r&&cne((2147483647-i)/d)&&ke("overflow"),i+=(s-r)*d,r=s;for(let c of e)if(c2147483647&&ke("overflow"),c===r){let l=i;for(let f=36;;f+=36){let m=f<=a?1:f>=a+26?26:f-a;if(l=0))try{t.hostname=jr.toASCII(t.hostname)}catch{}return en(Re(t))}function Nc(e){let t=nt(e,!0);if(t.hostname&&(!t.protocol||uo.indexOf(t.protocol)>=0))try{t.hostname=jr.toUnicode(t.hostname)}catch{}return tt(Re(t),tt.defaultChars+"%")}function j(e,t){if(!(this instanceof j))return new j(e,t);t||cn(e)||(t=e||{},e="default"),this.inline=new Qa,this.block=new Ha,this.core=new _a,this.renderer=new wa,this.linkify=new Ya,this.validateLink=Lc,this.normalizeLink=Ic,this.normalizeLinkText=Nc,this.utils=tr,this.helpers=Ge({},ar),this.options={},this.configure(e),t&&this.set(t)}j.prototype.set=function(e){return Ge(this.options,e),this};j.prototype.configure=function(e){let t=this;if(cn(e)){let n=e;if(e=Ac[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 ot=j;var Pc=/^#[^\s#.,,。;;::!?!?()[\]{}<>]+(?:\/[^\s#.,,。;;::!?!?()[\]{}<>]+)*$/u;function kn(e,t){if(t||e.length===0)return e;let n=e.split(/\r?\n/),r=n.filter(i=>!Rc(i));return r.length===n.length?e:Gc(Bc(r)).join(` +`)}function Rc(e){let t=e.trim();return t?t.split(/\s+/).every(n=>Pc.test(n)):!1}function Bc(e){let t=0,n=e.length;for(;tt&&!e[n-1].trim();)n-=1;return e.slice(t,n)}function Gc(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 qc="#[^\\s#.,\uFF0C\u3002;\uFF1B:\uFF1A!?\uFF01\uFF1F()[\\]{}<>]+(?:\\/[^\\s#.,\uFF0C\u3002;\uFF1B:\uFF1A!?\uFF01\uFF1F()[\\]{}<>]+)*";var zc=/[\p{L}\p{N}_/#]/u,Hc=new Set(["code","pre"]),Oc="ahs-ob-tag";function bn(e){if(!e||!e.includes("#"))return e;let t="",n=0,r=[];for(;nn){let s=e.slice(n,a);t+=r.length===0?so(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?so(s):s;break}let u=e.slice(n,o+1);Uc(u,r),t+=u,n=o+1}return t}function so(e){let t=new RegExp(qc,"gu"),n="",r=0,i;for(;(i=t.exec(e))!==null;){let a=i[0],o=i.index,u=o+a.length;if(!Wc(e,o))continue;let s=Tt([a])[0];s&&(n+=e.slice(r,o),n+=$c(a,s),r=u)}return r===0?e:n+e.slice(r)}function Wc(e,t){return t===0?!0:!zc.test(e[t-1]??"")}function $c(e,t){return`${co(e)}`}function Uc(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||!Hc.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 co(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var yn=class{constructor(t=new Z){this.deckNormalizationService=t}mapFilePathToDeck(t,n,r=[]){let i=Qc(t,n,r);if(i==="off")return{warnings:[]};let a=lo(t),o=a.lastIndexOf("/");if(o<0)return{warnings:[]};let u=a.slice(0,o);if(!u.trim())return{warnings:[]};let s=u.split("/").filter(Boolean);if(i==="folder-and-file"){let d=a.slice(o+1).replace(/\.[^.]+$/,"").trim();d&&s.push(d)}return s.some(d=>d.includes("::"))?{warnings:[{filePath:t,code:"deck_invalid_folder_segment"}]}:{deck:this.deckNormalizationService.normalize(s.join("/")),warnings:[]}}};function Qc(e,t,n){if(t==="off")return"off";let r=lo(e);return n.some(a=>{let o=Vc(a);return o.length>0&&jc(r,o)})?t==="folder"?"folder-and-file":"folder":t}function Vc(e){return e.trim().replace(/\\/g,"/").replace(/^\/+|\/+$/g,"")}function lo(e){return e.trim().replace(/\\/g,"/").replace(/^\/+/,"")}function jc(e,t){return e===t||e.startsWith(`${t}/`)}var Oe=class{constructor(t=new yn,n=new Z){this.folderDeckMappingService=t;this.deckNormalizationService=n}resolve(t,n){if(t.deckHint)return{resolvedDeck:{value:this.deckNormalizationService.normalize(t.deckHint),source:t.deckHintSource??"body"},warnings:[...t.deckWarnings]};let r=this.folderDeckMappingService.mapFilePathToDeck(t.filePath,n.folderDeckMode,n.alternateFolderDeckModeFolders);return r.deck?{resolvedDeck:{value:r.deck,source:"folder"},warnings:[...t.deckWarnings,...r.warnings]}:{resolvedDeck:{value:this.deckNormalizationService.normalize(n.defaultDeck),source:"default"},warnings:[...t.deckWarnings,...r.warnings,{filePath:t.filePath,code:"deck_fallback_default"}]}}};function We(e){return`${e.filePath}\0${e.code}\0${Kr(e.params)}`}function Kr(e){return e===void 0?"":e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(n=>Kr(n)).join(",")}]`:`{${Object.entries(e).sort(([n],[r])=>n.localeCompare(r)).map(([n,r])=>`${JSON.stringify(n)}:${Kr(r)}`).join(",")}}`}function xn({href:e,label:t,escapeHref:n=!0}){return`${po(t)}`}function ut(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 po(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var Kc=new ot({breaks:!0,html:!0,linkify:!0}),Zc=/`[^`\n]+`/g,Yc=/==(.+?)==/g,Cn=class{constructor(t,n=new ce,r=new Oe,i=new X,a=()=>Date.now(),o=()=>`g_${Q(`${Date.now()}_${Math.random()}_${Date.now()}`).slice(0,12)}`,u=()=>(this.sequence+=1,`i_${Q(`${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=Jc(n.groupBlocks??{}),d=new Set,c=new Map,l=[],f=new Map,m=new Set,p=[],F=0,k=0,b=0,x=0,C=this.buildGroupBacklinkAnchor(t[0]??null,r);for(let h of t){if(h.items.length>o.length)throw new S("errors.noteFieldMapping.qaGroupSlotCapacityExceeded",{modelName:i,capacity:o.length,itemCount:h.items.length,filePath:h.filePath,blockStartLine:h.blockStartLine});let M=await this.resolveRecoveredGroup(h,s,i,a,o),T=M.groupId??h.groupId??this.createGroupId(),D=ul(M.items,o),I=tl(h.items,D,this.createItemId,o);if(I.length>o.length)throw new S("errors.noteFieldMapping.qaGroupSlotCapacityExceeded",{modelName:i,capacity:o.length,itemCount:I.length,filePath:h.filePath,blockStartLine:h.blockStartLine});let A=nl(I,o),R=this.deckResolutionService.resolve({filePath:h.filePath,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:h.deckWarnings},r);for(let N of R.warnings)c.set(We(N),N);let y=R.resolvedDeck.value;d.has(y)||(await this.ankiGateway.ensureDeckExists(y),d.add(y));let w=I.map(N=>({...N,title:Zr(N.title,!1),answer:Zr(kn(N.answer,r.keepPureTagLinesInCardBody),!0)})),_=Xc(a,Zr(h.stem,!1),w,this.buildGroupBacklinkAnchor(h,r)||C,r.obsidianBacklinkPlacement,u),L=M.noteId??h.noteId,P=M.loadedNote;if(L===void 0)L=await this.ankiGateway.addNote({deckName:y,modelName:i,fields:_,tags:h.tagsHint??[]}),F+=1,m.add(h.syncKey);else{if(P??(P=await this.tryLoadQaGroupNote(L,h,i)),P.kind==="missing"&&(L=await this.ankiGateway.addNote({deckName:y,modelName:i,fields:_,tags:h.tagsHint??[]}),F+=1,m.add(h.syncKey)),P.kind==="matching"){let N=P.note,re=!al(N.fields,_),Ee=!(N.deckNames??[]).includes(y),_e=et(h.tagsHint,N.tags),vn=_e.addTags.length>0||_e.removeTags.length>0;if(!re&&!Ee&&!vn){f.set(h.syncKey,L);let ko=this.now();p.push({groupId:T,noteId:L,filePath:h.filePath,headingText:h.headingText,backlinkHeadingText:h.backlinkHeadingText,headingLevel:h.headingLevel,stem:h.stem,src:h.src||Fe(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:y,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:[...R.warnings],tagsHint:h.tagsHint?[...h.tagsHint]:[],items:I,freeSlots:A,lastSyncedAt:M.stateRecord?.lastSyncedAt??ko,orphan:!1});continue}(re||Ee)&&await this.ankiGateway.updateNote({noteId:L,fields:_,deckName:Ee?y:void 0}),re&&(k+=1),!re&&vn&&(k+=1),Ee&&(x+=1),vn&&await this.ankiGateway.syncNoteTags([{noteId:L,addTags:_e.addTags,removeTags:_e.removeTags}]),m.add(h.syncKey)}if(P.kind==="model-mismatch"){let N=!(P.note.deckNames??[]).includes(y),re=et(h.tagsHint,P.note.tags),Ee=re.addTags.length>0||re.removeTags.length>0;try{await this.ankiGateway.updateNoteModel({noteId:L,modelName:i,fields:_})}catch(_e){throw qt({noteId:L,fromModel:P.actualModelName,toModel:P.expectedModelName,error:_e,location:`${h.filePath}:${h.blockStartLine}`})}N&&P.note.cardIds.length>0&&(await this.ankiGateway.changeDecks([{deckName:y,cardIds:P.note.cardIds}]),x+=1),Ee&&await this.ankiGateway.syncNoteTags([{noteId:L,addTags:re.addTags,removeTags:re.removeTags}]),k+=1,b+=1,m.add(h.syncKey)}}f.set(h.syncKey,L);let q=Object.fromEntries(I.filter(N=>N.itemId&&N.slot).map(N=>[N.itemId,N.slot]));(h.markerState!=="present-valid"||!this.groupMarkerService.isEquivalent(h.groupMarker,L,q,A)||ol(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:L,groupId:T,itemToSlot:q,freeSlots:A,sourceContent:h.sourceContent??""});let be=this.now();p.push({groupId:T,noteId:L,filePath:h.filePath,headingText:h.headingText,backlinkHeadingText:h.backlinkHeadingText,headingLevel:h.headingLevel,stem:h.stem,src:h.src||Fe(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:y,deckHint:h.deckHint,deckHintSource:h.deckHintSource,deckWarnings:[...R.warnings],tagsHint:h.tagsHint?[...h.tagsHint]:[],items:I,freeSlots:A,lastSyncedAt:m.has(h.syncKey)?be:M.stateRecord?.lastSyncedAt??be,orphan:!1})}return{created:F,updated:k,migratedNoteTypes:b,migratedDecks:x,markerWrites:l,resolvedNoteIds:f,touchedSyncKeys:[...m],syncedGroupBlocks:p,warnings:[...c.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)??il(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"?{...el(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?"":xn({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 S("errors.noteFieldMapping.noteTypeNotSelected.qaGroup");let r=t.noteFieldMappings[B("qa-group",n)];if(!O(r))throw new S("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:sl(i)}}};function Xc(e,t,n,r,i,a){if(!e.titleField)throw new S("errors.noteFieldMapping.qaGroupMissingTitle",{modelName:e.modelName});let o=r&&i==="question-last-line"?ut({title:t,body:""},r,i).title:t,u={[e.titleField]:o};for(let d of e.slots)u[d.questionField]="",u[d.answerField]="";for(let d of a)u[d]="";let s=new Map(e.slots.map(d=>[d.index,d]));for(let d of n){if(d.slot===void 0)continue;let c=s.get(d.slot);if(!c)continue;let l=r&&i!=="question-last-line"?ut({title:d.title,body:d.answer},r,i).body:d.answer;u[c.questionField]=d.title,u[c.answerField]=l}return u}function Jc(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 el(e,t,n,r){let i=[],a=new Set;for(let o of t.slots){let u=go(e.fields[o.questionField]??""),s=go(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 tl(e,t,n,r){let i=new Map,a=[];for(let l of t){let f=fo(l.title,l.answer),m=i.get(f);m?m.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],m=s.shift();if(m){o[l]={...f,itemId:m.itemId,slot:m.slot};continue}o[l]={...f,itemId:n()}}let d=new Set(o.map(l=>l.slot).filter(l=>typeof l=="number")),c=[...r].filter(l=>!d.has(l));for(let l of o){if(l.slot!==void 0)continue;let f=c.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 nl(e,t){let n=new Set(e.map(r=>r.slot).filter(r=>typeof r=="number"));return t.filter(r=>!n.has(r))}function fo(e,t){return`${e}\0${t}`}function rl(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 il(e){if(!(!e||e.length!==1))return e[0]}function al(e,t){let n=Object.keys(t).sort();for(let r of n)if((e[r]??"")!==(t[r]??""))return!1;return!0}function ol(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=Kc.renderInline(i).trim();return t?bn(a):a}function ul(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 go(e){return e.replace(/

]*>.*?<\/a><\/p>/g,"").replace(/
]*>.*?<\/a>/g,"").trim()}function sl(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 dl(e){let t=[];return{text:e.replace(Zc,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 cl="manual-render-v3",Ae=class{constructor(t=new Oe){this.deckResolutionService=t}resolve(t,n){let r=ll(t.cardType,n),i=this.deckResolutionService.resolve(t,n),a=i.resolvedDeck.value,o=n.noteFieldMappings[B(t.cardType,r)]??null,u=t.cardType==="cloze"&&t.clozeMode==="all"?"all":void 0,s={version:cl,cardType:t.cardType,clozeMode:u,noteModel:r,mapping:o,addObsidianBacklink:n.addObsidianBacklink,obsidianBacklinkLabel:n.obsidianBacklinkLabel,obsidianBacklinkPlacement:n.obsidianBacklinkPlacement,convertHighlightsToCloze:n.convertHighlightsToCloze,keepPureTagLinesInCardBody:n.keepPureTagLinesInCardBody},d=Q(JSON.stringify(s));return{deck:a,noteModel:r,renderConfigHash:d,warnings:i.warnings}}};function ll(e,t){if(Ei(e)){if(!t.clozeNoteType.trim())throw new S("errors.noteFieldMapping.noteTypeNotSelected.cloze");return t.clozeNoteType}if(!t.qaNoteType.trim())throw new S("errors.noteFieldMapping.noteTypeNotSelected.basic");return t.qaNoteType}var Yr=/`[^`\n]+`/g,Xr=/```[\s\S]*?```|~~~[\s\S]*?~~~/g,Sn=/==(.+?)==/g,Jr=/(?:(?0&&i.add(u)}for(let o of r.text.matchAll(Jr)){let u=o[1],s=u?Number(u):e.clozeMode==="all"?1:a++;Number.isInteger(s)&&s>0&&i.add(s)}return i}function $e(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,d)=>u.split(`@@${n}_${d}@@`).join(o(s)),a)}}var Fn=class{constructor(t=new Ae){this.renderConfigService=t}plan(t,n,r,i){let a=new Map,o=new Set(n.pendingWriteBack.filter(x=>x.markerKind!=="group-gi").map(x=>Ie(x.filePath,x.blockStartLine,x.rawBlockHash))),u=new Set,s=[],d=[],c=[],l=[],f=[],m=[],p=new Map,F=0;for(let x of t){if(a.has(x.syncKey))throw new Error(`Duplicate syncKey detected in current scan: ${x.syncKey}`);if(a.set(x.syncKey,x),x.noteId!==void 0){let R=z(x.noteId);if(u.has(R))throw new Error(`Duplicate noteId detected in current scan: ${x.noteId}`);u.add(R)}let C=x.noteId!==void 0?n.cards[z(x.noteId)]:void 0,h=this.renderConfigService.resolve(x,i);for(let R of h.warnings)p.set(We(R),R);let M=x.noteId,T=Ie(x.filePath,x.blockStartLine,x.rawBlockHash),D={card:{...x,noteId:M},noteId:M,deck:h.deck,noteModel:h.noteModel,renderConfigHash:h.renderConfigHash};if(!M){s.push(D);continue}if(fl(C,x,i)){d.push(D);continue}if(l.push(D),(x.idMarkerState!=="present-valid"||x.noteIdSource!=="marker"||o.has(T))&&m.push(D),!C){c.push(D);continue}let I=C.rawBlockHash!==x.rawBlockHash||C.renderConfigHash!==h.renderConfigHash||!ji(C.tagsHint,x.tagsHint)||C.orphan,A=C.deck!==h.deck;I&&c.push(D),A&&f.push(D),!I&&!A&&(F+=1)}let k=new Set(r),b=Object.values(n.cards).filter(x=>k.has(x.filePath)&&!u.has(z(x.noteId)));return{toCreate:s,toRebuild:d,toUpdate:c,toVerifyDeck:l,toChangeDeck:f,toRewriteMarker:m,toOrphan:b,unchangedCards:F,warnings:Array.from(p.values())}}};function fl(e,t,n){if(!e||e.cardType!=="cloze"||t.cardType!=="cloze")return!1;let r=Se(e.cardType,e.clozeMode);if(r!=="sequential"||t.clozeMode!=="all")return!1;let i=ei({bodyMarkdown:e.bodyMarkdown,clozeMode:r,convertHighlightsToCloze:n.convertHighlightsToCloze}),a=ei({bodyMarkdown:t.bodyMarkdown,clozeMode:t.clozeMode,convertHighlightsToCloze:n.convertHighlightsToCloze});return i.size>a.size}var mo=new ot({breaks:!0,html:!0,linkify:!0}),gl=/(?`\\[${k.trim()}\\]`),d=d.replace(ml,(F,k)=>`\\(${k.trim()}\\)`),i&&r.convertHighlightsToCloze&&(d=d.replace(Sn,"{$1}")),i&&(d=d.replace(Jr,(F,k,b)=>`{{c${k?Number(k):n.card.clozeMode==="all"?1:l++}::${b}}}`)),d=d.replace(kl,(F,k)=>{let b=r.resourceResolver.resolveEmbed(k,n.card.filePath);return b?(c.push({kind:b.kind,fileName:b.fileName,absolutePath:b.absolutePath,altText:b.altText}),b.kind==="audio"?`[sound:${b.fileName}]`:`${st(b.altText??b.fileName)}`):F}),d=d.replace(bl,(F,k)=>{let b=r.resourceResolver.resolveWikiLink(k,n.card.filePath);return b?`${st(b.displayText)}`:F}),d=d.replace(Sn,"$1");let f=$e(d,hl,"MATH");d=f.text,d=s.restore(d),d=u.restore(d);let m=(a?mo.renderInline(d):mo.render(d)).trim(),p=f.restore(m,st);return{html:a?p:bn(p),media:c}}};function yl(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 st(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var dt=class extends S{constructor(t){super("errors.currentFileOutOfScope",{filePath:t}),this.name="CurrentFileOutOfScopeError"}},Ue=class extends S{constructor(){super("errors.runScopeNotConfigured"),this.name="RunScopeNotConfiguredError"}},wn=class{constructor(t,n,r,i=new Zt(t),a=new Fn,o=new Mn,u=new Ot(r),s=new Yt(t),d=new Ae,c=()=>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 Pe;if(this.qaGroupSyncService=new Cn(r,void 0,void 0,void 0,void 0,void 0,void 0,this.vaultGateway.createBacklink.bind(this.vaultGateway)),xl(d)){this.renderConfigService=d,this.now=c;return}this.renderConfigService=new Ae,this.now=d}async syncVault(t){pe(t),this.assertRunScopeConfigured(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(pe(n),this.assertRunScopeConfigured(n),!this.scanScopeService.isPathInScope(t,n.scopeMode,n.includeFolders,n.excludeFolders))throw new dt(t);let r=await this.pluginStateRepository.load(),i=await this.fileIndexerService.indexFile(t,n,r);return this.syncIndexedResult(i,r,n)}assertRunScopeConfigured(t){if(!gt(t.scopeMode,t.includeFolders))throw new Ue}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 m of[...i.toCreate,...i.toRebuild,...i.toUpdate])o.has(m.card.syncKey)||o.set(m.card.syncKey,this.renderer.render(m,a));let u=await this.ankiBatchExecutor.execute(i,o,m=>Promise.resolve(this.renderer.render(m,a)),r.noteFieldMappings),s=await this.qaGroupSyncService.sync(t.groupBlocks,n,r),d=new Map(t.indexedFiles.map(m=>[m.filePath,m])),c=await this.markdownWriteBackService.write(u.markerWrites,d,s.markerWrites),l=Cl(n,t.scopedFilePaths,s.syncedGroupBlocks),f=this.buildNextState(n,t.cards,t.indexedFiles,s.syncedGroupBlocks,r,new Set([...u.touchedSyncKeys,...s.touchedSyncKeys,...c.writtenSyncKeys]),u.resolvedNoteIds,i.toOrphan,l);if(f.pendingWriteBack=[...n.pendingWriteBack.filter(m=>!new Set(t.scopedFilePaths).has(m.filePath)),...c.pendingEntries],this.markFilesDirty(f,[...c.failureFiles.map(m=>m.filePath),...c.conflictFiles]),await this.pluginStateRepository.save(f),c.failureFiles.length>0)throw this.createWriteBackFailureError(c.failureFiles);return{scannedFiles:t.scannedFiles,scannedCards:t.cards.length+t.groupBlocks.length,created:u.created+s.created,rebuilt:u.rebuilt,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:c.writtenSyncKeys.length,markerWriteConflictFiles:c.conflictFiles,warnings:Sl(i.warnings,s.warnings)}}buildNextState(t,n,r,i,a,o,u,s,d){let c=this.now(),l=Qn(a),f=new Set(r.filter(k=>k.content!==void 0).map(k=>k.filePath)),m=new Map;for(let k of i){let b=m.get(k.filePath);b?b.push(k):m.set(k.filePath,[k])}let p={files:{...t.files},cards:{...t.cards},groupBlocks:{...t.groupBlocks??{}},pendingWriteBack:[...t.pendingWriteBack]};for(let k of f)delete p.files[k];for(let[k,b]of Object.entries(p.cards))f.has(b.filePath)&&delete p.cards[k];for(let[k,b]of Object.entries(p.groupBlocks??{}))f.has(b.filePath)&&delete p.groupBlocks?.[k];let F=new Map;for(let k of n){let b=u.get(k.syncKey)??k.noteId;b!==void 0&&F.set(k.syncKey,b)}for(let k of r){if(k.content===void 0)continue;let b=Array.from(new Set(k.cards.map(x=>F.get(x.syncKey)).filter(x=>x!==void 0)));p.files[k.filePath]={filePath:k.filePath,fileHash:k.fileHash,fileStamp:k.fileStamp,deckRulesFingerprint:l,lastIndexedAt:c,noteIds:b,groupIds:(m.get(k.filePath)??[]).map(x=>x.groupId)}}for(let k of n){let b=F.get(k.syncKey);if(b===void 0)continue;let x=t.cards[z(b)]??(k.noteId!==void 0?t.cards[z(k.noteId)]:void 0),C=this.renderConfigService.resolve(k,a);p.cards[z(b)]={noteId:b,filePath:k.filePath,heading:k.heading,backlinkHeadingText:k.backlinkHeadingText,headingLevel:k.headingLevel,bodyMarkdown:k.bodyMarkdown,cardType:k.cardType,clozeMode:k.clozeMode,blockStartOffset:k.blockStartOffset,blockEndOffset:k.blockEndOffset,blockStartLine:k.blockStartLine,bodyStartLine:k.bodyStartLine,blockEndLine:k.blockEndLine,contentEndLine:k.contentEndLine,markerLine:k.markerLine,rawBlockText:k.rawBlockText,rawBlockHash:k.rawBlockHash,renderConfigHash:C.renderConfigHash,deck:C.deck,deckHint:k.deckHint,deckHintSource:k.deckHintSource,deckWarnings:[...k.deckWarnings],tagsHint:k.tagsHint,lastSyncedAt:o.has(k.syncKey)?c:x?.lastSyncedAt??0,orphan:!1}}for(let k of s)p.cards[z(k.noteId)]={...k,orphan:!0};for(let k of i)p.groupBlocks??(p.groupBlocks={}),p.groupBlocks[k.groupId]=k;for(let k of d)p.groupBlocks??(p.groupBlocks={}),p.groupBlocks[k.groupId]={...k,orphan:!0};return p}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 S("errors.writeBack.summary",{fileCount:t.length},{failures:t})}};function xl(e){return typeof e=="object"&&e!==null&&"resolve"in e}function Cl(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 Sl(...e){let t=new Map;for(let n of e)for(let r of n)t.set(We(r),r);return[...t.values()]}var ct=class extends ho.Plugin{constructor(){super(...arguments);this.settings=H;this.noticeService=new Nt;this.ankiGateway=new wt(()=>this.settings.ankiConnectUrl);this.deckTemplateInsertionService=new mt}async onload(){let n=new vt(this);this.pluginConfigRepository=new Et(n);let r=new Lt(n),i=new At(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=H,this.noticeService.error(g("notice.invalidSettingsRestored"))}let a=new wn(i,r,this.ankiGateway);this.syncCurrentFileUseCase=new Ft(a),this.syncVaultUseCase=new Mt(a),this.clearCurrentFileSyncedCardsUseCase=new St(r,this.ankiGateway,i),this.cleanupEmptyDecksUseCase=new ht(this.ankiGateway),Ai(this),this.addSettingTab(new Gt(this))}async updateSettings(n){if(!this.pluginConfigRepository)return;let r=Ce({...this.settings,...n});try{await this.pluginConfigRepository.save(r),this.settings=r}catch(i){this.noticeService.error(xe(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(g("notice.noActiveMarkdownForSync"));return}if(!this.syncCurrentFileUseCase){this.noticeService.error(g("notice.syncUseCaseNotInitialized"));return}try{let r=await this.syncCurrentFileUseCase.execute(n.path,this.settings);this.noticeService.showSyncSummary("currentFile",r)}catch(r){if(r instanceof dt||r instanceof Ue){this.noticeService.info(lt(r));return}console.error("Current file sync failed.",r),this.noticeService.error(xe(r,"notice.currentFileSyncFailed"))}}async runSyncVault(){if(!this.syncVaultUseCase){this.noticeService.error(g("notice.syncUseCaseNotInitialized"));return}try{let n=await this.syncVaultUseCase.execute(this.settings);this.noticeService.showSyncSummary("vault",n)}catch(n){if(n instanceof Ue){this.noticeService.info(lt(n));return}console.error("Vault sync failed.",n),this.noticeService.error(xe(n,"notice.vaultSyncFailed"))}}async insertDeckTemplateToCurrentFile(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(g("notice.noActiveMarkdownForDeckTemplateInsertion"));return}if(!this.vaultGateway){this.noticeService.error(g("notice.vaultGatewayNotInitialized"));return}try{let r=await this.vaultGateway.readMarkdownFile(n.path);if(!r){this.noticeService.error(g("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(g("notice.deckTemplateAlreadyCurrent"));return}await this.vaultGateway.replaceMarkdownFile(n.path,i.expectedContent,i.nextContent),this.noticeService.info(g("notice.deckTemplateInserted",{deck:i.insertedDeck}))}catch(r){console.error("Deck template insertion failed.",r),this.noticeService.error(xe(r,"notice.deckTemplateInsertionFailed"))}}async runClearCurrentFileSyncedCards(){let n=this.app.workspace.getActiveFile();if(!n||n.extension.toLowerCase()!=="md"){this.noticeService.error(g("notice.noActiveMarkdownForReset"));return}if(!this.clearCurrentFileSyncedCardsUseCase){this.noticeService.error(g("notice.clearCurrentFileUseCaseNotInitialized"));return}try{if(!await this.clearCurrentFileSyncedCardsUseCase.hasTrackedCards(n.path)){this.noticeService.info(g("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(xe(r,"notice.clearCurrentFileFailed"))}}async runCleanupEmptyDecks(){if(!this.cleanupEmptyDecksUseCase){this.noticeService.error(g("notice.cleanupEmptyDecksUseCaseNotInitialized"));return}try{let n=await this.cleanupEmptyDecksUseCase.listCandidates();if(n.length===0){this.noticeService.info(g("notice.noEmptyDeckCandidates"));return}let r=await new It(this.app,n).openAndGetSelection();if(r===null){this.noticeService.info(g("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(xe(n,"notice.cleanupEmptyDecksFailed"))}}};var Fl=ct; diff --git a/src/application/config/PluginSettings.test.ts b/src/application/config/PluginSettings.test.ts index 427d53d..e89ac4e 100644 --- a/src/application/config/PluginSettings.test.ts +++ b/src/application/config/PluginSettings.test.ts @@ -76,6 +76,7 @@ describe("PluginSettings", () => { expect(DEFAULT_SETTINGS.folderDeckMode).toBe("folder-and-file"); expect(DEFAULT_SETTINGS.qaGroupMarker).toBe("#anki-list"); expect(DEFAULT_SETTINGS.cardAnswerCutoffMode).toBe("heading-block"); + expect(DEFAULT_SETTINGS.alternateFolderDeckModeFolders).toEqual([]); expect(DEFAULT_SETTINGS.obsidianBacklinkLabel).toBe(DEFAULT_OBSIDIAN_BACKLINK_LABEL); expect(DEFAULT_SETTINGS.obsidianBacklinkPlacement).toBe("answer-last-line"); expect(DEFAULT_SETTINGS.syncObsidianTagsToAnki).toBe(true); @@ -111,6 +112,40 @@ describe("PluginSettings", () => { }); }); + it("defaults alternate folder deck mode override folders to an empty array when missing", () => { + const settings = mergePluginSettings({ + defaultDeck: "Default", + }); + + expect(settings.alternateFolderDeckModeFolders).toEqual([]); + }); + + it("preserves alternate folder deck mode override folders using the current folder-list convention", () => { + const settings = mergePluginSettings({ + alternateFolderDeckModeFolders: ["notes", "notes/sub", "notes"], + }); + + expect(settings.alternateFolderDeckModeFolders).toEqual(["notes", "notes/sub", "notes"]); + }); + + it("rejects non-array alternate folder deck mode override folders", () => { + expectPluginUserError(() => { + validatePluginSettings({ + ...DEFAULT_SETTINGS, + alternateFolderDeckModeFolders: "notes" as never, + }); + }, "errors.settings.alternateFolderDeckModeFoldersArray"); + }); + + it("rejects non-string alternate folder deck mode override folder entries", () => { + expectPluginUserError(() => { + validatePluginSettings({ + ...DEFAULT_SETTINGS, + alternateFolderDeckModeFolders: ["notes", 1] as never, + }); + }, "errors.settings.alternateFolderDeckModeFoldersStrings"); + }); + it("normalizes cached Anki note types on load and save paths", () => { const settings = mergePluginSettings({ ankiNoteTypeCache: [" Custom Basic ", "", "Cloze", "Custom Basic"], diff --git a/src/application/config/PluginSettings.ts b/src/application/config/PluginSettings.ts index 6e5a58f..04706b5 100644 --- a/src/application/config/PluginSettings.ts +++ b/src/application/config/PluginSettings.ts @@ -60,6 +60,7 @@ export interface PluginSettings { scopeMode: ScopeMode; includeFolders: string[]; excludeFolders: string[]; + alternateFolderDeckModeFolders: string[]; addObsidianBacklink: boolean; obsidianBacklinkLabel: string; obsidianBacklinkPlacement: ObsidianBacklinkPlacement; @@ -89,6 +90,7 @@ export const DEFAULT_SETTINGS: PluginSettings = { scopeMode: "include", includeFolders: [], excludeFolders: [], + alternateFolderDeckModeFolders: [], addObsidianBacklink: true, obsidianBacklinkLabel: DEFAULT_OBSIDIAN_BACKLINK_LABEL, obsidianBacklinkPlacement: "answer-last-line", @@ -144,6 +146,7 @@ export function mergePluginSettings(settings?: Partial | null): ankiModelFieldCache: partialSettings.ankiModelFieldCache ?? DEFAULT_SETTINGS.ankiModelFieldCache, includeFolders: partialSettings.includeFolders ?? DEFAULT_SETTINGS.includeFolders, excludeFolders: partialSettings.excludeFolders ?? DEFAULT_SETTINGS.excludeFolders, + alternateFolderDeckModeFolders: partialSettings.alternateFolderDeckModeFolders ?? DEFAULT_SETTINGS.alternateFolderDeckModeFolders, }); } @@ -204,6 +207,7 @@ export function validatePluginSettings(settings: PluginSettings): void { validateFolderList(settings.includeFolders, "include"); validateFolderList(settings.excludeFolders, "exclude"); + validateFolderList(settings.alternateFolderDeckModeFolders, "alternateFolderDeckMode"); if (!settings.ankiConnectUrl.trim()) { throw new PluginUserError("errors.settings.ankiConnectUrlRequired"); @@ -256,14 +260,30 @@ function validateAnkiModelFieldCache(ankiModelFieldCache: AnkiModelFieldCache): } } -function validateFolderList(folderList: string[], label: "include" | "exclude"): void { +function validateFolderList(folderList: string[], label: "include" | "exclude" | "alternateFolderDeckMode"): void { if (!Array.isArray(folderList)) { - throw new PluginUserError(label === "include" ? "errors.settings.includeFoldersArray" : "errors.settings.excludeFoldersArray"); + if (label === "include") { + throw new PluginUserError("errors.settings.includeFoldersArray"); + } + + if (label === "exclude") { + throw new PluginUserError("errors.settings.excludeFoldersArray"); + } + + throw new PluginUserError("errors.settings.alternateFolderDeckModeFoldersArray"); } for (const folder of folderList) { if (typeof folder !== "string") { - throw new PluginUserError(label === "include" ? "errors.settings.includeFoldersStrings" : "errors.settings.excludeFoldersStrings"); + if (label === "include") { + throw new PluginUserError("errors.settings.includeFoldersStrings"); + } + + if (label === "exclude") { + throw new PluginUserError("errors.settings.excludeFoldersStrings"); + } + + throw new PluginUserError("errors.settings.alternateFolderDeckModeFoldersStrings"); } } } diff --git a/src/application/services/FileIndexerService.test.ts b/src/application/services/FileIndexerService.test.ts index 62f81b9..4262e07 100644 --- a/src/application/services/FileIndexerService.test.ts +++ b/src/application/services/FileIndexerService.test.ts @@ -299,6 +299,75 @@ describe("FileIndexerService", () => { expect(result.skippedUnchangedFiles).toBe(0); expect(vaultGateway.readCalls).toEqual(["notes/one.md"]); }); + + it("changes the fingerprint and forces re-read when alternate folder deck mode overrides changed", async () => { + const content = ["#### One", "Body"].join("\n"); + const oldSettings = createIndexSettingsForPath("notes/one.md", { folderDeckMode: "folder" }); + const newSettings = createIndexSettingsForPath("notes/one.md", { + folderDeckMode: "folder", + alternateFolderDeckModeFolders: ["notes"], + }); + const vaultGateway = new FakeManualSyncVaultGateway({ + "notes/one.md": content, + }); + const service = new FileIndexerService(vaultGateway); + const state = { + files: { + "notes/one.md": { + filePath: "notes/one.md", + fileHash: "hash-a", + fileStamp: `1:${content.length}`, + deckRulesFingerprint: createDeckRulesFingerprint(oldSettings), + lastIndexedAt: 1, + noteIds: [10], + }, + }, + cards: { + "10": { + noteId: 10, + filePath: "notes/one.md", + heading: "One", + backlinkHeadingText: "One", + headingLevel: 4, + bodyMarkdown: "Body", + cardType: "basic" as const, + blockStartOffset: 0, + blockEndOffset: 10, + blockStartLine: 1, + bodyStartLine: 2, + blockEndLine: 2, + contentEndLine: 2, + rawBlockText: content, + rawBlockHash: "hash-card", + renderConfigHash: "render-hash", + deck: "notes", + deckWarnings: [], + tagsHint: [], + lastSyncedAt: 1, + orphan: false, + }, + }, + pendingWriteBack: [], + }; + + expect(createDeckRulesFingerprint(oldSettings)).not.toBe(createDeckRulesFingerprint(newSettings)); + + const result = await service.indexVault(newSettings, state); + + expect(result.skippedUnchangedFiles).toBe(0); + expect(vaultGateway.readCalls).toEqual(["notes/one.md"]); + }); + + it("normalizes alternate folder deck mode override ordering inside the fingerprint", () => { + const first = createIndexSettingsForPath("notes/one.md", { + alternateFolderDeckModeFolders: ["notes/sub", "notes"], + }); + const second = createIndexSettingsForPath("notes/one.md", { + alternateFolderDeckModeFolders: ["notes", "notes/sub"], + }); + + expect(createDeckRulesFingerprint(first)).toBe(createDeckRulesFingerprint(second)); + }); }); function createIndexSettingsForPath(filePath: string, overrides: Parameters[0] = {}) { diff --git a/src/application/services/FileIndexerService.ts b/src/application/services/FileIndexerService.ts index 428486c..4e664a5 100644 --- a/src/application/services/FileIndexerService.ts +++ b/src/application/services/FileIndexerService.ts @@ -291,7 +291,7 @@ export function createFileStamp(mtime: number, size: number): string { return `${mtime}:${size}`; } -const DECK_RULES_FINGERPRINT_VERSION = "deck-rules-v4"; +const DECK_RULES_FINGERPRINT_VERSION = "deck-rules-v5"; export function createDeckRulesFingerprint(settings: PluginSettings): string { return hashString(JSON.stringify({ @@ -302,6 +302,7 @@ export function createDeckRulesFingerprint(settings: PluginSettings): string { fileDeckEnabled: settings.fileDeckEnabled, fileDeckMarker: settings.fileDeckMarker, folderDeckMode: settings.folderDeckMode, + alternateFolderDeckModeFolders: [...settings.alternateFolderDeckModeFolders].sort(), syncObsidianTagsToAnki: settings.syncObsidianTagsToAnki, keepPureTagLinesInCardBody: settings.keepPureTagLinesInCardBody, })); diff --git a/src/application/services/QaGroupSyncService.ts b/src/application/services/QaGroupSyncService.ts index cad2b33..07142c1 100644 --- a/src/application/services/QaGroupSyncService.ts +++ b/src/application/services/QaGroupSyncService.ts @@ -138,7 +138,7 @@ export class QaGroupSyncService { deckHint: block.deckHint, deckHintSource: block.deckHintSource, deckWarnings: block.deckWarnings, - } as never, settings.defaultDeck, settings.folderDeckMode); + } as never, settings); for (const warning of deckResolution.warnings) { warningMap.set(getDeckResolutionWarningKey(warning), warning); } diff --git a/src/application/services/RenderConfigService.ts b/src/application/services/RenderConfigService.ts index 04adee7..8a4dbb4 100644 --- a/src/application/services/RenderConfigService.ts +++ b/src/application/services/RenderConfigService.ts @@ -21,7 +21,7 @@ export class RenderConfigService { resolve(card: IndexedCard, settings: PluginSettings): RenderPlan { const noteModel = resolveNoteModel(card.cardType, settings); - const deckResolution = this.deckResolutionService.resolve(card, settings.defaultDeck, settings.folderDeckMode); + const deckResolution = this.deckResolutionService.resolve(card, settings); const deck = deckResolution.resolvedDeck.value; const mapping = settings.noteFieldMappings[createNoteFieldMappingKey(card.cardType, noteModel)] ?? null; const clozeMode = card.cardType === "cloze" && card.clozeMode === "all" diff --git a/src/domain/manual-sync/services/DeckResolutionService.test.ts b/src/domain/manual-sync/services/DeckResolutionService.test.ts index 9def670..e050c24 100644 --- a/src/domain/manual-sync/services/DeckResolutionService.test.ts +++ b/src/domain/manual-sync/services/DeckResolutionService.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "vitest"; +import type { PluginSettings } from "@/application/config/PluginSettings"; import type { IndexedCard } from "@/domain/manual-sync/entities/IndexedCard"; import { DeckResolutionService } from "./DeckResolutionService"; @@ -12,7 +13,7 @@ describe("DeckResolutionService", () => { filePath: "课程/数学/第一章/导数.md", deckHint: "显式/Deck", deckHintSource: "frontmatter", - }), "Default", "folder"); + }), createDeckSettings({ folderDeckMode: "folder" })); expect(result.resolvedDeck).toEqual({ value: "显式::Deck", @@ -24,7 +25,7 @@ describe("DeckResolutionService", () => { it("uses folder mapping when no explicit deck exists", () => { const service = new DeckResolutionService(); - const result = service.resolve(createIndexedCard({ filePath: "课程/数学/第一章/导数.md" }), "Default", "folder"); + const result = service.resolve(createIndexedCard({ filePath: "课程/数学/第一章/导数.md" }), createDeckSettings({ folderDeckMode: "folder" })); expect(result.resolvedDeck).toEqual({ value: "课程::数学::第一章", @@ -35,7 +36,7 @@ describe("DeckResolutionService", () => { it("supports folder-and-file mapping mode", () => { const service = new DeckResolutionService(); - const result = service.resolve(createIndexedCard({ filePath: "课程/数学/第一章/导数.md" }), "Default", "folder-and-file"); + const result = service.resolve(createIndexedCard({ filePath: "课程/数学/第一章/导数.md" }), createDeckSettings({ folderDeckMode: "folder-and-file" })); expect(result.resolvedDeck).toEqual({ value: "课程::数学::第一章::导数", @@ -46,7 +47,10 @@ describe("DeckResolutionService", () => { it("falls back to default deck for root-level files and emits a warning", () => { const service = new DeckResolutionService(); - const result = service.resolve(createIndexedCard({ filePath: "导数.md" }), " Default/Deck ", "folder-and-file"); + const result = service.resolve(createIndexedCard({ filePath: "导数.md" }), createDeckSettings({ + defaultDeck: " Default/Deck ", + folderDeckMode: "folder-and-file", + })); expect(result.resolvedDeck).toEqual({ value: "Default::Deck", @@ -58,7 +62,7 @@ describe("DeckResolutionService", () => { it("warns and falls back to default deck when folder mapping is invalid", () => { const service = new DeckResolutionService(); - const result = service.resolve(createIndexedCard({ filePath: "课程::非法/导数.md" }), "Default", "folder"); + const result = service.resolve(createIndexedCard({ filePath: "课程::非法/导数.md" }), createDeckSettings({ folderDeckMode: "folder" })); expect(result.resolvedDeck.value).toBe("Default"); expect(result.warnings.map((warning) => warning.code)).toEqual([ @@ -70,10 +74,35 @@ describe("DeckResolutionService", () => { filePath: "课程::非法/导数.md", deckHint: "显式::Deck", deckHintSource: "body", - }), "Default", "folder").resolvedDeck.value).toBe("显式::Deck"); + }), createDeckSettings({ folderDeckMode: "folder" })).resolvedDeck.value).toBe("显式::Deck"); + }); + + it("uses the opposite folder mapping mode when the file path hits an alternate override folder", () => { + const service = new DeckResolutionService(); + + const result = service.resolve(createIndexedCard({ filePath: "notes/sub/topic.md" }), createDeckSettings({ + folderDeckMode: "folder", + alternateFolderDeckModeFolders: ["notes/sub"], + })); + + expect(result.resolvedDeck).toEqual({ + value: "notes::sub::topic", + source: "folder", + }); }); }); +function createDeckSettings( + overrides: Partial> = {}, +): Pick { + return { + defaultDeck: "Default", + folderDeckMode: "folder-and-file", + alternateFolderDeckModeFolders: [], + ...overrides, + }; +} + function createIndexedCard(overrides: Partial = {}): IndexedCard { return { noteId: overrides.noteId, diff --git a/src/domain/manual-sync/services/DeckResolutionService.ts b/src/domain/manual-sync/services/DeckResolutionService.ts index ece58f3..16d9f25 100644 --- a/src/domain/manual-sync/services/DeckResolutionService.ts +++ b/src/domain/manual-sync/services/DeckResolutionService.ts @@ -1,4 +1,4 @@ -import type { FolderDeckMode } from "@/application/config/PluginSettings"; +import type { PluginSettings } from "@/application/config/PluginSettings"; import type { IndexedCard } from "@/domain/manual-sync/entities/IndexedCard"; import type { DeckResolutionResult } from "@/domain/manual-sync/value-objects/DeckResolution"; @@ -11,7 +11,7 @@ export class DeckResolutionService { private readonly deckNormalizationService = new DeckNormalizationService(), ) {} - resolve(card: IndexedCard, defaultDeck: string, folderDeckMode: FolderDeckMode): DeckResolutionResult { + resolve(card: IndexedCard, settings: Pick): DeckResolutionResult { if (card.deckHint) { return { resolvedDeck: { @@ -22,7 +22,11 @@ export class DeckResolutionService { }; } - const folderMapping = this.folderDeckMappingService.mapFilePathToDeck(card.filePath, folderDeckMode); + const folderMapping = this.folderDeckMappingService.mapFilePathToDeck( + card.filePath, + settings.folderDeckMode, + settings.alternateFolderDeckModeFolders, + ); if (folderMapping.deck) { return { resolvedDeck: { @@ -35,7 +39,7 @@ export class DeckResolutionService { return { resolvedDeck: { - value: this.deckNormalizationService.normalize(defaultDeck), + value: this.deckNormalizationService.normalize(settings.defaultDeck), source: "default", }, warnings: [ diff --git a/src/domain/manual-sync/services/FolderDeckMappingService.test.ts b/src/domain/manual-sync/services/FolderDeckMappingService.test.ts index 5ed9c52..a4ca4af 100644 --- a/src/domain/manual-sync/services/FolderDeckMappingService.test.ts +++ b/src/domain/manual-sync/services/FolderDeckMappingService.test.ts @@ -20,6 +20,26 @@ describe("FolderDeckMappingService", () => { }); }); + it("uses the opposite folder deck mode inside alternate override folders", () => { + const service = new FolderDeckMappingService(); + + expect(service.mapFilePathToDeck("notes/sub/topic.md", "folder", ["notes/sub"]).deck).toBe("notes::sub::topic"); + expect(service.mapFilePathToDeck("notes/sub/topic.md", "folder-and-file", ["notes/sub"]).deck).toBe("notes::sub"); + }); + + it("applies alternate overrides to descendants without matching sibling prefixes", () => { + const service = new FolderDeckMappingService(); + + expect(service.mapFilePathToDeck("notes/sub/topic.md", "folder", ["notes"]).deck).toBe("notes::sub::topic"); + expect(service.mapFilePathToDeck("notes2/sub/topic.md", "folder", ["notes"]).deck).toBe("notes2::sub"); + }); + + it("ignores alternate overrides when folder deck mode is off", () => { + const service = new FolderDeckMappingService(); + + expect(service.mapFilePathToDeck("notes/sub/topic.md", "off", ["notes/sub"])).toEqual({ warnings: [] }); + }); + it("returns empty for root-level files", () => { const service = new FolderDeckMappingService(); diff --git a/src/domain/manual-sync/services/FolderDeckMappingService.ts b/src/domain/manual-sync/services/FolderDeckMappingService.ts index 24a4492..76f34c5 100644 --- a/src/domain/manual-sync/services/FolderDeckMappingService.ts +++ b/src/domain/manual-sync/services/FolderDeckMappingService.ts @@ -11,24 +11,27 @@ export interface FolderDeckMappingResult { export class FolderDeckMappingService { constructor(private readonly deckNormalizationService = new DeckNormalizationService()) {} - mapFilePathToDeck(filePath: string, mode: FolderDeckMode): FolderDeckMappingResult { - if (mode === "off") { + mapFilePathToDeck(filePath: string, mode: FolderDeckMode, alternateFolderDeckModeFolders: string[] = []): FolderDeckMappingResult { + const effectiveMode = resolveEffectiveFolderDeckMode(filePath, mode, alternateFolderDeckModeFolders); + + if (effectiveMode === "off") { return { warnings: [] }; } - const lastSlash = filePath.lastIndexOf("/"); + const normalizedFilePath = normalizeFilePath(filePath); + const lastSlash = normalizedFilePath.lastIndexOf("/"); if (lastSlash < 0) { return { warnings: [] }; } - const folderPath = filePath.slice(0, lastSlash); + const folderPath = normalizedFilePath.slice(0, lastSlash); if (!folderPath.trim()) { return { warnings: [] }; } const segments = folderPath.split("/").filter(Boolean); - if (mode === "folder-and-file") { - const fileName = filePath.slice(lastSlash + 1).replace(/\.[^.]+$/, "").trim(); + if (effectiveMode === "folder-and-file") { + const fileName = normalizedFilePath.slice(lastSlash + 1).replace(/\.[^.]+$/, "").trim(); if (fileName) { segments.push(fileName); } @@ -48,4 +51,34 @@ export class FolderDeckMappingService { warnings: [], }; } +} + +function resolveEffectiveFolderDeckMode(filePath: string, mode: FolderDeckMode, alternateFolderDeckModeFolders: string[]): FolderDeckMode { + if (mode === "off") { + return "off"; + } + + const normalizedFilePath = normalizeFilePath(filePath); + const hasAlternateOverride = alternateFolderDeckModeFolders.some((folderPath) => { + const normalizedFolderPath = normalizeFolderPath(folderPath); + return normalizedFolderPath.length > 0 && isPathInsideFolder(normalizedFilePath, normalizedFolderPath); + }); + + if (!hasAlternateOverride) { + return mode; + } + + return mode === "folder" ? "folder-and-file" : "folder"; +} + +function normalizeFolderPath(folderPath: string): string { + return folderPath.trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, ""); +} + +function normalizeFilePath(filePath: string): string { + return filePath.trim().replace(/\\/g, "/").replace(/^\/+/, ""); +} + +function isPathInsideFolder(filePath: string, folderPath: string): boolean { + return filePath === folderPath || filePath.startsWith(`${folderPath}/`); } \ No newline at end of file diff --git a/src/infrastructure/persistence/DataJsonPluginConfigRepository.test.ts b/src/infrastructure/persistence/DataJsonPluginConfigRepository.test.ts index 0f0af07..fe3f06a 100644 --- a/src/infrastructure/persistence/DataJsonPluginConfigRepository.test.ts +++ b/src/infrastructure/persistence/DataJsonPluginConfigRepository.test.ts @@ -63,6 +63,20 @@ describe("DataJsonPluginConfigRepository", () => { expect(settings.folderDeckMode).toBe("off"); }); + it("persists alternate folder deck mode overrides across save and reload", async () => { + const store = new InMemoryPluginDataStore(); + const repository = new DataJsonPluginConfigRepository(store); + + await repository.save({ + ...DEFAULT_SETTINGS, + alternateFolderDeckModeFolders: ["notes", "notes/sub"], + }); + + const reloaded = await repository.load(); + + expect(reloaded.alternateFolderDeckModeFolders).toEqual(["notes", "notes/sub"]); + }); + it("normalizes blank backlink labels on load and save", async () => { const store = new InMemoryPluginDataStore({ settings: { diff --git a/src/presentation/i18n/messages/en.ts b/src/presentation/i18n/messages/en.ts index a87b223..8cede41 100644 --- a/src/presentation/i18n/messages/en.ts +++ b/src/presentation/i18n/messages/en.ts @@ -196,6 +196,17 @@ export const en = { failedLoad: "Failed to load folders from the current vault.", expandFolder: "Expand {{name}}", collapseFolder: "Collapse {{name}}", + folderDeckModeOverride: { + ariaLabel: "Toggle the alternate folder deck mapping mode for {{name}}", + hint: { + folder: "This folder uses the folder-only deck name by itself", + folderAndFile: "This folder uses the folder-and-file deck name by itself", + }, + title: { + folder: "Global mode is folder-and-file; enable this to use folder-only deck names for this folder", + folderAndFile: "Global mode is folder-only; enable this to use folder-and-file deck names for this folder", + }, + }, }, cards: { cardTypes: { @@ -377,6 +388,8 @@ export const en = { includeFoldersStrings: "Include folders must only contain strings.", excludeFoldersArray: "Exclude folders must be an array.", excludeFoldersStrings: "Exclude folders must only contain strings.", + alternateFolderDeckModeFoldersArray: "Alternate folder deck mode folders must be an array.", + alternateFolderDeckModeFoldersStrings: "Alternate folder deck mode 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.", diff --git a/src/presentation/i18n/messages/zh.ts b/src/presentation/i18n/messages/zh.ts index e999c44..3552a8f 100644 --- a/src/presentation/i18n/messages/zh.ts +++ b/src/presentation/i18n/messages/zh.ts @@ -194,6 +194,17 @@ export const zh = { failedLoad: "读取当前 vault 文件夹失败。", expandFolder: "展开 {{name}}", collapseFolder: "收起 {{name}}", + folderDeckModeOverride: { + ariaLabel: "切换 {{name}} 的文件夹牌组映射模式", + hint: { + folder: "本文件夹单独采用「文件夹」作为牌组名", + folderAndFile: "本文件夹单独采用「文件夹及文件名」作为牌组名", + }, + title: { + folder: "当前全局为「文件夹及文件名」,勾选后此文件夹改用「文件夹」作为牌组名", + folderAndFile: "当前全局为「文件夹」,勾选后此文件夹改用「文件夹及文件名」作为牌组名", + }, + }, }, cards: { cardTypes: { @@ -375,6 +386,8 @@ export const zh = { includeFoldersStrings: "包含文件夹列表中只能包含字符串。", excludeFoldersArray: "排除文件夹必须是数组。", excludeFoldersStrings: "排除文件夹列表中只能包含字符串。", + alternateFolderDeckModeFoldersArray: "文件夹牌组模式覆盖列表必须是数组。", + alternateFolderDeckModeFoldersStrings: "文件夹牌组模式覆盖列表中只能包含字符串。", ankiConnectUrlRequired: "AnkiConnect URL 不能为空。", ankiNoteTypeCacheArray: "Anki 笔记模板缓存必须是数组。", ankiNoteTypeCacheStrings: "Anki 笔记模板缓存中只能包含字符串。", diff --git a/src/presentation/settings/PluginSettingTab.test.ts b/src/presentation/settings/PluginSettingTab.test.ts index e995856..450ab9e 100644 --- a/src/presentation/settings/PluginSettingTab.test.ts +++ b/src/presentation/settings/PluginSettingTab.test.ts @@ -1658,6 +1658,98 @@ describe("PluginSettingTab", () => { expect(getEmptyCallCount(tab.containerEl)).toBe(initialEmptyCount); }); + it("renders folder deck mode override controls for checked include rows when folder mapping is enabled", async () => { + const plugin = new FakePlugin(); + plugin.settings = normalizePluginSettings({ + ...plugin.settings, + scopeMode: "include", + includeFolders: ["notes/sub"], + folderDeckMode: "folder", + }); + const tab = new AnkiHeadingSyncSettingTab(plugin as never); + + tab.display(); + await queryByDataset(tab.containerEl, "settingsCardToggle", "scope").trigger("click"); + await flushPromises(); + + const overrideCheckbox = queryByDataset(tab.containerEl, "folderDeckModeOverride", "notes/sub"); + const overrideAttributes = overrideCheckbox as unknown as { title?: string; "aria-label"?: string }; + expect(overrideCheckbox.classList.contains("ahs-settings-folder-override-checkbox")).toBe(true); + expect(overrideAttributes.title).toBe("当前全局为「文件夹」,勾选后此文件夹改用「文件夹及文件名」作为牌组名"); + expect(overrideAttributes["aria-label"]).toBe("切换 sub 的文件夹牌组映射模式"); + expect(() => queryByDataset(tab.containerEl, "folderDeckModeOverrideHint", "notes/sub")).toThrow(); + }); + + it("toggling a folder deck mode override only updates alternateFolderDeckModeFolders and shows the hint", async () => { + const plugin = new FakePlugin(); + plugin.settings = normalizePluginSettings({ + ...plugin.settings, + scopeMode: "include", + includeFolders: ["notes/sub"], + folderDeckMode: "folder", + }); + const tab = new AnkiHeadingSyncSettingTab(plugin as never); + + tab.display(); + await queryByDataset(tab.containerEl, "settingsCardToggle", "scope").trigger("click"); + await flushPromises(); + + const overrideCheckbox = queryByDataset(tab.containerEl, "folderDeckModeOverride", "notes/sub"); + overrideCheckbox.checked = true; + await overrideCheckbox.trigger("change"); + + expect(plugin.settings.includeFolders).toEqual(["notes/sub"]); + expect(plugin.settings.alternateFolderDeckModeFolders).toEqual(["notes/sub"]); + expect(plugin.updateCalls).toContainEqual({ + alternateFolderDeckModeFolders: ["notes/sub"], + }); + const hint = queryByDataset(tab.containerEl, "folderDeckModeOverrideHint", "notes/sub"); + expect(hint.classList.contains("ahs-settings-folder-override-hint")).toBe(true); + expect(hint.textContent).toContain("文件夹及文件名"); + }); + + it("cleans folder deck mode overrides for an unchecked include folder and its descendants", async () => { + const plugin = new FakePlugin(); + plugin.settings = normalizePluginSettings({ + ...plugin.settings, + scopeMode: "include", + includeFolders: ["notes"], + folderDeckMode: "folder", + alternateFolderDeckModeFolders: ["notes", "notes/sub"], + }); + const tab = new AnkiHeadingSyncSettingTab(plugin as never); + + tab.display(); + await queryByDataset(tab.containerEl, "settingsCardToggle", "scope").trigger("click"); + await flushPromises(); + + const notesCheckbox = queryByDataset(tab.containerEl, "folderPath", "notes"); + notesCheckbox.checked = false; + await notesCheckbox.trigger("change"); + + expect(plugin.settings.includeFolders).toEqual([]); + expect(plugin.settings.alternateFolderDeckModeFolders).toEqual([]); + }); + + it("hides folder deck mode override controls when folder mapping is off", async () => { + const plugin = new FakePlugin(); + plugin.settings = normalizePluginSettings({ + ...plugin.settings, + scopeMode: "include", + includeFolders: ["notes/sub"], + folderDeckMode: "off", + alternateFolderDeckModeFolders: ["notes/sub"], + }); + const tab = new AnkiHeadingSyncSettingTab(plugin as never); + + tab.display(); + await queryByDataset(tab.containerEl, "settingsCardToggle", "scope").trigger("click"); + await flushPromises(); + + expect(() => queryByDataset(tab.containerEl, "folderDeckModeOverride", "notes/sub")).toThrow(); + expect(plugin.settings.alternateFolderDeckModeFolders).toEqual(["notes/sub"]); + }); + it("shows an explicit warning when include mode has no selected folders", async () => { const plugin = new FakePlugin(); plugin.settings = normalizePluginSettings({ diff --git a/src/presentation/settings/PluginSettingTab.ts b/src/presentation/settings/PluginSettingTab.ts index 1c6557d..373d591 100644 --- a/src/presentation/settings/PluginSettingTab.ts +++ b/src/presentation/settings/PluginSettingTab.ts @@ -1627,7 +1627,32 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { const currentSelection = scopeMode === "include" ? this.plugin.settings.includeFolders : this.plugin.settings.excludeFolders; const nextSelection = toggleFolderTreeSelection(this.folderTree, currentSelection, folderPath, checked); - await this.plugin.updateSettings(scopeMode === "include" ? { includeFolders: nextSelection } : { excludeFolders: nextSelection }); + if (scopeMode === "include") { + const nextAlternateFolderDeckModeFolders = checked + ? this.plugin.settings.alternateFolderDeckModeFolders + : this.plugin.settings.alternateFolderDeckModeFolders.filter((path) => !isPathInsideFolder(path, folderPath)); + + await this.plugin.updateSettings({ + includeFolders: nextSelection, + alternateFolderDeckModeFolders: nextAlternateFolderDeckModeFolders, + }); + } else { + await this.plugin.updateSettings({ excludeFolders: nextSelection }); + } + + this.renderCard("scope"); + } + + private async updateAlternateFolderDeckModeFolder(folderPath: string, checked: boolean): Promise { + const nextAlternateFolderDeckModeFolders = checked + ? (this.plugin.settings.alternateFolderDeckModeFolders.includes(folderPath) + ? [...this.plugin.settings.alternateFolderDeckModeFolders] + : [...this.plugin.settings.alternateFolderDeckModeFolders, folderPath]) + : this.plugin.settings.alternateFolderDeckModeFolders.filter((path) => path !== folderPath); + + await this.plugin.updateSettings({ + alternateFolderDeckModeFolders: nextAlternateFolderDeckModeFolders, + }); this.renderCard("scope"); } @@ -1670,11 +1695,40 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { void this.updateFolderSelection(scopeMode, node.path, checkbox.checked); }); - const labelEl = row.createSpan({ text: node.name }); + const contentEl = row.createDiv(); + addClasses(contentEl, "ahs-settings-folder-label-stack"); + + const labelEl = contentEl.createSpan({ text: node.name }); labelEl.dataset.folderPathLabel = node.path; addClasses(labelEl, "ahs-settings-folder-label"); this.applyFluidEllipsis(labelEl); + if (scopeMode === "include" && node.checked && this.plugin.settings.folderDeckMode !== "off") { + const overrideCheckbox = row.createEl("input"); + const overrideLabel = t("settings.scope.folderDeckModeOverride.ariaLabel", { name: node.name }); + const overrideTitle = this.getFolderDeckModeOverrideTitle(); + const overrideChecked = this.plugin.settings.alternateFolderDeckModeFolders.includes(node.path); + + overrideCheckbox.type = "checkbox"; + overrideCheckbox.checked = overrideChecked; + overrideCheckbox.dataset.folderDeckModeOverride = node.path; + overrideCheckbox.setAttr("aria-label", overrideLabel); + overrideCheckbox.setAttr("title", overrideTitle); + addClasses(overrideCheckbox, "ahs-settings-folder-override-checkbox"); + overrideCheckbox.addEventListener("click", (event?: Event) => { + event?.stopPropagation(); + }); + overrideCheckbox.addEventListener("change", () => { + void this.updateAlternateFolderDeckModeFolder(node.path, overrideCheckbox.checked); + }); + + if (overrideChecked) { + const hintEl = contentEl.createDiv({ text: this.getFolderDeckModeOverrideHint() }); + hintEl.dataset.folderDeckModeOverrideHint = node.path; + addClasses(hintEl, "ahs-settings-folder-override-hint"); + } + } + if (!hasChildren || !expanded) { return; } @@ -1708,6 +1762,22 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { return scopeMode === "include" ? this.plugin.settings.includeFolders : this.plugin.settings.excludeFolders; } + private getFolderDeckModeOverrideHint(): string { + if (this.plugin.settings.folderDeckMode === "folder") { + return t("settings.scope.folderDeckModeOverride.hint.folderAndFile"); + } + + return t("settings.scope.folderDeckModeOverride.hint.folder"); + } + + private getFolderDeckModeOverrideTitle(): string { + if (this.plugin.settings.folderDeckMode === "folder") { + return t("settings.scope.folderDeckModeOverride.title.folderAndFile"); + } + + return t("settings.scope.folderDeckModeOverride.title.folder"); + } + private createInlineControlGroup(containerEl: HTMLElement, label: string): HTMLElement { const groupEl = containerEl.createEl("label"); addClasses(groupEl, "ahs-settings-inline-control-group"); @@ -1875,6 +1945,16 @@ export class AnkiHeadingSyncSettingTab extends PluginSettingTab { } } +function normalizeFolderScopePath(path: string): string { + return path.trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, ""); +} + +function isPathInsideFolder(filePath: string, folderPath: string): boolean { + const normalizedFilePath = normalizeFolderScopePath(filePath); + const normalizedFolderPath = normalizeFolderScopePath(folderPath); + return normalizedFilePath === normalizedFolderPath || normalizedFilePath.startsWith(`${normalizedFolderPath}/`); +} + function getScopeModeSummary(scopeMode: ScopeMode): string { if (scopeMode === "include") { return t("settings.scope.summary.include"); diff --git a/styles.css b/styles.css index 895a60a..24ae600 100644 --- a/styles.css +++ b/styles.css @@ -200,7 +200,7 @@ .anki-heading-sync-settings .ahs-settings-folder-row { display: grid; - grid-template-columns: 24px 24px minmax(0, 1fr); + grid-template-columns: 24px 24px minmax(0, 1fr) auto; align-items: center; column-gap: 0; width: 100%; @@ -238,6 +238,44 @@ min-width: 0; } +.anki-heading-sync-settings .ahs-settings-folder-label-stack { + display: flex; + flex-direction: column; + min-width: 0; + gap: 2px; +} + +.anki-heading-sync-settings .ahs-settings-folder-override-checkbox { + justify-self: end; + width: 16px; + height: 16px; + margin: 0; + appearance: none; + border: 1.5px solid var(--background-modifier-border); + border-radius: 999px; + background: var(--background-primary); + box-shadow: none; + cursor: pointer; +} + +.anki-heading-sync-settings .ahs-settings-folder-override-checkbox:checked { + border-color: var(--interactive-accent); + background-image: radial-gradient(circle, var(--interactive-accent) 0 4px, transparent 4px); + background-repeat: no-repeat; + background-position: center; +} + +.anki-heading-sync-settings .ahs-settings-folder-override-checkbox:focus-visible { + outline: 2px solid var(--interactive-accent); + outline-offset: 2px; +} + +.anki-heading-sync-settings .ahs-settings-folder-override-hint { + color: var(--text-muted); + font-size: var(--font-ui-smaller); + line-height: 1.35; +} + .anki-heading-sync-settings .ahs-settings-inline-control-group { display: inline-flex; align-items: center;