您需要先安装一个扩展,例如 篡改猴、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.6 // @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/* // @grant GM_addStyle // @run-at document-start // @license MIT // ==/UserScript== (function () { 'use strict'; // --- Style Injection --- GM_addStyle(` @font-face { font-family: 'VazirmatnCustom'; src: local('Vazirmatn'); unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF; } html, body, p, span, div, h1, h2, h3, h4, h5, h6, a, li, ul, ol, td, th, input, textarea { font-family: 'VazirmatnCustom', 'Noto Sans', 'Noto Color Emoji', sans-serif !important; } `); // --- Efficient Character Replacement --- const characterReplacements = { '\u064A': '\u06CC', // Arabic Yeh -> Persian Yeh '\u0643': '\u06A9' // Arabic Kaf -> Persian Kaf }; const persianRegex = /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/; const fixText = (text) => text.replace(/[\u064A\u0643]/g, char => characterReplacements[char]); // --- High-Performance DOM Traversal --- const fixPersianCharsInNode = (rootNode) => { const treeWalker = document.createTreeWalker(rootNode, NodeFilter.SHOW_TEXT); let currentNode; while ((currentNode = treeWalker.nextNode())) { const parentTag = currentNode.parentElement?.tagName; if (parentTag === 'SCRIPT' || parentTag === 'STYLE') continue; const originalValue = currentNode.nodeValue; if (!persianRegex.test(originalValue)) continue; // Skip non-Persian text const fixedValue = fixText(originalValue); if (originalValue !== fixedValue) { currentNode.nodeValue = fixedValue; } } }; // --- Input and Textarea Handling --- const processInputElement = (el) => { if (el.dataset.__persianFixAttached) return; el.dataset.__persianFixAttached = "true"; if (el.value && persianRegex.test(el.value)) { el.value = fixText(el.value); } el.addEventListener('input', () => { const originalValue = el.value; if (!persianRegex.test(originalValue)) return; const fixedValue = fixText(originalValue); if (originalValue !== fixedValue) { const start = el.selectionStart; const end = el.selectionEnd; el.value = fixedValue; el.setSelectionRange(start, end); } }); }; const processAllInputs = (root = document) => { const elements = root.querySelectorAll('input[type="text"], textarea'); for (const el of elements) { processInputElement(el); } }; // --- Throttled Mutation Observer for Dynamic Content --- let observerScheduled = false; const pendingMutations = []; const observer = new MutationObserver((mutations) => { pendingMutations.push(...mutations); if (!observerScheduled) { observerScheduled = true; setTimeout(() => { for (const mutation of pendingMutations.splice(0)) { for (const node of mutation.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { fixPersianCharsInNode(node); processAllInputs(node); } } } observerScheduled = false; }, 100); // Throttle to every 100 ms } }); // --- Script Initialization --- const start = () => { fixPersianCharsInNode(document.body); processAllInputs(document); observer.observe(document.body, { childList: true, subtree: true }); }; const waitForBody = () => { if (document.body) { start(); } else { requestAnimationFrame(waitForBody); } }; waitForBody(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址