keyToShowClass | 快捷键启动自定义样式

Press a shortcut key to activate the specified host's custom styling. | 点击某个快捷键,来启动你指定的host的自定义的样式

// ==UserScript==
// @name        keyToShowClass | 快捷键启动自定义样式
// @namespace   https://leizingyiu.net
// @match       http*://*/*
// @grant       none
// @version     20250309
// @author      leizingyiu
// @description Press a shortcut key to activate the specified host's custom styling. | 点击某个快捷键,来启动你指定的host的自定义的样式
// @license     GNU AGPLv3

// ==/UserScript==

prefix = "yiu_lib_show_info_";
// 定义样式模板字典
const dict = {
  "example":"⬇️",
  "liblib.art": {
    KeyC: `
      .${prefix}$/{code/} [class^=ImageCard_mask],
      .${prefix}$/{code/} [class^=ImageCard_imageCard] {
        opacity: 1 !important;
        background: #00000000 !important;
        color: #000 !important;
      }

      .${prefix}$/{code/} [class^=ImageCard_nickName],
      .${prefix}$/{code/} [class^=ImageGenerateInfoPopover_generateBtn] {
        color: #fff !important;
        text-shadow: unset !important;
        mix-blend-mode: difference;
      }

      .${prefix}$/{code/} [class^=ImageCard_drawBtn],
      .${prefix}$/{code/} .opacity-0 {
        opacity: 1 !important;
      }

      [class^=ImageCard_mask],
      [class^=ImageCard_imageCard] {
        transition: opacity 0.2s ease, background 0.2s ease, color 0.2s ease !important;
      }

      [class^=ImageCard_nickName],
      [class^=ImageGenerateInfoPopover_generateBtn] {
        transition: text-shadow 0.2s ease, color 0.2s ease !important;
      }

      [class^=ImageCard_drawBtn], .opacity-0 {
        transition: opacity 0.2s ease;
      }
    `,
  },
  // 可以扩展其他主机和按键
};

// 获取当前主机名
const currentHost = window.location.host;

function hasSetting(host) {
  for (const [hostKey, styles] of Object.entries(dict)) {
    if (host.includes(hostKey)) {
      return true; // 如果当前主机包含字典中的主机名,则返回对应的样式模板
    }
  }
  return false; // 如果没有匹配的主机名,返回 null
}

// 根据主机名获取对应的样式模板
function getHostStyles(host) {
  for (const [hostKey, styles] of Object.entries(dict)) {
    if (host.includes(hostKey)) {
      return styles; // 如果当前主机包含字典中的主机名,则返回对应的样式模板
    }
  }
  return null; // 如果没有匹配的主机名,返回 null
}

// 动态生成样式内容
function generateStyleContent(template, code) {
  return template.replace(/\$\/\{code\/\}/g, code); // 替换所有 $/{code/} 占位符
}

// 初始化样式
function initializeStyles() {
  const hostStyles = getHostStyles(currentHost); // 获取当前主机的样式模板

  if (!hostStyles) {
    console.error(`未找到与主机 ${currentHost} 匹配的样式模板`);
    return;
  }

  // 遍历主机的所有按键样式模板
  for (const [key, styleTemplate] of Object.entries(hostStyles)) {
    const styleContent = generateStyleContent(styleTemplate, key); // 替换占位符

    const styleElement = document.createElement("style");
    styleElement.textContent = styleContent; // 设置样式内容
    document.head.appendChild(styleElement); // 添加到 <head>
  }
}

// 初始化事件监听器
function initializeEventListeners() {
  const hostStyles = getHostStyles(currentHost); // 获取当前主机的样式模板

  if (!hostStyles) {
    console.error(`未找到与主机 ${currentHost} 匹配的样式模板`);
    return;
  }

  const toggleClass = (e) => {
    const key = e.code; // 获取按键代码
    console.log("key to show class : toggleClass : start");

    const isKeySupported = hostStyles.hasOwnProperty(key); // 检查按键是否在样式模板中

    if (isKeySupported) {
      console.log("key to show class : toggleClass : KeySupported");

      if (e.type === "keydown") {
        document.body.classList.add(`${prefix}${key}`); // 添加动态类名
      } else if (e.type === "keyup") {
        document.body.classList.remove(`${prefix}${key}`); // 移除动态类名
      }
    }
  };

  window.addEventListener("keydown", toggleClass);
  window.addEventListener("keyup", toggleClass);
}

// 主函数:初始化样式和事件监听器
function main() {
  console.log("key to show class : main : start");

  initializeStyles(); // 初始化样式
  initializeEventListeners(); // 初始化事件监听器

  console.log("key to show class : main : end ");
}

// window.addEventListener('load',function(){
//   if(hasSetting(currentHost)==true){
//     main();
//   }
// })

/**
 * 监听页面状态变化的函数
 * @param {Object} options - 配置对象,用于启用或禁用特定事件监听
 * @param {boolean} options.onUrlChange - 是否监听地址栏变化(hashchange 和 popstate)
 * @param {boolean} options.onPageNavigation - 是否监听页面前进或后退(popstate)
 * @param {boolean} options.onPageLoad - 是否监听页面加载完成(DOMContentLoaded 和 load)
 * @param {Function} [options.commonCallback] - 通用回调函数,适用于所有事件
 * @param {Object} callbacks - 回调函数对象(可选)
 * @param {Function} callbacks.onUrlChangeCallback - 地址栏变化时的回调
 * @param {Function} callbacks.onPageNavigationCallback - 页面前进或后退时的回调
 * @param {Function} callbacks.onPageLoadCallback - 页面加载完成时的回调
 */
function listenPageStateChanges(options = {}, callbacks = {}) {
  const {
    onUrlChange = false,
    onPageNavigation = false,
    onPageLoad = false,
    commonCallback, // 通用回调函数
  } = options;

  const {
    onUrlChangeCallback = commonCallback,
    onPageNavigationCallback = commonCallback,
    onPageLoadCallback = commonCallback,
  } = callbacks;

  // 1. 地址栏变化(hashchange 和 popstate)
  if (onUrlChange && typeof onUrlChangeCallback === "function") {
    window.addEventListener("hashchange", () => {
       onUrlChangeCallback(window.location.href);
    });

    window.addEventListener("popstate", () => {
       onUrlChangeCallback(window.location.href);
    });
  }

  // 2. 页面前进或后退(popstate)
  if (onPageNavigation && typeof onPageNavigationCallback === "function") {
    window.addEventListener("popstate", () => {
       onPageNavigationCallback(window.location.href);
    });
  }

  // 3. 页面加载完成(DOMContentLoaded 和 load)
  if (onPageLoad && typeof onPageLoadCallback === "function") {
    document.addEventListener("DOMContentLoaded", () => {
       onPageLoadCallback("DOMContentLoaded");
    });

    window.addEventListener("load", () => {
       onPageLoadCallback("load");
    });
  }
}

console.log("key to show class", hasSetting(currentHost));

if (hasSetting(currentHost) == true) {
  listenPageStateChanges(
    {
      onUrlChange: true, // 启用地址栏变化监听
      onPageNavigation: true, // 启用页面导航监听
      onPageLoad: true, // 启用页面加载完成监听
      commonCallback: (data) => {
        main(data);
      },
    },
    {
      // 如果需要单独定义某个事件的回调,可以在这里覆盖 commonCallback
      // 例如:
      // onUrlChangeCallback: (newUrl) => {
      //   console.log('单独处理地址栏变化:', newUrl);
      // },
    },
  );
}

QingJ © 2025

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