网页字体替换增强器

替换网页默认字体。可根据需求修改脚本中的字体设置。使用前需确保已安装所需字体。记得修改浏览器自带的字体设置。

当前为 2025-05-02 提交的版本,查看 最新版本

// ==UserScript==
// @name         网页字体替换增强器
// @namespace    chNt6w8D6cVSQE93BSC8VS6QxNshGaSP9QcK82kruzbN5E4K2TJKxbNjpAXDfJKe
// @description  替换网页默认字体。可根据需求修改脚本中的字体设置。使用前需确保已安装所需字体。记得修改浏览器自带的字体设置。
// @version      9
// @license      Apache License 2.0
// @author       Ckrvxr
// @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_latin:        ["MiSans", "MiSans L3", ""],
        sans_simplified:   ["MiSans", "MiSans L3", ""],
        sans_traditional:  ["MiSans TC", "MiSans L3", ""],
        serif_latin:       ["屏显臻宋", "", ""],
        serif_simplified:  ["屏显臻宋", "", ""],
        serif_traditional: ["屏显臻宋", "", ""],
        mono_latin:        ["Cascadia Code", "Cascadia Mono", ""]
    };

    // 加载配置
    function loadConfig() {
        return {
            sans_latin:        GM_getValue("sans_latin",        defaultConfig.sans_latin),
            sans_simplified:   GM_getValue("sans_simplified",   defaultConfig.sans_simplified),
            sans_traditional:  GM_getValue("sans_traditional",  defaultConfig.sans_traditional),
            serif_latin:       GM_getValue("serif_latin",       defaultConfig.serif_latin),
            serif_simplified:  GM_getValue("serif_simplified",  defaultConfig.serif_simplified),
            serif_traditional: GM_getValue("serif_traditional", defaultConfig.serif_traditional),
            mono_latin:        GM_getValue("mono_latin",        defaultConfig.mono_latin)
        };
    }

    // 保存配置
    function saveConfig(config) {
        Object.keys(config).forEach(key => {
            GM_setValue(key, config[key]);
        });
    }

    function createConfigUI(config) {
        // 锁定页面滚动
        document.body.style.overflow         = "hidden";
        document.documentElement.style.overflowX = "";
        document.documentElement.style.overflowY = "hidden";

        // 创建面板容器
        const panel = document.createElement("div");
        panel.id = "font-config-panel";
        panel.style.cssText = `
            position: fixed;
            inset: 0;
            background: #ffffff;
            overflow-y: auto;
            padding: 4rem;
            font-family: sans-serif;
            color: #333333;
            z-index: 999999;
            max-height: 100vh;
            box-sizing: border-box;
        `;

        // 标题区域
        const title = document.createElement("h1");
        title.textContent = "字体替换增强器 · 配置面板";
        title.style.cssText = `
            margin: 0 0 1rem;
            font-size: 1.5rem;
            text-align: center;
            color: #333333;
            position: relative;
        `;

        // 标题装饰线
        const titleUnderline = document.createElement("div");
        titleUnderline.style.cssText = `
            position: absolute;
            bottom: 0;
            left: 50%;
            transform: translateX(-50%);
            width: 60px;
            height: 3px;
            background: linear-gradient(90deg, #4f46e5, #ec4899);
            border-radius: 1px;
        `;
        title.appendChild(titleUnderline);

        // 输入组生成器
        const createInputGroup = (type, label) => {
            const container = document.createElement("div");
            container.style.marginBottom = "1rem";

            // 标签
            const titleLabel = document.createElement("label");
            titleLabel.textContent = label;
            titleLabel.style.cssText = `
                display: block;
                margin-bottom: 0.5rem;
                font-weight: 600;
                color: #333333;
                font-size: 1rem;
            `;

            // 输入容器
            const inputContainer = document.createElement("div");
            inputContainer.style.cssText = `
                display: grid;
                grid-template-columns: repeat(3, 1fr);
                gap: 2rem;
            `;

            // 创建输入框
            config[type].forEach((value, index) => {
                const input = document.createElement("input");
                input.type = "text";
                input.value = value;
                input.dataset.type = type;
                input.dataset.index = index;
                input.placeholder = `备选字体 ${index + 1}`;
                input.style.cssText = `
                    width: 100%;
                    padding: 0.5rem;
                    border: 1px solid #cccccc;
                    border-radius: 6px;
                    font-size: 0.875rem;
                    color: #333333;
                    background: #f9f9f9;
                    transition: all 0.2s;
                `;
                inputContainer.appendChild(input);
            });

            container.appendChild(titleLabel);
            container.appendChild(inputContainer);
            return container;
        };

        // 按钮生成器
        const createButton = (text, colorScheme) => {
            const btn = document.createElement("button");
            btn.textContent = text;
            btn.style.cssText = `
                flex: 1;
                padding: 0.75rem;
                border: none;
                border-radius: 6px;
                font-weight: 600;
                cursor: pointer;
                transition: all 0.2s;
                margin: 0.5rem 0;
                color: white;
                background: ${colorScheme.base};
                box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            `;

            // 悬停效果
            btn.addEventListener("mouseover", () => {
                btn.style.background = colorScheme.hover;
                btn.style.transform = "translateY(-1px)";
            });
            btn.addEventListener("mouseout", () => {
                btn.style.background = colorScheme.base;
                btn.style.transform = "translateY(0)";
            });

            return btn;
        };

        // 颜色方案
        const colorSchemes = {
            primary:   { base: "#4f46e5", hover: "#4338ca" },
            secondary: { base: "#3b82f6", hover: "#2563eb" },
            success:   { base: "#10b981", hover: "#0b8a5e" },
            warning:   { base: "#f59e0b", hover: "#d97706" },
            danger:    { base: "#ef4444", hover: "#dc2626" },
            info:      { base: "#64748b", hover: "#475569" }
        };

        // 文件导入元素
        const importInput = document.createElement("input");
        importInput.type = "file";
        importInput.accept = ".json";
        importInput.style.display = "none";

        // 导入按钮
        const importBtn = createButton("导入配置", colorSchemes.warning);
        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(config);
                
                alert("配置已导入,请刷新页面生效");
                panel.remove();
                restorePageScroll();
            } catch (e) {
                alert("导入失败:无效的配置文件");
            }
        };

        // 导出按钮
        const exportBtn = createButton("导出配置", colorSchemes.info);
        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);
        };

        // 重置按钮
        const resetBtn = createButton("重置默认", colorSchemes.danger);
        resetBtn.onclick = () => {
            if (confirm("确定要重置所有配置为默认值吗?")) {
                Object.keys(defaultConfig).forEach(key => {
                    config[key] = [...defaultConfig[key]];
                });
                saveConfig(config);
                
                alert("配置已重置,请刷新页面生效");
                panel.remove();
                restorePageScroll();
            }
        };

        // 保存按钮
        const saveBtn = createButton("保存配置", colorSchemes.success);
        saveBtn.onclick = () => {
            const inputs = panel.querySelectorAll("input");
            inputs.forEach(input => {
                config[input.dataset.type][input.dataset.index] = input.value;
            });
            saveConfig(config);
            
            alert("配置已保存,请刷新页面生效");
            panel.remove();
            restorePageScroll();
        };

        // 关闭按钮
        const closeBtn = createButton("关闭面板", colorSchemes.secondary);
        closeBtn.onclick = () => {
            panel.remove();
            restorePageScroll();
        };

        // 恢复页面滚动
        function restorePageScroll() {
            document.body.style.overflow = "";
            document.documentElement.style.overflowX = "";
            document.documentElement.style.overflowY = "";
        }

        // 组装面板内容
        panel.appendChild(title);
        panel.appendChild(createInputGroup("sans_latin", "无衬线 拉丁文"));
        panel.appendChild(createInputGroup("sans_simplified", "无衬线 简化字形"));
        panel.appendChild(createInputGroup("sans_traditional", "无衬线 传统字形"));
        panel.appendChild(createInputGroup("serif_latin", "衬线 拉丁文"));
        panel.appendChild(createInputGroup("serif_simplified", "衬线 简化字形"));
        panel.appendChild(createInputGroup("serif_traditional", "衬线 传统字形"));
        panel.appendChild(createInputGroup("mono_latin", "等宽 拉丁文"));

        // 动作按钮组1
        const actionRow1 = document.createElement("div");
        actionRow1.style.cssText = `
            display: flex;
            gap: 0.75rem;
            margin: 1rem 0;
        `;
        actionRow1.appendChild(importBtn);
        actionRow1.appendChild(exportBtn);
        actionRow1.appendChild(resetBtn);
        panel.appendChild(actionRow1);

        // 动作按钮组2
        const actionRow2 = document.createElement("div");
        actionRow2.style.cssText = `
            display: flex;
            gap: 0.75rem;
            margin: 1rem 0;
        `;
        actionRow2.appendChild(saveBtn);
        actionRow2.appendChild(closeBtn);
        panel.appendChild(actionRow2);

        // 插入面板到页面
        document.body.appendChild(panel);
    }

    // 生成 CSS 样式
    function generateCSS(config) {
        const [sans_latin_1, sans_latin_2, sans_latin_3] = config.sans_latin;
        const [sans_simplified_1, sans_simplified_2, sans_simplified_3] = config.sans_simplified;
        const [sans_traditional_1, sans_traditional_2, sans_traditional_3] = config.sans_traditional;
        const [serif_latin_1, serif_latin_2, serif_latin_3] = config.serif_latin;
        const [serif_simplified_1, serif_simplified_2, serif_simplified_3] = config.serif_simplified;
        const [serif_traditional_1, serif_traditional_2, serif_traditional_3] = config.serif_traditional;
        const [mono_latin_1, mono_latin_2, mono_latin_3] = config.mono_latin;

        let additionalStyles = "";

        // 特殊网站样式适配
        const currentUrl = window.location.href;
        if (currentUrl.startsWith("https://gf.qytechs.cn/")) {
            additionalStyles += `
                pre {
                    font-family: "Courier New" !important;
                }
            `;
        }
        if (currentUrl.startsWith("https://chat.qwen.ai/")) {
            additionalStyles += `
                .ͼ1 .cm-scroller {
                    font-family: "Courier New" !important;
                }
            `;
        }

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

        /* 无衬线 简化字形 */
        @font-face { font-family: "HarmonyOS Sans"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "Noto Sans SC"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "SimHei"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "黑体"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "Microsoft YaHei"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "微软雅黑"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "Microsoft YaHei UI"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "微软雅黑 UI"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "PingFang SC"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "Hiragino Sans GB"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }
        @font-face { font-family: "STHeiti"; src: local("${sans_simplified_1}"), local("${sans_simplified_2}"), local("${sans_simplified_3}"); }

        /* 无衬线 传统字形 */
        @font-face { font-family: "Noto Sans TC"; src: local("${sans_traditional_1}"), local("${sans_traditional_2}"), local("${sans_traditional_3}"); }
        @font-face { font-family: "Microsoft JhengHei"; src: local("${sans_traditional_1}"), local("${sans_traditional_2}"), local("${sans_traditional_3}"); }
        @font-face { font-family: "微軟正黑體"; src: local("${sans_traditional_1}"), local("${sans_traditional_2}"), local("${sans_traditional_3}"); }
        @font-face { font-family: "Microsoft JhengHei UI"; src: local("${sans_traditional_1}"), local("${sans_traditional_2}"), local("${sans_traditional_3}"); }
        @font-face { font-family: "MHei"; src: local("${sans_traditional_1}"), local("${sans_traditional_2}"), local("${sans_traditional_3}"); }

        /* 衬线 拉丁文 */
        @font-face { font-family: "Times New Roman"; src: local("${serif_latin_1}"), local("${serif_latin_2}"), local("${serif_latin_3}"); }
        @font-face { font-family: "Georgia"; src: local("${serif_latin_1}"), local("${serif_latin_2}"), local("${serif_latin_3}"); }

        /* 衬线 简化字形 */
        @font-face { font-family: "SimSun"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "宋体"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "NSimSun"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "新宋体"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "FangSong"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "FangSong_GB2312"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "仿宋"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "STSong"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "STFangsong"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }
        @font-face { font-family: "STZhongsong"; src: local("${serif_simplified_1}"), local("${serif_simplified_2}"), local("${serif_simplified_3}"); }

        /* 等宽 拉丁文 */
        @font-face { font-family: "Menlo"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Monaco"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Consolas"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Courier"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Courier New"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Andale Mono"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Ubuntu Mono"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Fira Code"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Fira Mono"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "DejaVu Sans Mono"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Liberation Mono"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }
        @font-face { font-family: "Source Code Pro"; src: local("${mono_latin_1}"), local("${mono_latin_2}"), local("${mono_latin_3}"); }

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

        ${additionalStyles}
    `; 
    }

    // 初始化配置
    const config = loadConfig();

    // 注册(不可用)右键菜单
    GM_registerMenuCommand("配置面板", () => createConfigUI(config));

    // 注入样式
    GM_addStyle(generateCSS(config));
})();

QingJ © 2025

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