AI Chat Font & Direction Fixer

Dynamically fixes RTL/LTR direction, justifies Persian text, and allows font switching on AI chatbots.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        AI Chat Font & Direction Fixer
// @name:fa     اصلاح فونت و جهت‌دهی چت‌بات‌ها
// @namespace   https://github.com/gemini-user/ai-chat-styler
// @version     4.1
// @description Dynamically fixes RTL/LTR direction, justifies Persian text, and allows font switching on AI chatbots.
// @description:fa اصلاح پویای جهت نوشتار، ترازبندی متن فارسی و امکان انتخاب فونت در چت‌بات‌های هوش مصنوعی.
// @author      Your Assistant
// @match       https://chatgpt.com/*
// @match       https://gemini.google.com/*
// @match       https://chat.qwen.ai/*
// @match       https://grok.com/*
// @match       https://chat.deepseek.com/*
// @match       https://copilot.chat.github.com/*
// @grant       GM_addStyle
// @grant       GM_registerMenuCommand
// @grant       GM_getValue
// @grant       GM_setValue
// @run-at      document-body
// ==/UserScript==

(function() {
    'use strict';

    // --- بخش اول: تنظیمات فونت و منو ---

    const fonts = {
        vazirmatn: {
            menuName: 'انتخاب فونت: وزیرمتن',
            cssName: "'Vazirmatn'",
            cdnUrl: 'https://cdn.jsdelivr.net/gh/rastikerdar/[email protected]/Vazirmatn-font-face.css'
        },
        vazirCode: {
            menuName: 'انتخاب فونت: وزیر کد',
            cssName: "'Vazir Code'",
            cdnUrl: 'https://cdn.jsdelivr.net/npm/[email protected]/dist/font-face.css'
        },
        iranSans: {
            menuName: 'انتخاب فونت: ایران سنس',
            cssName: "'IRANSans-medium'",
            cdnUrl: 'https://cdn.jsdelivr.net/npm/[email protected]/iransans/font.css'
        }
    };

    const selectedFontKey = GM_getValue('selectedFont', 'vazirmatn');
    const selectedFont = fonts[selectedFontKey];

    Object.keys(fonts).forEach(key => {
        GM_registerMenuCommand(fonts[key].menuName, () => {
            GM_setValue('selectedFont', key);
            window.location.reload();
        });
    });

    // --- بخش دوم: استایل‌های پایه (فونت و کد) ---

    const css = `
        @import url('${fonts.vazirmatn.cdnUrl}');
        @import url('${fonts.vazirCode.cdnUrl}');
        @import url('${fonts.iranSans.cdnUrl}');

        /* اعمال فونت انتخاب شده به تمام بخش‌های متنی */
        body, button, input, textarea, div, p, span, li,
        h1, h2, h3, h4, h5, h6, a, label, strong, td, th {
            font-family: ${selectedFont.cssName}, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
        }

        /* استایل ثابت برای بلوک‌های کد */
        pre, code, kbd, samp, pre *, code * {
            font-family: 'Consolas', 'Menlo', 'monospace' !important;
            direction: ltr !important;
            text-align: left !important;
        }
    `;
    GM_addStyle(css);

    // --- بخش سوم: منطق هوشمند جاوااسکریپت برای اصلاح جهت‌دهی و ترازبندی ---

    const persianRegex = /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF]/;

    function fixDirection(element) {
        // از دستکاری بلوک‌های کد و منوهای قابل ویرایش خودداری کن
        if (!element || element.nodeType !== 1 || element.isContentEditable || element.closest('pre, code, nav, [role="navigation"], [role="menu"]')) {
            return;
        }

        // فقط عناصر متنی اصلی را بررسی کن
        if (element.matches('p, li, h1, h2, h3, h4, h5, h6, blockquote, td, th, div')) {
            // بررسی کن آیا خود عنصر یا فرزندانش متن فارسی دارند
            const hasPersian = persianRegex.test(element.textContent);

            if (hasPersian) {
                element.style.direction = 'rtl';
                element.style.textAlign = 'justify'; // <--- تغییر اصلی: ترازبندی دوطرفه برای متن فارسی
            } else {
                // اگر هیچ متن فارسی در عنصر و فرزندانش نبود، به حالت پیش‌فرض برگردان
                if (!element.querySelector('[style*="direction: rtl"]')) {
                    element.style.direction = 'ltr';
                    element.style.textAlign = 'left';
                }
            }
        }
    }

    // مشاهده‌گر برای شناسایی تغییرات زنده در صفحه (مثل پاسخ‌های جدید چت‌بات)
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node.nodeType === 1) { // اگر یک عنصر HTML بود
                    fixDirection(node); // خود عنصر را بررسی کن
                    node.querySelectorAll('p, li, h1, h2, h3, h4, div').forEach(fixDirection); // فرزندانش را هم بررسی کن
                }
            });
        });
    });

    // مشاهده‌گر را روی کل بدنه صفحه فعال کن
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // یک اسکن اولیه برای محتوایی که از قبل در صفحه وجود دارد
    document.querySelectorAll('p, li, h1, h2, h3, h4, div').forEach(fixDirection);

})();