Greasy Fork

GitHub Collapse Markdown

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

// ==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();

})();