// ==UserScript== // @name 编辑网页 // @namespace http://tampermonkey.net/ // @version 1.2.9 // @description 这是一个能编辑任何网页文本的扩展 // @author yhu // @license GPL-3.0 // @match *://*/* // @grant none // ==/UserScript== (function() { 'use strict'; let currentElement = null; let isSourceEditing = false; let originalHtml = ''; let sourceTextarea = null; let closeButton = null; let longPressTimer = null; let isLongPress = false; let errorOverlay = null; let errorCount = 0; const MAX_ERRORS = 5; function showErrorOverlay(errorMessage) { if (errorOverlay) { errorOverlay.remove(); errorOverlay = null; } errorOverlay = document.createElement('div'); errorOverlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;z-index:99999;background:rgba(0,0,0,0.85);display:flex;align-items:center;justify-content:center;font-family:Arial,sans-serif;'; let panel = document.createElement('div'); panel.style.cssText = 'background:#2d2d2d;border-radius:12px;padding:40px 50px;max-width:600px;width:90%;box-shadow:0 20px 60px rgba(0,0,0,0.8);border:1px solid #444;'; let icon = document.createElement('div'); icon.textContent = '⚠'; icon.style.cssText = 'font-size:48px;text-align:center;color:#ff6b6b;margin-bottom:16px;'; let title = document.createElement('h2'); title.textContent = '脚本运行时发生错误'; title.style.cssText = 'color:#fff;text-align:center;margin:0 0 12px 0;font-weight:400;font-size:24px;'; let message = document.createElement('p'); message.textContent = errorMessage || '未知错误,请检查控制台获取详细信息。'; message.style.cssText = 'color:#aaa;text-align:center;margin:0 0 24px 0;font-size:15px;line-height:1.6;word-break:break-all;'; let detail = document.createElement('p'); detail.textContent = '错误计数: ' + (errorCount + 1) + '/' + MAX_ERRORS; detail.style.cssText = 'color:#666;text-align:center;margin:0 0 24px 0;font-size:13px;'; let btnGroup = document.createElement('div'); btnGroup.style.cssText = 'display:flex;gap:12px;justify-content:center;flex-wrap:wrap;'; let reloadBtn = document.createElement('button'); reloadBtn.textContent = '重新加载页面'; reloadBtn.style.cssText = 'padding:10px 28px;background:#4a9eff;color:#fff;border:none;border-radius:6px;font-size:15px;cursor:pointer;transition:background 0.2s;'; reloadBtn.addEventListener('mouseenter', () => { reloadBtn.style.background = '#6ab0ff'; }); reloadBtn.addEventListener('mouseleave', () => { reloadBtn.style.background = '#4a9eff'; }); reloadBtn.addEventListener('click', () => { window.location.reload(); }); let closeBtn = document.createElement('button'); closeBtn.textContent = '关闭提示'; closeBtn.style.cssText = 'padding:10px 28px;background:#555;color:#fff;border:none;border-radius:6px;font-size:15px;cursor:pointer;transition:background 0.2s;'; closeBtn.addEventListener('mouseenter', () => { closeBtn.style.background = '#666'; }); closeBtn.addEventListener('mouseleave', () => { closeBtn.style.background = '#555'; }); closeBtn.addEventListener('click', () => { if (errorOverlay) { errorOverlay.remove(); errorOverlay = null; } }); btnGroup.appendChild(reloadBtn); btnGroup.appendChild(closeBtn); panel.appendChild(icon); panel.appendChild(title); panel.appendChild(message); panel.appendChild(detail); panel.appendChild(btnGroup); errorOverlay.appendChild(panel); document.body.appendChild(errorOverlay); } function errorHandler(error) { errorCount++; let errorMsg = error.message || String(error); if (error.stack) { errorMsg += '\n' + error.stack.split('\n').slice(0, 3).join('\n'); } console.error('[编辑网页] 捕获到错误:', error); if (errorCount >= MAX_ERRORS) { showErrorOverlay('错误次数过多 (' + MAX_ERRORS + '),脚本可能已进入不稳定状态。\n' + errorMsg); return; } showErrorOverlay(errorMsg); } window.addEventListener('error', function(e) { if (e.target.tagName === 'SCRIPT') { errorHandler(e.message || '脚本加载错误'); } }); function safeExecute(fn, context) { try { return fn.apply(context || null, Array.prototype.slice.call(arguments, 2)); } catch (e) { errorHandler(e); return null; } } function edit(el) { safeExecute(function() { if (el.isContentEditable || el.closest('button,a,[role="button"]')) return; if (currentElement) { currentElement.contentEditable = 'false'; currentElement.style.outline = ''; currentElement.style.backgroundColor = ''; currentElement = null; } el.contentEditable = 'true'; el.style.outline = '2px dashed #4a9eff'; el.style.backgroundColor = 'rgba(74,158,255,0.1)'; el.focus(); let obs = new MutationObserver(function() { el.style.color = '#4caf50'; obs.disconnect(); }); obs.observe(el, { childList: true, subtree: true, characterData: true }); el.addEventListener('blur', function() { obs.disconnect(); el.contentEditable = 'false'; el.style.outline = ''; el.style.backgroundColor = ''; currentElement = null; }, { once: true }); currentElement = el; }, this, el); } function exitSourceEdit() { safeExecute(function() { if (sourceTextarea) { sourceTextarea.remove(); sourceTextarea = null; } if (closeButton) { closeButton.remove(); closeButton = null; } isSourceEditing = false; }, this); } function createCloseButton() { return safeExecute(function() { let btn = document.createElement('button'); btn.textContent = '✕'; btn.style.cssText = 'position:fixed;top:10px;right:10px;z-index:10001;background:#ff4444;color:white;border:none;border-radius:4px;font-size:20px;width:36px;height:36px;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,0.3);transition:all 0.2s;display:flex;align-items:center;justify-content:center;'; btn.addEventListener('mouseenter', function() { btn.style.background = '#ff6666'; btn.style.transform = 'scale(1.05)'; }); btn.addEventListener('mouseleave', function() { btn.style.background = '#ff4444'; btn.style.transform = 'scale(1)'; }); btn.addEventListener('click', function() { safeExecute(function() { if (sourceTextarea && sourceTextarea.value !== originalHtml) { let newDoc = sourceTextarea.value; document.open(); document.write(newDoc); document.close(); } exitSourceEdit(); }, this); }); return btn; }, this) || null; } function setupLongPress() { document.body.addEventListener('mousedown', function(e) { safeExecute(function() { let link = e.target.closest('a'); if (link && link.href) { longPressTimer = setTimeout(function() { isLongPress = true; e.preventDefault(); e.stopPropagation(); window.open(link.href, '_blank'); }, 500); } }, this, e); }, true); document.body.addEventListener('mouseup', function() { safeExecute(function() { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; } isLongPress = false; }, this); }, true); document.body.addEventListener('mouseleave', function() { safeExecute(function() { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; } isLongPress = false; }, this); }, true); } function setupMainClick() { document.body.addEventListener('click', function(e) { safeExecute(function() { if (isLongPress) { e.preventDefault(); e.stopPropagation(); isLongPress = false; return; } let link = e.target.closest('a'); if (link && link.href) { e.preventDefault(); e.stopPropagation(); return; } if (e.detail === 2) { if (isSourceEditing) { e.preventDefault(); e.stopPropagation(); exitSourceEdit(); return; } e.preventDefault(); e.stopPropagation(); isSourceEditing = true; originalHtml = document.documentElement.outerHTML; let textarea = document.createElement('textarea'); textarea.value = originalHtml; textarea.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;z-index:10000;font-family:monospace;font-size:14px;background:#1e1e1e;color:#d4d4d4;border:none;padding:10px;padding-top:50px;'; textarea.contentEditable = 'true'; document.body.appendChild(textarea); textarea.focus(); sourceTextarea = textarea; closeButton = createCloseButton(); if (closeButton) { document.body.appendChild(closeButton); } textarea.addEventListener('blur', function() { safeExecute(function() { if (textarea.value !== originalHtml) { let newDoc = textarea.value; document.open(); document.write(newDoc); document.close(); } exitSourceEdit(); }, this); }, { once: true }); return; } if (isSourceEditing) return; if (e.target.isContentEditable) return; if (currentElement && !currentElement.contains(e.target)) { currentElement.contentEditable = 'false'; currentElement.style.outline = ''; currentElement.style.backgroundColor = ''; currentElement = null; } let node = e.target; while (node && node.nodeType === Node.TEXT_NODE) node = node.parentElement; if (!node) return; let target = node.closest('p,h1,h2,h3,h4,h5,h6,li,span,div,label,td,th,figcaption,legend'); if (target) { e.preventDefault(); e.stopPropagation(); edit(target); } }, this, e); }, true); } safeExecute(function() { setupLongPress(); setupMainClick(); console.log('[编辑网页] 脚本已加载 v1.2.9,错误控制已启用'); }, this); })();