Greasy Fork is available in English.
全局修改字体
当前为
// ==UserScript==
// @name 全局字体
// @author gemini
// @version 1.07
// @match *://*/*
// @run-at document-start
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @namespace http://greasyfork.icu/users/22620
// @description 全局修改字体
// ==/UserScript==
(function() {
'use strict';
// --- 配置常量 ---
const DEFAULT_CONFIG = {
font: '微软雅黑',
exclusions: 'i, [class*="ico"], [class*="fa"], [class*="emoji"]',
enabled: true
};
const STORAGE_KEYS = {
font: 'config_my_new_font',
exclusions: 'config_icon_exclusion_selectors',
enabled: 'config_font_enabled'
};
// --- 状态管理 ---
class FontManager {
constructor() {
this.config = {
font: DEFAULT_CONFIG.font,
exclusions: DEFAULT_CONFIG.exclusions,
enabled: DEFAULT_CONFIG.enabled
};
this.styleElement = null;
this.configUpdateCallbacks = [];
}
// 加载配置
loadConfig() {
this.config.font = GM_getValue(STORAGE_KEYS.font, DEFAULT_CONFIG.font);
this.config.enabled = GM_getValue(STORAGE_KEYS.enabled, DEFAULT_CONFIG.enabled);
const storedExclusions = GM_getValue(STORAGE_KEYS.exclusions, DEFAULT_CONFIG.exclusions);
this.config.exclusions = storedExclusions;
console.log(`⚙️ 配置加载: 字体=${this.config.font}, 启用=${this.config.enabled}, 排除项=${storedExclusions}`);
}
// 保存配置
saveConfig() {
GM_setValue(STORAGE_KEYS.font, this.config.font);
GM_setValue(STORAGE_KEYS.exclusions, this.config.exclusions);
GM_setValue(STORAGE_KEYS.enabled, this.config.enabled);
}
// 添加配置更新回调
onConfigUpdate(callback) {
this.configUpdateCallbacks.push(callback);
}
// 触发配置更新回调
triggerConfigUpdate() {
this.configUpdateCallbacks.forEach(callback => callback(this.config));
}
// 生成排除选择器字符串
getExclusionSelector() {
return this.config.exclusions
.split(',')
.map(s => s.trim())
.filter(Boolean) // 使用 Boolean 函数过滤空值
.map(selector => `:not(${selector})`)
.join('');
}
// 生成 CSS
generateCSS(fontFamily = this.config.font) {
const exclusionSelector = this.getExclusionSelector();
return `
/* 全局字体修改 - ${new Date().toLocaleTimeString()} */
*${exclusionSelector} {
font-family: ${fontFamily} !important;
}
`;
}
// 注入 CSS
injectCSS(css) {
this.removeCSS();
this.styleElement = GM_addStyle(css);
return this.styleElement;
}
// 移除 CSS
removeCSS() {
if (this.styleElement?.parentNode) {
this.styleElement.parentNode.removeChild(this.styleElement);
this.styleElement = null;
}
}
// 应用字体(两个阶段)
async applyFont() {
if (!this.config.enabled) {
this.removeCSS();
return;
}
// 阶段一:立即注入
const initialCSS = this.generateCSS(this.config.font);
this.injectCSS(initialCSS);
console.log(`⏱️ 阶段一:注入初始字体: ${this.config.font}`);
// 阶段二:等待字体加载完成后更新
try {
await document.fonts?.ready;
const protectedFonts = new Set();
document.fonts?.forEach?.(fontFace => {
const fontFamily = fontFace.family.replace(/"/g, '');
if (fontFamily) protectedFonts.add(`"${fontFamily}"`);
});
const protectedFontFamily = [...protectedFonts].join(', ');
const finalFontFamily = protectedFontFamily
? `${this.config.font}, ${protectedFontFamily}`
: this.config.font;
const finalCSS = this.generateCSS(finalFontFamily);
this.injectCSS(finalCSS);
console.log(`✅ 阶段二:最终字体: ${finalFontFamily}`);
} catch (error) {
console.warn('⚠️ 字体加载出错,使用初始字体:', error);
}
}
// 更新配置并重新应用
updateConfig(updates) {
Object.assign(this.config, updates);
this.saveConfig();
this.applyFont();
this.triggerConfigUpdate();
}
// 切换启用状态
toggleEnabled() {
const newEnabled = !this.config.enabled;
this.updateConfig({ enabled: newEnabled });
console.log(newEnabled ? '✅ 字体效果已启用' : '❌ 字体效果已禁用');
}
// 重置为默认配置
resetToDefault() {
if (confirm('确定要将所有配置恢复为默认值吗?')) {
Object.assign(this.config, DEFAULT_CONFIG);
this.saveConfig();
this.applyFont();
this.triggerConfigUpdate();
console.log('🔄 配置已重置为默认值');
}
}
}
// --- 菜单管理 ---
class MenuManager {
constructor(fontManager) {
this.fontManager = fontManager;
this.commands = new Map();
// 监听配置更新
this.fontManager.onConfigUpdate(() => this.updateMenu());
}
// 注册所有菜单命令
registerAll() {
this.registerToggleCommand();
this.registerFontConfigCommand();
this.registerExclusionsConfigCommand();
this.registerResetCommand();
}
// 注册切换命令
registerToggleCommand() {
const label = this.fontManager.config.enabled
? '❌ 禁用字体效果'
: '✅ 启用字体效果';
const id = GM_registerMenuCommand(label, () => {
this.fontManager.toggleEnabled();
});
this.commands.set('toggle', id);
}
// 注册字体配置命令
registerFontConfigCommand() {
const id = GM_registerMenuCommand('🖋️ 配置字体名称', () => {
const currentFont = this.fontManager.config.font;
const newFont = prompt(
'请输入新的字体名称 (用逗号分隔,例如: "MiSans", system-ui, sans-serif)',
currentFont
);
if (newFont?.trim()) {
this.fontManager.updateConfig({ font: newFont.trim() });
alert('字体名称已保存并立即生效!');
}
});
this.commands.set('font', id);
}
// 注册排除列表配置命令
registerExclusionsConfigCommand() {
const id = GM_registerMenuCommand('🚫 配置排除元素列表', () => {
const currentExclusions = this.fontManager.config.exclusions;
const newExclusions = prompt(
'请输入新的排除元素选择器 (用逗号分隔,用于保护图标字体等,例如: i, [class*="ico"])',
currentExclusions
);
if (newExclusions !== null) {
this.fontManager.updateConfig({ exclusions: newExclusions.trim() });
alert('排除列表已保存并立即生效!');
}
});
this.commands.set('exclusions', id);
}
// 注册重置命令
registerResetCommand() {
const id = GM_registerMenuCommand('🗑️ 恢复默认设置', () => {
this.fontManager.resetToDefault();
});
this.commands.set('reset', id);
}
// 更新所有菜单
updateMenu() {
// 重新注册所有菜单以更新标签
this.commands.forEach(id => {
try {
GM_unregisterMenuCommand(id);
} catch (e) {
// 忽略未注册的命令
}
});
this.commands.clear();
this.registerAll();
}
}
// --- 主执行流程 ---
const fontManager = new FontManager();
const menuManager = new MenuManager(fontManager);
// 初始化
fontManager.loadConfig();
menuManager.registerAll();
// 根据启用状态决定是否应用字体
if (fontManager.config.enabled) {
// 延迟执行以确保 DOM 已加载
const applyFont = () => fontManager.applyFont();
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', applyFont);
} else {
applyFont();
}
}
// 暴露到全局便于调试
window.GlobalFontManager = fontManager;
console.log('🎨 全局字体脚本已加载');
})();