GitHub Collapse Markdown

🚀 简洁高效的GitHub Markdown标题折叠脚本:智能嵌套🧠+快捷键⌨️+目录📑+搜索🔍+状态记忆💾+简约GUI🔘

目前為 2025-07-02 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        GitHub Collapse Markdown
// @version     3.2.3
// @description 🚀 简洁高效的GitHub Markdown标题折叠脚本:智能嵌套🧠+快捷键⌨️+目录📑+搜索🔍+状态记忆💾+简约GUI🔘
// @license     MIT
// @author      Xyea
// @namespace   https://github.com/Mottie
// @match       https://github.com/*
// @match       https://gist.github.com/*
// @match       https://help.github.com/*
// @run-at      document-idle
// @grant       GM_addStyle
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_registerMenuCommand
// @icon        https://github.githubassets.com/pinned-octocat.svg
// ==/UserScript==

(() => {
	"use strict";

	// 配置常量
	const CONFIG = {
		debug: GM_getValue("ghcm-debug-mode", false), // 调试模式开关
		colors: GM_getValue("ghcm-colors", [
			"#6778d0", "#ac9c3d", "#b94a73", "#56ae6c", "#9750a1", "#ba543d"
		]),
		animation: {
			duration: 200,
			easing: "cubic-bezier(0.4, 0, 0.2, 1)",
			maxAnimatedElements: GM_getValue("ghcm-performance-mode", false) ? 0 : 20, // 根据用户设置
			batchSize: 10 // 批量处理大小
		},
		selectors: {
			markdownContainers: [
			".markdown-body",
			".markdown-format",
				".comment-body"
			],
			headers: ["H1", "H2", "H3", "H4", "H5", "H6"],
			excludeClicks: [".anchor", ".octicon-link", "a", "img"]
		},
		classes: {
			collapsed: "ghcm-collapsed",
			hidden: "ghcm-hidden",
			hiddenByParent: "ghcm-hidden-by-parent",
			noContent: "ghcm-no-content",
			tocContainer: "ghcm-toc-container",
			searchContainer: "ghcm-search-container",
			menuContainer: "ghcm-menu-container",
			menuButton: "ghcm-menu-button",
			bookmarked: "ghcm-bookmarked"
		},
		hotkeys: {
			enabled: GM_getValue("ghcm-hotkeys-enabled", true),
			toggleAll: "ctrl+shift+a", // 切换所有折叠
			collapseAll: "ctrl+shift+c", // 折叠所有
			expandAll: "ctrl+shift+e", // 展开所有
			showToc: "ctrl+shift+l", // 显示目录
			search: "ctrl+shift+f", // 搜索
			menu: "ctrl+shift+m" // 显示菜单
		},
		memory: {
			enabled: GM_getValue("ghcm-memory-enabled", true),
			key: "ghcm-page-states"
		}
	};

	// 日志控制函数
	const Logger = {
		log: (...args) => {
			if (CONFIG.debug) {
				console.log(...args);
			}
		},
		warn: (...args) => {
			console.warn(...args);
		},
		error: (...args) => {
			console.error(...args);
		}
	};

	// GUI菜单管理器
	class MenuManager {
		constructor(app) {
			this.app = app;
			this.isVisible = false;
			this.menuContainer = null;
			this.menuButton = null;
			this.init();
		}

		init() {
			this.createMenuButton();
			this.addMenuStyles();
		}

		addMenuStyles() {
			GM_addStyle(`
				/* 菜单按钮 */
				.${CONFIG.classes.menuButton} {
					position: fixed;
					bottom: 20px;
					right: 20px;
					width: 50px;
					height: 50px;
					background: #6b7280;
					border: none;
					border-radius: 50%;
					cursor: pointer;
					z-index: 9999;
					box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
					transition: all 0.2s ease;
					display: flex;
					align-items: center;
					justify-content: center;
					font-size: 18px;
					color: white;
					user-select: none;
				}

				.${CONFIG.classes.menuButton}:hover {
					background: #4b5563;
					transform: translateY(-1px);
					box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
				}

				.${CONFIG.classes.menuButton}:active {
					transform: translateY(0) scale(0.95);
				}

				.${CONFIG.classes.menuButton}.menu-open {
					background: #374151;
					transform: rotate(45deg);
				}

				/* 菜单容器 */
				.${CONFIG.classes.menuContainer} {
					position: fixed;
					bottom: 80px;
					right: 20px;
					width: 300px;
					background: rgba(255, 255, 255, 0.98);
					backdrop-filter: blur(10px);
					border: 1px solid #e5e7eb;
					border-radius: 12px;
					box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
					z-index: 9998;
					opacity: 0;
					transform: translateY(10px) scale(0.95);
					transition: all 0.25s ease;
					overflow: hidden;
					font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
				}

				.${CONFIG.classes.menuContainer}.show {
					opacity: 1;
					transform: translateY(0) scale(1);
				}

				/* 菜单头部 */
				.ghcm-menu-header {
					padding: 16px 20px 12px;
					background: #f9fafb;
					color: #374151;
					text-align: center;
					border-bottom: 1px solid #e5e7eb;
				}

				.ghcm-menu-title {
					font-size: 16px;
					font-weight: 600;
					margin: 0 0 4px;
				}

				.ghcm-menu-subtitle {
					font-size: 11px;
					opacity: 0.7;
					margin: 0;
				}

				/* 菜单内容 */
				.ghcm-menu-content {
					padding: 0;
					max-height: 400px;
					overflow-y: auto;
				}

				/* 菜单分组 */
				.ghcm-menu-group {
					padding: 12px 0;
					border-bottom: 1px solid #f3f4f6;
				}

				.ghcm-menu-group:last-child {
					border-bottom: none;
				}

				.ghcm-menu-group-title {
					font-size: 10px;
					font-weight: 600;
					color: #9ca3af;
					text-transform: uppercase;
					letter-spacing: 0.5px;
					margin: 0 20px 8px;
				}

				/* 菜单项 */
				.ghcm-menu-item {
					display: flex;
					align-items: center;
					padding: 10px 20px;
					cursor: pointer;
					transition: background-color 0.15s ease;
					color: #374151;
					text-decoration: none;
					font-size: 13px;
					line-height: 1.4;
				}

				.ghcm-menu-item:hover {
					background: #f3f4f6;
					color: #1f2937;
				}

				.ghcm-menu-item:active {
					background: #e5e7eb;
				}

				.ghcm-menu-item-icon {
					width: 20px;
					height: 20px;
					margin-right: 12px;
					display: flex;
					align-items: center;
					justify-content: center;
					font-size: 16px;
					flex-shrink: 0;
				}

				.ghcm-menu-item-text {
					flex: 1;
					font-weight: 500;
				}

				.ghcm-menu-item-shortcut {
					font-size: 10px;
					color: #9ca3af;
					background: #f3f4f6;
					padding: 2px 6px;
					border-radius: 3px;
					font-family: Monaco, 'Courier New', monospace;
				}

				.ghcm-menu-item-badge {
					background: #6b7280;
					color: white;
					font-size: 10px;
					padding: 2px 6px;
					border-radius: 6px;
					font-weight: 500;
				}

				/* 切换开关 */
				.ghcm-menu-toggle {
					position: relative;
					width: 36px;
					height: 18px;
					background: #d1d5db;
					border-radius: 9px;
					transition: background 0.2s ease;
					cursor: pointer;
				}

				.ghcm-menu-toggle.active {
					background: #6b7280;
				}

				.ghcm-menu-toggle::after {
					content: '';
					position: absolute;
					top: 2px;
					left: 2px;
					width: 14px;
					height: 14px;
					background: white;
					border-radius: 50%;
					transition: transform 0.2s ease;
					box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
				}

				.ghcm-menu-toggle.active::after {
					transform: translateX(18px);
				}

				/* 统计信息 */
				.ghcm-menu-stats {
					padding: 12px 20px;
					background: #f9fafb;
					font-size: 11px;
					color: #6b7280;
					line-height: 1.5;
				}

				.ghcm-menu-stats-item {
					display: flex;
					justify-content: space-between;
					margin-bottom: 3px;
				}

				.ghcm-menu-stats-item:last-child {
					margin-bottom: 0;
				}

				.ghcm-menu-stats-value {
					font-weight: 600;
					color: #374151;
				}

				/* 深色主题适配 */
				@media (prefers-color-scheme: dark) {
					.${CONFIG.classes.menuContainer} {
						background: rgba(31, 41, 55, 0.98);
						border-color: #374151;
					}

					.ghcm-menu-header {
						background: #1f2937;
						color: #f9fafb;
						border-bottom-color: #374151;
					}

					.ghcm-menu-item {
						color: #e5e7eb;
					}

					.ghcm-menu-item:hover {
						background: #374151;
						color: #f9fafb;
					}

					.ghcm-menu-group {
						border-bottom-color: #374151;
					}

					.ghcm-menu-group-title {
						color: #9ca3af;
					}

					.ghcm-menu-item-shortcut {
						background: #374151;
						color: #9ca3af;
					}

					.ghcm-menu-stats {
						background: #1f2937;
						color: #9ca3af;
					}

					.ghcm-menu-stats-value {
						color: #e5e7eb;
					}
				}

				/* 响应式设计 */
				@media (max-width: 480px) {
					.${CONFIG.classes.menuContainer} {
						right: 15px;
						width: calc(100vw - 30px);
						max-width: 320px;
					}

					.${CONFIG.classes.menuButton} {
						right: 15px;
						bottom: 15px;
					}
				}
			`);
		}

		createMenuButton() {
			this.menuButton = document.createElement('button');
			this.menuButton.className = CONFIG.classes.menuButton;
			this.menuButton.innerHTML = '⚙️';
			this.menuButton.title = 'GitHub Collapse Markdown 设置';

			this.menuButton.addEventListener('click', (e) => {
				e.stopPropagation();
				this.toggle();
			});

			document.body.appendChild(this.menuButton);
		}

		createMenuContainer() {
			const container = document.createElement('div');
			container.className = CONFIG.classes.menuContainer;

			container.innerHTML = `
				<div class="ghcm-menu-header">
					<h3 class="ghcm-menu-title">📝 Collapse Markdown</h3>
					<p class="ghcm-menu-subtitle">智能标题折叠工具</p>
				</div>
				<div class="ghcm-menu-content">
					${this.generateMenuContent()}
				</div>
			`;

			this.setupMenuEvents(container);
			return container;
		}

		generateMenuContent() {
			const stats = this.getStatistics();

			return `
				<div class="ghcm-menu-stats">
					<div class="ghcm-menu-stats-item">
						<span>总标题数</span>
						<span class="ghcm-menu-stats-value">${stats.total}</span>
					</div>
					<div class="ghcm-menu-stats-item">
						<span>已折叠</span>
						<span class="ghcm-menu-stats-value">${stats.collapsed}</span>
					</div>
					<div class="ghcm-menu-stats-item">
						<span>可见</span>
						<span class="ghcm-menu-stats-value">${stats.visible}</span>
					</div>
				</div>

				<div class="ghcm-menu-group">
					<div class="ghcm-menu-group-title">基础操作</div>
					<div class="ghcm-menu-item" data-action="collapseAll">
						<div class="ghcm-menu-item-icon">📁</div>
						<div class="ghcm-menu-item-text">折叠所有</div>
						<div class="ghcm-menu-item-shortcut">${CONFIG.hotkeys.collapseAll}</div>
					</div>
					<div class="ghcm-menu-item" data-action="expandAll">
						<div class="ghcm-menu-item-icon">📂</div>
						<div class="ghcm-menu-item-text">展开所有</div>
						<div class="ghcm-menu-item-shortcut">${CONFIG.hotkeys.expandAll}</div>
					</div>
					<div class="ghcm-menu-item" data-action="toggleAll">
						<div class="ghcm-menu-item-icon">🔄</div>
						<div class="ghcm-menu-item-text">智能切换</div>
						<div class="ghcm-menu-item-shortcut">${CONFIG.hotkeys.toggleAll}</div>
					</div>
				</div>

				<div class="ghcm-menu-group">
					<div class="ghcm-menu-group-title">工具功能</div>
					<div class="ghcm-menu-item" data-action="showToc">
						<div class="ghcm-menu-item-icon">📑</div>
						<div class="ghcm-menu-item-text">目录导航</div>
						<div class="ghcm-menu-item-shortcut">${CONFIG.hotkeys.showToc}</div>
					</div>
					<div class="ghcm-menu-item" data-action="showSearch">
						<div class="ghcm-menu-item-icon">🔍</div>
						<div class="ghcm-menu-item-text">搜索标题</div>
						<div class="ghcm-menu-item-shortcut">${CONFIG.hotkeys.search}</div>
					</div>
				</div>

				<div class="ghcm-menu-group">
					<div class="ghcm-menu-group-title">设置选项</div>
					<div class="ghcm-menu-item" data-action="togglePerformance">
						<div class="ghcm-menu-item-icon">⚡</div>
						<div class="ghcm-menu-item-text">性能模式</div>
						<div class="ghcm-menu-toggle ${CONFIG.animation.maxAnimatedElements === 0 ? 'active' : ''}" data-toggle="performance"></div>
					</div>
					<div class="ghcm-menu-item" data-action="toggleMemory">
						<div class="ghcm-menu-item-icon">💾</div>
						<div class="ghcm-menu-item-text">状态记忆</div>
						<div class="ghcm-menu-toggle ${CONFIG.memory.enabled ? 'active' : ''}" data-toggle="memory"></div>
					</div>
					<div class="ghcm-menu-item" data-action="toggleHotkeys">
						<div class="ghcm-menu-item-icon">⌨️</div>
						<div class="ghcm-menu-item-text">快捷键</div>
						<div class="ghcm-menu-toggle ${CONFIG.hotkeys.enabled ? 'active' : ''}" data-toggle="hotkeys"></div>
					</div>
					<div class="ghcm-menu-item" data-action="toggleDebug">
						<div class="ghcm-menu-item-icon">🐛</div>
						<div class="ghcm-menu-item-text">调试模式</div>
						<div class="ghcm-menu-toggle ${CONFIG.debug ? 'active' : ''}" data-toggle="debug"></div>
					</div>
				</div>

				<div class="ghcm-menu-group">
					<div class="ghcm-menu-group-title">重置功能</div>
					<div class="ghcm-menu-item" data-action="resetStates">
						<div class="ghcm-menu-item-icon">🔄</div>
						<div class="ghcm-menu-item-text">重置状态</div>
					</div>
					<div class="ghcm-menu-item" data-action="clearMemory">
						<div class="ghcm-menu-item-icon">🗑️</div>
						<div class="ghcm-menu-item-text">清除记忆</div>
					</div>
				</div>

				<div class="ghcm-menu-group">
					<div class="ghcm-menu-group-title">帮助信息</div>
					<div class="ghcm-menu-item" data-action="showHelp">
						<div class="ghcm-menu-item-icon">❓</div>
						<div class="ghcm-menu-item-text">使用说明</div>
					</div>
				</div>
			`;
		}

		setupMenuEvents(container) {
			// 点击菜单项事件
			container.addEventListener('click', (e) => {
				const item = e.target.closest('.ghcm-menu-item');
				if (!item) return;

				const action = item.getAttribute('data-action');
				const toggle = e.target.closest('.ghcm-menu-toggle');

				if (toggle) {
					this.handleToggle(toggle);
					return;
				}

				if (action) {
					this.handleAction(action);
					this.hide();
				}
			});

			// 阻止菜单容器内的点击事件冒泡
			container.addEventListener('click', (e) => {
				e.stopPropagation();
			});
		}

		handleAction(action) {
			switch (action) {
				case 'collapseAll':
					this.app.collapseManager.collapseAll();
					break;
				case 'expandAll':
					this.app.collapseManager.expandAll();
					break;
				case 'toggleAll':
					this.app.collapseManager.toggleAll();
					break;
				case 'showToc':
					this.app.tocGenerator.toggle();
					break;
				case 'showSearch':
					this.app.searchManager.toggle();
					break;
				case 'togglePerformance':
					this.app.togglePerformanceMode();
					this.refreshMenu();
					break;
				case 'toggleMemory':
					this.app.toggleMemory();
					this.refreshMenu();
					break;
				case 'toggleHotkeys':
					this.app.toggleHotkeys();
					this.refreshMenu();
					break;
				case 'toggleDebug':
					this.app.toggleDebug();
					this.refreshMenu();
					break;
				case 'resetStates':
					if (confirm('确定要重置当前页面的所有折叠状态吗?')) {
						this.app.resetAllStates();
						this.refreshMenu();
					}
					break;
				case 'clearMemory':
					if (confirm('确定要清除所有页面的记忆数据吗?')) {
						this.app.clearAllMemory();
						this.refreshMenu();
					}
					break;
				case 'showHelp':
					this.app.showHotkeyHelp();
					break;
			}
		}

		handleToggle(toggle) {
			const toggleType = toggle.getAttribute('data-toggle');
			const isActive = toggle.classList.contains('active');

			toggle.classList.toggle('active', !isActive);

			switch (toggleType) {
				case 'performance':
					this.app.togglePerformanceMode();
					break;
				case 'memory':
					this.app.toggleMemory();
					break;
				case 'hotkeys':
					this.app.toggleHotkeys();
					break;
				case 'debug':
					this.app.toggleDebug();
					break;
			}
		}

		getStatistics() {
			const headers = this.app.collapseManager.getAllHeaders();
			const collapsed = headers.filter(h => h.classList.contains(CONFIG.classes.collapsed));
			const visible = headers.filter(h =>
				!h.classList.contains(CONFIG.classes.collapsed) &&
				!h.classList.contains(CONFIG.classes.noContent)
			);

			return {
				total: headers.length,
				collapsed: collapsed.length,
				visible: visible.length
			};
		}

		refreshMenu() {
			if (this.menuContainer && this.isVisible) {
				const content = this.menuContainer.querySelector('.ghcm-menu-content');
				if (content) {
					content.innerHTML = this.generateMenuContent();
					this.setupMenuEvents(this.menuContainer);
				}
			}
		}

		show() {
			if (this.isVisible) return;

			if (this.menuContainer) {
				this.menuContainer.remove();
			}

			this.menuContainer = this.createMenuContainer();
			document.body.appendChild(this.menuContainer);

			// 动画显示
			requestAnimationFrame(() => {
				this.menuContainer.classList.add('show');
			});

			this.menuButton.classList.add('menu-open');
			this.isVisible = true;

			// 点击外部关闭
			setTimeout(() => {
				document.addEventListener('click', this.hideOnClickOutside);
			}, 100);
		}

		hide() {
			if (!this.isVisible || !this.menuContainer) return;

			this.menuContainer.classList.remove('show');
			this.menuButton.classList.remove('menu-open');

			setTimeout(() => {
				if (this.menuContainer) {
					this.menuContainer.remove();
					this.menuContainer = null;
				}
			}, 300);

			this.isVisible = false;
			document.removeEventListener('click', this.hideOnClickOutside);
		}

		toggle() {
			if (this.isVisible) {
				this.hide();
			} else {
				this.show();
			}
		}

		hideOnClickOutside = (e) => {
			if (!this.menuContainer?.contains(e.target) &&
				!this.menuButton?.contains(e.target)) {
				this.hide();
			}
		}
	}

	// 状态管理
	class StateManager {
		constructor() {
			this.headerStates = new Map();
			this.observers = [];
			this.pageUrl = window.location.href;
		}

		setHeaderState(headerKey, state) {
			this.headerStates.set(headerKey, state);
			this.saveToMemory();
		}

		getHeaderState(headerKey) {
			return this.headerStates.get(headerKey);
		}

		generateHeaderKey(element) {
			const level = this.getHeaderLevel(element);
			const text = element.textContent?.trim() || "";
			const position = Array.from(element.parentElement?.children || []).indexOf(element);
			return `${level}-${text}-${position}`;
		}

		getHeaderLevel(element) {
			return parseInt(element.nodeName.replace(/[^\d]/, ""), 10);
		}

		clear() {
			this.headerStates.clear();
			this.saveToMemory();
		}

		// 状态记忆功能
		saveToMemory() {
			if (!CONFIG.memory.enabled) return;

			try {
				const pageStates = GM_getValue(CONFIG.memory.key, {});
				const currentStates = {};

				this.headerStates.forEach((state, key) => {
					currentStates[key] = state.isCollapsed;
				});

				pageStates[this.pageUrl] = currentStates;
				GM_setValue(CONFIG.memory.key, pageStates);
			} catch (e) {
				Logger.warn("[GHCM] 保存状态失败:", e);
			}
		}

		loadFromMemory() {
			if (!CONFIG.memory.enabled) return;

			try {
				const pageStates = GM_getValue(CONFIG.memory.key, {});
				const currentStates = pageStates[this.pageUrl];

				if (currentStates) {
					Object.entries(currentStates).forEach(([key, isCollapsed]) => {
						this.headerStates.set(key, { isCollapsed });
					});
					Logger.log(`[GHCM] 已加载 ${Object.keys(currentStates).length} 个已保存的状态`);
				}
			} catch (e) {
				Logger.warn("[GHCM] 加载状态失败:", e);
			}
		}

		clearMemory() {
			try {
				const pageStates = GM_getValue(CONFIG.memory.key, {});
				delete pageStates[this.pageUrl];
				GM_setValue(CONFIG.memory.key, pageStates);
				Logger.log("[GHCM] 已清除当前页面的记忆状态");
			} catch (e) {
				Logger.warn("[GHCM] 清除状态失败:", e);
			}
		}
	}

	// 快捷键管理器
	class HotkeyManager {
		constructor(collapseManager) {
			this.collapseManager = collapseManager;
			this.setupHotkeys();
		}

		setupHotkeys() {
			if (!CONFIG.hotkeys.enabled) return;

			document.addEventListener('keydown', this.handleKeyDown.bind(this));
			Logger.log("[GHCM] 快捷键已启用:", Object.entries(CONFIG.hotkeys)
				.filter(([k, v]) => k !== 'enabled')
				.map(([k, v]) => `${k}: ${v}`)
				.join(', '));
		}

		handleKeyDown(event) {
			if (!CONFIG.hotkeys.enabled) return;

			const combo = this.getKeyCombo(event);

			switch (combo) {
				case CONFIG.hotkeys.collapseAll:
					event.preventDefault();
					this.collapseManager.collapseAll();
					break;
				case CONFIG.hotkeys.expandAll:
					event.preventDefault();
					this.collapseManager.expandAll();
					break;
				case CONFIG.hotkeys.toggleAll:
					event.preventDefault();
					this.collapseManager.toggleAll();
					break;
				case CONFIG.hotkeys.showToc:
					event.preventDefault();
					this.collapseManager.toggleToc();
					break;
				case CONFIG.hotkeys.search:
					event.preventDefault();
					this.collapseManager.toggleSearch();
					break;
				case CONFIG.hotkeys.menu:
					event.preventDefault();
					if (this.collapseManager.menuManager) {
						this.collapseManager.menuManager.toggle();
					}
					break;
			}
		}

		getKeyCombo(event) {
			const keys = [];
			if (event.ctrlKey) keys.push('ctrl');
			if (event.shiftKey) keys.push('shift');
			if (event.altKey) keys.push('alt');
			if (event.metaKey) keys.push('meta');

			const key = event.key.toLowerCase();
			if (key !== 'control' && key !== 'shift' && key !== 'alt' && key !== 'meta') {
				keys.push(key);
			}

			return keys.join('+');
		}
	}

	// 目录生成器
	class TocGenerator {
		constructor() {
			this.tocContainer = null;
			this.isVisible = false;
		}

		generateToc() {
			const headers = this.getAllHeaders();
			if (headers.length === 0) return null;

			const toc = document.createElement('div');
			toc.className = CONFIG.classes.tocContainer;
			toc.innerHTML = `
				<div class="ghcm-toc-header">
					<h3>📑 目录导航</h3>
					<button class="ghcm-toc-close" title="关闭目录">✕</button>
				</div>
				<div class="ghcm-toc-content">
					${this.generateTocItems(headers)}
				</div>
			`;

			this.setupTocEvents(toc);
			return toc;
		}

		getAllHeaders() {
			const headers = [];
			CONFIG.selectors.markdownContainers.forEach(container => {
				if (container) {
					CONFIG.selectors.headers.forEach(headerTag => {
						const elements = DOMUtils.$$(`${container} ${headerTag.toLowerCase()}`);
						elements.forEach(el => {
							headers.push({
								element: el,
								level: parseInt(headerTag.replace('H', ''), 10),
								text: el.textContent.trim(),
								id: this.getHeaderId(el)
							});
						});
					});
				}
			});
			return headers.sort((a, b) => this.getElementPosition(a.element) - this.getElementPosition(b.element));
		}

		generateTocItems(headers) {
			return headers.map(header => {
				const indent = (header.level - 1) * 20;
				const isCollapsed = header.element.classList.contains(CONFIG.classes.collapsed);
				const collapseIcon = isCollapsed ? '▶' : '▼';

				return `
					<div class="ghcm-toc-item" style="padding-left: ${indent}px;" data-level="${header.level}">
						<span class="ghcm-toc-collapse-icon">${collapseIcon}</span>
						<a href="#${header.id}" class="ghcm-toc-link" data-header-id="${header.id}">
							${header.text}
						</a>
					</div>
				`;
			}).join('');
		}

		getHeaderId(element) {
			// 尝试获取已有的ID
			const anchor = element.querySelector('.anchor');
			if (anchor) return anchor.getAttribute('href')?.slice(1) || '';

			const id = element.id || element.getAttribute('id');
			if (id) return id;

			// 生成ID
			return 'header-' + element.textContent.trim().toLowerCase()
				.replace(/[^\w\s-]/g, '')
				.replace(/\s+/g, '-');
		}

		getElementPosition(element) {
			let position = 0;
			let current = element;
			while (current && current.parentNode) {
				const siblings = Array.from(current.parentNode.children);
				position += siblings.indexOf(current);
				current = current.parentNode;
			}
			return position;
		}

		setupTocEvents(toc) {
			// 关闭按钮
			toc.querySelector('.ghcm-toc-close').addEventListener('click', () => {
				this.hideToc();
			});

			// 点击目录项
			toc.querySelectorAll('.ghcm-toc-link').forEach(link => {
				link.addEventListener('click', (e) => {
					e.preventDefault();
					const headerId = link.getAttribute('data-header-id');
					this.scrollToHeader(headerId);
				});
			});
		}

		scrollToHeader(headerId) {
			const element = document.getElementById(headerId) ||
							document.querySelector(`[id="${headerId}"]`) ||
							document.querySelector(`#user-content-${headerId}`);

			if (element) {
				element.scrollIntoView({ behavior: 'smooth', block: 'start' });
				// 如果标题被折叠,自动展开其父级
				this.expandParentHeaders(element);

				// 更新目录显示状态
				setTimeout(() => {
					this.refreshTocStates();
				}, 500);
			}
		}

		// 刷新目录中的折叠状态显示
		refreshTocStates() {
			if (!this.tocContainer) return;

			const tocItems = this.tocContainer.querySelectorAll('.ghcm-toc-item');
			tocItems.forEach(item => {
				const link = item.querySelector('.ghcm-toc-link');
				const headerId = link.getAttribute('data-header-id');
				const icon = item.querySelector('.ghcm-toc-collapse-icon');

				// 查找对应的标题元素
				const headerElement = document.getElementById(headerId) ||
									 document.querySelector(`[id="${headerId}"]`) ||
									 document.querySelector(`#user-content-${headerId}`);

				if (headerElement && icon) {
					const isCollapsed = headerElement.classList.contains('ghcm-collapsed');
					icon.textContent = isCollapsed ? '▶' : '▼';
				}
			});
		}

		expandParentHeaders(targetElement) {
			// 找到对应的collapseManager实例并展开到该标题
			if (window.ghcmInstance && window.ghcmInstance.collapseManager) {
				window.ghcmInstance.collapseManager.expandToHeader(targetElement);
			}
		}

		showToc() {
			if (this.tocContainer) {
				this.tocContainer.remove();
			}

			this.tocContainer = this.generateToc();
			if (this.tocContainer) {
				document.body.appendChild(this.tocContainer);
				this.isVisible = true;

				// 确保状态正确显示
				setTimeout(() => {
					this.refreshTocStates();
				}, 100);
			}
		}

		hideToc() {
			if (this.tocContainer) {
				this.tocContainer.remove();
				this.tocContainer = null;
				this.isVisible = false;
			}
		}

		toggle() {
			if (this.isVisible) {
				this.hideToc();
			} else {
				this.showToc();
			}
		}
	}

	// 搜索功能
	class SearchManager {
		constructor(collapseManager) {
			this.collapseManager = collapseManager;
			this.searchContainer = null;
			this.isVisible = false;
		}

		createSearchUI() {
			const container = document.createElement('div');
			container.className = CONFIG.classes.searchContainer;
			container.innerHTML = `
				<div class="ghcm-search-header">
					<h3>🔍 搜索标题</h3>
					<button class="ghcm-search-close" title="关闭搜索">✕</button>
				</div>
				<div class="ghcm-search-content">
					<input type="text" class="ghcm-search-input" placeholder="输入关键词搜索标题..." autocomplete="off">
					<div class="ghcm-search-results"></div>
				</div>
			`;

			this.setupSearchEvents(container);
			return container;
		}

		setupSearchEvents(container) {
			const input = container.querySelector('.ghcm-search-input');
			const results = container.querySelector('.ghcm-search-results');
			const closeBtn = container.querySelector('.ghcm-search-close');

			// 实时搜索
			let searchTimeout;
			input.addEventListener('input', () => {
				clearTimeout(searchTimeout);
				searchTimeout = setTimeout(() => {
					this.performSearch(input.value.trim(), results);
				}, 300);
			});

			// 关闭搜索
			closeBtn.addEventListener('click', () => {
				this.hideSearch();
			});

			// 自动聚焦
			setTimeout(() => input.focus(), 100);
		}

		performSearch(query, resultsContainer) {
			if (!query) {
				resultsContainer.innerHTML = '<div class="ghcm-search-hint">请输入搜索关键词</div>';
				return;
			}

			const headers = this.getAllSearchableHeaders();
			const matches = headers.filter(header =>
				header.text.toLowerCase().includes(query.toLowerCase())
			);

			if (matches.length === 0) {
				resultsContainer.innerHTML = '<div class="ghcm-search-no-results">未找到匹配的标题</div>';
				return;
			}

			const resultHtml = matches.map(header => `
				<div class="ghcm-search-result" data-header-element="${header.id}">
					<span class="ghcm-search-level">H${header.level}</span>
					<span class="ghcm-search-text">${this.highlightMatch(header.text, query)}</span>
				</div>
			`).join('');

			resultsContainer.innerHTML = resultHtml;

			// 添加点击事件
			resultsContainer.querySelectorAll('.ghcm-search-result').forEach(result => {
				result.addEventListener('click', () => {
					const headerId = result.getAttribute('data-header-element');
					this.jumpToHeader(headerId);
				});
			});
		}

		getAllSearchableHeaders() {
			const headers = [];
			let index = 0;

			CONFIG.selectors.markdownContainers.forEach(container => {
				if (container) {
					CONFIG.selectors.headers.forEach(headerTag => {
						const elements = DOMUtils.$$(`${container} ${headerTag.toLowerCase()}`);
						elements.forEach(el => {
							headers.push({
								element: el,
								level: parseInt(headerTag.replace('H', ''), 10),
								text: el.textContent.trim(),
								id: `search-header-${index++}`
							});
							el.setAttribute('data-search-id', `search-header-${index - 1}`);
						});
					});
				}
			});

			return headers;
		}

		highlightMatch(text, query) {
			const regex = new RegExp(`(${query})`, 'gi');
			return text.replace(regex, '<mark>$1</mark>');
		}

		jumpToHeader(headerId) {
			const element = document.querySelector(`[data-search-id="${headerId}"]`);
			if (element) {
				// 展开到该标题
				this.collapseManager.expandToHeader(element);
				// 隐藏搜索界面
				this.hideSearch();
			}
		}

		showSearch() {
			if (this.searchContainer) {
				this.searchContainer.remove();
			}

			this.searchContainer = this.createSearchUI();
			document.body.appendChild(this.searchContainer);
			this.isVisible = true;
		}

		hideSearch() {
			if (this.searchContainer) {
				this.searchContainer.remove();
				this.searchContainer = null;
				this.isVisible = false;
			}
		}

		toggle() {
			if (this.isVisible) {
				this.hideSearch();
			} else {
				this.showSearch();
			}
		}
	}

	// DOM 工具类
	class DOMUtils {
		static $(selector, parent = document) {
			return parent.querySelector(selector);
		}

		static $$(selector, parent = document) {
			return Array.from(parent.querySelectorAll(selector));
		}

		static isHeader(element) {
			return CONFIG.selectors.headers.includes(element.nodeName);
		}

		static isInMarkdown(element) {
			return CONFIG.selectors.markdownContainers.some(selector =>
				element.closest(selector)
			);
		}

		static getHeaderContainer(header) {
			return header.closest('.markdown-heading') || header;
		}

		static clearSelection() {
			const selection = window.getSelection?.() || document.selection;
			if (selection) {
				if (selection.removeAllRanges) {
					selection.removeAllRanges();
				} else if (selection.empty) {
					selection.empty();
				}
			}
		}
	}

	// 样式管理器
	class StyleManager {
		constructor() {
			this.arrowColors = document.createElement("style");
			this.init();
		}

		init() {
			this.addBaseStyles();
			this.addColorStyles();
			document.head.appendChild(this.arrowColors);
		}

		addBaseStyles() {
			const headerSelectors = this.generateHeaderSelectors();

	GM_addStyle(`
				/* 基础样式 */
				${headerSelectors.base} {
			position: relative;
			padding-right: 3em;
			cursor: pointer;
					transition: all ${CONFIG.animation.duration}ms ${CONFIG.animation.easing};
				}

				/* 箭头指示器 */
				${headerSelectors.after} {
			display: inline-block;
			position: absolute;
			right: 0.5em;
					top: 50%;
					transform: translateY(-50%);
			font-size: 0.8em;
					font-weight: bold;
					pointer-events: none;
					transition: transform ${CONFIG.animation.duration}ms ${CONFIG.animation.easing};
				}

				/* 各级标题的箭头内容 */
				${this.generateArrowContent()}

				/* 折叠状态的箭头旋转 */
				.${CONFIG.classes.collapsed}:after {
					transform: translateY(-50%) rotate(-90deg);
				}

				/* 隐藏元素 */
				.${CONFIG.classes.hidden},
				.${CONFIG.classes.hiddenByParent} {
					display: none !important;
					opacity: 0 !important;
				}

				/* 无内容标题 */
				.${CONFIG.classes.noContent}:after {
					display: none !important;
				}

				/* 禁用链接事件 */
				.octicon-link,
				.octicon-link > * {
					pointer-events: none;
				}

				/* 平滑动画 */
				.ghcm-transitioning {
					transition: opacity ${CONFIG.animation.duration}ms ${CONFIG.animation.easing},
					           transform ${CONFIG.animation.duration}ms ${CONFIG.animation.easing};
				}

				/* 目录容器样式 */
				.${CONFIG.classes.tocContainer} {
					position: fixed;
					top: 20px;
					right: 20px;
					width: 300px;
					max-height: 70vh;
					background: var(--color-canvas-default, #ffffff);
					border: 1px solid var(--color-border-default, #d0d7de);
					border-radius: 8px;
					box-shadow: 0 8px 24px rgba(0,0,0,0.12);
					z-index: 10000;
					overflow: hidden;
					font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
				}

				.ghcm-toc-header {
					padding: 8px 12px;
					background: var(--color-canvas-subtle, #f6f8fa);
					border-bottom: 1px solid var(--color-border-default, #d0d7de);
					display: flex;
					justify-content: space-between;
					align-items: center;
					min-height: 36px;
				}

				.ghcm-toc-header h3 {
					margin: 0;
					font-size: 13px;
					font-weight: 600;
					color: var(--color-fg-default, #24292f);
					line-height: 1.2;
				}

				.ghcm-toc-close {
					background: none;
					border: none;
					font-size: 14px;
					cursor: pointer;
					padding: 2px 4px;
					border-radius: 3px;
					color: var(--color-fg-muted, #656d76);
					line-height: 1;
				}

				.ghcm-toc-close:hover {
					background: var(--color-danger-subtle, #ffebe9);
					color: var(--color-danger-fg, #cf222e);
				}

				.ghcm-toc-content {
					max-height: calc(70vh - 44px);
					overflow-y: auto;
					padding: 6px 0;
				}

				.ghcm-toc-item {
					display: flex;
					align-items: center;
					padding: 4px 16px;
					border-radius: 4px;
					margin: 1px 8px;
					cursor: pointer;
				}

				.ghcm-toc-item:hover {
					background: var(--color-neutral-subtle, #f6f8fa);
				}

				.ghcm-toc-collapse-icon {
					font-size: 10px;
					margin-right: 8px;
					color: var(--color-fg-muted, #656d76);
					min-width: 12px;
				}

				.ghcm-toc-link {
					text-decoration: none;
					color: var(--color-fg-default, #24292f);
					font-size: 13px;
					line-height: 1.4;
					flex: 1;
				}

				.ghcm-toc-link:hover {
					color: var(--color-accent-fg, #0969da);
				}

				/* 搜索容器样式 */
				.${CONFIG.classes.searchContainer} {
					position: fixed;
					top: 50%;
					left: 50%;
					transform: translate(-50%, -50%);
					width: 480px;
					max-width: 90vw;
					max-height: 80vh;
					background: var(--color-canvas-default, #ffffff);
					border: 1px solid var(--color-border-default, #d0d7de);
					border-radius: 12px;
					box-shadow: 0 16px 32px rgba(0,0,0,0.24);
					z-index: 10001;
					overflow: hidden;
					font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
				}

				.ghcm-search-header {
					padding: 16px 20px;
					background: var(--color-canvas-subtle, #f6f8fa);
					border-bottom: 1px solid var(--color-border-default, #d0d7de);
					display: flex;
					justify-content: space-between;
					align-items: center;
				}

				.ghcm-search-header h3 {
					margin: 0;
					font-size: 16px;
					font-weight: 600;
					color: var(--color-fg-default, #24292f);
				}

				.ghcm-search-close {
					background: none;
					border: none;
					font-size: 18px;
					cursor: pointer;
					padding: 6px;
					border-radius: 6px;
					color: var(--color-fg-muted, #656d76);
				}

				.ghcm-search-close:hover {
					background: var(--color-danger-subtle, #ffebe9);
					color: var(--color-danger-fg, #cf222e);
				}

				.ghcm-search-content {
					padding: 20px;
				}

				.ghcm-search-input {
					width: 100%;
					padding: 12px 16px;
					border: 2px solid var(--color-border-default, #d0d7de);
					border-radius: 8px;
					font-size: 16px;
					background: var(--color-canvas-default, #ffffff);
					color: var(--color-fg-default, #24292f);
					outline: none;
					transition: border-color 0.2s;
				}

				.ghcm-search-input:focus {
					border-color: var(--color-accent-emphasis, #0969da);
				}

				.ghcm-search-results {
					margin-top: 16px;
					max-height: 400px;
					overflow-y: auto;
				}

				.ghcm-search-result {
					display: flex;
					align-items: center;
					padding: 12px 16px;
					border-radius: 8px;
					cursor: pointer;
					margin: 4px 0;
					border: 1px solid transparent;
				}

				.ghcm-search-result:hover {
					background: var(--color-neutral-subtle, #f6f8fa);
					border-color: var(--color-border-default, #d0d7de);
				}

				.ghcm-search-level {
					background: var(--color-accent-subtle, #ddf4ff);
					color: var(--color-accent-fg, #0969da);
					padding: 2px 6px;
					border-radius: 4px;
					font-size: 11px;
					font-weight: 600;
					margin-right: 12px;
					min-width: 24px;
					text-align: center;
				}

				.ghcm-search-text {
					flex: 1;
					font-size: 14px;
					color: var(--color-fg-default, #24292f);
				}

				.ghcm-search-text mark {
					background: var(--color-attention-subtle, #fff8c5);
					color: var(--color-attention-fg, #9a6700);
					padding: 1px 2px;
					border-radius: 2px;
				}

				.ghcm-search-hint, .ghcm-search-no-results {
					text-align: center;
					padding: 40px 20px;
					color: var(--color-fg-muted, #656d76);
					font-style: italic;
				}

				/* 深色主题适配 */
				@media (prefers-color-scheme: dark) {
					.${CONFIG.classes.tocContainer},
					.${CONFIG.classes.searchContainer} {
						background: var(--color-canvas-default, #0d1117);
						border-color: var(--color-border-default, #30363d);
					}
				}
			`);
		}

		generateHeaderSelectors() {
			const containers = CONFIG.selectors.markdownContainers;
			const headers = CONFIG.selectors.headers.map(h => h.toLowerCase());

			const baseSelectors = [];
			const afterSelectors = [];

			containers.forEach(container => {
				if (container) {
					headers.forEach(header => {
						baseSelectors.push(`${container} ${header}`);
						baseSelectors.push(`${container} ${header}.heading-element`);
						afterSelectors.push(`${container} ${header}:after`);
						afterSelectors.push(`${container} ${header}.heading-element:after`);
					});
				}
			});

			return {
				base: baseSelectors.join(", "),
				after: afterSelectors.join(", ")
			};
		}

		generateArrowContent() {
			return CONFIG.selectors.headers.map((header, index) => {
				const level = index + 1;
				const containers = CONFIG.selectors.markdownContainers;
				const selectors = [];

				containers.forEach(container => {
					if (container) {
						selectors.push(`${container} ${header.toLowerCase()}:after`);
						selectors.push(`${container} ${header.toLowerCase()}.heading-element:after`);
					}
				});

				return `${selectors.join(", ")} { content: "${level}▼"; }`;
			}).join("\n");
		}

		addColorStyles() {
			const styles = CONFIG.selectors.headers.map((header, index) => {
				const containers = CONFIG.selectors.markdownContainers;
				const selectors = [];

				containers.forEach(container => {
					if (container) {
						selectors.push(`${container} ${header.toLowerCase()}:after`);
						selectors.push(`${container} ${header.toLowerCase()}.heading-element:after`);
					}
				});

				return `${selectors.join(", ")} { color: ${CONFIG.colors[index]}; }`;
			}).join("\n");

			this.arrowColors.textContent = styles;
		}

		updateColors(newColors) {
			CONFIG.colors = newColors;
			GM_setValue("ghcm-colors", newColors);
			this.addColorStyles();
		}
	}

	// 折叠功能核心类
	class CollapseManager {
		constructor(stateManager) {
			this.stateManager = stateManager;
			this.animationQueue = new Map();
		}

		toggle(header, isShiftClicked = false) {
			if (!header || header.classList.contains(CONFIG.classes.noContent)) {
				return;
			}

			const startTime = performance.now();
			const level = this.stateManager.getHeaderLevel(header);
			const isCollapsed = !header.classList.contains(CONFIG.classes.collapsed);

			Logger.log("[GHCM] Toggle:", header, "Level:", level, "Will collapse:", isCollapsed);

			if (isShiftClicked) {
				this.toggleAllSameLevel(level, isCollapsed);
			} else {
				this.toggleSingle(header, isCollapsed);
			}

			// 性能监控
			const endTime = performance.now();
			const duration = endTime - startTime;

			if (duration > 100 && CONFIG.animation.maxAnimatedElements > 0) {
				Logger.warn(`[GHCM] 检测到性能问题 (${duration.toFixed(1)}ms),建议启用性能模式`);

				// 自动降级性能设置
				if (!GM_getValue("ghcm-auto-performance-warned", false)) {
					CONFIG.animation.maxAnimatedElements = Math.max(5, CONFIG.animation.maxAnimatedElements / 2);
					Logger.log(`[GHCM] 自动调整动画阈值为: ${CONFIG.animation.maxAnimatedElements}`);
					GM_setValue("ghcm-auto-performance-warned", true);
				}
			}

			DOMUtils.clearSelection();
			this.dispatchToggleEvent(header, level, isCollapsed);
		}

		toggleSingle(header, isCollapsed) {
			header.classList.toggle(CONFIG.classes.collapsed, isCollapsed);
			this.updateContent(header, isCollapsed);
		}

		toggleAllSameLevel(level, isCollapsed) {
			const headerName = CONFIG.selectors.headers[level - 1].toLowerCase();
			const selectors = CONFIG.selectors.markdownContainers
				.filter(container => container)
				.map(container => `${container} ${headerName}, ${container} ${headerName}.heading-element`)
				.join(", ");

			DOMUtils.$$(selectors).forEach(header => {
				if (DOMUtils.isHeader(header)) {
					header.classList.toggle(CONFIG.classes.collapsed, isCollapsed);
					this.updateContent(header, isCollapsed);
				}
			});
		}

		updateContent(header, isCollapsed) {
			const level = this.stateManager.getHeaderLevel(header);
			const headerKey = this.stateManager.generateHeaderKey(header);
			const elements = this.getContentElements(header, level);

			// 分析元素:区分普通内容和子标题
			const analyzedElements = elements.map(el => {
				const childHeader = DOMUtils.isHeader(el) ? el : el.querySelector(CONFIG.selectors.headers.join(","));
				return {
					element: el,
					isHeader: !!childHeader,
					childHeader: childHeader,
					childHeaderCollapsed: childHeader ? childHeader.classList.contains(CONFIG.classes.collapsed) : false
				};
			});

			// 更新状态
			this.stateManager.setHeaderState(headerKey, {
				isCollapsed,
				elements: analyzedElements
			});

			// 执行智能动画(考虑子标题状态)
			this.animateElementsIntelligent(analyzedElements, isCollapsed, headerKey);
		}

		getContentElements(header, level) {
			const container = DOMUtils.getHeaderContainer(header);
			const elements = [];
			let nextElement = container.nextElementSibling;

			// 构建同级和更高级别的选择器
			const higherLevelSelectors = CONFIG.selectors.headers
				.slice(0, level)
				.map(h => h.toLowerCase())
				.join(",");

			while (nextElement) {
				// 如果遇到同级或更高级别的标题,停止
				if (nextElement.matches(higherLevelSelectors) ||
					(nextElement.classList?.contains('markdown-heading') &&
					nextElement.querySelector(higherLevelSelectors))) {
				break;
			}

				elements.push(nextElement);
				nextElement = nextElement.nextElementSibling;
			}

			return elements;
		}

		animateElements(elements, isCollapsed, headerKey) {
			// 取消之前的动画
			if (this.animationQueue.has(headerKey)) {
				clearTimeout(this.animationQueue.get(headerKey));
				this.animationQueue.delete(headerKey);
			}

			// 性能优化:如果元素太多,直接切换而不做动画
			if (elements.length > CONFIG.animation.maxAnimatedElements) {
				this.toggleElementsInstantly(elements, isCollapsed);
				return;
			}

			// 对于适量元素,使用优化的批量动画
			this.animateElementsBatch(elements, isCollapsed, headerKey);
		}

		// 新的智能动画方法,考虑子标题状态
		animateElementsIntelligent(analyzedElements, isCollapsed, headerKey) {
			// 取消之前的动画
			if (this.animationQueue.has(headerKey)) {
				clearTimeout(this.animationQueue.get(headerKey));
				this.animationQueue.delete(headerKey);
			}

			Logger.log(`[GHCM] 智能动画: ${analyzedElements.length} 个元素, 阈值: ${CONFIG.animation.maxAnimatedElements}`);

			// 性能优化:如果元素太多,直接切换
			if (analyzedElements.length > CONFIG.animation.maxAnimatedElements) {
				Logger.log(`[GHCM] 元素过多,使用即时切换模式`);
				this.toggleElementsIntelligentInstantly(analyzedElements, isCollapsed);
				return;
			}

			// 使用智能批量动画
			Logger.log(`[GHCM] 使用批量动画模式`);
			this.animateElementsIntelligentBatch(analyzedElements, isCollapsed, headerKey);
		}

		// 智能即时切换(性能模式)
		toggleElementsIntelligentInstantly(analyzedElements, isCollapsed) {
			Logger.log(`[GHCM] 性能模式:即时切换 ${analyzedElements.length} 个元素`);

			analyzedElements.forEach(({ element, isHeader, childHeader, childHeaderCollapsed }) => {
				if (isCollapsed) {
					// 折叠:隐藏所有内容
					element.classList.add(CONFIG.classes.hiddenByParent);
					element.style.display = 'none';
				} else {
					// 展开:根据子标题状态决定是否显示
					element.classList.remove(CONFIG.classes.hiddenByParent);
					element.style.display = 'block';

					// 如果是子标题且原本是折叠的,需要保持其内容隐藏
					if (isHeader && childHeaderCollapsed) {
						setTimeout(() => {
							this.ensureChildHeaderContentHidden(childHeader);
						}, 10);
					}

					// 清理动画样式
					element.style.removeProperty('opacity');
					element.style.removeProperty('transform');
					element.style.removeProperty('transition');
					element.classList.remove('ghcm-transitioning');
				}
			});
		}

				// 智能批量动画
		animateElementsIntelligentBatch(analyzedElements, isCollapsed, headerKey) {
			// 检查是否应该使用动画
			if (CONFIG.animation.maxAnimatedElements === 0) {
				this.toggleElementsIntelligentInstantly(analyzedElements, isCollapsed);
				return;
			}

			const batches = this.createIntelligentBatches(analyzedElements, CONFIG.animation.batchSize);

			const processBatch = (batchIndex) => {
				if (batchIndex >= batches.length) return;

				const batch = batches[batchIndex];

            if (isCollapsed) {
					this.collapseIntelligentBatch(batch);
				} else {
					this.expandIntelligentBatch(batch);
				}

				// 处理下一个批次
				if (batchIndex < batches.length - 1) {
					const timeout = setTimeout(() => {
						processBatch(batchIndex + 1);
					}, 30); // 减少延迟,让动画更流畅

					this.animationQueue.set(`${headerKey}-batch-${batchIndex}`, timeout);
				}
			};

			processBatch(0);
		}

		createIntelligentBatches(analyzedElements, batchSize) {
			const batches = [];
			for (let i = 0; i < analyzedElements.length; i += batchSize) {
				batches.push(analyzedElements.slice(i, i + batchSize));
			}
			return batches;
		}

				collapseIntelligentBatch(batch) {
			Logger.log(`[GHCM] 折叠动画批次: ${batch.length} 个元素`);

			// 折叠批次:先设置初始状态和过渡效果
			batch.forEach(({ element }) => {
				element.style.opacity = '1';
				element.style.transform = 'translateY(0)';
				element.style.transition = `opacity ${CONFIG.animation.duration}ms ${CONFIG.animation.easing}, transform ${CONFIG.animation.duration}ms ${CONFIG.animation.easing}`;
			});

			// 使用requestAnimationFrame确保样式已应用
			requestAnimationFrame(() => {
				batch.forEach(({ element }) => {
					element.style.opacity = '0';
					element.style.transform = 'translateY(-8px)';
				});

				// 动画完成后隐藏元素
                    					setTimeout(() => {
					batch.forEach(({ element }) => {
						element.classList.add(CONFIG.classes.hiddenByParent);
						element.style.display = 'none';
						element.style.removeProperty('opacity');
						element.style.removeProperty('transform');
						element.style.removeProperty('transition');
					});
					Logger.log(`[GHCM] 折叠动画批次完成`);
				}, CONFIG.animation.duration);
			});
		}

				expandIntelligentBatch(batch) {
			Logger.log(`[GHCM] 展开动画批次: ${batch.length} 个元素`);

			// 展开批次:先显示元素但设为初始动画状态
			batch.forEach(({ element, isHeader, childHeader, childHeaderCollapsed }) => {
				element.classList.remove(CONFIG.classes.hiddenByParent);
				element.style.display = 'block';
				element.style.opacity = '0';
				element.style.transform = 'translateY(-8px)';
				element.style.transition = `opacity ${CONFIG.animation.duration}ms ${CONFIG.animation.easing}, transform ${CONFIG.animation.duration}ms ${CONFIG.animation.easing}`;
			});

			// 使用requestAnimationFrame确保DOM更新完成
			requestAnimationFrame(() => {
				batch.forEach(({ element, isHeader, childHeader, childHeaderCollapsed }) => {
					element.style.opacity = '1';
					element.style.transform = 'translateY(0)';

					// 如果是子标题且原本是折叠的,确保其内容保持隐藏
					if (isHeader && childHeaderCollapsed) {
						// 延迟执行,确保动画和DOM更新完成
                        setTimeout(() => {
							this.ensureChildHeaderContentHidden(childHeader);
						}, CONFIG.animation.duration + 50);
					}
				});

				// 清理样式
				setTimeout(() => {
					batch.forEach(({ element }) => {
						element.style.removeProperty('opacity');
						element.style.removeProperty('transform');
						element.style.removeProperty('transition');
					});
					Logger.log(`[GHCM] 展开动画批次完成`);
				}, CONFIG.animation.duration);
			});
		}

		// 确保子标题的内容保持隐藏状态
		ensureChildHeaderContentHidden(childHeader) {
			if (!childHeader || !childHeader.classList.contains(CONFIG.classes.collapsed)) {
				return;
			}

			const childLevel = this.stateManager.getHeaderLevel(childHeader);
			const childElements = this.getContentElements(childHeader, childLevel);

			// 立即隐藏子标题的内容,不使用动画
			childElements.forEach(element => {
				element.classList.add(CONFIG.classes.hiddenByParent);
				element.style.display = 'none';
				element.style.removeProperty('opacity');
				element.style.removeProperty('transform');
				element.classList.remove('ghcm-transitioning');
			});

			Logger.log(`[GHCM] 已恢复子标题的折叠状态:`, childHeader.textContent.trim());
		}

		// 即时切换,无动画
		toggleElementsInstantly(elements, isCollapsed) {
			// 批量DOM操作,减少重排
			const fragment = document.createDocumentFragment();

			elements.forEach(element => {
				if (isCollapsed) {
					element.classList.add(CONFIG.classes.hiddenByParent);
					element.style.display = 'none';
            } else {
					element.classList.remove(CONFIG.classes.hiddenByParent);
					element.style.display = 'block';
					// 清理可能存在的动画样式
					element.style.removeProperty('opacity');
					element.style.removeProperty('transform');
					element.classList.remove('ghcm-transitioning');
				}
			});
		}

		// 批量动画处理
		animateElementsBatch(elements, isCollapsed, headerKey) {
			const batches = this.createBatches(elements, CONFIG.animation.batchSize);
			let completedBatches = 0;

			const processBatch = (batchIndex) => {
				if (batchIndex >= batches.length) return;

				const batch = batches[batchIndex];

				// 为每个批次准备DOM变更
            if (isCollapsed) {
					this.collapseBatch(batch);
				} else {
					this.expandBatch(batch);
				}

				completedBatches++;

				// 处理下一个批次
				if (batchIndex < batches.length - 1) {
					const timeout = setTimeout(() => {
						processBatch(batchIndex + 1);
					}, 50); // 批次间短暂延迟

					this.animationQueue.set(`${headerKey}-batch-${batchIndex}`, timeout);
				}
			};

			processBatch(0);
		}

		createBatches(elements, batchSize) {
			const batches = [];
			for (let i = 0; i < elements.length; i += batchSize) {
				batches.push(elements.slice(i, i + batchSize));
			}
			return batches;
		}

		collapseBatch(batch) {
			// 先设置初始状态
			batch.forEach(element => {
				element.style.transition = `opacity ${CONFIG.animation.duration}ms ${CONFIG.animation.easing}`;
				element.style.opacity = '1';
			});

			// 触发动画
			requestAnimationFrame(() => {
				batch.forEach(element => {
					element.style.opacity = '0';
				});

				// 动画完成后隐藏
                    setTimeout(() => {
					batch.forEach(element => {
						element.classList.add(CONFIG.classes.hiddenByParent);
						element.style.display = 'none';
						element.style.removeProperty('opacity');
						element.style.removeProperty('transition');
					});
				}, CONFIG.animation.duration);
			});
		}

		expandBatch(batch) {
			// 先显示元素但设为透明
			batch.forEach(element => {
				element.classList.remove(CONFIG.classes.hiddenByParent);
				element.style.display = 'block';
				element.style.opacity = '0';
				element.style.transition = `opacity ${CONFIG.animation.duration}ms ${CONFIG.animation.easing}`;
			});

			// 触发淡入动画
			requestAnimationFrame(() => {
				batch.forEach(element => {
					element.style.opacity = '1';
				});

				// 清理样式
                        setTimeout(() => {
					batch.forEach(element => {
						element.style.removeProperty('opacity');
						element.style.removeProperty('transition');
					});
				}, CONFIG.animation.duration);
			});
		}

		// 展开到指定标题(用于hash导航)
		expandToHeader(targetHeader) {
			if (!targetHeader) return;

			const level = this.stateManager.getHeaderLevel(targetHeader);
			let current = targetHeader;

			// 向上查找所有父级标题并展开
			while (current) {
				const container = DOMUtils.getHeaderContainer(current);
				let previous = container.previousElementSibling;
				let foundParent = false;

				// 查找更高级别的父标题
				while (previous) {
					const parentHeader = this.findHeaderInElement(previous, level - 1);
					if (parentHeader) {
						if (parentHeader.classList.contains(CONFIG.classes.collapsed)) {
							this.toggleSingle(parentHeader, false);
						}
						current = parentHeader;
						foundParent = true;
						break;
					}
					previous = previous.previousElementSibling;
				}

				if (!foundParent) break;
			}

			// 滚动到目标位置
			this.scrollToElement(targetHeader);
		}

		findHeaderInElement(element, maxLevel) {
			if (DOMUtils.isHeader(element)) {
				const elementLevel = this.stateManager.getHeaderLevel(element);
				if (elementLevel < maxLevel) return element;
			}

			// 查找容器内的标题
			for (let i = 1; i < maxLevel; i++) {
				const headerName = CONFIG.selectors.headers[i - 1].toLowerCase();
				const header = element.querySelector(headerName) ||
							  element.querySelector(`${headerName}.heading-element`);
				if (header) return header;
			}

			return null;
		}

		scrollToElement(element) {
			if (!element) return;

			const targetPosition = element.offsetTop - 100; // 留出一些顶部空间

			// 平滑滚动
			window.scrollTo({
				top: targetPosition,
				behavior: 'smooth'
			});

			// 延迟再次确保位置正确
                    setTimeout(() => {
				if (Math.abs(window.scrollY - targetPosition) > 50) {
					window.scrollTo({
						top: targetPosition,
						behavior: 'smooth'
					});
				}
			}, 500);
		}

		dispatchToggleEvent(header, level, isCollapsed) {
			document.dispatchEvent(new CustomEvent("ghcm:toggle-complete", {
				detail: { header, level, isCollapsed }
			}));

			// 如果是展开操作,检查并恢复子标题状态
			if (!isCollapsed) {
				setTimeout(() => {
					this.checkAndRestoreChildHeaderStates(header, level);
				}, CONFIG.animation.duration + 100);
			}
		}

		// 检查并恢复子标题的折叠状态
		checkAndRestoreChildHeaderStates(parentHeader, parentLevel) {
			const container = DOMUtils.getHeaderContainer(parentHeader);
			let nextElement = container.nextElementSibling;

			// 查找所有子标题并恢复其状态
            while (nextElement) {
				// 停止条件:遇到同级或更高级别的标题
				const higherLevelSelectors = CONFIG.selectors.headers
					.slice(0, parentLevel)
					.map(h => h.toLowerCase())
					.join(",");

				if (nextElement.matches(higherLevelSelectors) ||
					(nextElement.classList?.contains('markdown-heading') &&
					nextElement.querySelector(higherLevelSelectors))) {
                    break;
                }

				// 检查是否是子标题
				const childHeader = DOMUtils.isHeader(nextElement) ?
					nextElement : nextElement.querySelector(CONFIG.selectors.headers.join(","));

				if (childHeader && childHeader.classList.contains(CONFIG.classes.collapsed)) {
					// 确保这个子标题的内容保持隐藏
					this.ensureChildHeaderContentHidden(childHeader);
				}

                nextElement = nextElement.nextElementSibling;
            }
        }

		// 批量操作方法
		getAllHeaders() {
			const headers = [];
			CONFIG.selectors.markdownContainers.forEach(container => {
				if (container) {
					CONFIG.selectors.headers.forEach(headerTag => {
						const elements = DOMUtils.$$(`${container} ${headerTag.toLowerCase()}`);
						headers.push(...elements.filter(el => DOMUtils.isHeader(el)));
					});
				}
			});
			return headers;
		}

		collapseAll() {
			const headers = this.getAllHeaders();
			let count = 0;

			headers.forEach(header => {
				if (!header.classList.contains(CONFIG.classes.collapsed) &&
					!header.classList.contains(CONFIG.classes.noContent)) {
					header.classList.add(CONFIG.classes.collapsed);
					this.updateContent(header, true);
					count++;
				}
			});

			Logger.log(`[GHCM] 已折叠 ${count} 个标题`);
			this.showNotification(`📁 已折叠 ${count} 个标题`);
		}

		expandAll() {
			const headers = this.getAllHeaders();
			let count = 0;

			headers.forEach(header => {
				if (header.classList.contains(CONFIG.classes.collapsed)) {
					header.classList.remove(CONFIG.classes.collapsed);
					this.updateContent(header, false);
					count++;
				}
			});

			Logger.log(`[GHCM] 已展开 ${count} 个标题`);
			this.showNotification(`📂 已展开 ${count} 个标题`);
		}

		toggleAll() {
			const headers = this.getAllHeaders();
			const collapsedCount = headers.filter(h =>
				h.classList.contains(CONFIG.classes.collapsed)
			).length;
			const totalCount = headers.filter(h =>
				!h.classList.contains(CONFIG.classes.noContent)
			).length;

			// 如果超过一半已折叠,则全部展开;否则全部折叠
			if (collapsedCount > totalCount / 2) {
				this.expandAll();
			} else {
				this.collapseAll();
			}
		}

		// 按级别批量操作
		collapseLevel(level) {
			const headerTag = CONFIG.selectors.headers[level - 1];
			if (!headerTag) return;

			const headers = [];
			CONFIG.selectors.markdownContainers.forEach(container => {
				if (container) {
					const elements = DOMUtils.$$(`${container} ${headerTag.toLowerCase()}`);
					headers.push(...elements.filter(el => DOMUtils.isHeader(el)));
				}
			});

			let count = 0;
			headers.forEach(header => {
				if (!header.classList.contains(CONFIG.classes.collapsed) &&
					!header.classList.contains(CONFIG.classes.noContent)) {
					header.classList.add(CONFIG.classes.collapsed);
					this.updateContent(header, true);
					count++;
				}
			});

			Logger.log(`[GHCM] 已折叠 ${count} 个 H${level} 标题`);
			this.showNotification(`📁 已折叠 ${count} 个 H${level} 标题`);
		}

		expandLevel(level) {
			const headerTag = CONFIG.selectors.headers[level - 1];
			if (!headerTag) return;

			const headers = [];
			CONFIG.selectors.markdownContainers.forEach(container => {
				if (container) {
					const elements = DOMUtils.$$(`${container} ${headerTag.toLowerCase()}`);
					headers.push(...elements.filter(el => DOMUtils.isHeader(el)));
				}
			});

			let count = 0;
			headers.forEach(header => {
				if (header.classList.contains(CONFIG.classes.collapsed)) {
					header.classList.remove(CONFIG.classes.collapsed);
					this.updateContent(header, false);
					count++;
				}
			});

			Logger.log(`[GHCM] 已展开 ${count} 个 H${level} 标题`);
			this.showNotification(`📂 已展开 ${count} 个 H${level} 标题`);
		}

		// 通知功能
		showNotification(message) {
			// 创建通知元素
			const notification = document.createElement('div');
			notification.style.cssText = `
				position: fixed;
				top: 20px;
				left: 50%;
				transform: translateX(-50%);
				background: var(--color-canvas-default, #ffffff);
				border: 1px solid var(--color-border-default, #d0d7de);
				border-radius: 8px;
				padding: 12px 20px;
				box-shadow: 0 4px 12px rgba(0,0,0,0.15);
				z-index: 10002;
				font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
				font-size: 14px;
				color: var(--color-fg-default, #24292f);
				opacity: 0;
				transition: opacity 0.3s ease;
			`;
			notification.textContent = message;

			document.body.appendChild(notification);

			// 显示动画
			requestAnimationFrame(() => {
				notification.style.opacity = '1';
			});

			// 自动消失
			setTimeout(() => {
				notification.style.opacity = '0';
				setTimeout(() => {
					if (notification.parentNode) {
						notification.parentNode.removeChild(notification);
					}
				}, 300);
			}, 2000);
		}

		// 加载已保存的状态
		loadSavedStates() {
			this.stateManager.loadFromMemory();

			// 分层应用已保存的状态(从高级别到低级别)
			for (let level = 1; level <= 6; level++) {
				this.applyStatesForLevel(level);
			}
		}

		applyStatesForLevel(level) {
			const headers = this.getAllHeaders().filter(h =>
				this.stateManager.getHeaderLevel(h) === level
			);

			headers.forEach(header => {
				const headerKey = this.stateManager.generateHeaderKey(header);
				const savedState = this.stateManager.getHeaderState(headerKey);

				if (savedState && savedState.isCollapsed) {
					Logger.log(`[GHCM] 恢复 H${level} 标题状态:`, header.textContent.trim());
					header.classList.add(CONFIG.classes.collapsed);
					this.updateContent(header, true);
			}
		});
	}

		applyStateToElement(headerKey, state) {
			// 保留原方法作为备用
			const headers = this.getAllHeaders();
			headers.forEach(header => {
				const currentKey = this.stateManager.generateHeaderKey(header);
				if (currentKey === headerKey && state.isCollapsed) {
					header.classList.add(CONFIG.classes.collapsed);
					this.updateContent(header, true);
				}
			});
		}

		// 代理目录和搜索功能
		toggleToc() {
			if (this.tocGenerator) {
				this.tocGenerator.toggle();
			}
		}

		toggleSearch() {
			if (this.searchManager) {
				this.searchManager.toggle();
			}
		}

		// 检查标题是否有内容
		markEmptyHeaders() {
			CONFIG.selectors.markdownContainers.forEach(containerSelector => {
				if (!containerSelector) return;

				CONFIG.selectors.headers.forEach(headerName => {
					const headerSelector = `${containerSelector} ${headerName.toLowerCase()}`;
					DOMUtils.$$(headerSelector).concat(
						DOMUtils.$$(`${headerSelector}.heading-element`)
					).forEach(header => {
						const level = this.stateManager.getHeaderLevel(header);
						const elements = this.getContentElements(header, level);

						if (elements.length === 0) {
							header.classList.add(CONFIG.classes.noContent);
						} else {
							header.classList.remove(CONFIG.classes.noContent);
						}
					});
				});
			});
		}
	}

	// 事件管理器
	class EventManager {
		constructor(collapseManager) {
			this.collapseManager = collapseManager;
			this.setupEventListeners();
		}

		setupEventListeners() {
			// 点击事件
			document.addEventListener("click", this.handleClick.bind(this), true);

			// Hash 变化事件
			window.addEventListener("hashchange", this.handleHashChange.bind(this));

			// DOM 变化监听(如果有其他脚本修改DOM)
			if (window.ghmo) {
				window.addEventListener("ghmo:dom", this.handleDOMChange.bind(this));
			}

			// 页面加载完成后初始化
			if (document.readyState === 'loading') {
				document.addEventListener('DOMContentLoaded', this.handleDOMChange.bind(this));
			} else {
				setTimeout(() => this.handleDOMChange(), 200);
			}
		}

		handleClick(event) {
			let target = event.target;

			// 处理SVG点击
			if (target.nodeName === "path") {
				target = target.closest("svg");
			}

			// 跳过排除的元素
			if (!target || this.shouldSkipElement(target)) {
				return;
			}

			// 查找最近的标题元素
			const header = target.closest(CONFIG.selectors.headers.map(h => h.toLowerCase()).join(","));

			if (header && DOMUtils.isHeader(header) && DOMUtils.isInMarkdown(header)) {
				event.preventDefault();
				Logger.log("[GHCM] Header clicked:", header);
				this.collapseManager.toggle(header, event.shiftKey);
			}
		}

		shouldSkipElement(element) {
			const nodeName = element.nodeName?.toLowerCase();

			return CONFIG.selectors.excludeClicks.some(selector => {
				if (selector.startsWith('.')) {
					return element.classList.contains(selector.slice(1));
				}
				return nodeName === selector;
			});
		}

		handleHashChange() {
			const hash = window.location.hash.replace(/#/, "");
			if (hash) {
				this.openHashTarget(hash);
			}
		}

		handleDOMChange() {
			// 重新标记空标题
			this.collapseManager.markEmptyHeaders();

			// 处理当前hash
			this.handleHashChange();
		}

		openHashTarget(id) {
			// 尝试多种ID格式
			const possibleSelectors = [
				`#user-content-${id}`,
				`#${id}`,
				`[id="${id}"]`
			];

			let targetElement = null;
			for (const selector of possibleSelectors) {
				targetElement = DOMUtils.$(selector);
				if (targetElement) break;
			}

			if (!targetElement) return;

			// 查找对应的标题
			let header = targetElement;
			if (!DOMUtils.isHeader(header)) {
				header = targetElement.closest(CONFIG.selectors.headers.map(h => h.toLowerCase()).join(","));
			}

			if (header && DOMUtils.isHeader(header)) {
				this.collapseManager.expandToHeader(header);
			}
		}
	}

	// 主应用类
	class GitHubCollapseMarkdown {
		constructor() {
			this.stateManager = new StateManager();
			this.styleManager = new StyleManager();
			this.collapseManager = new CollapseManager(this.stateManager);
			this.tocGenerator = new TocGenerator();
			this.searchManager = new SearchManager(this.collapseManager);
			this.menuManager = new MenuManager(this);
			this.hotkeyManager = new HotkeyManager(this.collapseManager);
			this.eventManager = new EventManager(this.collapseManager);

			// 将附加功能关联到折叠管理器
			this.collapseManager.tocGenerator = this.tocGenerator;
			this.collapseManager.searchManager = this.searchManager;
			this.collapseManager.menuManager = this.menuManager;

			this.init();
		}

		init() {
			const performanceMode = GM_getValue("ghcm-performance-mode", false);
			const memoryEnabled = CONFIG.memory.enabled;
			const hotkeysEnabled = CONFIG.hotkeys.enabled;

			const animationStatus = performanceMode ? "性能模式 (无动画)" : "标准模式 (有动画)";

			Logger.log(`[GHCM] Initializing GitHub Collapse Markdown (Optimized v3.2.3) - ${animationStatus}`);
			Logger.log(`[GHCM] 🧠 智能嵌套状态管理: 启用`);
			Logger.log(`[GHCM] 🎨 现代GUI界面: 启用`);
			Logger.log(`[GHCM] 动画阈值: ${CONFIG.animation.maxAnimatedElements} 个元素`);
			Logger.log(`[GHCM] 状态记忆: ${memoryEnabled ? "启用" : "禁用"}`);
			Logger.log(`[GHCM] 快捷键: ${hotkeysEnabled ? "启用" : "禁用"}`);

			// 添加菜单命令
			this.setupMenuCommands();

			// 初始检查和状态加载
				setTimeout(() => {
				this.collapseManager.markEmptyHeaders();

				// 加载已保存的折叠状态
				if (memoryEnabled) {
					this.collapseManager.loadSavedStates();
				}
				}, 500);

			// 监听折叠状态变化,更新目录显示和菜单统计
			document.addEventListener('ghcm:toggle-complete', () => {
				if (this.tocGenerator.isVisible) {
					setTimeout(() => {
						this.tocGenerator.refreshTocStates();
					}, CONFIG.animation.duration + 150);
				}
				// 如果菜单打开,刷新统计信息
				if (this.menuManager.isVisible) {
					setTimeout(() => {
						this.menuManager.refreshMenu();
					}, CONFIG.animation.duration + 150);
				}
			});
		}

		setupMenuCommands() {
			try {
				// === 基础操作 ===
				GM_registerMenuCommand("📁 折叠所有标题", () => {
					this.collapseManager.collapseAll();
				});

				GM_registerMenuCommand("📂 展开所有标题", () => {
					this.collapseManager.expandAll();
				});

				GM_registerMenuCommand("🔄 智能切换", () => {
					this.collapseManager.toggleAll();
				});

				// === 工具功能 ===
				GM_registerMenuCommand("📑 目录导航", () => {
					this.tocGenerator.toggle();
				});

				GM_registerMenuCommand("🔍 搜索标题", () => {
					this.searchManager.toggle();
				});

				// === 设置选项 ===
				GM_registerMenuCommand("⚡ 性能模式", () => {
					this.togglePerformanceMode();
				});

				GM_registerMenuCommand("💾 状态记忆", () => {
					this.toggleMemory();
				});

				GM_registerMenuCommand("⌨️ 快捷键", () => {
					this.toggleHotkeys();
				});

				GM_registerMenuCommand("🐛 调试模式", () => {
					this.toggleDebug();
				});

				// === 重置功能 ===
				GM_registerMenuCommand("🔄 重置折叠状态", () => {
					this.resetAllStates();
				});

				GM_registerMenuCommand("🗑️ 清除记忆数据", () => {
					this.clearAllMemory();
				});

				// === 信息帮助 ===
				GM_registerMenuCommand("📊 当前统计", () => {
					this.showStatistics();
				});

				GM_registerMenuCommand("❓ 快捷键说明", () => {
					this.showHotkeyHelp();
				});

			} catch (e) {
				Logger.warn("[GHCM] 菜单功能不可用:", e);
			}
		}

		toggleMemory() {
			const newState = !CONFIG.memory.enabled;
			CONFIG.memory.enabled = newState;
			GM_setValue("ghcm-memory-enabled", newState);

			const status = newState ? "启用" : "禁用";
			Logger.log(`[GHCM] 状态记忆已${status}`);
			this.collapseManager.showNotification(`💾 状态记忆已${status}`);
		}

		toggleHotkeys() {
			const newState = !CONFIG.hotkeys.enabled;
			CONFIG.hotkeys.enabled = newState;
			GM_setValue("ghcm-hotkeys-enabled", newState);

			const status = newState ? "启用" : "禁用";
			Logger.log(`[GHCM] 快捷键已${status}`);
			this.collapseManager.showNotification(`⌨️ 快捷键已${status}`);

			if (newState) {
				// 重新绑定快捷键
				this.hotkeyManager.setupHotkeys();
			}
		}

		toggleDebug() {
			const newState = !CONFIG.debug;
			CONFIG.debug = newState;
			GM_setValue("ghcm-debug-mode", newState);

			const status = newState ? "启用" : "禁用";
			Logger.log(`[GHCM] 调试模式已${status}`);
			this.collapseManager.showNotification(`🐛 调试模式已${status}`);
		}

		togglePerformanceMode() {
			const isPerformanceMode = CONFIG.animation.maxAnimatedElements === 0;
			const newState = !isPerformanceMode;

			if (newState) {
				// 启用性能模式(禁用动画)
				CONFIG.animation.maxAnimatedElements = 0;
				GM_setValue("ghcm-performance-mode", true);
				Logger.log("[GHCM] 已启用性能模式 - 动画已禁用");
				this.collapseManager.showNotification("⚡ 性能模式已启用");
			} else {
				// 禁用性能模式(启用动画)
				CONFIG.animation.maxAnimatedElements = 20;
				GM_setValue("ghcm-performance-mode", false);
				Logger.log("[GHCM] 已禁用性能模式 - 动画已启用");
				this.collapseManager.showNotification("🎬 动画效果已启用");
			}
		}

		clearAllMemory() {
			if (confirm("确定要清除所有页面的折叠状态记忆吗?")) {
				GM_setValue(CONFIG.memory.key, {});
				this.stateManager.clear();
				Logger.log("[GHCM] 已清除所有记忆数据");
				this.collapseManager.showNotification("🗑️ 已清除所有记忆数据");
			}
		}

		showHotkeyHelp() {
			const helpContent = `
GitHub Collapse Markdown - 使用说明

✨ 快捷键:
• ${CONFIG.hotkeys.collapseAll} - 折叠所有标题
• ${CONFIG.hotkeys.expandAll} - 展开所有标题
• ${CONFIG.hotkeys.toggleAll} - 智能切换
• ${CONFIG.hotkeys.showToc} - 目录导航
• ${CONFIG.hotkeys.search} - 搜索标题
• ${CONFIG.hotkeys.menu} - 显示/隐藏菜单

🖱️ 鼠标操作:
• 点击标题 - 折叠/展开该标题
• Shift + 点击 - 折叠/展开同级别所有标题
• 点击右下角设置按钮 - 打开GUI菜单

🔥 核心功能:
• 🧠 智能嵌套状态 - 展开父标题时保持子标题折叠状态
• 💾 状态记忆 - 自动记住每个页面的折叠状态
• ⚡ 性能优化 - 大量内容时自动优化动画
• 📑 目录导航 - 快速跳转到任意标题
• 🔍 实时搜索 - 搜索标题内容并快速定位
• 🎨 现代GUI界面 - 美观简约的设置面板

⚙️ 设置说明:
• 点击右下角浮动按钮打开现代化GUI菜单
• 所有功能都支持实时切换,无需刷新页面
• 性能模式可在长文档中提高响应速度
• 状态记忆和快捷键都支持自由切换
			`.trim();

			alert(helpContent);
		}

		showStatistics() {
			const headers = this.collapseManager.getAllHeaders();
			const collapsed = headers.filter(h => h.classList.contains(CONFIG.classes.collapsed));
			const visible = headers.filter(h =>
				!h.classList.contains(CONFIG.classes.collapsed) &&
				!h.classList.contains(CONFIG.classes.noContent)
			);

			const levelStats = {};
			for (let i = 1; i <= 6; i++) {
				const levelHeaders = headers.filter(h =>
					this.stateManager.getHeaderLevel(h) === i
				);
				if (levelHeaders.length > 0) {
					levelStats[`H${i}`] = {
						total: levelHeaders.length,
						collapsed: levelHeaders.filter(h => h.classList.contains(CONFIG.classes.collapsed)).length
					};
				}
			}

			const levelStatsText = Object.entries(levelStats)
				.map(([level, stats]) =>
					`${level}: ${stats.total}个 (${stats.collapsed}个已折叠)`
				).join(', ');

			const statsContent = `
📊 当前页面统计

📝 标题概况:
• 总计:${headers.length} 个标题
• 已折叠:${collapsed.length} 个
• 可见:${visible.length} 个

📋 级别分布:${levelStatsText || '无标题'}

⚙️ 功能状态:
• 性能模式:${CONFIG.animation.maxAnimatedElements === 0 ? '🟢 启用' : '🔴 禁用'}
• 状态记忆:${CONFIG.memory.enabled ? '🟢 启用' : '🔴 禁用'}
• 快捷键:${CONFIG.hotkeys.enabled ? '🟢 启用' : '🔴 禁用'}
			`.trim();

			alert(statsContent);
		}

		resetAllStates() {
			// 移除所有折叠状态
			DOMUtils.$$(".ghcm-collapsed").forEach(element => {
				element.classList.remove(CONFIG.classes.collapsed);
			});

			// 显示所有隐藏的内容
			DOMUtils.$$(".ghcm-hidden-by-parent").forEach(element => {
				element.classList.remove(CONFIG.classes.hiddenByParent);
				element.style.display = '';
				element.style.opacity = '';
				element.style.transform = '';
			});

			// 清空状态
			this.stateManager.clear();

			Logger.log("[GHCM] 已重置所有折叠状态");
		}
	}

	// 启动应用
	window.ghcmInstance = new GitHubCollapseMarkdown();

})();