您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Apply Vazir font to Persian/RTL content across selected websites
当前为
// ==UserScript== // @name Persian Font Fix (Vazir) // @namespace https://gf.qytechs.cn/en/scripts/538095-persian-font-fix-vazir // @version 1.8 // @description Apply Vazir font to Persian/RTL content across selected websites // @author TheSina // @match *://*.telegram.org/* // @match *://*.x.com/* // @match *://*.twitter.com/* // @match *://*.instagram.com/* // @match *://*.facebook.com/* // @match *://*.whatsapp.com/* // @match *://*.github.com/* // @match *://*.youtube.com/* // @match *://*.soundcloud.com/* // @match *://www.google.com/* // @match *://gemini.google.com/* // @match *://translate.google.com/* // @match *://*.chatgpt.com/* // @match *://*.openai.com/* // @match *://fa.wikipedia.org/* // @match *://app.slack.com/* // @match *://*.goodreads.com/* // @match *://*.reddit.com/* // @grant GM_addStyle // @run-at document-start // @license MIT // ==/UserScript== (function () { 'use strict'; // --- Font Injection (Broad Compatibility) --- GM_addStyle(` @font-face { font-family: 'VazirmatnFixed'; src: local('Vazirmatn'), local('Noto Sans'); font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; } body, span, div, p, a, li, td, th, input, textarea, button, [class*="text"], [class*="font"], [class*="label"] { font-family: 'VazirmatnFixed', 'Noto Sans', sans-serif !important; } `); const persianRegex = /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/; const replacementRegex = /[\u064A\u0643]/g; const replacements = { '\u064A': '\u06CC', '\u0643': '\u06A9' }; const fixText = text => persianRegex.test(text) ? text.replace(replacementRegex, c => replacements[c] || c) : text; const fixPersianCharsInNode = root => { if (!persianRegex.test(root.textContent)) return; const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false); let node; while ((node = walker.nextNode())) { if (!node.parentElement || ['SCRIPT', 'STYLE'].includes(node.parentElement.tagName)) continue; const original = node.nodeValue; const fixed = fixText(original); if (original !== fixed) node.nodeValue = fixed; } }; const processInputElement = el => { if (el.dataset.__persianFixAttached) return; el.dataset.__persianFixAttached = "true"; const fixInput = () => { const original = el.value; if (!original || !persianRegex.test(original)) return; const fixed = fixText(original); if (original !== fixed) { const start = el.selectionStart; const end = el.selectionEnd; el.value = fixed; if (start !== null && end !== null) el.setSelectionRange(start, end); } }; if (persianRegex.test(el.value)) fixInput(); el.addEventListener('input', () => requestIdleCallback(fixInput)); }; const processAllInputs = root => { root.querySelectorAll('input[type="text"], input[type="search"], textarea').forEach(processInputElement); }; // --- Observer (with throttle) --- const pending = new Set(); let throttleRunning = false; const runThrottle = () => { if (throttleRunning) return; throttleRunning = true; const applyFix = () => { pending.forEach(node => { fixPersianCharsInNode(node); processAllInputs(node); }); pending.clear(); throttleRunning = false; }; 'requestIdleCallback' in window ? requestIdleCallback(applyFix, { timeout: 300 }) : setTimeout(applyFix, 200); }; const observer = new MutationObserver(mutations => { for (const m of mutations) { m.addedNodes.forEach(node => { if ( (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) && document.body.contains(node) ) { if (node.textContent && persianRegex.test(node.textContent)) { pending.add(node); } } }); } runThrottle(); }); const start = () => { fixPersianCharsInNode(document.body); processAllInputs(document); observer.observe(document.body, { childList: true, subtree: true }); }; if (document.body) { start(); } else { new MutationObserver((_, obs) => { if (document.body) { obs.disconnect(); start(); } }).observe(document.documentElement, { childList: true }); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址