软替换网页默认字体

替换网页默认字体,默认为 MiSans、FZYouSong GBK 509R(方正悠宋)、Cascadia Mono。可根据需求修改脚本中的字体设置。使用前需确保已安装所需字体。

目前為 2025-03-18 提交的版本,檢視 最新版本

// ==UserScript==
// @name         软替换网页默认字体
// @namespace    chNt6w8D6cVSQE93BSC8VS6QxNshGaSP9QcK82kruzbN5E4K2TJKxbNjpAXDfJKe
// @description  替换网页默认字体,默认为 MiSans、FZYouSong GBK 509R(方正悠宋)、Cascadia Mono。可根据需求修改脚本中的字体设置。使用前需确保已安装所需字体。
// @version      6
// @license      Apache License 2.0
// @author       Anonymous
// @compatible   firefox
// @compatible   safari
// @compatible   chrome
// @match        *://*/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @run-at       document-start
// ==/UserScript==
(function () {
  "use strict";

  const defaultConfig = {
    sans: ["MiSans", "MiSans L3", "Arial"],
    serif: ["FZYouSong GBK 509R", "Times New Roman", "Arial"],
    mono: ["Cascadia Mono", "Arial", "Arial"],
  };

  function loadConfig() {
    return {
      sans: GM_getValue("sansFonts", defaultConfig.sans),
      serif: GM_getValue("serifFonts", defaultConfig.serif),
      mono: GM_getValue("monoFonts", defaultConfig.mono),
    };
  }

  function saveConfig() {
    GM_setValue("sansFonts", config.sans);
    GM_setValue("serifFonts", config.serif);
    GM_setValue("monoFonts", config.mono);
  }

  function createConfigUI() {
    const overlay = document.createElement("div");
    overlay.style = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 999999;
        `;

    const panel = document.createElement("div");
    panel.style = `
            background: #fff;
            padding: 24px;
            border-radius: 12px;
            width: 500px;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
            font-family: Arial, sans-serif;
        `;

    const title = document.createElement("h2");
    title.textContent = "软替换网页默认字体配置";
    title.style = `
            margin: 0 0 24px;
            text-align: center;
            color: #333;
        `;
    panel.appendChild(title);

    const createInputGroup = (type, label) => {
      const container = document.createElement("div");
      container.style.marginBottom = "20px";

      const titleLabel = document.createElement("label");
      titleLabel.textContent = label;
      titleLabel.style = `
                display: block;
                margin-bottom: 12px;
                font-weight: 600;
                color: #555;
            `;
      container.appendChild(titleLabel);

      for (let i = 0; i < 3; i++) {
        const input = document.createElement("input");
        input.type = "text";
        input.value = config[type][i];
        input.dataset.type = type;
        input.dataset.index = i;
        input.placeholder = `字体 ${i + 1}`;
        input.style = `
                    width: 100%;
                    padding: 8px;
                    margin-bottom: 8px;
                    border: 1px solid #ddd;
                    border-radius: 4px;
                    font-size: 14px;
                `;

        const labelEl = document.createElement("label");
        labelEl.textContent = `备选字体 ${i + 1}:`;
        labelEl.style = `
                    display: block;
                    margin-bottom: 4px;
                    color: #777;
                `;

        container.appendChild(labelEl);
        container.appendChild(input);
      }
      return container;
    };

    panel.appendChild(createInputGroup("sans", "无衬线字体"));
    panel.appendChild(createInputGroup("serif", "衬线字体"));
    panel.appendChild(createInputGroup("mono", "等宽字体"));

    const importExportSection = document.createElement("div");
    importExportSection.style.marginBottom = "20px";

    const buttonContainer = document.createElement("div");
    buttonContainer.style.display = "flex";
    buttonContainer.style.gap = "12px";

    const importInput = document.createElement("input");
    importInput.type = "file";
    importInput.accept = ".json";
    importInput.style.display = "none";

    const importBtn = document.createElement("button");
    importBtn.textContent = "导入配置";
    importBtn.style = `
            flex: 1;
            padding: 10px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        `;
    importBtn.onclick = () => importInput.click();

    importInput.onchange = async () => {
      try {
        const file = importInput.files[0];
        const content = await file.text();
        const importedConfig = JSON.parse(content);
        Object.assign(config, importedConfig);
        saveConfig();
        alert("配置已导入,请刷新页面生效");
        overlay.remove();
      } catch (e) {
        alert("导入失败:无效的配置文件");
      }
    };

    // 导出功能
    const exportBtn = document.createElement("button");
    exportBtn.textContent = "导出配置";
    exportBtn.style = `
            flex: 1;
            padding: 10px;
            background: #007BFF;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        `;
    exportBtn.onclick = () => {
      const blob = new Blob([JSON.stringify(config, null, 2)], {
        type: "application/json",
      });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "font-config.json";
      a.click();
      URL.revokeObjectURL(url);
    };

    buttonContainer.appendChild(importBtn);
    buttonContainer.appendChild(exportBtn);
    importExportSection.appendChild(buttonContainer);
    panel.appendChild(importExportSection);

    // 保存按钮
    const saveBtn = document.createElement("button");
    saveBtn.textContent = "保存配置";
    saveBtn.style = `
            width: 100%;
            padding: 12px;
            background: #333;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
        `;
    saveBtn.onclick = () => {
      const inputs = panel.querySelectorAll("input");
      inputs.forEach((input) => {
        config[input.dataset.type][input.dataset.index] = input.value;
      });
      saveConfig();
      alert("配置已保存,刷新页面后生效");
      overlay.remove();
    };

    panel.appendChild(saveBtn);
    overlay.appendChild(panel);
    document.body.appendChild(overlay);
  }

  function generateCSS() {
    const [sans1, sans2, sans3] = config.sans;
    const [serif1, serif2, serif3] = config.serif;
    const [mono1, mono2, mono3] = config.mono;

    return `
            /* 基本字体 */
            @font-face{font-family:sans-serif;src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:serif;src:local(${serif1}),local(${serif2}),local(${serif3});}
            @font-face{font-family:monospace;src:local(${mono1}),local(${mono2}),local(${mono3});}

            /* 无衬线字体 拉丁文 */
            @font-face{font-family:"Arial";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Cambria";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Calibri";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Verdana";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Helvetica";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Helvetica Neue";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"HelveticaNeue";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"San Francisco";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"San Francisco Pro";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Segoe UI";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Google Sans";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Google Sans Text";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Roboto";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Noto Sans";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Lucida Sans";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Lucida Grande";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"DejaVu Sans";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Liberation Sans";src:local(${sans1}),local(${sans2}),local(${sans3});}
            @font-face{font-family:"Open Sans";src:local(${sans1}),local(${sans2}),local(${sans3});}

            /* 无衬线字体 简化字形 */
            @font-face{font-family:"HarmonyOS Sans";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 鸿蒙字体 */
            @font-face{font-family:"Noto Sans SC";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 谷歌豆腐字体 */
            @font-face{font-family:"SimHei";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 中易黑体 ( Windows 里的 黑体 ) */
            @font-face{font-family:"黑体";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 中易黑体 ( Windows 里的 黑体 ) */
            @font-face{font-family:"HarmonyOS Sans";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 鸿蒙字体 */
            @font-face{font-family:"Noto Sans SC";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 谷歌豆腐字体 */
            @font-face{font-family:"SimHei";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 中易黑体 ( Windows 里的 黑体 ) */
            @font-face{font-family:"黑体";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 中易黑体 ( Windows 里的 黑体 ) */
            @font-face{font-family:"Microsoft YaHei";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 微软雅黑 */
            @font-face{font-family:"微软雅黑";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 微软雅黑 */
            @font-face{font-family:"Microsoft YaHei UI";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 微软雅黑 UI */
            @font-face{font-family:"微软雅黑 UI";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 微软雅黑 UI */
            @font-face{font-family:"PingFang SC";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 苹方 */
            @font-face{font-family:"Hiragino Sans GB";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 冬青黑体 */
            @font-face{font-family:"STHeiti";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 华文黑体 */

            /* 无衬线字体 传统字形 */
            @font-face{font-family:"Noto Sans TC";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 谷歌豆腐字体 */
            @font-face{font-family:"Microsoft JhengHei";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 微軟正黑體 */
            @font-face{font-family:"微軟正黑體";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 微軟正黑體 */
            @font-face{font-family:"Microsoft JhengHei UI";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 微軟正黑體 */
            @font-face{font-family:"微軟正黑體修正";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 微軟正黑體 */
            @font-face{font-family:"MHei";src:local(${sans1}),local(${sans2}),local(${sans3});}/* 蒙纳黑体 */

            /* 衬线字体 简化字形 */
            @font-face{font-family:"SimSun";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 中易宋体 ( Windows 里的 宋体 ) */
            @font-face{font-family:"宋体";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 中易宋体 ( Windows 里的 宋体 ) */
            @font-face{font-family:"NSimSun";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 中易新宋体 ( Windows 里的 新宋体 ) */
            @font-face{font-family:"新宋体";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 中易新宋体 ( Windows 里的 新宋体 ) */
            @font-face{font-family:"FangSong";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 中易仿宋 ( Windows 里的 仿宋 ) */
            @font-face{font-family:"FangSong_GB2312";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 中易仿宋 ( Windows 里的 仿宋 ) */
            @font-face{font-family:"仿宋";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 中易仿宋 ( Windows 里的 仿宋 ) */
            @font-face{font-family:"仿宋_GB2312";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 中易仿宋 ( Windows 里的 仿宋 ) */
            @font-face{font-family:"STSong";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 华文宋体 */
            @font-face{font-family:"STFangsong";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 华文仿宋 */
            @font-face{font-family:"STZhongsong";src:local(${serif1}),local(${serif2}),local(${serif3});}/* 华文中宋 */

            /* 等宽字体(代码) */
            @font-face{font-family:"Menlo";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Monaco";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Consolas";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Courier";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Courier New";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Andale Mono";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Ubuntu Mono";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Fira Code";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Fira Mono";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"DejaVu Sans Mono";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Liberation Mono";src:local(${mono1}),local(${mono2}),local(${mono3});}
            @font-face{font-family:"Source Code Pro";src:local(${mono1}),local(${mono2}),local(${mono3});}

            /* 字体渲染优化 */
            body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}
        `;
  }

  const config = loadConfig();

  GM_registerMenuCommand("配置界面", createConfigUI);

  GM_addStyle(generateCSS());
})();