选中文本后自动弹窗可编码/解码Base64
// ==UserScript== // @name Base64小助手 // @namespace https://github.com/soyadokio/UserScript // @version 20250109 // @description 选中文本后自动弹窗可编码/解码Base64 // @author SoyaDokio // @license MIT // @match *://*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=v2ex.com // @grant none // ==/UserScript== (function() { 'use strict'; let popupIframe = null; // 监听鼠标抬起事件 document.addEventListener('mouseup', function (e) { const selectedText = window.getSelection().toString().trim(); // 创建 iframe 悬浮框 if (selectedText) { createIframePopup(e.pageX, e.pageY, selectedText); } // 移除 iframe 悬浮框 else { removePopup(); } }); // 创建 iframe 悬浮框 function createIframePopup(x, y, selectedText) { // 先移除已存在的悬浮框 removePopup(); popupIframe = document.createElement('iframe'); popupIframe.style.position = 'absolute'; popupIframe.style.left = `${x + 10}px`; popupIframe.style.top = `${y + 10}px`; popupIframe.style.width = '235px'; popupIframe.style.height = '65px'; popupIframe.style.border = '1px solid #ddd'; popupIframe.style.borderRadius = '5px'; popupIframe.style.backgroundColor = 'white'; popupIframe.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)'; popupIframe.style.zIndex = '9999'; // 加载 iframe 内容 document.body.appendChild(popupIframe); const iframeDoc = popupIframe.contentDocument || popupIframe.contentWindow.document; iframeDoc.open(); iframeDoc.write(generateIframeContent(selectedText)); iframeDoc.close(); } // 生成 iframe 内部的 HTML 内容 function generateIframeContent(selectedText) { return ` <!DOCTYPE html> <html> <head> <style> body { margin: 0; padding: 4px; font-family: Arial, sans-serif; font-size: 12px; } .button-container { margin-bottom: 4px; } button { margin: 0 4px 0 0; padding: 2px 8px; font-size: 12px; cursor: pointer; } .output-container { display: flex; align-items: center; } input { width: 170px; height: 20px; font-size: 12px; margin-right: 4px; padding: 2px; } .copy-btn { cursor: pointer; font-size: 12px; color: #007bff; text-decoration: underline; } .copy-btn:hover { color: #0056b3; } .checkmark { display: none; color: green; font-size: 20px; transform: scale(0.9); transform-origin: center; } </style> </head> <body> <div class="button-container"> <button id="atob-btn">atob</button> <button id="btoa-btn">btoa</button> </div> <div class="output-container"> <input type="text" id="output" readonly /> <span class="copy-btn" id="copy-btn">复制</span> <span class="checkmark" id="checkmark">✔</span> </div> <script> (function () { const atobBtn = document.getElementById('atob-btn'); const btoaBtn = document.getElementById('btoa-btn'); const outputField = document.getElementById('output'); const copyBtn = document.getElementById('copy-btn'); const cmIcon = document.getElementById('checkmark'); let selectedText = ${JSON.stringify(selectedText)}; // atob 按钮点击事件 atobBtn.addEventListener('click', function () { try { outputField.value = atob(selectedText); } catch (e) { outputField.value = '错误: 无效输入'; } }); // btoa 按钮点击事件 btoaBtn.addEventListener('click', function () { try { outputField.value = btoa(selectedText); } catch (e) { outputField.value = '错误: 无效输入'; } }); // 复制按钮点击事件 copyBtn.addEventListener('click', function () { if (outputField.value) { navigator.clipboard.writeText(outputField.value).then(() => { copyBtn.style.display = 'none'; cmIcon.style.display = 'inline'; setTimeout(() => { cmIcon.style.display = 'none'; copyBtn.style.display = 'inline'; }, 2000); }); } }); })(); </script> </body> </html> `; } // 移除悬浮框 function removePopup() { if (popupIframe) { document.body.removeChild(popupIframe); popupIframe = null; } } })();