Greasy Fork is available in English.
全局修改字体
当前为
// ==UserScript==
// @name 全局字体
// @author gemini
// @version 1.02
// @match *://*/*
// @run-at document-start
// @grant GM_addStyle
// @description 全局修改字体
// @namespace http://greasyfork.icu/users/22620
// ==/UserScript==
(function() {
'use strict';
// --- 配置项 ---
const MY_NEW_FONT = '"MiSans"';
// 常见的图标字体、特殊符号、特殊元素选择器数组
// 脚本只会对 不匹配 这些选择器 的元素应用新字体
const ICON_EXCLUSION_SELECTORS_ARRAY = [
'i',
'[class*="ico"]',
'[class*="fa"]'
];
// 通过 `:not()` 组合,生成最终的排除选择器。
// 例如:':not(i):not([class*="icon"])'
const ICON_EXCLUSION_SELECTOR_STRING = ICON_EXCLUSION_SELECTORS_ARRAY
.map(selector => `:not(${selector})`)
.join('');
// --- 内部变量 (不暴露到全局) ---
let phaseOneStyleElement = null;
/**
* 根据字体名称和排除选择器生成完整的 CSS 规则。
* @param {string} fontFamily - 要应用的 font-family 字符串。
* @returns {string} 完整的 CSS 内容。
*/
const generateCSS = (fontFamily) => {
return `
/* 全局选择器,排除图标和特殊符号元素 */
*${ICON_EXCLUSION_SELECTOR_STRING} {
font-family: ${fontFamily} !important;
}
`;
};
/**
* 阶段一:在 document-start 立即注入初始 CSS 以防止闪烁 (FOUC)。
* @param {string} newFontFamily - 要使用的主要字体。
*/
const injectPhaseOneCSS = (newFontFamily) => {
const cssContent = generateCSS(newFontFamily);
phaseOneStyleElement = GM_addStyle(cssContent);
console.log(`⏱️ 阶段一:立即注入初始字体: ${newFontFamily}`);
};
/**
* 阶段二:等待所有字体加载完成,识别并保护页面原有字体(特别是图标字体),然后更新 CSS。
* @param {string} newFontFamily - 要使用的主要字体。
*/
const runPhaseTwo = async (newFontFamily) => {
try {
// 等待所有 @font-face 规则加载完成
await document.fonts.ready;
const protectedFontNames = new Set();
// 遍历所有已加载的 FontFace,收集其 family 名称
document.fonts.forEach(fontFace => {
protectedFontNames.add(`"${fontFace.family}"`);
});
// 将 Set 转换为数组并用逗号连接,形成字体栈
const protectedFontFamily = Array.from(protectedFontNames).join(', ');
let finalFontFamily;
if (protectedFontFamily) {
finalFontFamily = `${newFontFamily}, ${protectedFontFamily}`;
} else {
// 如果没有识别到其他字体
finalFontFamily = `${newFontFamily}`;
}
const cssContentFinal = generateCSS(finalFontFamily);
// 更新阶段一注入的 <style> 元素的内容,实现平滑过渡
if (phaseOneStyleElement && typeof phaseOneStyleElement.textContent !== 'undefined') {
phaseOneStyleElement.textContent = cssContentFinal;
console.log("✅ 阶段二:全局字体已最终更新并保护原有字体:", finalFontFamily);
} else {
// 备用:如果 GM_addStyle 返回的对象无法直接修改 textContent,则再次注入
GM_addStyle(cssContentFinal);
console.log("✅ 阶段二:全局字体已最终更新并保护原有字体 (通过再次注入):", finalFontFamily);
}
} catch (error) {
console.error("⚠️ 字体加载或识别过程中出错,将保持初始字体设置:", error);
}
};
// --- 脚本主执行流程 ---
injectPhaseOneCSS(MY_NEW_FONT);
runPhaseTwo(MY_NEW_FONT);
})();