文本大爆炸

仿照锤子的大爆炸,使用本地分词逻辑对选中文本进行分词

当前为 2024-09-25 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         文本大爆炸
// @namespace    http://tampermonkey.net/
// @author       突徒土兔
// @version      1
// @description  仿照锤子的大爆炸,使用本地分词逻辑对选中文本进行分词
// @match        *://*/*
// @icon         https://s2.loli.net/2024/09/25/6PxlMHA7EZVqwsJ.png
// ==/UserScript==

(function () {
    "use strict";
  
    let button = null;
    let popupContainer = null;
  
    /**
     * 创建样式
     * 该函数用于创建并插入样式表,定义按钮和弹出窗口的样式。
     */
    function createStyles() {
      const style = document.createElement("style");
      style.textContent = `
              .word-explosion-button {
                  position: absolute; /* 修改为 absolute,方便根据选中区域定位 */
                  background-color: rgba(217, 12, 12, 0.4);
                  color: #000;
                  border: none;
                  border-radius: 50%;
                  cursor: pointer;
                  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                  font-size: 16px;
                  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                  transition: all 0.3s ease;
                  z-index: 9999;
                  width: 30px; /* 设置按钮的宽度 */
                  height: 30px; /* 设置按钮的高度 */
                  display: flex;
                  justify-content: center;
                  align-items: center;
              }
              .word-explosion-button:hover {
                  background-color: rgba(217, 12, 12, 0.75);
                  box-shadow: 0 4px 20px rgba(0,0,0,0.15);
              }
              .word-explosion-popup {
                  position: fixed;
                  top: 50%;
                  left: 50%;
                  transform: translate(-50%, -50%);
                  background-color: rgba(240, 240, 240, 0.8);
                  backdrop-filter: blur(10px);
                  padding: 20px;
                  border-radius: 10px;
                  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
                  z-index: 10000;
                  max-width: 80%;
                  max-height: 80%;
                  overflow: auto;
                  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                  display: flex;
                  flex-wrap: wrap;
                  justify-content: center;
                  align-items: center;
              }
              .word-explosion-word {
                  margin: 2px;
                  padding: 4px 8px;
                  background-color: rgba(255, 255, 255, 0.5);
                  border: none;
                  border-radius: 10px;
                  cursor: pointer;
                  transition: all 0.3s ease;
                  font-size: 14px;
                  display: inline-flex;
                  align-items: center;
              }
              .word-explosion-word.selected {
                  background-color: #0078D4;
                  color: white;
              }
              .word-explosion-copy {
                  display: block;
                  margin-top: 15px;
                  padding: 10px 20px;
                  background-color: #0078D4;
                  color: white;
                  border: none;
                  border-radius: 20px;
                  cursor: pointer;
                  font-size: 14px;
                  transition: all 0.3s ease;
              }
              .word-explosion-copy:hover {
                  background-color: #106EBE;
              }
          `;
      document.head.appendChild(style);
    }
  
    /**
     * 创建按钮
     * 该函数用于创建并插入一个按钮,用于触发大爆炸功能。
     */
    function createButton() {
      button = document.createElement("button");
      button.textContent = "💥";
      button.className = "word-explosion-button";
      button.style.display = "none";
      document.body.appendChild(button);
    }
  
    /**
     * 显示按钮并将其定位到选中文本旁边
     * 该函数用于在选中文本时显示按钮,并将其定位到选中文本的旁边。
     */
    function showButtonAtSelection() {
      const selection = window.getSelection();
      if (selection.rangeCount > 0) {
        const range = selection.getRangeAt(0);
        const rect = range.getBoundingClientRect(); // 获取选中区域的矩形框
        button.style.top = `${rect.bottom + window.scrollY + 5}px`; // 按钮显示在选中区域下方
        button.style.left = `${rect.left + window.scrollX}px`; // 按钮靠左边缘
        button.style.display = "block";
      }
    }
  
    /**
     * 隐藏按钮
     * 该函数用于隐藏按钮。
     */
    function hideButton() {
      button.style.display = "none";
    }
  
    /**
     * 创建弹出窗口
     * 该函数用于创建并插入一个弹出窗口,用于显示分词结果。
     */
    function createPopup() {
      popupContainer = document.createElement("div");
      popupContainer.className = "word-explosion-popup";
      popupContainer.style.display = "none";
      document.body.appendChild(popupContainer);
    }
  
    /**
     * 显示弹出窗口
     * 该函数用于显示弹出窗口,并填充分词结果。
     * @param {Array} words - 分词结果数组
     */
    function showPopup(words) {
      popupContainer.innerHTML = "";
      words.forEach((word) => {
        const wordButton = document.createElement("button");
        wordButton.textContent = word;
        wordButton.className = "word-explosion-word";
        wordButton.addEventListener("click", () =>
          wordButton.classList.toggle("selected")
        );
        popupContainer.appendChild(wordButton);
      });
  
      const copyButton = document.createElement("button");
      copyButton.textContent = "复制选中文本";
      copyButton.className = "word-explosion-copy";
      copyButton.style.width = "100%";
      copyButton.addEventListener("click", copySelectedWords);
      popupContainer.appendChild(copyButton);
  
      popupContainer.style.display = "flex";
    }
  
    /**
     * 隐藏弹出窗口
     * 该函数用于隐藏弹出窗口。
     */
    function hidePopup() {
      popupContainer.style.display = "none";
    }
  
    /**
     * 改进的分词函数
     * 该函数用于对输入的文本进行分词。
     * @param {string} text - 需要分词的文本
     * @returns {Array} - 分词结果数组
     */
    function wordExplosion(text) {
      const regex =
        /[\u4e00-\u9fa5]|[a-zA-Z]+|[0-9]+|[^\u4e00-\u9fa5a-zA-Z0-9]+/g;
      return text.match(regex) || [];
    }
  
    /**
     * 复制选中的单词
     * 该函数用于将选中的单词复制到剪贴板。
     */
    function copySelectedWords() {
      const selectedWords = Array.from(
        popupContainer.querySelectorAll(".word-explosion-word.selected")
      )
        .map((button) => button.textContent)
        .join("");
      navigator.clipboard
        .writeText(selectedWords)
        .then(() => {
          alert(`已复制:${selectedWords}!`);
        })
        .catch((err) => {
          console.error("复制失败: ", err);
        });
    }
  
    /**
     * 监听选择事件
     * 该函数用于监听用户的选择事件,当用户选中文本时,显示按钮并定位到选中文本旁边。
     */
    document.addEventListener("selectionchange", function () {
      const selection = window.getSelection();
      if (selection.toString().trim() !== "") {
        showButtonAtSelection(); // 选中文本时显示按钮并定位
      } else {
        hideButton();
      }
    });
  
    /**
     * 监听按钮点击事件
     * 该函数用于监听按钮点击事件,当按钮被点击时,显示弹出窗口并隐藏按钮。
     */
    function onButtonClick() {
      const selection = window.getSelection();
      const text = selection.toString();
      const words = wordExplosion(text);
      showPopup(words);
      hideButton();
    }
  
    /**
     * 初始化
     * 该函数用于初始化样式、按钮和弹出窗口,并添加事件监听器。
     */
    function initialize() {
      createStyles();
      createButton();
      createPopup();
      button.addEventListener("click", onButtonClick);
    }
  
    /**
     * 点击其他地方时关闭弹窗
     * 该函数用于监听点击事件,当点击事件发生在按钮或弹出窗口之外时,隐藏弹出窗口。
     */
    document.addEventListener("click", function (event) {
      if (event.target !== button && !popupContainer.contains(event.target)) {
        hidePopup();
      }
    });
  
    // 启动初始化
    initialize();
  })();