Automated bi-directional text alignment for smooth Right-to-Left (RTL) languages reading across all websites and AI platforms.
// ==UserScript==
// @name Universal Auto RTL
// @namespace https://greasyfork.org
// @version 3.0.0
// @description Automated bi-directional text alignment for smooth Right-to-Left (RTL) languages reading across all websites and AI platforms.
// @author MetaSA
// @license MIT
// @match *://*/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
const rtlRegex = /[\u0600-\u06FF\u0750-\u077F\u0590-\u05FF\uFB50-\uFDFF\uFE70-\uFEFF]/;
function adjustDirection(node) {
if (!node || node.nodeType !== 1) return;
if (node.closest('pre, code') || ['PRE', 'CODE', 'SCRIPT', 'STYLE', 'NOSCRIPT'].includes(node.tagName)) return;
const text = node.textContent ? node.textContent.trim() : '';
if (!text) return;
const firstChar = text.charAt(0);
if (rtlRegex.test(firstChar)) {
node.style.setProperty('direction', 'rtl', 'important');
node.style.setProperty('text-align', 'right', 'important');
} else if (/[a-zA-Z]/.test(firstChar)) {
node.style.setProperty('direction', 'ltr', 'important');
node.style.setProperty('text-align', 'left', 'important');
}
}
const observer = new MutationObserver((mutations) => {
for (let i = 0; i < mutations.length; i++) {
const mutation = mutations[i];
if (mutation.type === 'childList') {
const addedNodes = mutation.addedNodes;
for (let j = 0; j < addedNodes.length; j++) {
const node = addedNodes[j];
if (node.nodeType === 1) {
if (node.matches('p, span, div, li, h1, h2, h3, h4, h5, h6, textarea, input')) {
adjustDirection(node);
}
const children = node.querySelectorAll('p, span, div, li, h1, h2, h3, h4, h5, h6, textarea, input');
for (let k = 0; k < children.length; k++) {
adjustDirection(children[k]);
}
}
}
} else if (mutation.type === 'characterData') {
adjustDirection(mutation.target.parentElement);
}
}
});
if (document.body) {
init();
} else {
document.addEventListener('DOMContentLoaded', init);
}
function init() {
observer.observe(document.body, {
childList: true,
subtree: true,
characterData: true
});
const initialNodes = document.querySelectorAll('p, span, div, li, h1, h2, h3, h4, h5, h6, textarea, input');
for (let i = 0; i < initialNodes.length; i++) {
adjustDirection(initialNodes[i]);
}
}
})();