您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Base64编解码工具,支持位置记忆、夜间模式和拖动功能
当前为
// ==UserScript== // @name Linux.do Base64 script // @namespace http://tampermonkey.net/ // @version 1.3 // @description Base64编解码工具,支持位置记忆、夜间模式和拖动功能 // @author Xavier // @match https://linux.do/* // @grant GM_setClipboard // @grant GM_getValue // @grant GM_setValue // ==/UserScript== (function() { 'use strict'; // 创建主容器 const container = document.createElement('div'); container.id = 'b64Container'; Object.assign(container.style, { position: 'fixed', zIndex: 9999, borderRadius: '8px', fontFamily: 'inherit', cursor: 'move' }); // 初始化位置 const savedPosition = GM_getValue('b64Position', null); if (savedPosition) { container.style.left = `${savedPosition.x}px`; container.style.top = `${savedPosition.y}px`; container.style.bottom = 'auto'; container.style.right = 'auto'; } else { container.style.bottom = '20px'; container.style.right = '20px'; container.style.left = 'auto'; container.style.top = 'auto'; } // 主触发器 const trigger = document.createElement('div'); trigger.innerHTML = 'Base64'; Object.assign(trigger.style, { padding: '8px 16px', borderRadius: '6px', fontSize: '14px', cursor: 'pointer', transition: 'all 0.2s', backgroundColor: 'var(--primary)', color: 'var(--secondary)', boxShadow: '0 2px 5px rgba(0,0,0,0.2)' }); // 拖动功能 let isDragging = false; let offsetX = 0; let offsetY = 0; container.addEventListener('mousedown', (e) => { isDragging = true; const rect = container.getBoundingClientRect(); offsetX = e.clientX - rect.left; offsetY = e.clientY - rect.top; }); document.addEventListener('mousemove', (e) => { if (isDragging) { const x = e.clientX - offsetX; const y = e.clientY - offsetY; container.style.left = `${x}px`; container.style.top = `${y}px`; container.style.right = 'auto'; container.style.bottom = 'auto'; } }); document.addEventListener('mouseup', () => { if (isDragging) { const rect = container.getBoundingClientRect(); GM_setValue('b64Position', { x: rect.left, y: rect.top }); } isDragging = false; }); // 下拉菜单容器 const menu = document.createElement('div'); menu.style.cssText = ` position: absolute; bottom: 100%; right: 0; width: 140px; background: var(--secondary); border-radius: 6px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); margin-bottom: 8px; opacity: 0; transform: translateY(10px); transition: all 0.25s ease; pointer-events: none; `; // 创建菜单项 const createMenuItem = (text) => { const item = document.createElement('div'); item.textContent = text; item.style.cssText = ` padding: 10px 16px; font-size: 13px; cursor: pointer; color: var(--primary); transition: background 0.2s; text-align: left; line-height: 1.4; `; item.onmouseenter = () => item.style.background = 'rgba(0,0,0,0.08)'; item.onmouseleave = () => item.style.background = ''; return item; }; const decodeItem = createMenuItem('解析本页 Base64'); const encodeItem = createMenuItem('文本转 Base64'); menu.append(decodeItem, encodeItem); container.append(trigger, menu); // 菜单切换逻辑 const toggleMenu = (show) => { menu.style.opacity = show ? 1 : 0; menu.style.transform = show ? 'translateY(0)' : 'translateY(10px)'; menu.style.pointerEvents = show ? 'all' : 'none'; }; // 主题适配 const updateTheme = () => { const isDark = document.body.getAttribute('data-theme') === 'dark'; trigger.style.backgroundColor = isDark ? 'var(--primary)' : 'var(--secondary)'; trigger.style.color = isDark ? 'var(--secondary)' : 'var(--primary)'; }; // 复制提示样式 const notificationStyle = document.createElement('style'); notificationStyle.textContent = ` .b64-copy-notification { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background: rgba(0, 200, 0, 0.9); color: white; padding: 10px 20px; border-radius: 4px; font-size: 14px; z-index: 10000; animation: fadeOut 2s forwards; animation-delay: 0.5s; } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } `; document.head.appendChild(notificationStyle); // 显示复制提示 function showCopyNotification() { const notification = document.createElement('div'); notification.className = 'b64-copy-notification'; notification.textContent = '已复制到剪贴板'; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 2500); } // 解码功能 let isParsed = false; let originalTexts = {}; const decodeBase64 = () => { const base64Regex = /([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?/g; if (isParsed) { // 恢复原始文本 Object.entries(originalTexts).forEach(([wrapperId, text]) => { const wrapper = document.getElementById(wrapperId); if (wrapper) { const textNode = document.createTextNode(text); wrapper.replaceWith(textNode); } }); originalTexts = {}; isParsed = false; } else { document.querySelectorAll('div.post, div.cooked').forEach(container => { const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT); while (walker.nextNode()) { const node = walker.currentNode; if (node.textContent.length > 20) { const decodedContent = node.textContent.replace(base64Regex, match => { try { const decoded = decodeURIComponent(escape(atob(match))); return decoded !== match ? `<span class="b64-decoded" style=" color: #FF7F28; background: rgba(255, 127, 40, 0.1); cursor: pointer; transition: all 0.2s; padding: 1px 2px; border-radius: 3px; ">${decoded}</span>` : match; } catch { return match; } }); if (decodedContent !== node.textContent) { const wrapper = document.createElement('span'); const wrapperId = `b64-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`; wrapper.id = wrapperId; wrapper.innerHTML = decodedContent; wrapper.querySelectorAll('.b64-decoded').forEach(span => { span.onclick = (e) => { GM_setClipboard(span.textContent); showCopyNotification(); e.target.style.opacity = '0.7'; setTimeout(() => e.target.style.opacity = '', 500); }; }); originalTexts[wrapperId] = node.textContent; node.replaceWith(wrapper); } } } }); isParsed = true; } }; // 编码功能 const encodeBase64 = () => { const text = prompt('请输入要编码的文本:'); if (text) { const encoded = btoa(unescape(encodeURIComponent(text))); GM_setClipboard(encoded); alert('已复制到剪贴板: ' + encoded); } }; // 事件绑定 trigger.addEventListener('click', (e) => { e.stopPropagation(); toggleMenu(menu.style.opacity === '0'); }); decodeItem.addEventListener('click', () => { decodeBase64(); toggleMenu(false); }); encodeItem.addEventListener('click', () => { encodeBase64(); toggleMenu(false); }); // 初始化 document.body.appendChild(container); updateTheme(); // 主题变化监听 new MutationObserver(updateTheme).observe(document.body, { attributes: true, attributeFilter: ['data-theme'] }); // 点击外部关闭 document.addEventListener('click', (e) => { if (!container.contains(e.target)) toggleMenu(false); }); // 全局样式 const style = document.createElement('style'); style.textContent = ` .b64-decoded:hover { background: rgba(255, 127, 40, 0.2) !important; } .b64-decoded:active { background: rgba(255, 127, 40, 0.3) !important; } `; document.head.appendChild(style); })();