Transliterate to Inuktitut (with Bug Fixes)

Converts website text into Inuktitut syllabics, avoiding UI issues

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Transliterate to Inuktitut (with Bug Fixes)
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  Converts website text into Inuktitut syllabics, avoiding UI issues
// @author       You
// @match        *://*/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Elements to ignore (search bars, buttons, UI elements)
    const ignoredTags = ["INPUT", "TEXTAREA", "BUTTON", "SELECT", "SCRIPT", "STYLE", "META"];

    // English to Inuktitut syllabics substitutions
    const letterSubstitutions = {
        "ch": "ᑕᔭ", "sh": "ᓴ", "th": "ᓴ", "ng": "ᖕ", "wh": "Ꮩ", "w": "ᐍ",
        "y": "ᔨ", "j": "ᔭ", "k": "ᒃ", "d": "ᑕ", "b": "ᐱ", "c": "ᑐ",
        "f": "ᓴ", "p": "ᑉ", "g": "ᑕ", "q": "ᖯ", "z": "ᓯ"
    };

    // Latin to Inuktitut syllabic mapping (lowercase)
    const translitMapLower = {
        "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": "ᓯ"
    };

    // Latin to Inuktitut syllabic mapping (uppercase)
    const translitMapUpper = {
        "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 adjustEnglishLetters(word) {
        for (const [key, value] of Object.entries(letterSubstitutions)) {
            word = word.replace(new RegExp(key, "gi"), value);
        }
        return word;
    }

    function transliterateText(text) {
        return text.replace(/\b[a-zA-Z]+\b/g, word => {
            word = adjustEnglishLetters(word.toLowerCase()); // Adjust before mapping

            let result = '';
            for (let char of word) {
                // Check for uppercase and apply the corresponding map
                if (char === char.toUpperCase()) {
                    result += translitMapUpper[char] || translitMapLower[char.toLowerCase()] || char;
                } else {
                    result += translitMapLower[char] || char;
                }
            }
            return result;
        });
    }

    function transliterateNode(node) {
        if (node.nodeType === Node.TEXT_NODE && node.parentNode && !ignoredTags.includes(node.parentNode.tagName)) {
            node.nodeValue = transliterateText(node.nodeValue);
        } else if (node.nodeType === Node.ELEMENT_NODE) {
            for (let child of node.childNodes) {
                transliterateNode(child);
            }
        }
    }

    function observeDOMChanges() {
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(node => transliterateNode(node));
                }
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });
    }

    transliterateNode(document.body);
    observeDOMChanges();

})();