diff --git a/tampermonkey/LLMs-RTL.user.js b/tampermonkey/LLMs-RTL.user.js new file mode 100644 index 0000000..1874669 --- /dev/null +++ b/tampermonkey/LLMs-RTL.user.js @@ -0,0 +1,94 @@ +// ==UserScript== +// @name ChatGPT RTL +// @namespace http://chat.openai.com +// @namespace http://deepseek.com +// @author Alireza Farzaneh +// @version 0.1.2.1 +// @description Fixes the direction of RTL languages in LLM's interface +// @match https://chat.openai.com/* +// @match https://chatgpt.com/* +// @match https://chat.deepseek.com/* +// @match https://claude.ai/* +// @match https://chat.qwen.ai/* +// @match https://www.perplexity.ai/search/* +// @match https://cinny.5hezari.ir/* +// @match https://cinny.khce.ir/* +// @match moz-extension://6dce14b2-eef1-481c-8248-93364cca89d7/options.html +// @grant none +// ==/UserScript== + +// Mirror of https://github.com/HUSSEIN-Syu/LLMs-RTL/raw/refs/heads/main/LLMs-RTL.user.js + +(function() { + "use strict"; + const RTL_REGEX = + /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/; + + const styleId = "deepseek-rtl-fix-style"; + if (!document.getElementById(styleId)) { + const style = document.createElement("style"); + style.id = styleId; + style.textContent = ` + .deepseek-rtl-applied, .deepseek-rtl-applied * { + direction: rtl !important; + text-align: right !important; + } + `; + document.head.appendChild(style); + } + + function applyRTLToNode(node) { + if (!node) return; + let elem = null; + if (node.nodeType === Node.TEXT_NODE) { + elem = node.parentElement; + } else if (node.nodeType === Node.ELEMENT_NODE) { + elem = node; + } + if (!elem) return; + + if (elem.closest(".deepseek-rtl-applied")) return; + + const txt = elem.textContent || ""; + if (RTL_REGEX.test(txt)) { + elem.classList.add("deepseek-rtl-applied"); + } + } + + function initialScan(root) { + if (!root) root = document.body; + const walker = document.createTreeWalker( + root, + NodeFilter.SHOW_TEXT, + null, + false, + ); + let cur; + while ((cur = walker.nextNode())) { + applyRTLToNode(cur); + } + } + + initialScan(document.body); + + const observer = new MutationObserver((mutations) => { + for (const mut of mutations) { + if (mut.type === "childList") { + for (const nd of mut.addedNodes) { + applyRTLToNode(nd); + if (nd.nodeType === Node.ELEMENT_NODE) { + initialScan(nd); + } + } + } else if (mut.type === "characterData") { + applyRTLToNode(mut.target); + } + } + }); + + observer.observe(document.body, { + childList: true, + subtree: true, + characterData: true, + }); +})(); diff --git a/tampermonkey/sable-rtl.js b/tampermonkey/Sable-RTL.user.js similarity index 100% rename from tampermonkey/sable-rtl.js rename to tampermonkey/Sable-RTL.user.js