/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/core.ts function getHeaderLevel(text, startHeaderLevel) { const match = text.match(/^#+/); if (!match) return [0, 0]; let level = match ? match[0].length : 0; return [level - startHeaderLevel + 1, level]; } function getNextNumber(cntNums, headerLevel) { let nextNums = [...cntNums]; if (nextNums.length >= headerLevel) { nextNums = nextNums.slice(0, headerLevel); nextNums[nextNums.length - 1]++; } else { while (nextNums.length < headerLevel) { nextNums.push(1); } } return nextNums; } function isNeedInsertNumber(text, splitor) { const match = text.match(/^(#{1,6})\s+(.*)/); if (!match) return false; const contentAfterHash = match[2]; if (splitor == " ") { return !/^\d+(?:\.\d+)*\s+/.test(contentAfterHash); } else { return !contentAfterHash.contains(splitor); } } function isNeedUpdateNumber(nextNumsStr, text, splitor) { const match = text.match(/^(#{1,6})\s+(.*)/); if (!match) return false; const contentAfterHash = match[2]; let cntNumsStr; if (splitor == " ") { const numMatch = contentAfterHash.match(/^(\d+(?:\.\d+)*)\s+/); if (!numMatch) return true; cntNumsStr = numMatch[1]; } else { const parts = contentAfterHash.split(splitor); if (parts.length < 2) return true; cntNumsStr = parts[0].trim(); } return nextNumsStr !== cntNumsStr; } function removeHeaderNumber(text, splitor) { const match = text.match(/^(#{1,6})\s+(.*)/); if (!match) return text; const sharp = match[1]; const contentAfterHash = match[2]; if (splitor == " ") { const header = contentAfterHash.replace(/^\d+(?:\.\d+)*\s+/, ""); return sharp + " " + header; } else { if (!contentAfterHash.contains(splitor)) return text; const parts = contentAfterHash.split(splitor); const header = parts.slice(1).join(splitor).trim(); return sharp + " " + header; } } function isHeader(text) { return /^#{1,6} .*/.test(text.trim()); } function analyzeHeaderLevels(content) { const lines = content.split("\n"); const usedLevels = /* @__PURE__ */ new Set(); let isCodeBlock = false; let headerCount = 0; for (const line of lines) { if (line.startsWith("```")) { isCodeBlock = !isCodeBlock; if (line.slice(3).includes("```")) { isCodeBlock = !isCodeBlock; } } if (isCodeBlock) continue; if (isHeader(line)) { const match = line.match(/^#+/); if (match) { const level = match[0].length; usedLevels.add(level); headerCount++; } } } if (usedLevels.size === 0) { return { minLevel: 0, maxLevel: 0, usedLevels: [], isEmpty: true, headerCount: 0 }; } const levels = Array.from(usedLevels).sort((a, b) => a - b); if (levels.length === 1) { const singleLevel = levels[0]; return { minLevel: singleLevel, maxLevel: Math.min(singleLevel + 2, 6), // 默认扩展2级,但不超过H6 usedLevels: levels, isEmpty: false, headerCount }; } return { minLevel: levels[0], maxLevel: levels[levels.length - 1], usedLevels: levels, isEmpty: false, headerCount }; } var init_core = __esm({ "src/core.ts"() { } }); // src/utils.ts function getYaml(editor) { var _a; const matchResult = editor.getValue().match(YAML_REGEX); return (_a = matchResult == null ? void 0 : matchResult[0]) != null ? _a : ""; } function getAutoNumberingYaml(editor) { var _a; const yaml = getYaml(editor); const parsedYaml = (0, import_obsidian.parseYaml)(yaml.slice(4, -4)); return (_a = parsedYaml == null ? void 0 : parsedYaml["header-auto-numbering"]) != null ? _a : ""; } function setAutoNumberingYaml(editor, value = DEFAULT_YAML_SETTING) { const yaml = getYaml(editor); let parsedYaml = (0, import_obsidian.parseYaml)(yaml.slice(4, -4)); if (!parsedYaml) { parsedYaml = {}; } parsedYaml["header-auto-numbering"] = value; const newContent = `--- ${(0, import_obsidian.stringifyYaml)(parsedYaml)}--- `; const startPosition = { line: 0, ch: 0 }; let endOffset = yaml.length; if (yaml.length > 0) { const contentAfterYaml = editor.getValue().substring(yaml.length, yaml.length + 1); if (contentAfterYaml === "\n") { endOffset += 1; } } const endPosition = editor.offsetToPos(endOffset); editor.replaceRange(newContent, startPosition, endPosition); } var import_obsidian, YAML_REGEX, DEFAULT_YAML_SETTING; var init_utils = __esm({ "src/utils.ts"() { import_obsidian = require("obsidian"); YAML_REGEX = /^---\n(?:((?:.|\n)*?)\n)?---(?=\n|$)/; DEFAULT_YAML_SETTING = [ "state on", "start-level h2", "end-level h6", "start-at 1", "separator ." ]; } }); // src/i18n/en.ts var en_default; var init_en = __esm({ "src/i18n/en.ts"() { en_default = { settings: { title: "Header Enhancer Settings", general: "General", language: { name: "Language", desc: "Language for automatic numbering" }, statusBar: { name: "Show on Status Bar", desc: "Show current header level on status bar" }, sidebar: { name: "Show on Sidebar", desc: "Show Header Enhancer icon in the sidebar ribbon" }, autoDetect: { name: "Auto Detect Header Level", desc: "Automatically detect and use the highest and lowest header levels in the document for numbering" }, headerLevel: { start: { name: "Start Header Level", desc: "The starting level for headers" }, max: { name: "Max Header Level", desc: "Maximum level for headers" } }, autoNumbering: { title: "Header Auto Numbering", globalToggle: { name: "Enable Auto Numbering Function", desc: "Master switch to enable/disable the entire auto numbering functionality. When disabled, no documents will have auto numbering regardless of other settings." }, globalDisabled: { title: "Auto Numbering Function Disabled", description: "The auto numbering function is currently disabled globally. Enable it above to access other auto numbering settings and use the sidebar button to control individual documents." }, mode: { name: "Auto Numbering Mode", desc: "Control how header auto numbering works", off: "Off", on: "On", yaml: "Controlled by YAML" }, headerLevel: { name: "Header Level Numbering Method", toggleLabel: "\u{1F527} Enable Auto Detection", desc: { autoDetect: "\u2705 Auto Detection Mode: Intelligently determine numbering range based on document content", manual: "\u2699\uFE0F Manual Setting Mode: Use fixed level range settings", yamlControl: "\u{1F4CB} YAML Control Mode: Configure through file frontmatter" } }, startNumber: { name: "Start Number", desc: "Start numbering at this number", placeholder: "Enter a number" }, separator: { name: "Number Separator", desc: "Separator between numbers (one of '. , / -')", placeholder: "Enter separator" }, headerSeparator: { name: "Header Separator", desc: "Separator between header number and text", error: "You can't change header separator when auto numbering is enabled" }, updateBacklinks: { name: "Update Backlinks", desc: "\u26A0\uFE0F Warning: Automatically update backlinks when headers change. May impact performance in large vaults." }, endLevelError: "Max header level should be greater than or equal to start header level", startLevelError: "Start header level should be less than or equal to max header level", format: { name: "Your auto numbering format is", fromLevel: "from", toLevel: "to", autoDetect: "Auto Detect", manual: "Manual", yamlControlled: "[Controlled by YAML]", disabled: "[Disabled]" }, removeConfirmation: { title: "Turn Off Auto Numbering", message: "You are about to turn off auto numbering. What would you like to do with existing numbering in your documents?", warningTitle: "\u26A0\uFE0F Performance Warning", warningMessage: "This operation will scan all markdown files in your vault. In large vaults, this may take several minutes and temporarily impact Obsidian's performance.", removeAndTurnOff: "Remove all numbering and turn off", removeAndTurnOffDesc: "Scan all files and remove header numbering, then disable auto numbering", turnOffOnly: "Turn off without removing", turnOffOnlyDesc: "Disable auto numbering but keep existing numbers in documents", cancel: "Cancel", processing: "Processing files...", progressStatus: "Processed {current} of {total} files", completed: "Successfully removed numbering from {count} files", error: "Error occurred while processing files: {error}", noNumberingFound: "No files with header numbering were found", manualTip: "You can also manually disable auto numbering for individual files using the sidebar button." }, activationConfirmation: { title: "Enable Auto Numbering", message: "You are about to enable auto numbering. What would you like to do with existing documents in your vault?", warningTitle: "\u26A0\uFE0F Performance Warning", warningMessage: "This operation will scan all markdown files in your vault. In large vaults, this may take several minutes and temporarily impact Obsidian's performance.", addToAll: "Add numbering to all documents", addToAllDesc: "Scan all files and add header numbering to existing documents", turnOnOnly: "Turn on without adding", turnOnOnlyDesc: "Enable auto numbering but keep existing documents unchanged", cancel: "Cancel", processing: "Adding numbering to files...", progressStatus: "Processed {current} of {total} files", completed: "Successfully added numbering to {count} files", error: "Error occurred while processing files: {error}", noHeadersFound: "No files with headers were found", manualTip: "You can also manually enable auto numbering for individual files using the sidebar button." } }, headerFont: { title: "Header Font Settings", separate: { name: "Separate Header Font", desc: "Use different font settings for markdown headers (# ## ###)" }, preview: { title: "Header Font Preview", sample: "Sample Header" }, family: { name: "Font Family", desc: "Header font family (inherit from global font by default)", options: { inherit: "Inherit from global font" } }, size: { name: "Font Size", desc: "Header font size (inherit from global font size by default)", options: { inherit: "Inherit from global size", smaller: "Smaller", small: "Small", normal: "Normal", large: "Large", larger: "Larger", xlarge: "Extra Large", xxlarge: "Extra Extra Large" } } }, titleFont: { title: "Title Font Settings", separate: { name: "Separate Title Font", desc: "Use different font settings for document titles" }, preview: { title: "Title Font Preview", sample: "Sample Document Title" }, family: { name: "Font Family", desc: "Title font family (inherit from global font by default)", options: { inherit: "Inherit from global font" } }, size: { name: "Font Size", desc: "Title font size (inherit from global font size by default)", options: { inherit: "Inherit from global size", smaller: "Smaller", small: "Small", normal: "Normal", large: "Large", larger: "Larger", xlarge: "Extra Large", xxlarge: "Extra Extra Large" } } }, yamlMode: { fallback: { name: "Documents without YAML configuration", desc: "Choose how to handle documents that don't have YAML configuration", noNumbering: "No numbering", useDefault: "Use default settings" }, defaultStartLevel: { name: "Default Start Level", desc: "Default starting header level for documents without YAML" }, defaultEndLevel: { name: "Default End Level", desc: "Default ending header level for documents without YAML" }, defaultStartNumber: { name: "Default Start Number", desc: "Default starting number for documents without YAML" }, defaultSeparator: { name: "Default Separator", desc: "Default number separator for documents without YAML" } }, resetSettings: { name: "Reset Settings", confirm: "Are you sure you want to reset settings to default?" }, moreInfo: "More Information", author: "Author: ", license: "License: ", githubRepo: "GitHub Repository: ", anyQuestion: "Any questions? " }, autoDetection: { currentDocument: "Current Document Analysis", noActiveDocument: "No active document", noHeaders: "No headers detected", detected: "Detected levels", range: "Level range", mapping: "Number mapping", totalHeaders: "Total headers", modes: { autoDetect: "\u{1F527} Current Mode: Auto Detect - Intelligently determine numbering range based on document content", yamlControl: "\u2699\uFE0F Current Mode: YAML Control - Configure through file frontmatter", manual: "\u{1F3AF} Current Mode: Manual - Use fixed level range" }, info: { yamlMode: { title: "\u2699\uFE0F YAML Control Mode", description: "In this mode, header numbering is controlled by YAML frontmatter in files. Please add the following configuration at the beginning of your document:", usage: "You can use plugin commands to quickly add or modify these configurations." }, offMode: { title: "\u23F8\uFE0F Auto Numbering Disabled", description: 'Header auto numbering is currently disabled. To enable auto numbering, please select "On" or "Controlled by YAML" mode above.' } } }, statusBar: { title: "Header Enhancer", off: "Off", on: "On", yaml: "YAML", auto: "Auto", autoNoHeaders: "Auto(No Headers)", globalDisabled: "Global Disabled", documentEnabled: "Document On", documentDisabled: "Document Off" }, commands: { toggleGlobalAutoNumbering: "Toggle Global Auto Numbering", toggleDocumentAutoNumbering: "Toggle Document Auto Numbering", resetAutoNumberingYaml: "Reset Auto Numbering YAML", removeAutoNumberingYaml: "Remove Auto Numbering YAML", applyCustomYamlConfig: "Apply Custom YAML Configuration" }, notices: { noActiveView: "No active MarkdownView, cannot toggle auto numbering.", globalDisabledNotice: "Auto numbering is globally disabled. Enable it in settings first.", globalAutoNumberingEnabled: "Global auto numbering enabled", globalAutoNumberingDisabled: "Global auto numbering disabled", autoNumberingEnabledForDocument: "Auto numbering enabled for this document", autoNumberingDisabledForDocument: "Auto numbering disabled for this document", yamlAlreadyExists: "auto numbering yaml already exists", yamlNotExists: "auto numbering yaml not exists", yamlTemplateInserted: "YAML configuration template inserted successfully" } }; } }); // src/i18n/zh.ts var zh_default; var init_zh = __esm({ "src/i18n/zh.ts"() { zh_default = { settings: { title: "\u6807\u9898\u589E\u5F3A\u5668\u8BBE\u7F6E", general: "\u5E38\u89C4", language: { name: "\u8BED\u8A00", desc: "\u81EA\u52A8\u7F16\u53F7\u7684\u8BED\u8A00" }, statusBar: { name: "\u5728\u72B6\u6001\u680F\u663E\u793A", desc: "\u5728\u72B6\u6001\u680F\u663E\u793A\u5F53\u524D\u6807\u9898\u7EA7\u522B" }, sidebar: { name: "\u5728\u4FA7\u8FB9\u680F\u663E\u793A", desc: "\u5728\u4FA7\u8FB9\u680F\u529F\u80FD\u533A\u663E\u793A\u6807\u9898\u589E\u5F3A\u5668\u56FE\u6807" }, autoDetect: { name: "\u81EA\u52A8\u68C0\u6D4B\u6807\u9898\u7EA7\u522B", desc: "\u6839\u636E\u4E0A\u4E0B\u6587\u81EA\u52A8\u68C0\u6D4B\u6807\u9898\u7EA7\u522B" }, headerLevel: { start: { name: "\u8D77\u59CB\u6807\u9898\u7EA7\u522B", desc: "\u6807\u9898\u7684\u8D77\u59CB\u7EA7\u522B" }, max: { name: "\u6700\u5927\u6807\u9898\u7EA7\u522B", desc: "\u6807\u9898\u7684\u6700\u5927\u7EA7\u522B" } }, autoNumbering: { title: "\u6807\u9898\u81EA\u52A8\u7F16\u53F7", globalToggle: { name: "\u542F\u7528\u81EA\u52A8\u7F16\u53F7\u529F\u80FD", desc: "\u4E3B\u5F00\u5173\uFF0C\u7528\u4E8E\u542F\u7528/\u7981\u7528\u6574\u4E2A\u81EA\u52A8\u7F16\u53F7\u529F\u80FD\u3002\u7981\u7528\u65F6\uFF0C\u65E0\u8BBA\u5176\u4ED6\u8BBE\u7F6E\u5982\u4F55\uFF0C\u90FD\u4E0D\u4F1A\u6709\u6587\u6863\u8FDB\u884C\u81EA\u52A8\u7F16\u53F7\u3002" }, globalDisabled: { title: "\u81EA\u52A8\u7F16\u53F7\u529F\u80FD\u5DF2\u7981\u7528", description: "\u81EA\u52A8\u7F16\u53F7\u529F\u80FD\u5F53\u524D\u5728\u5168\u5C40\u8303\u56F4\u5185\u88AB\u7981\u7528\u3002\u8BF7\u5728\u4E0A\u65B9\u542F\u7528\u5B83\u4EE5\u8BBF\u95EE\u5176\u4ED6\u81EA\u52A8\u7F16\u53F7\u8BBE\u7F6E\u5E76\u4F7F\u7528\u4FA7\u8FB9\u680F\u6309\u94AE\u63A7\u5236\u5355\u4E2A\u6587\u6863\u3002" }, mode: { name: "\u81EA\u52A8\u7F16\u53F7\u6A21\u5F0F", desc: "\u63A7\u5236\u6807\u9898\u81EA\u52A8\u7F16\u53F7\u7684\u5DE5\u4F5C\u65B9\u5F0F", off: "\u5173\u95ED", on: "\u542F\u7528", yaml: "\u901A\u8FC7YAML\u63A7\u5236" }, headerLevel: { name: "\u6807\u9898\u5C42\u7EA7\u7F16\u53F7\u65B9\u5F0F", toggleLabel: "\u{1F527} \u542F\u7528\u81EA\u52A8\u68C0\u6D4B", desc: { autoDetect: "\u2705 \u81EA\u52A8\u68C0\u6D4B\u6A21\u5F0F\uFF1A\u6839\u636E\u6587\u6863\u5185\u5BB9\u667A\u80FD\u786E\u5B9A\u7F16\u53F7\u8303\u56F4", manual: "\u2699\uFE0F \u624B\u52A8\u8BBE\u7F6E\u6A21\u5F0F\uFF1A\u4F7F\u7528\u56FA\u5B9A\u7684\u5C42\u7EA7\u8303\u56F4\u8BBE\u7F6E", yamlControl: "\u{1F4CB} YAML\u63A7\u5236\u6A21\u5F0F\uFF1A\u901A\u8FC7\u6587\u4EF6\u524D\u7F6E\u5143\u6570\u636E\u914D\u7F6E" } }, startNumber: { name: "\u8D77\u59CB\u6570\u5B57", desc: "\u4ECE\u6B64\u6570\u5B57\u5F00\u59CB\u7F16\u53F7", placeholder: "\u8F93\u5165\u6570\u5B57", error: "\u8D77\u59CB\u6570\u5B57\u5FC5\u987B\u662F\u6709\u6548\u6570\u5B57" }, separator: { name: "\u6570\u5B57\u5206\u9694\u7B26", desc: "\u6570\u5B57\u4E4B\u95F4\u7684\u5206\u9694\u7B26\uFF08. , / - \u4E2D\u7684\u4E00\u4E2A\uFF09", placeholder: "\u8F93\u5165\u5206\u9694\u7B26", error: "\u5206\u9694\u7B26\u5FC5\u987B\u662F\u4EE5\u4E0B\u4E4B\u4E00\uFF1A. , / -" }, headerSeparator: { name: "\u6807\u9898\u5206\u9694\u7B26", desc: "\u6570\u5B57\u548C\u6807\u9898\u6587\u672C\u4E4B\u95F4\u7684\u5206\u9694\u7B26", error: "\u65E0\u6548\u7684\u6807\u9898\u5206\u9694\u7B26" }, updateBacklinks: { name: "\u66F4\u65B0\u53CD\u5411\u94FE\u63A5", desc: "\u26A0\uFE0F \u8B66\u544A\uFF1A\u5F53\u6807\u9898\u6539\u53D8\u65F6\u81EA\u52A8\u66F4\u65B0\u53CD\u5411\u94FE\u63A5\u3002\u5728\u5927\u578B\u77E5\u8BC6\u5E93\u4E2D\u53EF\u80FD\u4F1A\u5F71\u54CD\u6027\u80FD\u3002" }, endLevelError: "\u6700\u5927\u6807\u9898\u7EA7\u522B\u5E94\u8BE5\u5927\u4E8E\u6216\u7B49\u4E8E\u8D77\u59CB\u6807\u9898\u7EA7\u522B", startLevelError: "\u8D77\u59CB\u6807\u9898\u7EA7\u522B\u5E94\u8BE5\u5C0F\u4E8E\u6216\u7B49\u4E8E\u6700\u5927\u6807\u9898\u7EA7\u522B", format: { name: "\u5F53\u524D\u683C\u5F0F", fromLevel: "\u4ECE", toLevel: "\u5230", autoDetect: "\u81EA\u52A8\u68C0\u6D4B", manual: "\u624B\u52A8", yamlControlled: "\uFF08YAML\u63A7\u5236\uFF09", disabled: "\uFF08\u5DF2\u5173\u95ED\uFF09" }, removeConfirmation: { title: "\u5173\u95ED\u81EA\u52A8\u7F16\u53F7", message: "\u60A8\u5373\u5C06\u5173\u95ED\u81EA\u52A8\u7F16\u53F7\u529F\u80FD\u3002\u5BF9\u4E8E\u6587\u6863\u4E2D\u73B0\u6709\u7684\u7F16\u53F7\uFF0C\u60A8\u5E0C\u671B\u5982\u4F55\u5904\u7406\uFF1F", warningTitle: "\u26A0\uFE0F \u6027\u80FD\u8B66\u544A", warningMessage: "\u6B64\u64CD\u4F5C\u5C06\u626B\u63CF\u77E5\u8BC6\u5E93\u4E2D\u7684\u6240\u6709markdown\u6587\u4EF6\u3002\u5728\u5927\u578B\u77E5\u8BC6\u5E93\u4E2D\uFF0C\u8FD9\u53EF\u80FD\u9700\u8981\u51E0\u5206\u949F\u65F6\u95F4\u5E76\u6682\u65F6\u5F71\u54CDObsidian\u7684\u6027\u80FD\u3002", removeAndTurnOff: "\u79FB\u9664\u6240\u6709\u7F16\u53F7\u5E76\u5173\u95ED", removeAndTurnOffDesc: "\u626B\u63CF\u6240\u6709\u6587\u4EF6\u5E76\u79FB\u9664\u6807\u9898\u7F16\u53F7\uFF0C\u7136\u540E\u7981\u7528\u81EA\u52A8\u7F16\u53F7", turnOffOnly: "\u4EC5\u5173\u95ED\u4E0D\u79FB\u9664", turnOffOnlyDesc: "\u7981\u7528\u81EA\u52A8\u7F16\u53F7\u4F46\u4FDD\u7559\u6587\u6863\u4E2D\u7684\u73B0\u6709\u7F16\u53F7", cancel: "\u53D6\u6D88", processing: "\u6B63\u5728\u5904\u7406\u6587\u4EF6...", progressStatus: "\u5DF2\u5904\u7406 {current}/{total} \u4E2A\u6587\u4EF6", completed: "\u6210\u529F\u4ECE {count} \u4E2A\u6587\u4EF6\u4E2D\u79FB\u9664\u7F16\u53F7", error: "\u5904\u7406\u6587\u4EF6\u65F6\u53D1\u751F\u9519\u8BEF\uFF1A{error}", noNumberingFound: "\u672A\u627E\u5230\u5305\u542B\u6807\u9898\u7F16\u53F7\u7684\u6587\u4EF6", manualTip: "\u4F60\u4E5F\u53EF\u4EE5\u901A\u8FC7\u4FA7\u8FB9\u680F\u6309\u94AE\u624B\u52A8\u5173\u95ED\u5355\u4E2A\u6587\u4EF6\u7684\u81EA\u52A8\u7F16\u53F7\u3002" }, activationConfirmation: { title: "\u542F\u7528\u81EA\u52A8\u7F16\u53F7", message: "\u60A8\u5373\u5C06\u542F\u7528\u81EA\u52A8\u7F16\u53F7\u529F\u80FD\u3002\u5BF9\u4E8E\u77E5\u8BC6\u5E93\u4E2D\u73B0\u6709\u7684\u6587\u6863\uFF0C\u60A8\u5E0C\u671B\u5982\u4F55\u5904\u7406\uFF1F", warningTitle: "\u26A0\uFE0F \u6027\u80FD\u8B66\u544A", warningMessage: "\u6B64\u64CD\u4F5C\u5C06\u626B\u63CF\u77E5\u8BC6\u5E93\u4E2D\u7684\u6240\u6709markdown\u6587\u4EF6\u3002\u5728\u5927\u578B\u77E5\u8BC6\u5E93\u4E2D\uFF0C\u8FD9\u53EF\u80FD\u9700\u8981\u51E0\u5206\u949F\u65F6\u95F4\u5E76\u6682\u65F6\u5F71\u54CDObsidian\u7684\u6027\u80FD\u3002", addToAll: "\u4E3A\u6240\u6709\u6587\u6863\u6DFB\u52A0\u7F16\u53F7", addToAllDesc: "\u626B\u63CF\u6240\u6709\u6587\u4EF6\u5E76\u4E3A\u73B0\u6709\u6587\u6863\u6DFB\u52A0\u6807\u9898\u7F16\u53F7", turnOnOnly: "\u4EC5\u542F\u7528\u4E0D\u6DFB\u52A0", turnOnOnlyDesc: "\u542F\u7528\u81EA\u52A8\u7F16\u53F7\u529F\u80FD\u4F46\u4FDD\u6301\u73B0\u6709\u6587\u6863\u4E0D\u53D8", cancel: "\u53D6\u6D88", processing: "\u6B63\u5728\u4E3A\u6587\u4EF6\u6DFB\u52A0\u7F16\u53F7...", progressStatus: "\u5DF2\u5904\u7406 {current}/{total} \u4E2A\u6587\u4EF6", completed: "\u6210\u529F\u4E3A {count} \u4E2A\u6587\u4EF6\u6DFB\u52A0\u7F16\u53F7", error: "\u5904\u7406\u6587\u4EF6\u65F6\u53D1\u751F\u9519\u8BEF\uFF1A{error}", noHeadersFound: "\u672A\u627E\u5230\u5305\u542B\u6807\u9898\u7684\u6587\u4EF6", manualTip: "\u4F60\u4E5F\u53EF\u4EE5\u901A\u8FC7\u4FA7\u8FB9\u680F\u6309\u94AE\u624B\u52A8\u542F\u7528\u5355\u4E2A\u6587\u4EF6\u7684\u81EA\u52A8\u7F16\u53F7\u3002" } }, headerFont: { title: "\u6807\u9898\u5B57\u4F53\u8BBE\u7F6E", separate: { name: "\u72EC\u7ACB\u6807\u9898\u5B57\u4F53", desc: "\u4E3Amarkdown\u6807\u9898\u4F7F\u7528\u72EC\u7ACB\u7684\u5B57\u4F53\u8BBE\u7F6E (# ## ###)" }, preview: { title: "\u6807\u9898\u5B57\u4F53\u9884\u89C8", sample: "\u793A\u4F8B\u6807\u9898" }, family: { name: "\u5B57\u4F53\u65CF", desc: "\u6807\u9898\u5B57\u4F53\u65CF\uFF08\u9ED8\u8BA4\u7EE7\u627F\u5168\u5C40\u5B57\u4F53\uFF09", options: { inherit: "\u7EE7\u627F\u5168\u5C40\u5B57\u4F53" } }, size: { name: "\u5B57\u4F53\u5927\u5C0F", desc: "\u6807\u9898\u5B57\u4F53\u5927\u5C0F\uFF08\u9ED8\u8BA4\u7EE7\u627F\u5168\u5C40\u5B57\u4F53\u5927\u5C0F\uFF09", options: { inherit: "\u7EE7\u627F\u5168\u5C40\u5927\u5C0F", smaller: "\u8F83\u5C0F", small: "\u5C0F", normal: "\u6B63\u5E38", large: "\u5927", larger: "\u8F83\u5927", xlarge: "\u7279\u5927", xxlarge: "\u8D85\u5927" } } }, titleFont: { title: "\u6587\u6863\u6807\u9898\u5B57\u4F53\u8BBE\u7F6E", separate: { name: "\u72EC\u7ACB\u6587\u6863\u6807\u9898\u5B57\u4F53", desc: "\u4E3A\u6587\u6863\u6807\u9898\u4F7F\u7528\u72EC\u7ACB\u7684\u5B57\u4F53\u8BBE\u7F6E" }, preview: { title: "\u6587\u6863\u6807\u9898\u5B57\u4F53\u9884\u89C8", sample: "\u793A\u4F8B\u6587\u6863\u6807\u9898" }, family: { name: "\u5B57\u4F53\u65CF", desc: "\u6587\u6863\u6807\u9898\u5B57\u4F53\u65CF\uFF08\u9ED8\u8BA4\u7EE7\u627F\u5168\u5C40\u5B57\u4F53\uFF09", options: { inherit: "\u7EE7\u627F\u5168\u5C40\u5B57\u4F53" } }, size: { name: "\u5B57\u4F53\u5927\u5C0F", desc: "\u6587\u6863\u6807\u9898\u5B57\u4F53\u5927\u5C0F\uFF08\u9ED8\u8BA4\u7EE7\u627F\u5168\u5C40\u5B57\u4F53\u5927\u5C0F\uFF09", options: { inherit: "\u7EE7\u627F\u5168\u5C40\u5927\u5C0F", smaller: "\u8F83\u5C0F", small: "\u5C0F", normal: "\u6B63\u5E38", large: "\u5927", larger: "\u8F83\u5927", xlarge: "\u7279\u5927", xxlarge: "\u8D85\u5927" } } }, yamlMode: { fallback: { name: "\u6CA1\u6709YAML\u914D\u7F6E\u7684\u6587\u6863\u5904\u7406\u65B9\u5F0F", desc: "\u9009\u62E9\u5982\u4F55\u5904\u7406\u6CA1\u6709YAML\u914D\u7F6E\u7684\u6587\u6863", noNumbering: "\u4E0D\u7F16\u53F7", useDefault: "\u4F7F\u7528\u9ED8\u8BA4\u8BBE\u7F6E" }, defaultStartLevel: { name: "\u9ED8\u8BA4\u8D77\u59CB\u5C42\u7EA7", desc: "\u6CA1\u6709YAML\u914D\u7F6E\u7684\u6587\u6863\u4F7F\u7528\u7684\u9ED8\u8BA4\u8D77\u59CB\u6807\u9898\u5C42\u7EA7" }, defaultEndLevel: { name: "\u9ED8\u8BA4\u7ED3\u675F\u5C42\u7EA7", desc: "\u6CA1\u6709YAML\u914D\u7F6E\u7684\u6587\u6863\u4F7F\u7528\u7684\u9ED8\u8BA4\u7ED3\u675F\u6807\u9898\u5C42\u7EA7" }, defaultStartNumber: { name: "\u9ED8\u8BA4\u8D77\u59CB\u6570\u5B57", desc: "\u6CA1\u6709YAML\u914D\u7F6E\u7684\u6587\u6863\u4F7F\u7528\u7684\u9ED8\u8BA4\u8D77\u59CB\u7F16\u53F7" }, defaultSeparator: { name: "\u9ED8\u8BA4\u5206\u9694\u7B26", desc: "\u6CA1\u6709YAML\u914D\u7F6E\u7684\u6587\u6863\u4F7F\u7528\u7684\u9ED8\u8BA4\u6570\u5B57\u5206\u9694\u7B26" } }, resetSettings: { name: "\u91CD\u7F6E\u8BBE\u7F6E", confirm: "\u60A8\u786E\u5B9A\u8981\u5C06\u6240\u6709\u8BBE\u7F6E\u91CD\u7F6E\u4E3A\u9ED8\u8BA4\u503C\u5417\uFF1F" }, moreInfo: "\u66F4\u591A\u4FE1\u606F", author: "\u4F5C\u8005\uFF1A", license: "\u8BB8\u53EF\u8BC1\uFF1A", githubRepo: "GitHub \u4ED3\u5E93\uFF1A", anyQuestion: "\u6709\u4EFB\u4F55\u95EE\u9898\uFF1F" }, autoDetection: { currentDocument: "\u5F53\u524D\u6587\u6863\u68C0\u6D4B\u7ED3\u679C", noActiveDocument: "\u6CA1\u6709\u6D3B\u52A8\u6587\u6863", noHeaders: "\u672A\u68C0\u6D4B\u5230\u6807\u9898", detected: "\u68C0\u6D4B\u5230\u5C42\u7EA7", range: "\u5C42\u7EA7\u8303\u56F4", mapping: "\u7F16\u53F7\u6620\u5C04", totalHeaders: "\u6807\u9898\u603B\u6570", modes: { autoDetect: "\u{1F527} \u5F53\u524D\u6A21\u5F0F\uFF1A\u81EA\u52A8\u68C0\u6D4B - \u5C06\u6839\u636E\u6587\u6863\u5185\u5BB9\u667A\u80FD\u786E\u5B9A\u7F16\u53F7\u8303\u56F4", yamlControl: "\u2699\uFE0F \u5F53\u524D\u6A21\u5F0F\uFF1AYAML\u63A7\u5236 - \u901A\u8FC7\u6587\u4EF6\u524D\u7F6E\u5143\u6570\u636E\u914D\u7F6E", manual: "\u{1F3AF} \u5F53\u524D\u6A21\u5F0F\uFF1A\u624B\u52A8\u8BBE\u7F6E - \u4F7F\u7528\u56FA\u5B9A\u7684\u5C42\u7EA7\u8303\u56F4" }, info: { yamlMode: { title: "\u2699\uFE0F YAML\u63A7\u5236\u6A21\u5F0F", description: "\u5728\u6B64\u6A21\u5F0F\u4E0B\uFF0C\u6807\u9898\u7F16\u53F7\u7531\u6587\u4EF6\u7684YAML\u524D\u7F6E\u5143\u6570\u636E\u63A7\u5236\u3002\u8BF7\u5728\u6587\u6863\u5F00\u5934\u6DFB\u52A0\u5982\u4E0B\u914D\u7F6E\uFF1A", usage: "\u60A8\u53EF\u4EE5\u4F7F\u7528\u63D2\u4EF6\u547D\u4EE4\u6765\u5FEB\u901F\u6DFB\u52A0\u6216\u4FEE\u6539\u8FD9\u4E9B\u914D\u7F6E\u3002" }, offMode: { title: "\u23F8\uFE0F \u81EA\u52A8\u7F16\u53F7\u5DF2\u5173\u95ED", description: '\u5F53\u524D\u6807\u9898\u81EA\u52A8\u7F16\u53F7\u529F\u80FD\u5DF2\u7981\u7528\u3002\u8981\u542F\u7528\u81EA\u52A8\u7F16\u53F7\uFF0C\u8BF7\u5728\u4E0A\u65B9\u9009\u62E9"\u542F\u7528"\u6216"\u901A\u8FC7YAML\u63A7\u5236"\u6A21\u5F0F\u3002' } } }, statusBar: { title: "\u6807\u9898\u589E\u5F3A\u5668", off: "\u5173\u95ED", on: "\u542F\u7528", yaml: "YAML", auto: "\u81EA\u52A8", autoNoHeaders: "\u81EA\u52A8(\u65E0\u6807\u9898)", globalDisabled: "\u5168\u5C40\u7981\u7528", documentEnabled: "\u6587\u6863\u542F\u7528", documentDisabled: "\u6587\u6863\u5173\u95ED" }, commands: { toggleGlobalAutoNumbering: "\u5207\u6362\u5168\u5C40\u81EA\u52A8\u7F16\u53F7", toggleDocumentAutoNumbering: "\u5207\u6362\u6587\u6863\u81EA\u52A8\u7F16\u53F7", resetAutoNumberingYaml: "\u91CD\u7F6E\u81EA\u52A8\u7F16\u53F7YAML\u914D\u7F6E", removeAutoNumberingYaml: "\u79FB\u9664\u81EA\u52A8\u7F16\u53F7YAML\u914D\u7F6E", applyCustomYamlConfig: "\u4E3A\u5F53\u524D\u6587\u4EF6\u5E94\u7528\u81EA\u5B9A\u4E49\u914D\u7F6E" }, notices: { noActiveView: "\u6CA1\u6709\u6D3B\u8DC3\u7684MarkdownView\uFF0C\u65E0\u6CD5\u5207\u6362\u81EA\u52A8\u7F16\u53F7\u3002", globalDisabledNotice: "\u81EA\u52A8\u7F16\u53F7\u5728\u5168\u5C40\u8303\u56F4\u5185\u88AB\u7981\u7528\u3002\u8BF7\u5148\u5728\u8BBE\u7F6E\u4E2D\u542F\u7528\u3002", globalAutoNumberingEnabled: "\u5168\u5C40\u81EA\u52A8\u7F16\u53F7\u5DF2\u542F\u7528", globalAutoNumberingDisabled: "\u5168\u5C40\u81EA\u52A8\u7F16\u53F7\u5DF2\u7981\u7528", autoNumberingEnabledForDocument: "\u5DF2\u4E3A\u6B64\u6587\u6863\u542F\u7528\u81EA\u52A8\u7F16\u53F7", autoNumberingDisabledForDocument: "\u5DF2\u4E3A\u6B64\u6587\u6863\u7981\u7528\u81EA\u52A8\u7F16\u53F7", yamlAlreadyExists: "\u81EA\u52A8\u7F16\u53F7YAML\u914D\u7F6E\u5DF2\u5B58\u5728", yamlNotExists: "\u81EA\u52A8\u7F16\u53F7YAML\u914D\u7F6E\u4E0D\u5B58\u5728", yamlTemplateInserted: "YAML\u914D\u7F6E\u6A21\u677F\u5DF2\u6210\u529F\u63D2\u5165" } }; } }); // src/i18n/index.ts var translations, I18n; var init_i18n = __esm({ "src/i18n/index.ts"() { init_en(); init_zh(); translations = { en: en_default, zh: zh_default }; I18n = class { constructor() { this.currentLanguage = "en"; } static getInstance() { if (!I18n.instance) { I18n.instance = new I18n(); } return I18n.instance; } setLanguage(lang) { if (translations[lang]) { this.currentLanguage = lang; } } t(key, placeholders) { const keys = key.split("."); let value = translations[this.currentLanguage]; for (const k of keys) { if (value && value[k]) { value = value[k]; } else { value = translations["en"]; for (const fallbackKey of keys) { if (value && value[fallbackKey]) { value = value[fallbackKey]; } else { return key; } } } } let result = typeof value === "string" ? value : key; if (placeholders) { for (const [placeholder, replacement] of Object.entries(placeholders)) { result = result.replace(new RegExp(`\\{${placeholder}\\}`, "g"), replacement); } } return result; } }; } }); // src/config.ts function getAutoNumberingConfig(setting, editor, getDocumentState, currentFilePath) { let config = { state: setting.autoNumberingMode !== "off" /* OFF */, startLevel: setting.startHeaderLevel, endLevel: setting.endHeaderLevel, startNumber: parseInt(setting.autoNumberingStartNumber), separator: setting.autoNumberingSeparator }; if (!setting.globalAutoNumberingEnabled) { config.state = false; return config; } if (getDocumentState && currentFilePath) { const documentEnabled = getDocumentState(currentFilePath); if (!documentEnabled) { config.state = false; return config; } } if (setting.autoNumberingMode === "yaml" /* YAML_CONTROLLED */) { config = applyYamlConfig(config, editor, setting); } else if (setting.isAutoDetectHeaderLevel && setting.autoNumberingMode === "on" /* ON */) { const content = editor.getValue(); const analysis = analyzeHeaderLevels(content); if (!analysis.isEmpty) { config.startLevel = analysis.minLevel; config.endLevel = analysis.maxLevel; } } return config; } function applyYamlConfig(config, editor, setting) { const yaml = getAutoNumberingYaml(editor); if (yaml === "") { if (setting.yamlFallbackMode === "no_numbering" /* NO_NUMBERING */) { config.state = false; } else { config.state = true; config.startLevel = setting.yamlDefaultStartLevel; config.endLevel = setting.yamlDefaultEndLevel; config.startNumber = parseInt(setting.yamlDefaultStartNumber); config.separator = setting.yamlDefaultSeparator; } return config; } let hasDeprecatedKeys = false; const deprecatedKeys = []; for (const item of yaml) { const [key, ...valueParts] = item.split(" "); const value = valueParts.join(" "); switch (key) { case "state": config.state = value === "on"; break; case "start-level": config.startLevel = parseInt(value.substring(1)); break; case "first-level": hasDeprecatedKeys = true; deprecatedKeys.push("first-level"); config.startLevel = parseInt(value.substring(1)); break; case "end-level": config.endLevel = parseInt(value.substring(1)); break; case "max": hasDeprecatedKeys = true; deprecatedKeys.push("max"); config.endLevel = config.startLevel + parseInt(value) - 1; break; case "start-at": config.startNumber = parseInt(value); break; case "separator": config.separator = value; break; } } if (hasDeprecatedKeys) { console.warn( `[Header Enhancer] Deprecated YAML keys detected: ${deprecatedKeys.join(", ")}. Please update to new format: use "start-level" instead of "first-level", and "end-level" instead of "max". The old format will be removed in a future version.` ); } return config; } var init_config = __esm({ "src/config.ts"() { init_setting(); init_utils(); init_core(); } }); // src/dialogs.ts var dialogs_exports = {}; __export(dialogs_exports, { AutoNumberingActivationDialog: () => AutoNumberingActivationDialog, AutoNumberingRemovalDialog: () => AutoNumberingRemovalDialog }); var import_obsidian2, AutoNumberingRemovalDialog, AutoNumberingActivationDialog; var init_dialogs = __esm({ "src/dialogs.ts"() { import_obsidian2 = require("obsidian"); init_i18n(); init_core(); init_config(); AutoNumberingRemovalDialog = class extends import_obsidian2.Modal { constructor(app, plugin, onConfirm) { super(app); this.progressContainer = null; this.isProcessing = false; this.plugin = plugin; this.onConfirm = onConfirm; this.setTitle("Auto Numbering Settings"); } onOpen() { const i18n = I18n.getInstance(); const { contentEl } = this; contentEl.empty(); contentEl.addClass("header-enhancer-removal-dialog"); contentEl.createEl("h2", { text: i18n.t("settings.autoNumbering.removeConfirmation.title"), cls: "modal-title" }); contentEl.createEl("p", { text: i18n.t("settings.autoNumbering.removeConfirmation.message"), cls: "modal-message" }); const actionsEl = contentEl.createDiv({ cls: "modal-actions" }); const removeAndTurnOffSetting = new import_obsidian2.Setting(actionsEl).setName(i18n.t("settings.autoNumbering.removeConfirmation.removeAndTurnOff")).setDesc(i18n.t("settings.autoNumbering.removeConfirmation.removeAndTurnOffDesc")).addButton((button) => { button.setButtonText(i18n.t("settings.autoNumbering.removeConfirmation.removeAndTurnOff")).setCta().onClick(async () => { if (!this.isProcessing) { await this.handleRemoveAndTurnOff(); } }); }); const warningEl = removeAndTurnOffSetting.descEl.createDiv({ cls: "setting-item-warning" }); warningEl.createEl("span", { text: i18n.t("settings.autoNumbering.removeConfirmation.warningTitle") + " ", cls: "warning-label" }); warningEl.createEl("span", { text: i18n.t("settings.autoNumbering.removeConfirmation.warningMessage"), cls: "warning-text" }); const manualTipEl = removeAndTurnOffSetting.descEl.createDiv({ cls: "setting-item-tip" }); manualTipEl.createEl("span", { text: i18n.t("settings.autoNumbering.removeConfirmation.manualTip"), cls: "manual-tip-text" }); new import_obsidian2.Setting(actionsEl).setName(i18n.t("settings.autoNumbering.removeConfirmation.turnOffOnly")).setDesc(i18n.t("settings.autoNumbering.removeConfirmation.turnOffOnlyDesc")).addButton((button) => { button.setButtonText(i18n.t("settings.autoNumbering.removeConfirmation.turnOffOnly")).onClick(async () => { if (!this.isProcessing) { await this.handleTurnOffOnly(); } }); }); const cancelButtonEl = actionsEl.createDiv({ cls: "modal-cancel" }); new import_obsidian2.Setting(cancelButtonEl).addButton((button) => { button.setButtonText(i18n.t("settings.autoNumbering.removeConfirmation.cancel")).onClick(() => { if (!this.isProcessing) { this.close(); } }); }); this.progressContainer = contentEl.createDiv({ cls: "progress-container", attr: { style: "display: none;" } }); } async handleRemoveAndTurnOff() { this.isProcessing = true; try { this.showProgress(); await this.removeAllHeaderNumbers(); await this.onConfirm(true); this.close(); } catch (error) { const i18n = I18n.getInstance(); new import_obsidian2.Notice(i18n.t("settings.autoNumbering.removeConfirmation.error", { error: error.message })); this.hideProgress(); } finally { this.isProcessing = false; } } async handleTurnOffOnly() { this.isProcessing = true; try { await this.onConfirm(false); this.close(); } finally { this.isProcessing = false; } } showProgress() { const i18n = I18n.getInstance(); if (this.progressContainer) { this.progressContainer.style.display = "block"; this.progressContainer.empty(); this.progressContainer.createEl("p", { text: i18n.t("settings.autoNumbering.removeConfirmation.processing"), cls: "progress-text" }); } this.contentEl.querySelectorAll("button").forEach((button) => { button.setAttribute("disabled", "true"); }); } hideProgress() { if (this.progressContainer) { this.progressContainer.style.display = "none"; this.progressContainer.empty(); } this.contentEl.querySelectorAll("button").forEach((button) => { button.removeAttribute("disabled"); }); } async removeAllHeaderNumbers() { const i18n = I18n.getInstance(); const markdownFiles = this.app.vault.getMarkdownFiles(); let processedCount = 0; let modifiedCount = 0; const batchSize = 5; const totalFiles = markdownFiles.length; for (let batchStart = 0; batchStart < totalFiles; batchStart += batchSize) { const batch = markdownFiles.slice(batchStart, Math.min(batchStart + batchSize, totalFiles)); for (const file of batch) { try { const modified = await this.processFile(file); if (modified) { modifiedCount++; await new Promise((resolve) => setTimeout(resolve, 10)); } processedCount++; this.updateProgress(processedCount, totalFiles); } catch (error) { console.error(`Error processing file ${file.path}:`, error); } await new Promise((resolve) => setTimeout(resolve, 5)); } await new Promise((resolve) => setTimeout(resolve, 50)); } if (modifiedCount > 0) { new import_obsidian2.Notice(i18n.t("settings.autoNumbering.removeConfirmation.completed", { count: modifiedCount.toString() })); } else { new import_obsidian2.Notice(i18n.t("settings.autoNumbering.removeConfirmation.noNumberingFound")); } } async processFile(file) { try { const activeLeaves = this.app.workspace.getLeavesOfType("markdown"); const isCurrentlyOpen = activeLeaves.some((leaf) => { const view = leaf.view; return view.file && view.file.path === file.path; }); const content = await this.app.vault.read(file); const lines = content.split("\n"); let modified = false; let isInCodeBlock = false; for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (line.startsWith("```")) { isInCodeBlock = !isInCodeBlock; continue; } if (isInCodeBlock) { continue; } if (isHeader(line)) { const newLine = removeHeaderNumber(line, this.plugin.settings.autoNumberingHeaderSeparator); if (newLine !== line) { lines[i] = newLine; modified = true; } } } if (modified) { await this.app.vault.modify(file, lines.join("\n")); if (isCurrentlyOpen) { await new Promise((resolve) => setTimeout(resolve, 20)); } if (this.plugin.settings.updateBacklinks) { } } return modified; } catch (error) { console.error(`Error processing file ${file.path}:`, error); return false; } } updateProgress(current, total) { const i18n = I18n.getInstance(); if (this.progressContainer) { const progressText = this.progressContainer.querySelector(".progress-text"); if (progressText) { progressText.textContent = i18n.t("settings.autoNumbering.removeConfirmation.progressStatus", { current: current.toString(), total: total.toString() }); } } } onClose() { this.isProcessing = false; } }; AutoNumberingActivationDialog = class extends import_obsidian2.Modal { constructor(app, plugin, onConfirm) { super(app); this.progressContainer = null; this.isProcessing = false; this.plugin = plugin; this.onConfirm = onConfirm; this.setTitle("Auto Numbering Settings"); } onOpen() { const i18n = I18n.getInstance(); const { contentEl } = this; contentEl.empty(); contentEl.addClass("header-enhancer-activation-dialog"); contentEl.createEl("h2", { text: i18n.t("settings.autoNumbering.activationConfirmation.title"), cls: "modal-title" }); contentEl.createEl("p", { text: i18n.t("settings.autoNumbering.activationConfirmation.message"), cls: "modal-message" }); const actionsEl = contentEl.createDiv({ cls: "modal-actions" }); const addToAllSetting = new import_obsidian2.Setting(actionsEl).setName(i18n.t("settings.autoNumbering.activationConfirmation.addToAll")).setDesc(i18n.t("settings.autoNumbering.activationConfirmation.addToAllDesc")).addButton((button) => { button.setButtonText(i18n.t("settings.autoNumbering.activationConfirmation.addToAll")).setCta().onClick(async () => { if (!this.isProcessing) { await this.handleAddToAll(); } }); }); const warningEl = addToAllSetting.descEl.createDiv({ cls: "setting-item-warning" }); warningEl.createEl("span", { text: i18n.t("settings.autoNumbering.activationConfirmation.warningTitle") + " ", cls: "warning-label" }); warningEl.createEl("span", { text: i18n.t("settings.autoNumbering.activationConfirmation.warningMessage"), cls: "warning-text" }); const tipEl = addToAllSetting.descEl.createDiv({ cls: "setting-item-tip" }); tipEl.createEl("span", { text: i18n.t("settings.autoNumbering.activationConfirmation.manualTip"), cls: "manual-tip-text" }); new import_obsidian2.Setting(actionsEl).setName(i18n.t("settings.autoNumbering.activationConfirmation.turnOnOnly")).setDesc(i18n.t("settings.autoNumbering.activationConfirmation.turnOnOnlyDesc")).addButton((button) => { button.setButtonText(i18n.t("settings.autoNumbering.activationConfirmation.turnOnOnly")).onClick(async () => { if (!this.isProcessing) { await this.handleTurnOnOnly(); } }); }); const cancelButtonEl = actionsEl.createDiv({ cls: "modal-cancel" }); new import_obsidian2.Setting(cancelButtonEl).addButton((button) => { button.setButtonText(i18n.t("settings.autoNumbering.activationConfirmation.cancel")).onClick(() => { if (!this.isProcessing) { this.close(); } }); }); this.progressContainer = contentEl.createDiv({ cls: "progress-container", attr: { style: "display: none;" } }); } async handleAddToAll() { this.isProcessing = true; try { this.showProgress(); await this.addHeaderNumbersToAllFiles(); await this.onConfirm(true); this.close(); } catch (error) { const i18n = I18n.getInstance(); new import_obsidian2.Notice(i18n.t("settings.autoNumbering.activationConfirmation.error", { error: error.message })); this.hideProgress(); } finally { this.isProcessing = false; } } async handleTurnOnOnly() { this.isProcessing = true; try { await this.onConfirm(false); this.close(); } finally { this.isProcessing = false; } } showProgress() { const i18n = I18n.getInstance(); if (this.progressContainer) { this.progressContainer.style.display = "block"; this.progressContainer.empty(); this.progressContainer.createEl("p", { text: i18n.t("settings.autoNumbering.activationConfirmation.processing"), cls: "progress-text" }); } this.contentEl.querySelectorAll("button").forEach((button) => { button.setAttribute("disabled", "true"); }); } hideProgress() { if (this.progressContainer) { this.progressContainer.style.display = "none"; this.progressContainer.empty(); } this.contentEl.querySelectorAll("button").forEach((button) => { button.removeAttribute("disabled"); }); } async addHeaderNumbersToAllFiles() { const i18n = I18n.getInstance(); const markdownFiles = this.app.vault.getMarkdownFiles(); let processedCount = 0; let modifiedCount = 0; const batchSize = 5; const totalFiles = markdownFiles.length; for (let batchStart = 0; batchStart < totalFiles; batchStart += batchSize) { const batch = markdownFiles.slice(batchStart, Math.min(batchStart + batchSize, totalFiles)); for (const file of batch) { try { const modified = await this.processFile(file); if (modified) { modifiedCount++; await new Promise((resolve) => setTimeout(resolve, 10)); } processedCount++; this.updateProgress(processedCount, totalFiles); } catch (error) { console.error(`Error processing file ${file.path}:`, error); } await new Promise((resolve) => setTimeout(resolve, 5)); } await new Promise((resolve) => setTimeout(resolve, 50)); } if (modifiedCount > 0) { new import_obsidian2.Notice(i18n.t("settings.autoNumbering.activationConfirmation.completed", { count: modifiedCount.toString() })); } else { new import_obsidian2.Notice(i18n.t("settings.autoNumbering.activationConfirmation.noHeadersFound")); } } async processFile(file) { var _a; try { const activeLeaves = this.app.workspace.getLeavesOfType("markdown"); const isCurrentlyOpen = activeLeaves.some((leaf) => { const view = leaf.view; return view.file && view.file.path === file.path; }); const content = await this.app.vault.read(file); const lines = content.split("\n"); let modified = false; const mockEditor = { getValue: () => content, lineCount: () => lines.length, getLine: (n) => lines[n] || "" }; const config = getAutoNumberingConfig(this.plugin.settings, mockEditor); config.state = true; let insertNumber = [Number(config.startNumber) - 1]; let isInCodeBlock = false; for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (line.startsWith("```")) { isInCodeBlock = !isInCodeBlock; if (line.slice(3).contains("```")) { isInCodeBlock = !isInCodeBlock; } } if (isInCodeBlock) { continue; } if (isHeader(line)) { const headerLevel = ((_a = line.match(/^#+/)) == null ? void 0 : _a[0].length) || 0; if (headerLevel < config.startLevel || headerLevel > config.endLevel) { continue; } const adjustedLevel = headerLevel - config.startLevel + 1; insertNumber = getNextNumber(insertNumber, adjustedLevel); const insertNumberStr = insertNumber.join(config.separator); if (!line.includes(this.plugin.settings.autoNumberingHeaderSeparator)) { const newLine = "#".repeat(headerLevel) + " " + insertNumberStr + this.plugin.settings.autoNumberingHeaderSeparator + line.substring(headerLevel + 1); if (newLine !== line) { lines[i] = newLine; modified = true; } } } } if (modified) { await this.app.vault.modify(file, lines.join("\n")); if (isCurrentlyOpen) { await new Promise((resolve) => setTimeout(resolve, 20)); } } return modified; } catch (error) { console.error(`Error processing file ${file.path}:`, error); return false; } } updateProgress(current, total) { const i18n = I18n.getInstance(); if (this.progressContainer) { const progressText = this.progressContainer.querySelector(".progress-text"); if (progressText) { progressText.textContent = i18n.t("settings.autoNumbering.activationConfirmation.progressStatus", { current: current.toString(), total: total.toString() }); } } } onClose() { this.isProcessing = false; } }; } }); // src/setting.ts var import_obsidian3, DEFAULT_SETTINGS, HeaderEnhancerSettingTab; var init_setting = __esm({ "src/setting.ts"() { import_obsidian3 = require("obsidian"); init_i18n(); init_core(); DEFAULT_SETTINGS = { language: "en", showOnStatusBar: true, showOnSidebar: true, isAutoDetectHeaderLevel: false, // 自动检测文档中的标题层级功能 startHeaderLevel: 1, endHeaderLevel: 6, autoNumberingMode: "on" /* ON */, autoNumberingStartNumber: "1", autoNumberingSeparator: ".", autoNumberingHeaderSeparator: " ", updateBacklinks: false, // YAML mode specific settings yamlFallbackMode: "use_default" /* USE_DEFAULT */, yamlDefaultStartLevel: 2, yamlDefaultEndLevel: 6, yamlDefaultStartNumber: "1", yamlDefaultSeparator: ".", // Global function enablement - enabled by default for backward compatibility globalAutoNumberingEnabled: true, // Per-document state management - empty object as JSON string perDocumentStates: "{}", // Header font settings isSeparateHeaderFont: false, headerFontFamily: "inherit", headerFontSize: "inherit", // Title font settings isSeparateTitleFont: false, titleFontFamily: "inherit", titleFontSize: "inherit" }; HeaderEnhancerSettingTab = class extends import_obsidian3.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.formatPreviewSetting = null; this.autoDetectionPreviewContainer = null; this.plugin = plugin; } display() { const { containerEl } = this; const i18n = I18n.getInstance(); containerEl.empty(); this.formatPreviewSetting = null; this.autoDetectionPreviewContainer = null; containerEl.createEl("h1", { text: i18n.t("settings.title") }); containerEl.createEl("h2", { text: i18n.t("settings.general") }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.language.name")).setDesc(i18n.t("settings.language.desc")).addDropdown((dropdown) => { dropdown.addOption("en", "English"); dropdown.addOption("zh", "\u4E2D\u6587"); dropdown.setValue(this.plugin.settings.language); dropdown.onChange(async (value) => { this.plugin.settings.language = value; i18n.setLanguage(value); await this.plugin.saveSettings(); this.plugin.handleShowStateBarChange(); this.display(); }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.statusBar.name")).setDesc(i18n.t("settings.statusBar.desc")).addToggle((toggle) => { toggle.setValue(this.plugin.settings.showOnStatusBar).onChange(async (value) => { this.plugin.settings.showOnStatusBar = value; await this.plugin.saveSettings(); this.plugin.handleShowStateBarChange(); }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.sidebar.name")).setDesc(i18n.t("settings.sidebar.desc")).addToggle((toggle) => { toggle.setValue(this.plugin.settings.showOnSidebar).onChange(async (value) => { this.plugin.settings.showOnSidebar = value; await this.plugin.saveSettings(); this.plugin.handleShowSidebarChange(); }); }); containerEl.createEl("h2", { text: i18n.t("settings.autoNumbering.title") }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.autoNumbering.globalToggle.name")).setDesc(i18n.t("settings.autoNumbering.globalToggle.desc")).addToggle((toggle) => { toggle.setValue(this.plugin.settings.globalAutoNumberingEnabled).onChange(async (value) => { this.plugin.settings.globalAutoNumberingEnabled = value; await this.plugin.saveSettings(); this.plugin.handleShowStateBarChange(); this.plugin.updateRibbonIconState(); this.display(); }); }); if (!this.plugin.settings.globalAutoNumberingEnabled) { const globalDisabledInfo = containerEl.createDiv({ cls: "header-enhancer-global-disabled-info" }); globalDisabledInfo.style.cssText = ` margin: 1.5em 0; padding: 1.2em; border: 2px solid var(--text-muted); border-radius: 8px; background: var(--background-secondary); opacity: 0.8; `; globalDisabledInfo.innerHTML = `
${i18n.t("settings.autoNumbering.globalDisabled.title")}
${i18n.t("settings.autoNumbering.globalDisabled.description")}
`; return; } new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.autoNumbering.mode.name")).setDesc(i18n.t("settings.autoNumbering.mode.desc")).addDropdown((dropdown) => { dropdown.addOption("off" /* OFF */, i18n.t("settings.autoNumbering.mode.off")); dropdown.addOption("on" /* ON */, i18n.t("settings.autoNumbering.mode.on")); dropdown.addOption("yaml" /* YAML_CONTROLLED */, i18n.t("settings.autoNumbering.mode.yaml")); dropdown.setValue(this.plugin.settings.autoNumberingMode); dropdown.onChange(async (value) => { const newMode = value; if ((this.plugin.settings.autoNumberingMode === "on" /* ON */ || this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */) && newMode === "off" /* OFF */) { const { AutoNumberingRemovalDialog: AutoNumberingRemovalDialog2 } = await Promise.resolve().then(() => (init_dialogs(), dialogs_exports)); const dialog = new AutoNumberingRemovalDialog2( this.app, this.plugin, async (removeExisting) => { this.plugin.settings.autoNumberingMode = "off" /* OFF */; await this.plugin.saveSettings(); this.plugin.handleShowStateBarChange(); this.plugin.updateRibbonIconState(); this.display(); } ); dialog.open(); dropdown.setValue(this.plugin.settings.autoNumberingMode); } else if (this.plugin.settings.autoNumberingMode === "off" /* OFF */ && newMode === "on" /* ON */) { const { AutoNumberingActivationDialog: AutoNumberingActivationDialog2 } = await Promise.resolve().then(() => (init_dialogs(), dialogs_exports)); const dialog = new AutoNumberingActivationDialog2( this.app, this.plugin, async (addToAll) => { this.plugin.settings.autoNumberingMode = newMode; await this.plugin.saveSettings(); this.plugin.handleShowStateBarChange(); this.plugin.updateRibbonIconState(); this.display(); } ); dialog.open(); dropdown.setValue(this.plugin.settings.autoNumberingMode); } else { this.plugin.settings.autoNumberingMode = newMode; await this.plugin.saveSettings(); this.plugin.handleShowStateBarChange(); this.plugin.updateRibbonIconState(); this.display(); } }); }); if (this.plugin.settings.autoNumberingMode === "on" /* ON */) { this.renderAutoNumberingSettings(containerEl); } else if (this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */) { this.renderYamlModeSettings(containerEl); } else { const offInfo = containerEl.createDiv({ cls: "header-enhancer-off-info" }); offInfo.style.cssText = ` margin: 1.5em 0; padding: 1.2em; border: 2px solid var(--text-muted); border-radius: 8px; background: var(--background-secondary); opacity: 0.8; `; offInfo.innerHTML = `
${i18n.t("autoDetection.info.offMode.title")}
${i18n.t("autoDetection.info.offMode.description")}
`; } containerEl.createEl("h2", { text: i18n.t("settings.headerFont.title") }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.headerFont.separate.name")).setDesc(i18n.t("settings.headerFont.separate.desc")).addToggle((toggle) => { toggle.setValue(this.plugin.settings.isSeparateHeaderFont).onChange(async (value) => { this.plugin.settings.isSeparateHeaderFont = value; await this.plugin.saveSettings(); this.plugin.styleManager.applyCSSStyles(); this.display(); }); }); if (this.plugin.settings.isSeparateHeaderFont) { const previewContainer = containerEl.createDiv({ cls: "header-enhancer-font-preview" }); previewContainer.style.cssText = ` margin: 1em 0; padding: 1em; border: 1px solid var(--background-modifier-border); border-radius: 6px; background: var(--background-secondary); `; previewContainer.createEl("div", { text: i18n.t("settings.headerFont.preview.title"), cls: "setting-item-name" }); const previewContent = previewContainer.createDiv({ cls: "font-preview-content" }); for (let i = 1; i <= 3; i++) { const tagName = i === 1 ? "h1" : i === 2 ? "h2" : "h3"; const headerEl = previewContent.createEl(tagName, { text: `${i18n.t("settings.headerFont.preview.sample")} ${i}`, cls: "header-enhancer-preview-header" }); this.updateHeaderPreviewStyles(headerEl); } } this.createFontFamilySetting(containerEl, "header"); this.createFontSizeSetting(containerEl, "header"); containerEl.createEl("h2", { text: i18n.t("settings.titleFont.title") }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.titleFont.separate.name")).setDesc(i18n.t("settings.titleFont.separate.desc")).addToggle((toggle) => { toggle.setValue(this.plugin.settings.isSeparateTitleFont).onChange(async (value) => { this.plugin.settings.isSeparateTitleFont = value; await this.plugin.saveSettings(); this.plugin.styleManager.applyCSSStyles(); this.display(); }); }); if (this.plugin.settings.isSeparateTitleFont) { const previewContainer = containerEl.createDiv({ cls: "header-enhancer-title-font-preview" }); previewContainer.style.cssText = ` margin: 1em 0; padding: 1em; border: 1px solid var(--background-modifier-border); border-radius: 6px; background: var(--background-secondary); `; previewContainer.createEl("div", { text: i18n.t("settings.titleFont.preview.title"), cls: "setting-item-name" }); const previewContent = previewContainer.createDiv({ cls: "font-preview-content" }); const titleEl = previewContent.createEl("div", { text: i18n.t("settings.titleFont.preview.sample"), cls: "header-enhancer-preview-title" }); titleEl.style.cssText = "font-size: 1.5em; font-weight: bold; margin: 0.5em 0;"; this.updateTitlePreviewStyles(titleEl); } this.createFontFamilySetting(containerEl, "title"); this.createFontSizeSetting(containerEl, "title"); new import_obsidian3.Setting(containerEl).addButton((button) => { button.setButtonText(i18n.t("settings.resetSettings.name")).onClick(async () => { if (confirm( i18n.t("settings.resetSettings.confirm") )) { this.plugin.settings = DEFAULT_SETTINGS; await this.plugin.saveSettings(); this.display(); } }); }); containerEl.createEl("h2", { text: i18n.t("settings.moreInfo") }); containerEl.createEl("p", { text: i18n.t("settings.author") }).createEl("a", { text: "Hobee Liu", href: "https://github.com/HoBeedzc" }); containerEl.createEl("p", { text: i18n.t("settings.license") }).createEl("a", { text: "MIT", href: "https://github.com/HoBeedzc/obsidian-header-enhancer-plugin/blob/master/LICENSE" }); containerEl.createEl("p", { text: i18n.t("settings.githubRepo") }).createEl("a", { text: "obsidian-header-enhancer", href: "https://github.com/HoBeedzc/obsidian-header-enhancer-plugin" }); containerEl.createEl("p", { text: i18n.t("settings.anyQuestion") }).createEl("a", { text: "Github Issues", href: "https://github.com/HoBeedzc/obsidian-header-enhancer-plugin/issues" }); } /** * 渲染自动编号相关的设置项 */ renderAutoNumberingSettings(containerEl) { const i18n = I18n.getInstance(); const headerLevelSetting = new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.autoNumbering.headerLevel.name")); const updateSettingDesc = () => { if (this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */) { headerLevelSetting.setDesc(i18n.t("settings.autoNumbering.headerLevel.desc.yamlControl")); } else if (this.plugin.settings.isAutoDetectHeaderLevel && this.plugin.settings.autoNumberingMode === "on" /* ON */) { headerLevelSetting.setDesc(i18n.t("settings.autoNumbering.headerLevel.desc.autoDetect")); } else { headerLevelSetting.setDesc(i18n.t("settings.autoNumbering.headerLevel.desc.manual")); } }; updateSettingDesc(); headerLevelSetting.addToggle((toggle) => { toggle.setValue(this.plugin.settings.isAutoDetectHeaderLevel).onChange(async (value) => { this.plugin.settings.isAutoDetectHeaderLevel = value; await this.plugin.saveSettings(); updateSettingDesc(); this.display(); }).setDisabled(this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */); }); if (this.plugin.settings.isAutoDetectHeaderLevel && this.plugin.settings.autoNumberingMode === "on" /* ON */) { this.autoDetectionPreviewContainer = containerEl.createDiv({ cls: "header-enhancer-auto-detection-preview" }); this.autoDetectionPreviewContainer.style.cssText = ` margin: 1em 0; padding: 1.2em; border: 2px solid var(--color-green); border-radius: 8px; background: var(--background-secondary); position: relative; `; const previewTitle2 = this.autoDetectionPreviewContainer.createDiv(); previewTitle2.style.cssText = ` font-weight: 600; font-size: 1em; color: var(--color-green); margin-bottom: 0.8em; display: flex; align-items: center; `; previewTitle2.innerHTML = "\u{1F527} \u667A\u80FD\u68C0\u6D4B\u7ED3\u679C"; this.updateAutoDetectionPreview(); } else { new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.headerLevel.start.name")).setDesc(i18n.t("settings.headerLevel.start.desc")).addDropdown((dropdown) => { dropdown.addOption("1", "H1"); dropdown.addOption("2", "H2"); dropdown.addOption("3", "H3"); dropdown.addOption("4", "H4"); dropdown.addOption("5", "H5"); dropdown.addOption("6", "H6"); dropdown.setValue( this.plugin.settings.startHeaderLevel.toString() ); dropdown.setDisabled(this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */); dropdown.onChange(async (value) => { if (this.checkStartLevel(parseInt(value, 10))) { this.plugin.settings.startHeaderLevel = parseInt(value, 10); await this.plugin.saveSettings(); this.updateFormatPreview(); } else { new import_obsidian3.Notice( i18n.t("settings.autoNumbering.startLevelError") ); dropdown.setValue(this.plugin.settings.startHeaderLevel.toString()); } }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.headerLevel.max.name")).setDesc(i18n.t("settings.headerLevel.max.desc")).addDropdown((dropdown) => { dropdown.addOption("1", "H1"); dropdown.addOption("2", "H2"); dropdown.addOption("3", "H3"); dropdown.addOption("4", "H4"); dropdown.addOption("5", "H5"); dropdown.addOption("6", "H6"); dropdown.setValue( this.plugin.settings.endHeaderLevel.toString() ); dropdown.setDisabled(this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */); dropdown.onChange(async (value) => { if (this.checkEndLevel(parseInt(value, 10))) { this.plugin.settings.endHeaderLevel = parseInt( value, 10 ); await this.plugin.saveSettings(); this.updateFormatPreview(); } else { new import_obsidian3.Notice( i18n.t("settings.autoNumbering.endLevelError") ); dropdown.setValue(this.plugin.settings.endHeaderLevel.toString()); } }); }); } new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.autoNumbering.startNumber.name")).setDesc(i18n.t("settings.autoNumbering.startNumber.desc")).addDropdown((dropdown) => { dropdown.addOption("0", "0"); dropdown.addOption("1", "1"); dropdown.setValue(this.plugin.settings.autoNumberingStartNumber); dropdown.setDisabled(this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */); dropdown.onChange(async (value) => { this.plugin.settings.autoNumberingStartNumber = value; await this.plugin.saveSettings(); this.updateFormatPreview(); }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.autoNumbering.separator.name")).setDesc(i18n.t("settings.autoNumbering.separator.desc")).addDropdown((dropdown) => { dropdown.addOption(".", "."); dropdown.addOption(",", ","); dropdown.addOption("-", "-"); dropdown.addOption("/", "/"); dropdown.setValue(this.plugin.settings.autoNumberingSeparator); dropdown.setDisabled(this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */); dropdown.onChange(async (value) => { this.plugin.settings.autoNumberingSeparator = value; await this.plugin.saveSettings(); this.updateFormatPreview(); }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.autoNumbering.headerSeparator.name")).setDesc(i18n.t("settings.autoNumbering.headerSeparator.desc")).addDropdown((dropdown) => { dropdown.addOption(" ", "Tab"); dropdown.addOption(" ", "Space"); dropdown.setValue( this.plugin.settings.autoNumberingHeaderSeparator ); dropdown.setDisabled(this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */); dropdown.onChange(async (value) => { this.plugin.settings.autoNumberingHeaderSeparator = value; await this.plugin.saveSettings(); }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.autoNumbering.updateBacklinks.name")).setDesc(i18n.t("settings.autoNumbering.updateBacklinks.desc")).addToggle((toggle) => { toggle.setValue(this.plugin.settings.updateBacklinks).onChange(async (value) => { this.plugin.settings.updateBacklinks = value; await this.plugin.saveSettings(); }).setDisabled(this.plugin.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */); }); const formatPreviewContainer = containerEl.createDiv({ cls: "header-enhancer-format-preview-container" }); formatPreviewContainer.style.cssText = ` margin: 1.5em 0; `; const previewTitle = formatPreviewContainer.createDiv(); previewTitle.style.cssText = ` font-weight: 600; font-size: 1.1em; color: var(--text-accent); margin-bottom: 1em; display: flex; align-items: center; gap: 0.5em; `; previewTitle.innerHTML = `\u{1F3AF} ${i18n.t("settings.autoNumbering.format.name")}`; const previewContent = formatPreviewContainer.createDiv({ cls: "format-preview-content" }); this.formatPreviewSetting = { setDesc: (content) => { previewContent.innerHTML = content; } }; previewContent.innerHTML = this.getFormatPreview(); } /** * Create font family setting for header or title */ createFontFamilySetting(containerEl, type) { const i18n = I18n.getInstance(); const isHeader2 = type === "header"; const settingsKey = isHeader2 ? "settings.headerFont" : "settings.titleFont"; new import_obsidian3.Setting(containerEl).setName(i18n.t(`${settingsKey}.family.name`)).setDesc(i18n.t(`${settingsKey}.family.desc`)).addDropdown((dropdown) => { dropdown.addOption("inherit", i18n.t(`${settingsKey}.family.options.inherit`)); dropdown.addOption("Arial, sans-serif", "Arial"); dropdown.addOption("Helvetica, Arial, sans-serif", "Helvetica"); dropdown.addOption("Verdana, Geneva, sans-serif", "Verdana"); dropdown.addOption("Tahoma, Geneva, sans-serif", "Tahoma"); dropdown.addOption("'Trebuchet MS', Helvetica, sans-serif", "Trebuchet MS"); dropdown.addOption("'Lucida Sans Unicode', 'Lucida Grande', sans-serif", "Lucida Sans"); dropdown.addOption("Impact, Charcoal, sans-serif", "Impact"); dropdown.addOption("'Comic Sans MS', cursive", "Comic Sans MS"); dropdown.addOption("'Times New Roman', Times, serif", "Times New Roman"); dropdown.addOption("Georgia, serif", "Georgia"); dropdown.addOption("'Palatino Linotype', 'Book Antiqua', Palatino, serif", "Palatino"); dropdown.addOption("Garamond, serif", "Garamond"); dropdown.addOption("'Book Antiqua', Palatino, serif", "Book Antiqua"); dropdown.addOption("'Courier New', Courier, monospace", "Courier New"); dropdown.addOption("Consolas, 'Liberation Mono', monospace", "Consolas"); dropdown.addOption("Monaco, 'Lucida Console', monospace", "Monaco"); dropdown.addOption("'JetBrains Mono', Consolas, monospace", "JetBrains Mono"); dropdown.addOption("'Fira Code', Consolas, monospace", "Fira Code"); dropdown.addOption("Menlo, Monaco, monospace", "Menlo"); dropdown.addOption("'Microsoft YaHei', '\u5FAE\u8F6F\u96C5\u9ED1', Arial, sans-serif", "Microsoft YaHei (\u5FAE\u8F6F\u96C5\u9ED1)"); dropdown.addOption("'PingFang SC', '\u82F9\u65B9-\u7B80', 'Helvetica Neue', Arial, sans-serif", "PingFang SC (\u82F9\u65B9-\u7B80)"); dropdown.addOption("'Hiragino Sans GB', '\u51AC\u9752\u9ED1\u4F53\u7B80\u4F53\u4E2D\u6587', 'Microsoft YaHei', sans-serif", "Hiragino Sans GB (\u51AC\u9752\u9ED1\u4F53)"); dropdown.addOption("'Source Han Sans SC', '\u601D\u6E90\u9ED1\u4F53 CN', 'Noto Sans CJK SC', sans-serif", "Source Han Sans SC (\u601D\u6E90\u9ED1\u4F53)"); dropdown.addOption("'Noto Sans SC', '\u601D\u6E90\u9ED1\u4F53', sans-serif", "Noto Sans SC"); dropdown.addOption("SimHei, '\u9ED1\u4F53', sans-serif", "SimHei (\u9ED1\u4F53)"); dropdown.addOption("'WenQuanYi Micro Hei', '\u6587\u6CC9\u9A7F\u5FAE\u7C73\u9ED1', sans-serif", "WenQuanYi Micro Hei (\u6587\u6CC9\u9A7F\u5FAE\u7C73\u9ED1)"); dropdown.addOption("'Songti SC', '\u5B8B\u4F53-\u7B80', SimSun, serif", "Songti SC (\u5B8B\u4F53-\u7B80)"); dropdown.addOption("SimSun, '\u5B8B\u4F53', serif", "SimSun (\u5B8B\u4F53)"); dropdown.addOption("'Source Han Serif SC', '\u601D\u6E90\u5B8B\u4F53 CN', 'Noto Serif CJK SC', serif", "Source Han Serif SC (\u601D\u6E90\u5B8B\u4F53)"); dropdown.addOption("'Noto Serif SC', '\u601D\u6E90\u5B8B\u4F53', serif", "Noto Serif SC"); dropdown.addOption("'STSong', '\u534E\u6587\u5B8B\u4F53', SimSun, serif", "STSong (\u534E\u6587\u5B8B\u4F53)"); dropdown.addOption("'FangSong', '\u4EFF\u5B8B', serif", "FangSong (\u4EFF\u5B8B)"); dropdown.addOption("system-ui, -apple-system, sans-serif", "System UI"); dropdown.addOption("-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif", "System Default"); dropdown.addOption("'PingFang SC', 'Microsoft YaHei', 'Hiragino Sans GB', Arial, sans-serif", "\u4E2D\u82F1\u6587\u65E0\u886C\u7EBF\u6DF7\u5408"); dropdown.addOption("'Songti SC', 'Source Han Serif SC', 'Times New Roman', serif", "\u4E2D\u82F1\u6587\u886C\u7EBF\u6DF7\u5408"); const currentValue = isHeader2 ? this.plugin.settings.headerFontFamily : this.plugin.settings.titleFontFamily; const isEnabled = isHeader2 ? this.plugin.settings.isSeparateHeaderFont : this.plugin.settings.isSeparateTitleFont; dropdown.setValue(currentValue); dropdown.setDisabled(!isEnabled); dropdown.onChange(async (value) => { if (isHeader2) { this.plugin.settings.headerFontFamily = value; } else { this.plugin.settings.titleFontFamily = value; } await this.plugin.saveSettings(); if (isEnabled) { this.plugin.styleManager.applyCSSStyles(); if (isHeader2) { this.updateAllHeaderPreviewStyles(); } else { this.updateAllTitlePreviewStyles(); } } }); }); } /** * Create font size setting for header or title */ createFontSizeSetting(containerEl, type) { const i18n = I18n.getInstance(); const isHeader2 = type === "header"; const settingsKey = isHeader2 ? "settings.headerFont" : "settings.titleFont"; new import_obsidian3.Setting(containerEl).setName(i18n.t(`${settingsKey}.size.name`)).setDesc(i18n.t(`${settingsKey}.size.desc`)).addDropdown((dropdown) => { dropdown.addOption("inherit", i18n.t(`${settingsKey}.size.options.inherit`)); dropdown.addOption("0.8em", i18n.t(`${settingsKey}.size.options.smaller`) + " (0.8em)"); dropdown.addOption("0.9em", i18n.t(`${settingsKey}.size.options.small`) + " (0.9em)"); dropdown.addOption("1em", i18n.t(`${settingsKey}.size.options.normal`) + " (1em)"); dropdown.addOption("1.1em", i18n.t(`${settingsKey}.size.options.large`) + " (1.1em)"); dropdown.addOption("1.2em", i18n.t(`${settingsKey}.size.options.larger`) + " (1.2em)"); dropdown.addOption("1.3em", i18n.t(`${settingsKey}.size.options.xlarge`) + " (1.3em)"); dropdown.addOption("1.5em", i18n.t(`${settingsKey}.size.options.xxlarge`) + " (1.5em)"); dropdown.addOption("12px", "12px"); dropdown.addOption("14px", "14px"); dropdown.addOption("16px", "16px"); dropdown.addOption("18px", "18px"); dropdown.addOption("20px", "20px"); dropdown.addOption("24px", "24px"); dropdown.addOption("28px", "28px"); dropdown.addOption("32px", "32px"); dropdown.addOption("120%", "120%"); dropdown.addOption("140%", "140%"); const currentValue = isHeader2 ? this.plugin.settings.headerFontSize : this.plugin.settings.titleFontSize; const isEnabled = isHeader2 ? this.plugin.settings.isSeparateHeaderFont : this.plugin.settings.isSeparateTitleFont; dropdown.setValue(currentValue); dropdown.setDisabled(!isEnabled); dropdown.onChange(async (value) => { if (isHeader2) { this.plugin.settings.headerFontSize = value; } else { this.plugin.settings.titleFontSize = value; } await this.plugin.saveSettings(); if (isEnabled) { this.plugin.styleManager.applyCSSStyles(); if (isHeader2) { this.updateAllHeaderPreviewStyles(); } else { this.updateAllTitlePreviewStyles(); } } }); }); } /** * Update auto detection preview */ updateAutoDetectionPreview() { if (!this.autoDetectionPreviewContainer) return; const i18n = I18n.getInstance(); const activeView = this.app.workspace.getActiveViewOfType(import_obsidian3.MarkdownView); let contentContainer = this.autoDetectionPreviewContainer.querySelector(".preview-content"); if (!contentContainer) { contentContainer = this.autoDetectionPreviewContainer.createDiv({ cls: "preview-content" }); } if (!activeView) { contentContainer.innerHTML = `
${i18n.t("autoDetection.noActiveDocument")}
`; this.updateFormatPreview(); return; } const content = activeView.editor.getValue(); const analysis = analyzeHeaderLevels(content); contentContainer.innerHTML = `
${this.formatAnalysisResult(analysis)}
`; this.updateFormatPreview(); } /** * Format analysis result for display */ formatAnalysisResult(analysis) { const i18n = I18n.getInstance(); if (analysis.isEmpty) { return `
\u{1F4DD} ${i18n.t("autoDetection.noHeaders")}
`; } const levelNames = analysis.usedLevels.map((level) => `H${level}`).join(" "); const mappingInfo = analysis.usedLevels.map( (level, index) => `H${level}\u2192${index + 1}\u7EA7` ).join(" "); return `
${i18n.t("autoDetection.detected")}:
${levelNames}
${i18n.t("autoDetection.range")}: H${analysis.minLevel} - H${analysis.maxLevel}
${i18n.t("autoDetection.mapping")}:
${mappingInfo}
${i18n.t("autoDetection.totalHeaders")}: ${analysis.headerCount}
`; } /** * Get format preview string */ getFormatPreview() { const i18n = I18n.getInstance(); switch (this.plugin.settings.autoNumberingMode) { case "off" /* OFF */: return `
\u23F9\uFE0F
${i18n.t("settings.autoNumbering.format.disabled")}
`; case "yaml" /* YAML_CONTROLLED */: return `
\u{1F4C4}
${i18n.t("settings.autoNumbering.format.yamlControlled")}
`; case "on" /* ON */: default: const formatExample = this.plugin.settings.autoNumberingStartNumber + this.plugin.settings.autoNumberingSeparator + "1" + this.plugin.settings.autoNumberingSeparator + "1"; let levelInfo; let statusBadge; if (this.plugin.settings.isAutoDetectHeaderLevel) { const activeView = this.app.workspace.getActiveViewOfType(import_obsidian3.MarkdownView); if (activeView) { const content = activeView.editor.getValue(); const analysis = analyzeHeaderLevels(content); if (!analysis.isEmpty) { levelInfo = `${i18n.t("settings.autoNumbering.format.fromLevel")} H${analysis.minLevel} ${i18n.t("settings.autoNumbering.format.toLevel")} H${analysis.maxLevel}`; statusBadge = `${i18n.t("settings.autoNumbering.format.autoDetect")}`; } else { levelInfo = i18n.t("autoDetection.noHeaders"); statusBadge = `${i18n.t("settings.autoNumbering.format.autoDetect")}`; } } else { levelInfo = i18n.t("autoDetection.noActiveDocument"); statusBadge = `${i18n.t("settings.autoNumbering.format.autoDetect")}`; } } else { levelInfo = `${i18n.t("settings.autoNumbering.format.fromLevel")} H${this.plugin.settings.startHeaderLevel} ${i18n.t("settings.autoNumbering.format.toLevel")} H${this.plugin.settings.endHeaderLevel}`; statusBadge = `${i18n.t("settings.autoNumbering.format.manual")}`; } return `
${formatExample}
\u{1F4CF} ${levelInfo}
${statusBadge}
`; } } /** * Update format preview */ updateFormatPreview() { if (this.formatPreviewSetting) { this.formatPreviewSetting.setDesc(this.getFormatPreview()); } } /** * Validation methods */ checkEndLevel(maxLevel) { return this.plugin.settings.startHeaderLevel <= maxLevel; } checkStartLevel(startLevel) { return startLevel <= this.plugin.settings.endHeaderLevel; } checkStartNumber(startNumber) { const reg = /^[0-9]*$/; return reg.test(startNumber); } checkSeparator(separator) { if (separator.length != 1) { return false; } const separators = [".", ",", "-", "/"]; return separators.includes(separator); } checkHeaderSeparator(_separator) { if (this.plugin.settings.autoNumberingMode === "on" /* ON */) { return false; } return true; } /** * Update preview styles for a single header element */ updateHeaderPreviewStyles(headerEl) { if (this.plugin.settings.headerFontFamily && this.plugin.settings.headerFontFamily !== "inherit") { headerEl.style.fontFamily = this.plugin.settings.headerFontFamily; } else { headerEl.style.fontFamily = ""; } if (this.plugin.settings.headerFontSize && this.plugin.settings.headerFontSize !== "inherit") { headerEl.style.fontSize = this.plugin.settings.headerFontSize; } else { headerEl.style.fontSize = ""; } } /** * Update preview styles for title element */ updateTitlePreviewStyles(titleEl) { if (this.plugin.settings.titleFontFamily && this.plugin.settings.titleFontFamily !== "inherit") { titleEl.style.fontFamily = this.plugin.settings.titleFontFamily; } else { titleEl.style.fontFamily = ""; } if (this.plugin.settings.titleFontSize && this.plugin.settings.titleFontSize !== "inherit") { titleEl.style.fontSize = this.plugin.settings.titleFontSize; } else { titleEl.style.fontSize = ""; } } /** * Update preview styles for all preview headers */ updateAllHeaderPreviewStyles() { const previewHeaders = this.containerEl.querySelectorAll(".header-enhancer-preview-header"); previewHeaders.forEach((headerEl) => { this.updateHeaderPreviewStyles(headerEl); }); } /** * Update preview styles for all preview titles */ updateAllTitlePreviewStyles() { const previewTitles = this.containerEl.querySelectorAll(".header-enhancer-preview-title"); previewTitles.forEach((titleEl) => { this.updateTitlePreviewStyles(titleEl); }); } /** * 渲染 YAML 模式的设置项 */ renderYamlModeSettings(containerEl) { const i18n = I18n.getInstance(); const yamlExample = `["state on", "start-level h${this.plugin.settings.yamlDefaultStartLevel}", "end-level h${this.plugin.settings.yamlDefaultEndLevel}", "start-at ${this.plugin.settings.yamlDefaultStartNumber}", "separator ${this.plugin.settings.yamlDefaultSeparator}"]`; const yamlInfo = containerEl.createDiv({ cls: "header-enhancer-yaml-info" }); yamlInfo.style.cssText = ` margin: 1.5em 0; padding: 1.2em; border: 2px solid var(--color-blue); border-radius: 8px; background: var(--background-secondary); `; yamlInfo.innerHTML = `
${i18n.t("autoDetection.info.yamlMode.title")}
${i18n.t("autoDetection.info.yamlMode.description")}

---
header-auto-numbering: ${yamlExample}
---

${i18n.t("autoDetection.info.yamlMode.usage")}
`; new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.yamlMode.fallback.name")).setDesc(i18n.t("settings.yamlMode.fallback.desc")).addDropdown((dropdown) => { dropdown.addOption("no_numbering" /* NO_NUMBERING */, i18n.t("settings.yamlMode.fallback.noNumbering")); dropdown.addOption("use_default" /* USE_DEFAULT */, i18n.t("settings.yamlMode.fallback.useDefault")); dropdown.setValue(this.plugin.settings.yamlFallbackMode); dropdown.onChange(async (value) => { this.plugin.settings.yamlFallbackMode = value; await this.plugin.saveSettings(); this.display(); }); }); if (this.plugin.settings.yamlFallbackMode === "use_default" /* USE_DEFAULT */) { new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.yamlMode.defaultStartLevel.name")).setDesc(i18n.t("settings.yamlMode.defaultStartLevel.desc")).addDropdown((dropdown) => { dropdown.addOption("1", "H1"); dropdown.addOption("2", "H2"); dropdown.addOption("3", "H3"); dropdown.addOption("4", "H4"); dropdown.addOption("5", "H5"); dropdown.addOption("6", "H6"); dropdown.setValue(this.plugin.settings.yamlDefaultStartLevel.toString()); dropdown.onChange(async (value) => { const numValue = parseInt(value, 10); if (numValue <= this.plugin.settings.yamlDefaultEndLevel) { this.plugin.settings.yamlDefaultStartLevel = numValue; await this.plugin.saveSettings(); this.display(); } else { new import_obsidian3.Notice(i18n.t("settings.autoNumbering.startLevelError")); dropdown.setValue(this.plugin.settings.yamlDefaultStartLevel.toString()); } }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.yamlMode.defaultEndLevel.name")).setDesc(i18n.t("settings.yamlMode.defaultEndLevel.desc")).addDropdown((dropdown) => { dropdown.addOption("1", "H1"); dropdown.addOption("2", "H2"); dropdown.addOption("3", "H3"); dropdown.addOption("4", "H4"); dropdown.addOption("5", "H5"); dropdown.addOption("6", "H6"); dropdown.setValue(this.plugin.settings.yamlDefaultEndLevel.toString()); dropdown.onChange(async (value) => { const numValue = parseInt(value, 10); if (numValue >= this.plugin.settings.yamlDefaultStartLevel) { this.plugin.settings.yamlDefaultEndLevel = numValue; await this.plugin.saveSettings(); this.display(); } else { new import_obsidian3.Notice(i18n.t("settings.autoNumbering.endLevelError")); dropdown.setValue(this.plugin.settings.yamlDefaultEndLevel.toString()); } }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.yamlMode.defaultStartNumber.name")).setDesc(i18n.t("settings.yamlMode.defaultStartNumber.desc")).addDropdown((dropdown) => { dropdown.addOption("0", "0"); dropdown.addOption("1", "1"); dropdown.setValue(this.plugin.settings.yamlDefaultStartNumber); dropdown.onChange(async (value) => { this.plugin.settings.yamlDefaultStartNumber = value; await this.plugin.saveSettings(); this.display(); }); }); new import_obsidian3.Setting(containerEl).setName(i18n.t("settings.yamlMode.defaultSeparator.name")).setDesc(i18n.t("settings.yamlMode.defaultSeparator.desc")).addDropdown((dropdown) => { dropdown.addOption(".", "."); dropdown.addOption(",", ","); dropdown.addOption("-", "-"); dropdown.addOption("/", "/"); dropdown.setValue(this.plugin.settings.yamlDefaultSeparator); dropdown.onChange(async (value) => { this.plugin.settings.yamlDefaultSeparator = value; await this.plugin.saveSettings(); this.display(); }); }); } } }; } }); // src/main.ts var main_exports = {}; __export(main_exports, { default: () => HeaderEnhancerPlugin }); module.exports = __toCommonJS(main_exports); var import_obsidian6 = require("obsidian"); init_core(); init_utils(); init_setting(); init_config(); init_i18n(); // src/backlinks.ts var import_obsidian4 = require("obsidian"); var BacklinkManager = class { constructor(app) { this.app = app; } /** * Find backlinks pointing to a specific heading * @param targetFile Target file * @param oldHeading Original heading text (without # symbols) * @returns List of link updates needed */ async findHeadingBacklinks(targetFile, oldHeading) { const updates = []; try { const backlinksMap = this.app.metadataCache.getBacklinksForFile(targetFile); if (!backlinksMap) { return updates; } let actualMap = backlinksMap; if (backlinksMap.data && backlinksMap.data instanceof Map) { actualMap = backlinksMap.data; } if (!actualMap || actualMap.size === 0) { return updates; } for (const [sourcePath, references] of actualMap) { const sourceFile = this.app.vault.getAbstractFileByPath(sourcePath); if (!(sourceFile instanceof import_obsidian4.TFile)) continue; const content = await this.app.vault.read(sourceFile); const lines = content.split("\n"); for (const ref of references) { if (this.isReferenceCache(ref)) { const linkUpdate = this.extractHeaderLink( sourceFile, ref, lines, targetFile.basename, oldHeading ); if (linkUpdate) { updates.push(linkUpdate); } } } } } catch (error) { console.error("Error finding heading backlinks:", error); new import_obsidian4.Notice("Error finding backlinks: " + error.message); } return updates; } /** * Batch update header links in multiple files * @param updates List of header link updates to apply * @returns Whether all updates were successful */ async updateBacklinks(updates) { if (updates.length === 0) return true; const updatePromises = []; const backupData = []; try { for (const update of updates) { const originalContent = await this.app.vault.read(update.sourceFile); backupData.push({ file: update.sourceFile, content: originalContent }); updatePromises.push(this.updateSingleBacklink(update, originalContent)); } await Promise.all(updatePromises); return true; } catch (error) { console.error("Error updating backlinks:", error); try { const rollbackPromises = backupData.map( (backup) => this.app.vault.modify(backup.file, backup.content) ); await Promise.all(rollbackPromises); new import_obsidian4.Notice("Backlink update failed, changes rolled back"); } catch (rollbackError) { console.error("Failed to rollback changes:", rollbackError); new import_obsidian4.Notice("Critical error: Failed to rollback backlink changes"); } return false; } } /** * Update a single backlink */ async updateSingleBacklink(update, originalContent) { const lines = originalContent.split("\n"); const { line } = update.position.start; if (line >= lines.length) return; const oldLine = lines[line]; const newLine = oldLine.replace(update.oldLink, update.newLink); if (oldLine !== newLine) { lines[line] = newLine; const newContent = lines.join("\n"); await this.app.vault.modify(update.sourceFile, newContent); } } /** * Extract header link information from a reference */ extractHeaderLink(sourceFile, ref, lines, targetFileName, oldHeading) { const { line, ch } = ref.position.start; if (line >= lines.length) return null; const lineContent = lines[line]; const expectedLinkPrefix = `${targetFileName}#`; if (ref.link && ref.link.startsWith(expectedLinkPrefix)) { const linkHeading = ref.link.substring(expectedLinkPrefix.length); const normalizedLinkHeading = this.normalizeSpaces(linkHeading); const normalizedOldHeading = this.normalizeSpaces(oldHeading); if (normalizedLinkHeading === normalizedOldHeading || normalizedLinkHeading.includes(normalizedOldHeading) || normalizedOldHeading.includes(normalizedLinkHeading)) { const linkUpdate = { sourceFile, oldLink: ref.original, // Use original link text newLink: ref.original, // Set to same initially, will be updated in main.ts position: { start: { line: ref.position.start.line, ch: ref.position.start.col }, end: { line: ref.position.end.line, ch: ref.position.end.col } } }; return linkUpdate; } } return null; } /** * Type guard: check if reference is ReferenceCache type */ isReferenceCache(ref) { return ref && typeof ref === "object" && "position" in ref; } /** * Normalize spaces - convert multiple whitespace characters (including Tab) to single space */ normalizeSpaces(text) { return text.replace(/\s+/g, " ").trim(); } }; // src/editor/editor-handlers.ts var import_view = require("@codemirror/view"); var import_state = require("@codemirror/state"); var import_obsidian5 = require("obsidian"); init_core(); init_config(); init_setting(); var EditorHandlers = class { constructor(plugin) { this.plugin = plugin; } /** * 注册 CodeMirror 按键处理扩展 */ registerKeyHandlers() { return [ // Enter 键处理 import_state.Prec.highest( import_view.keymap.of([ { key: "Enter", run: (view) => { var _a; const state = view.state; const pos = state.selection.main.to; const currentLine = state.doc.lineAt(pos); if (!isHeader(currentLine.text)) { return false; } if (this.plugin.settings.autoNumberingMode === "off" /* OFF */) { return false; } const app = this.plugin.app; const activeView = app.workspace.getActiveViewOfType(import_obsidian5.MarkdownView); if (activeView) { const editor = activeView.editor; const filePath = (_a = activeView.file) == null ? void 0 : _a.path; const config = getAutoNumberingConfig( this.plugin.settings, editor, filePath ? (path) => this.plugin.getDocumentAutoNumberingState(path) : void 0, filePath ); if (!config.state) { return false; } } this.handlePressEnter(view); return true; } } ]) ), // Backspace 键处理 import_state.Prec.highest( import_view.keymap.of([ { key: "Backspace", run: (view) => { const state = view.state; const pos = state.selection.main.to; const currentLine = state.doc.lineAt(pos); if (!isHeader(currentLine.text)) { return false; } return this.handlePressBackspace(view); } } ]) ) ]; } /** * 处理 Enter 键按下事件 */ async handlePressEnter(view) { var _a; let state = view.state; let doc = state.doc; const pos = state.selection.main.to; const app = this.plugin.app; const activeView = app.workspace.getActiveViewOfType(import_obsidian5.MarkdownView); if (!activeView) { return false; } const currentLine = doc.lineAt(pos); const editor = activeView.editor; const filePath = (_a = activeView.file) == null ? void 0 : _a.path; const config = getAutoNumberingConfig( this.plugin.settings, editor, filePath ? (path) => this.plugin.getDocumentAutoNumberingState(path) : void 0, filePath ); if (!isHeader(currentLine.text) || !config.state) { return false; } const textBeforeCursor = currentLine.text.substring(0, pos - currentLine.from); const textAfterCursor = currentLine.text.substring(pos - currentLine.from); const changes = [{ from: currentLine.from, to: currentLine.to, insert: textBeforeCursor + "\n" + textAfterCursor }]; view.dispatch({ changes, selection: { anchor: currentLine.from + textBeforeCursor.length + 1 }, userEvent: "HeaderEnhancer.changeAutoNumbering" }); setTimeout(async () => { await this.plugin.handleAddHeaderNumber(activeView); if (this.plugin.settings.isAutoDetectHeaderLevel) { this.plugin.handleShowStateBarChange(); } }, 10); return true; } /** * 处理 Backspace 键按下事件 */ handlePressBackspace(view) { let state = view.state; let doc = state.doc; const pos = state.selection.main.to; const changes = []; if (!isHeader(doc.lineAt(pos).text)) { return false; } changes.push({ from: pos - 1, to: pos, insert: "" }); if (this.plugin.settings.autoNumberingMode === "on" /* ON */) { } view.dispatch({ changes, selection: { anchor: pos - 1 }, userEvent: "HeaderEnhancer.changeAutoNumbering" }); return true; } }; // src/styles/style-manager.ts var StyleManager = class { constructor(settings) { this.settings = settings; this.headerFontStyleEl = null; this.titleFontStyleEl = null; this.dialogStyleEl = null; this.ribbonIconStyleEl = null; } /** * Apply all CSS styles */ applyCSSStyles() { this.applyHeaderFontStyles(); this.applyTitleFontStyles(); this.applyDialogStyles(); this.applyRibbonIconStyles(); } /** * Remove all CSS styles */ removeCSSStyles() { this.removeHeaderFontStyles(); this.removeTitleFontStyles(); this.removeDialogStyles(); this.removeRibbonIconStyles(); } /** * Apply header font styles (# ## ### etc.) */ applyHeaderFontStyles() { this.removeHeaderFontStyles(); if (!this.settings.isSeparateHeaderFont) { return; } this.headerFontStyleEl = document.createElement("style"); this.headerFontStyleEl.id = "header-enhancer-header-font-styles"; let cssRules = ""; const headerSelectors = [ ".markdown-preview-view h1", ".markdown-preview-view h2", ".markdown-preview-view h3", ".markdown-preview-view h4", ".markdown-preview-view h5", ".markdown-preview-view h6", ".markdown-source-view.mod-cm6 .HyperMD-header-1", ".markdown-source-view.mod-cm6 .HyperMD-header-2", ".markdown-source-view.mod-cm6 .HyperMD-header-3", ".markdown-source-view.mod-cm6 .HyperMD-header-4", ".markdown-source-view.mod-cm6 .HyperMD-header-5", ".markdown-source-view.mod-cm6 .HyperMD-header-6" ].join(", "); if (this.settings.headerFontFamily && this.settings.headerFontFamily !== "inherit") { cssRules += `${headerSelectors} { font-family: ${this.settings.headerFontFamily} !important; } `; } if (this.settings.headerFontSize && this.settings.headerFontSize !== "inherit") { cssRules += `${headerSelectors} { font-size: ${this.settings.headerFontSize} !important; } `; } this.headerFontStyleEl.textContent = cssRules; if (cssRules) { document.head.appendChild(this.headerFontStyleEl); } } /** * 应用文档标题字体样式 */ applyTitleFontStyles() { this.removeTitleFontStyles(); if (!this.settings.isSeparateTitleFont) { return; } this.titleFontStyleEl = document.createElement("style"); this.titleFontStyleEl.id = "header-enhancer-title-font-styles"; let cssRules = ""; const titleSelectors = [ // 标签页中的文件标题 - 只针对特定的标签标题元素 ".workspace-tab-header-inner-title", ".workspace-tab-header .workspace-tab-header-inner-title", ".workspace-tabs .workspace-tab-header-inner-title", // 视图标题栏标题 ".workspace-leaf-content .view-header-title", // 文档内联标题(在文档中显示的主标题) ".inline-title", ".markdown-preview-view .inline-title", ".markdown-source-view .inline-title", // 文件资源管理器中的文件标题 ".nav-file-title-content", ".tree-item-inner.nav-file-title-content", // Frontmatter 标题显示 '.frontmatter-container .metadata-property[data-property-key="title"] .metadata-property-value' ].join(", "); if (this.settings.titleFontFamily && this.settings.titleFontFamily !== "inherit") { cssRules += `${titleSelectors} { font-family: ${this.settings.titleFontFamily} !important; } `; } if (this.settings.titleFontSize && this.settings.titleFontSize !== "inherit") { cssRules += `${titleSelectors} { font-size: ${this.settings.titleFontSize} !important; } `; } this.titleFontStyleEl.textContent = cssRules; if (cssRules) { document.head.appendChild(this.titleFontStyleEl); } } /** * Apply ribbon icon state styles */ applyRibbonIconStyles() { this.removeRibbonIconStyles(); this.ribbonIconStyleEl = document.createElement("style"); this.ribbonIconStyleEl.id = "header-enhancer-ribbon-icon-styles"; const ribbonIconCSS = ` /* Ribbon icon state styles for Header Enhancer */ .side-dock-ribbon-action[aria-label*="Header Enhancer"].header-enhancer-global-disabled { opacity: 0.4; } .side-dock-ribbon-action[aria-label*="Header Enhancer"].header-enhancer-global-disabled:hover { opacity: 0.6; } .side-dock-ribbon-action[aria-label*="Header Enhancer"].header-enhancer-document-enabled { color: var(--color-accent); } .side-dock-ribbon-action[aria-label*="Header Enhancer"].header-enhancer-document-enabled:hover { color: var(--color-accent-hover); } .side-dock-ribbon-action[aria-label*="Header Enhancer"].header-enhancer-document-disabled { opacity: 0.7; color: var(--text-muted); } .side-dock-ribbon-action[aria-label*="Header Enhancer"].header-enhancer-document-disabled:hover { opacity: 1; color: var(--text-normal); } /* Additional visual indicator for global disabled state */ .side-dock-ribbon-action[aria-label*="Header Enhancer"].header-enhancer-global-disabled::before { content: ""; position: absolute; top: 2px; right: 2px; width: 6px; height: 6px; border-radius: 50%; background-color: var(--text-error); z-index: 10; } `; this.ribbonIconStyleEl.textContent = ribbonIconCSS; document.head.appendChild(this.ribbonIconStyleEl); } /** * 应用对话框组件样式 */ applyDialogStyles() { this.removeDialogStyles(); this.dialogStyleEl = document.createElement("style"); this.dialogStyleEl.id = "header-enhancer-dialog-styles"; const dialogCSS = ` /* Auto numbering dialog styles - shared between removal and activation */ .header-enhancer-removal-dialog, .header-enhancer-activation-dialog { max-width: 500px; } .header-enhancer-removal-dialog .modal-title, .header-enhancer-activation-dialog .modal-title { margin-bottom: 1em; padding-bottom: 0.5em; color: var(--text-accent); border-bottom: 1px solid var(--background-modifier-border); } .header-enhancer-removal-dialog .modal-message, .header-enhancer-activation-dialog .modal-message { margin-bottom: 1.5em; line-height: 1.5; color: var(--text-normal); } .header-enhancer-removal-dialog .modal-actions, .header-enhancer-activation-dialog .modal-actions { margin-top: 1em; padding-top: 1em; border-top: 1px solid var(--background-modifier-border); } .header-enhancer-removal-dialog .modal-actions .setting-item, .header-enhancer-activation-dialog .modal-actions .setting-item { margin-bottom: 0.75em; padding: 0.75em; background-color: var(--background-secondary); border: 1px solid var(--background-modifier-border); border-radius: 6px; transition: all 0.2s ease; } .header-enhancer-removal-dialog .modal-actions .setting-item:hover, .header-enhancer-activation-dialog .modal-actions .setting-item:hover { background-color: var(--background-secondary-alt); border-color: var(--background-modifier-border-hover); } /* Warning and tip text styles */ .header-enhancer-removal-dialog .setting-item-warning, .header-enhancer-removal-dialog .setting-item-tip, .header-enhancer-activation-dialog .setting-item-warning, .header-enhancer-activation-dialog .setting-item-tip { margin-top: 0.5em; font-size: 0.85em; line-height: 1.3; } .header-enhancer-removal-dialog .warning-label, .header-enhancer-activation-dialog .warning-label { color: var(--text-error); font-weight: 600; } .header-enhancer-removal-dialog .warning-text, .header-enhancer-removal-dialog .progress-text, .header-enhancer-activation-dialog .warning-text, .header-enhancer-activation-dialog .progress-text { color: var(--text-muted); margin: 0; } .header-enhancer-removal-dialog .manual-tip-text, .header-enhancer-activation-dialog .manual-tip-text { color: var(--text-muted); font-style: italic; } .header-enhancer-removal-dialog .modal-cancel, .header-enhancer-activation-dialog .modal-cancel { margin-top: 1em; padding-top: 1em; text-align: center; border-top: 1px solid var(--background-modifier-border-focus); } .header-enhancer-removal-dialog .progress-container, .header-enhancer-activation-dialog .progress-container { margin-top: 1em; padding: 1em; background-color: var(--background-secondary); border: 1px solid var(--background-modifier-border); border-radius: 6px; text-align: center; } .header-enhancer-removal-dialog .progress-text, .header-enhancer-activation-dialog .progress-text { font-size: 0.9em; } .header-enhancer-removal-dialog button:disabled, .header-enhancer-activation-dialog button:disabled { opacity: 0.5; cursor: not-allowed; } `; this.dialogStyleEl.textContent = dialogCSS; document.head.appendChild(this.dialogStyleEl); } /** * 移除标题字体样式 */ removeHeaderFontStyles() { if (this.headerFontStyleEl) { this.headerFontStyleEl.remove(); this.headerFontStyleEl = null; } } /** * 移除文档标题字体样式 */ removeTitleFontStyles() { if (this.titleFontStyleEl) { this.titleFontStyleEl.remove(); this.titleFontStyleEl = null; } } /** * 移除对话框样式 */ removeDialogStyles() { if (this.dialogStyleEl) { this.dialogStyleEl.remove(); this.dialogStyleEl = null; } } /** * 移除侧边栏图标样式 */ removeRibbonIconStyles() { if (this.ribbonIconStyleEl) { this.ribbonIconStyleEl.remove(); this.ribbonIconStyleEl = null; } } /** * 更新设置引用(当设置改变时调用) */ updateSettings(newSettings) { this.settings = newSettings; } }; // src/main.ts var HeaderEnhancerPlugin = class extends import_obsidian6.Plugin { constructor() { super(...arguments); this.perDocumentStatesMap = /* @__PURE__ */ new Map(); } async onload() { await this.loadSettings(); this.backlinkManager = new BacklinkManager(this.app); this.editorHandlers = new EditorHandlers(this); this.styleManager = new StyleManager(this.settings); this.styleManager.applyCSSStyles(); this.ribbonIconEl = this.addRibbonIcon( "heading-glyph", "Header Enhancer", async (_evt) => { const i18n2 = I18n.getInstance(); const app = this.app; const activeView = app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView); if (!(activeView == null ? void 0 : activeView.file)) { new import_obsidian6.Notice(i18n2.t("notices.noActiveView")); return; } const filePath = activeView.file.path; if (!this.settings.globalAutoNumberingEnabled) { new import_obsidian6.Notice(i18n2.t("notices.globalDisabledNotice")); return; } const currentState = this.getDocumentAutoNumberingState(filePath); const newState = !currentState; await this.toggleDocumentState(activeView, newState); this.updateAllUIStates(); } ); this.statusBarItemEl = this.addStatusBarItem(); this.handleShowStateBarChange(); this.handleShowSidebarChange(); this.updateAllUIStates(); const keyHandlers = this.editorHandlers.registerKeyHandlers(); keyHandlers.forEach((handler) => this.registerEditorExtension(handler)); this.registerEvent( this.app.workspace.on("active-leaf-change", () => { this.updateAllUIStates(); }) ); this.registerEvent( this.app.workspace.on("file-open", () => { setTimeout(() => { this.updateAllUIStates(); }, 50); }) ); const i18n = I18n.getInstance(); this.addCommand({ id: "toggle-global-auto-numbering", name: i18n.t("commands.toggleGlobalAutoNumbering"), callback: async () => { const newState = !this.settings.globalAutoNumberingEnabled; this.settings.globalAutoNumberingEnabled = newState; await this.saveSettings(); new import_obsidian6.Notice(newState ? i18n.t("notices.globalAutoNumberingEnabled") : i18n.t("notices.globalAutoNumberingDisabled")); this.updateAllUIStates(); } }); this.addCommand({ id: "toggle-document-auto-numbering", name: i18n.t("commands.toggleDocumentAutoNumbering"), callback: async () => { const activeView = this.app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView); if (!(activeView == null ? void 0 : activeView.file)) { new import_obsidian6.Notice(i18n.t("notices.noActiveView")); return; } const filePath = activeView.file.path; if (!this.settings.globalAutoNumberingEnabled) { new import_obsidian6.Notice(i18n.t("notices.globalDisabledNotice")); return; } const currentState = this.getDocumentAutoNumberingState(filePath); const newState = !currentState; await this.toggleDocumentState(activeView, newState); this.updateAllUIStates(); } }); this.addCommand({ id: "reset-auto-numbering-yaml", name: i18n.t("commands.resetAutoNumberingYaml"), callback: () => { const app = this.app; const activeView = app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView); if (!activeView) { new import_obsidian6.Notice(i18n.t("notices.noActiveView")); return; } else { const editor = activeView.editor; const yaml = getAutoNumberingYaml(editor); if (yaml === "") { new import_obsidian6.Notice(i18n.t("notices.yamlNotExists")); } else { const value = [ "state on", "start-level h2", "end-level h6", "start-at 1", "separator ." ]; setAutoNumberingYaml(editor, value); } } } }); this.addCommand({ id: "remove-auto-numbering-yaml", name: i18n.t("commands.removeAutoNumberingYaml"), callback: () => { const app = this.app; const activeView = app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView); if (!activeView) { new import_obsidian6.Notice(i18n.t("notices.noActiveView")); return; } else { const editor = activeView.editor; const yaml = getAutoNumberingYaml(editor); if (yaml === "") { new import_obsidian6.Notice(i18n.t("notices.yamlNotExists")); } else { setAutoNumberingYaml(editor, []); } } } }); this.addCommand({ id: "apply-custom-yaml-config", name: i18n.t("commands.applyCustomYamlConfig"), callback: () => { const app = this.app; const activeView = app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView); if (!activeView) { new import_obsidian6.Notice(i18n.t("notices.noActiveView")); return; } else { const editor = activeView.editor; const yaml = getAutoNumberingYaml(editor); if (yaml !== "") { new import_obsidian6.Notice(i18n.t("notices.yamlAlreadyExists")); } else { const value = [ "state on", `start-level h${this.settings.yamlDefaultStartLevel}`, `end-level h${this.settings.yamlDefaultEndLevel}`, `start-at ${this.settings.yamlDefaultStartNumber}`, `separator ${this.settings.yamlDefaultSeparator}` ]; setAutoNumberingYaml(editor, value); new import_obsidian6.Notice(i18n.t("notices.yamlTemplateInserted")); } } } }); this.addSettingTab(new HeaderEnhancerSettingTab(this.app, this)); this.registerInterval( window.setInterval(() => { }, 5 * 60 * 1e3) ); } onunload() { this.styleManager.removeCSSStyles(); } async loadSettings() { this.settings = Object.assign( {}, DEFAULT_SETTINGS, await this.loadData() ); this.migrateSettings(); try { if (this.settings.perDocumentStates) { const parsedStates = JSON.parse(this.settings.perDocumentStates); this.perDocumentStatesMap = new Map(Object.entries(parsedStates)); } } catch (error) { console.warn("Failed to parse perDocumentStates, using empty map:", error); this.perDocumentStatesMap = /* @__PURE__ */ new Map(); } } /** * Migrate settings for backward compatibility */ migrateSettings() { if (this.settings.globalAutoNumberingEnabled === void 0) { this.settings.globalAutoNumberingEnabled = this.settings.autoNumberingMode !== "off" /* OFF */; } if (this.settings.perDocumentStates === void 0) { this.settings.perDocumentStates = "{}"; } } async saveSettings() { const statesObject = Object.fromEntries(this.perDocumentStatesMap.entries()); this.settings.perDocumentStates = JSON.stringify(statesObject); await this.saveData(this.settings); this.styleManager.updateSettings(this.settings); } /** * Get the current document auto numbering state * Legacy method - now uses unified state evaluation */ getDocumentAutoNumberingState(filePath) { const activeView = this.app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView); if (!(activeView == null ? void 0 : activeView.file) || activeView.file.path !== filePath) { return this.getSimpleDocumentState(filePath); } return this.getUnifiedDocumentState(activeView.editor, filePath); } /** * Get unified document auto numbering state - includes YAML parsing * This ensures UI and actual numbering use exactly the same logic */ getUnifiedDocumentState(editor, filePath) { const config = getAutoNumberingConfig( this.settings, editor, (path) => this.getSimpleDocumentState(path), filePath ); return config.state; } /** * Get simple document state without YAML parsing (for non-active documents) */ getSimpleDocumentState(filePath) { var _a; if (!this.settings.globalAutoNumberingEnabled) { return false; } if (this.perDocumentStatesMap.has(filePath)) { return (_a = this.perDocumentStatesMap.get(filePath)) != null ? _a : false; } return this.settings.autoNumberingMode !== "off" /* OFF */; } /** * Set the current document auto numbering state */ async setDocumentAutoNumberingState(filePath, enabled) { this.perDocumentStatesMap.set(filePath, enabled); await this.saveSettings(); } /** * Update all UI states (ribbon icon, status bar) */ updateAllUIStates() { this.updateRibbonIconState(); this.handleShowStateBarChange(); } /** * Update ribbon icon state based on global and document settings */ updateRibbonIconState() { const activeView = this.app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView); if (!(activeView == null ? void 0 : activeView.file)) { if (!this.settings.globalAutoNumberingEnabled) { this.ribbonIconEl.addClass("header-enhancer-global-disabled"); this.ribbonIconEl.removeClass("header-enhancer-document-enabled"); this.ribbonIconEl.removeClass("header-enhancer-document-disabled"); this.ribbonIconEl.setAttribute("aria-label", "Header Enhancer (Global Disabled)"); } else { this.ribbonIconEl.removeClass("header-enhancer-global-disabled"); this.ribbonIconEl.removeClass("header-enhancer-document-enabled"); this.ribbonIconEl.addClass("header-enhancer-document-disabled"); this.ribbonIconEl.setAttribute("aria-label", "Header Enhancer (No Active Document)"); } return; } const filePath = activeView.file.path; const globalEnabled = this.settings.globalAutoNumberingEnabled; const documentEnabled = this.getDocumentAutoNumberingState(filePath); if (!globalEnabled) { this.ribbonIconEl.addClass("header-enhancer-global-disabled"); this.ribbonIconEl.removeClass("header-enhancer-document-enabled"); this.ribbonIconEl.removeClass("header-enhancer-document-disabled"); this.ribbonIconEl.setAttribute("aria-label", "Header Enhancer (Global Disabled)"); } else if (documentEnabled) { this.ribbonIconEl.removeClass("header-enhancer-global-disabled"); this.ribbonIconEl.addClass("header-enhancer-document-enabled"); this.ribbonIconEl.removeClass("header-enhancer-document-disabled"); this.ribbonIconEl.setAttribute("aria-label", "Header Enhancer (Document Enabled)"); } else { this.ribbonIconEl.removeClass("header-enhancer-global-disabled"); this.ribbonIconEl.removeClass("header-enhancer-document-enabled"); this.ribbonIconEl.addClass("header-enhancer-document-disabled"); this.ribbonIconEl.setAttribute("aria-label", "Header Enhancer (Document Disabled)"); } } handleShowStateBarChange() { if (this.settings.showOnStatusBar) { const i18n = I18n.getInstance(); let autoNumberingStatus; if (!this.settings.globalAutoNumberingEnabled) { autoNumberingStatus = i18n.t("statusBar.globalDisabled"); } else { const activeView = this.app.workspace.getActiveViewOfType(import_obsidian6.MarkdownView); if (!(activeView == null ? void 0 : activeView.file)) { autoNumberingStatus = i18n.t("statusBar.off"); } else { const filePath = activeView.file.path; const documentEnabled = this.getDocumentAutoNumberingState(filePath); if (documentEnabled) { switch (this.settings.autoNumberingMode) { case "on" /* ON */: if (this.settings.isAutoDetectHeaderLevel) { const analysis = analyzeHeaderLevels(activeView.editor.getValue()); if (!analysis.isEmpty) { autoNumberingStatus = `${i18n.t("statusBar.auto")}(H${analysis.minLevel}-H${analysis.maxLevel})`; } else { autoNumberingStatus = i18n.t("statusBar.autoNoHeaders"); } } else { autoNumberingStatus = `${i18n.t("statusBar.on")}(H${this.settings.startHeaderLevel}-H${this.settings.endHeaderLevel})`; } break; case "yaml" /* YAML_CONTROLLED */: autoNumberingStatus = i18n.t("statusBar.yaml"); break; case "off" /* OFF */: default: autoNumberingStatus = i18n.t("statusBar.documentEnabled"); break; } } else { autoNumberingStatus = i18n.t("statusBar.documentDisabled"); } } } this.statusBarItemEl.setText( `${i18n.t("statusBar.title")}: ${autoNumberingStatus}` ); this.statusBarItemEl.show(); } else { this.statusBarItemEl.hide(); } } handleShowSidebarChange() { if (this.settings.showOnSidebar) { this.ribbonIconEl.show(); } else { this.ribbonIconEl.hide(); } } async handleAddHeaderNumber(view) { var _a; const editor = view.editor; const lineCount = editor.lineCount(); let docCharCount = 0; const filePath = (_a = view.file) == null ? void 0 : _a.path; const config = getAutoNumberingConfig( this.settings, editor, filePath ? (path) => this.getDocumentAutoNumberingState(path) : void 0, filePath ); if (!config.state) { return false; } const currentFile = view.file; const headerChanges = []; if (config.state) { let insertNumber = [Number(config.startNumber) - 1]; let isCodeBlock = false; for (let i = 0; i <= lineCount; i++) { const line = editor.getLine(i); docCharCount += line.length; if (line.startsWith("```")) { isCodeBlock = !isCodeBlock; if (line.slice(3).contains("```")) { isCodeBlock = !isCodeBlock; } } if (isCodeBlock) { continue; } if (isHeader(line)) { const [headerLevel, realHeaderLevel] = getHeaderLevel( line, config.startLevel ); if (headerLevel <= 0) { continue; } insertNumber = getNextNumber(insertNumber, headerLevel); const insertNumberStr = insertNumber.join(config.separator); let newLine = null; let originalHeading = null; if (isNeedInsertNumber( line, this.settings.autoNumberingHeaderSeparator )) { originalHeading = line.substring(realHeaderLevel + 1).trim(); newLine = "#".repeat(realHeaderLevel) + " " + insertNumberStr + this.settings.autoNumberingHeaderSeparator + line.substring(realHeaderLevel + 1); } else if (isNeedUpdateNumber( insertNumberStr, line, this.settings.autoNumberingHeaderSeparator )) { const textAfterSeparator = line.split(this.settings.autoNumberingHeaderSeparator)[1]; originalHeading = textAfterSeparator ? textAfterSeparator.trim() : null; const originNumberLength = line.split( this.settings.autoNumberingHeaderSeparator )[0].split(" ")[1].length; newLine = "#".repeat(realHeaderLevel) + " " + insertNumberStr + line.substring( realHeaderLevel + originNumberLength + 1 ); } if (newLine && newLine !== line && originalHeading) { headerChanges.push({ lineIndex: i, oldText: line, newText: newLine, originalHeading }); editor.setLine(i, newLine); } } } if (this.settings.updateBacklinks && headerChanges.length > 0 && currentFile) { await this.updateBacklinksForChanges(currentFile, headerChanges); } } return true; } /** * Handle backlink updates when headers change */ async updateBacklinksForChanges(currentFile, headerChanges) { try { for (const change of headerChanges) { const oldHeading = change.originalHeading; if (oldHeading && change.oldText !== change.newText) { const backlinks = await this.backlinkManager.findHeadingBacklinks( currentFile, oldHeading.trim() ); const updates = backlinks.map((link) => { const fullNewHeading = this.extractFullHeadingWithNumber(change.newText); const newLink = link.oldLink.replace( `#${oldHeading.trim()}`, `#${fullNewHeading}` ); return { ...link, newLink }; }); if (updates.length > 0) { await this.backlinkManager.updateBacklinks(updates); } } } } catch (error) { console.error("Error updating backlinks:", error); new import_obsidian6.Notice("Failed to update backlinks: " + error.message); } } /** * Extract plain heading text (remove # symbols and numbering) */ extractHeadingText(headerLine) { const match = headerLine.match(/^#+\s*(?:\d+[\.\-\/,]*\d*\s*[\t\s]*)?\s*(.+)$/); return match ? match[1].trim() : null; } /** * Extract full heading text with numbering (remove # symbols but keep numbering) */ extractFullHeadingWithNumber(headerLine) { const match = headerLine.match(/^#+\s*(.+)$/); return match ? match[1].trim() : headerLine; } async handleRemoveHeaderNumber(view) { var _a; const editor = view.editor; const lineCount = editor.lineCount(); const filePath = (_a = view.file) == null ? void 0 : _a.path; const config = getAutoNumberingConfig( this.settings, editor, filePath ? (path) => this.getDocumentAutoNumberingState(path) : void 0, filePath ); const currentFile = view.file; const headerChanges = []; for (let i = 0; i <= lineCount; i++) { const line = editor.getLine(i); if (isHeader(line)) { const [headerLevel, _] = getHeaderLevel( line, config.startLevel ); if (headerLevel <= 0) { continue; } const newLine = removeHeaderNumber( line, this.settings.autoNumberingHeaderSeparator ); if (newLine !== line) { const originalHeading = this.extractHeadingText(newLine); if (originalHeading) { headerChanges.push({ lineIndex: i, oldText: line, newText: newLine, originalHeading }); } editor.setLine(i, newLine); } } } if (this.settings.updateBacklinks && headerChanges.length > 0 && currentFile) { await this.updateBacklinksForRemoval(currentFile, headerChanges); } return true; } /** * Handle backlink updates when removing header numbers */ async updateBacklinksForRemoval(currentFile, headerChanges) { try { for (const change of headerChanges) { const oldFullHeading = this.extractFullHeadingWithNumber(change.oldText); const newHeading = change.originalHeading; if (oldFullHeading && newHeading) { const backlinks = await this.backlinkManager.findHeadingBacklinks( currentFile, oldFullHeading ); const updates = backlinks.map((link) => { const newLink = link.oldLink.replace( `#${oldFullHeading}`, `#${newHeading}` ); return { ...link, newLink }; }); if (updates.length > 0) { await this.backlinkManager.updateBacklinks(updates); } } } } catch (error) { console.error("Error updating backlinks for removal:", error); new import_obsidian6.Notice("Failed to update backlinks during removal: " + error.message); } } /** * Toggle document auto-numbering state * In YAML mode: synchronizes both perDocumentStatesMap and YAML state * In ON mode: only modifies perDocumentStatesMap */ async toggleDocumentState(activeView, newState) { var _a; const i18n = I18n.getInstance(); const filePath = (_a = activeView.file) == null ? void 0 : _a.path; if (!filePath) return; if (this.settings.autoNumberingMode === "yaml" /* YAML_CONTROLLED */) { await this.setDocumentAutoNumberingState(filePath, newState); const editor = activeView.editor; const yaml = getAutoNumberingYaml(editor); if (yaml === "") { const value = [ `state ${newState ? "on" : "off"}` ]; setAutoNumberingYaml(editor, value); } else { const yamlArray = yaml; let hasState = false; const newYaml = yamlArray.map((line) => { if (line.startsWith("state ")) { hasState = true; return `state ${newState ? "on" : "off"}`; } return line; }); if (!hasState) { newYaml.unshift(`state ${newState ? "on" : "off"}`); } setAutoNumberingYaml(editor, newYaml); } if (newState) { await this.handleAddHeaderNumber(activeView); new import_obsidian6.Notice(i18n.t("notices.autoNumberingEnabledForDocument")); } else { await this.handleRemoveHeaderNumber(activeView); new import_obsidian6.Notice(i18n.t("notices.autoNumberingDisabledForDocument")); } } else { await this.setDocumentAutoNumberingState(filePath, newState); if (newState) { await this.handleAddHeaderNumber(activeView); new import_obsidian6.Notice(i18n.t("notices.autoNumberingEnabledForDocument")); } else { await this.handleRemoveHeaderNumber(activeView); new import_obsidian6.Notice(i18n.t("notices.autoNumberingDisabledForDocument")); } } } }; /* nosourcemap */