Делает первую букву заглавной в реальном времени. Ну и после знаков препинания тоже
当前为
// ==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或关注我们的公众号极客氢云获取最新地址