Base64 文本解码器

选中文本时自动检测并解码 Base64 编码的内容,支持一键复制解码结果

目前为 2025-02-15 提交的版本。查看 最新版本

// ==UserScript==
// @name         Base64 文本解码器
// @name:en      Base64 Text Decoder
// @namespace    https://github.com/eep
// @version      1.0.0
// @description  选中文本时自动检测并解码 Base64 编码的内容,支持一键复制解码结果
// @description:en  Automatically detects and decodes Base64 encoded text when selected, with one-click copy feature
// @author       EEP
// @license      MIT
// @match        *://*/*
// @grant        GM_addStyle
// @run-at       document-end
// @supportURL   https://github.com/eep/base64-decoder/issues
// @homepageURL  https://github.com/eep/base64-decoder
// ==/UserScript==

(function () {
  'use strict';

  // 创建悬浮窗口元素
  const floatingWindow = document.createElement('div');
  floatingWindow.style.cssText = `
        position: fixed;
        padding: 10px;
        background: rgba(0, 0, 0, 0.8);
        color: white;
        border-radius: 5px;
        font-size: 14px;
        z-index: 9999;
        display: none;
        cursor: pointer;
        user-select: none;
    `;
  document.body.appendChild(floatingWindow);

  // 添加复制功能
  let decodedText = '';
  floatingWindow.addEventListener('click', async (e) => {
    e.stopPropagation();
    if (decodedText) {
      try {
        await navigator.clipboard.writeText(decodedText);
        const originalText = floatingWindow.textContent;
        floatingWindow.textContent = '复制成功!';
        setTimeout(() => {
          floatingWindow.textContent = originalText;
        }, 1000);
      } catch (err) {
        console.error('复制失败:', err);
      }
    }
  });

  // 判断字符串是否为纯英文
  function isEnglishOnly(text) {
    // 如果包含空格,则认为是普通英文句子
    if (text.includes(' ')) {
      return false;
    }
    // 检查是否只包含合法的 base64 字符
    if (!/^[A-Za-z0-9+/=]+$/.test(text)) {
      return false;
    }
    // 检查长度是否为 4 的倍数
    if (text.length % 4 !== 0) {
      return false;
    }
    // 检查填充字符的位置是否正确
    const paddingChar = text.indexOf('=');
    if (paddingChar !== -1) {
      // = 只能出现在末尾
      if (paddingChar < text.length - 2) {
        return false;
      }
      // 最多只能有两个 =
      if (text.slice(paddingChar).length > 2) {
        return false;
      }
    }
    return true;
  }

  // 尝试base64解码
  function tryBase64Decode(text) {
    try {
      const decoded = atob(text.trim());
      // 检查解码后的文本是否包含过多不可打印字符
      const unprintableChars = decoded.split('').filter((char) => {
        const code = char.charCodeAt(0);
        return code < 32 || code > 126;
      }).length;

      // 如果不可打印字符超过总长度的 20%,认为不是有效的文本
      if (unprintableChars / decoded.length > 0.2) {
        return null;
      }
      return decoded;
    } catch (e) {}
    return null;
  }

  // 用于存储延时器ID
  let decodeTimer = null;

  // 处理选择事件
  document.addEventListener('selectionchange', () => {
    // 清除之前的延时器
    if (decodeTimer) {
      clearTimeout(decodeTimer);
    }

    const selection = window.getSelection();
    const text = selection.toString();

    // 隐藏当前显示的窗口
    floatingWindow.style.display = 'none';

    if (text.length >= 20 && isEnglishOnly(text)) {
      // 设置500ms延时
      decodeTimer = setTimeout(() => {
        const decoded = tryBase64Decode(text);
        if (decoded) {
          const range = selection.getRangeAt(0);
          const rect = range.getBoundingClientRect();

          decodedText = decoded;
          floatingWindow.textContent = `Decoded: ${decoded}`;
          floatingWindow.style.display = 'block';
          floatingWindow.style.left = `${rect.left + window.scrollX}px`;
          floatingWindow.style.top = `${rect.bottom + window.scrollY + 5}px`;
        }
      }, 500);
    }
  });

  // 点击页面其他地方时隐藏悬浮窗口
  document.addEventListener('click', (e) => {
    if (e.target !== floatingWindow) {
      floatingWindow.style.display = 'none';
    }
  });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址