Автоматическая заглавная буква на лолзе

Делает первую букву заглавной в реальном времени. Ну и после знаков препинания тоже

目前為 2025-08-07 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Автоматическая заглавная буква на лолзе
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Делает первую букву заглавной в реальном времени. Ну и после знаков препинания тоже
// @author       eretly
// @match        https://lolz.live/*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const settings = {
        active: true
    };

    function getTextBeforeCaret(element) {
        const selection = window.getSelection();
        if (!selection.rangeCount) return '';
        const range = selection.getRangeAt(0);
        const preCaretRange = range.cloneRange();
        preCaretRange.selectNodeContents(element);
        preCaretRange.setEnd(range.startContainer, range.startOffset);
        return preCaretRange.toString();
    }

    function shouldCapitalize(textBefore) {
        if (!textBefore) return true;
        if (/^\s*@[a-zA-Z0-9_.-]+[,\s]\s*$/.test(textBefore)) return true;
        if (/[.!?]\s+$/.test(textBefore)) return true;
        if (/^\s*$/.test(textBefore)) return true;
        return false;
    }

    function insertCapitalizedChar(char) {
        const selection = window.getSelection();
        if (!selection.rangeCount) return false;
        const range = selection.getRangeAt(0);
        const upperChar = char.toUpperCase();
        range.deleteContents();
        const textNode = document.createTextNode(upperChar);
        range.insertNode(textNode);
        range.setStartAfter(textNode);
        range.collapse(true);
        selection.removeAllRanges();
        selection.addRange(range);
        return true;
    }

    function handleContentEditableInput(event) {
        if (!settings.active) return;
        const element = event.target;
        if (!element.isContentEditable) return;
        if (event.inputType === 'insertText' && event.data) {
            const char = event.data;
            if (!/[a-zA-Zа-яёА-ЯЁ]/.test(char)) return;
            const textBefore = getTextBeforeCaret(element);
            if (shouldCapitalize(textBefore)) {
                event.preventDefault();
                insertCapitalizedChar(char);
            }
        }
    }

    function handleTextAreaInput(event) {
        if (!settings.active) return;
        const element = event.target;

        if (!(element.tagName === 'TEXTAREA' ||
              (element.tagName === 'INPUT' && (element.type === 'text' || element.type === 'search')))) return;

        const value = element.value;
        const selectionStart = element.selectionStart;
        const selectionEnd = element.selectionEnd;

        if (selectionStart === selectionEnd && selectionStart > 0) {
            const lastChar = value[selectionStart - 1];
            if (/[a-zA-Zа-яёА-ЯЁ]/.test(lastChar)) {
                const textBefore = value.substring(0, selectionStart - 1);
                if (shouldCapitalize(textBefore)) {
                    const newValue = value.substring(0, selectionStart - 1) + lastChar.toUpperCase() + value.substring(selectionStart);
                    element.value = newValue;
                    element.setSelectionRange(selectionStart, selectionStart);
                }
            }
        }
    }


    function observeContentEditableMutations() {
        const observer = new MutationObserver(mutations => {
            for (const mutation of mutations) {
                if (mutation.type === 'childList' || mutation.type === 'characterData') {
                    const target = mutation.target;
                    const container = target.closest?.('[contenteditable="true"]') || target.parentNode;
                    if (!container) continue;
                    const text = container.innerText || container.textContent;
                    const lastChar = text.trim().slice(-1);
                    if (/[a-zа-яё]/.test(lastChar)) {
                        const before = text.trim().slice(0, -1);
                        if (shouldCapitalize(before)) {
                            const capitalized = before + lastChar.toUpperCase();
                            container.innerText = capitalized;
                            placeCursorAtEnd(container);
                        }
                    }
                }
            }
        });

        const targets = document.querySelectorAll('[contenteditable="true"]');
        targets.forEach(el => observer.observe(el, {
            characterData: true,
            childList: true,
            subtree: true
        }));
    }

    function placeCursorAtEnd(el) {
        const range = document.createRange();
        const sel = window.getSelection();
        range.selectNodeContents(el);
        range.collapse(false);
        sel.removeAllRanges();
        sel.addRange(range);
    }

    function initialize() {
        document.addEventListener('beforeinput', handleContentEditableInput, true);
        document.addEventListener('input', handleTextAreaInput, false);
        observeContentEditableMutations();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initialize);
    } else {
        initialize();
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址