content.js

🧩 Syntax:
// Transliteration mapping (Latin to Cyrillic)
const transliterationMap = {
    'ce': 'це',
    'ci': 'ци',
    'cy': 'ци',
    'sh': 'ш',
    'ch': 'ч',
    'ph': 'ф',
    'th': 'ҭ',
    'ya': 'я',
    'yo': 'йо',
    'yu': 'ю',
    'ye': 'йе',
    'ay': 'ай',
    'ey': 'ей',
    'iy': 'ий',
    'oy': 'ой',
    'uy': 'уй',
    'a': 'а',
    'b': 'б',
    'c': 'к',
    'd': 'д',
    'e': 'е',
    'f': 'ф',
    'g': 'г',
    'h': 'х',
    'i': 'и',
    'j': 'ж',
    'k': 'к',
    'l': 'л',
    'm': 'м',
    'n': 'н',
    'o': 'о',
    'p': 'п',
    'q': 'к',
    'r': 'р',
    's': 'с',
    't': 'т',
    'u': 'у',
    'v': 'в',
    'w': 'ў',
    'x': 'кс',
    'y': 'и',
    'z': 'з',
    'Ce': 'Це',
    'Ci': 'Ци',
    'Cy': 'Ци',
    'Sh': 'Ш',
    'Ch': 'Ч',
    'Ph': 'Ф',
    'Th': 'Ҭ',
    'Ya': 'Я',
    'Yo': 'Йо',
    'Yu': 'Ю',
    'Ye': 'Йе',
    'Ay': 'Ай',
    'Ey': 'Ей',
    'Iy': 'Ий',
    'Oy': 'Ой',
    'Uy': 'Уй',
    'A': 'А',
    'B': 'Б',
    'C': 'К',
    'D': 'Д',
    'E': 'Е',
    'F': 'Ф',
    'G': 'Г',
    'H': 'Х',
    'I': 'И',
    'J': 'Ж',
    'K': 'К',
    'L': 'Л',
    'M': 'М',
    'N': 'Н',
    'O': 'О',
    'P': 'П',
    'Q': 'К',
    'R': 'Р',
    'S': 'С',
    'T': 'Т',
    'U': 'У',
    'V': 'В',
    'W': 'Ў',
    'X': 'Кс',
    'Y': 'И',
    'Z': 'З',
};

function transliterateText(text) {
    // Sort keys by length (longest first) to prioritize multi-character matches
    const sortedKeys = Object.keys(transliterationMap).sort((a, b) => b.length - a.length);
    
    // Create a regex that matches any key in the map (case-sensitive)
    const regex = new RegExp(sortedKeys.map(k => k.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')).join('|'), 'g');
    
    // Replace matched Latin sequences with Cyrillic equivalents
    return text.replace(regex, match => transliterationMap[match] || match);
}

// Function to process all text nodes in the DOM
function transliteratePage() {
    const walker = document.createTreeWalker(
        document.body,
        NodeFilter.SHOW_TEXT,
        {
            acceptNode: function (node) {
                // Skip script, style, and input elements
                const parent = node.parentElement;
                if (parent.tagName === 'SCRIPT' || parent.tagName === 'STYLE' || parent.tagName === 'INPUT') {
                    return NodeFilter.FILTER_REJECT;
                }
                return NodeFilter.FILTER_ACCEPT;
            }
        },
        false
    );

    let node;
    while ((node = walker.nextNode())) {
        node.nodeValue = transliterateText(node.nodeValue);
    }
}

// Run transliteration when the page loads
transliteratePage();

// Observe DOM changes for dynamic content
const observer = new MutationObserver(transliteratePage);
observer.observe(document.body, { childList: true, subtree: true });