// ==UserScript== // @name 编辑网页 // @namespace http://tampermonkey.net/ // @version 1.2.1 // @description 这是一个能编辑任何网页文本的扩展 // @author yhu // @license GPL-3.0 // @match *://*/* // @grant GM_setValue // @grant GM_getValue // ==/UserScript== (function() { 'use strict'; let currentElement = null; let saveEnabled = GM_getValue('saveEnabled', false); const btn = document.createElement('div'); btn.style.cssText = 'position:fixed;bottom:20px;right:20px;width:24px;height:24px;border-radius:4px;cursor:pointer;z-index:9999;box-shadow:0 2px 6px rgba(0,0,0,0.3);background-color:' + (saveEnabled ? '#4caf50' : '#f44336'); btn.setAttribute('contenteditable', 'false'); btn.onclick = (e) => { e.stopPropagation(); saveEnabled = !saveEnabled; btn.style.backgroundColor = saveEnabled ? '#4caf50' : '#f44336'; GM_setValue('saveEnabled', saveEnabled); }; document.body.appendChild(btn); function getElementPath(el) { let path = ''; while (el && el !== document.body && el !== btn) { let idx = 1; let sibling = el.previousElementSibling; while (sibling) { if (sibling.tagName === el.tagName) idx++; sibling = sibling.previousElementSibling; } path = el.tagName.toLowerCase() + (idx > 1 ? '[' + idx + ']' : '') + (path ? '>' + path : ''); el = el.parentElement; } return path; } function saveChanges(el, originalText) { if (saveEnabled && el.innerText !== originalText) { localStorage.setItem('edited_' + window.location.href + '_' + getElementPath(el), el.innerText); } } function loadSavedChanges(el) { if (!saveEnabled) return; const key = 'edited_' + window.location.href + '_' + getElementPath(el); const saved = localStorage.getItem(key); if (saved && saved !== el.innerText) { el.innerText = saved; el.style.color = 'yellow'; return true; } return false; } function makeEditable(el) { if (el === btn || btn.contains(el)) return; if (el.isContentEditable || el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.closest('button, a, [role="button"]')) return; if (currentElement) { currentElement.contentEditable = 'false'; currentElement.style.outline = ''; currentElement.style.backgroundColor = ''; currentElement = null; } loadSavedChanges(el); el.contentEditable = 'true'; el.style.outline = '2px dashed #4a9eff'; el.style.backgroundColor = 'rgba(74, 158, 255, 0.1)'; el.focus(); const originalText = el.innerText; const observer = new MutationObserver(() => { el.style.color = 'yellow'; observer.disconnect(); }); observer.observe(el, { childList: true, subtree: true, characterData: true }); el.addEventListener('blur', () => { observer.disconnect(); if (el.innerText !== originalText) { saveChanges(el, originalText); el.style.color = 'yellow'; } el.contentEditable = 'false'; el.style.outline = ''; el.style.backgroundColor = ''; currentElement = null; }, { once: true }); currentElement = el; } document.body.addEventListener('click', (e) => { if (e.target === btn || btn.contains(e.target)) return; if (e.detail === 2 || 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; const editEl = node.closest('p, h1, h2, h3, h4, h5, h6, li, span, div, label, td, th, figcaption, legend'); if (editEl) { e.preventDefault(); e.stopPropagation(); makeEditable(editEl); } }, true); })();