您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Colors <em> text yellow and text within parentheses blue in Discord messages, handling split spans
// ==UserScript== // @name Discord Message Colorizer Enhanced // @namespace http://tampermonkey.net/ // @version 1.2 // @description Colors <em> text yellow and text within parentheses blue in Discord messages, handling split spans // @author Vishanka // @match https://discord.com/channels/* // @grant none // ==/UserScript== (function() { // 1. Inject CSS classes for styling function injectStyles() { const style = document.createElement('style'); style.textContent = ` /* Baseline color for all message content */ div[class*="messageContent_"] { color: #A2A2AC; } /* Highlight colors for specific patterns */ .highlight-yellow { color: #E0DF7F !important; } .highlight-blue { color: #737373 !important; } .highlight-white { color: #FFFFFF !important; } `; document.head.appendChild(style); } // 2. Function to style message content function styleMessageContent() { // Select all message items based on the class prefix const messageItems = document.querySelectorAll('li[class^="messageListItem_"]'); messageItems.forEach(messageItem => { const contentDiv = messageItem.querySelector('div[class*="messageContent_"]'); if (!contentDiv) return; // Skip if no content div found // a. Color all <em> elements yellow const emElements = contentDiv.querySelectorAll('em'); emElements.forEach(em => { if (!em.classList.contains('highlight-yellow')) { // Prevent reapplying em.classList.add('highlight-yellow'); } }); // b. Color text within parentheses blue colorTextWithinDelimiters(contentDiv, '(', ')', 'highlight-blue', false); // c. Color text within quotation marks white (#FFFFFF) // Supports straight quotes and smart quotes colorTextWithinQuotes(contentDiv, ['"', '“', '‘'], ['"', '”', '’'], 'highlight-white'); }); } /** * Helper function to color text within matched quotation marks. * @param {HTMLElement} container - The container element to search within. * @param {string[]} openDelimiters - The opening quotation marks. * @param {string[]} closeDelimiters - The closing quotation marks. * @param {string} highlightClass - The CSS class to apply for highlighting. */ function colorTextWithinQuotes(container, openDelimiters, closeDelimiters, highlightClass) { const spans = Array.from(container.querySelectorAll('span')); let buffer = []; // Collect spans inside the current quote spans.forEach(span => { const text = span.textContent; // Process span content character by character for (let i = 0; i < text.length; i++) { const char = text[i]; if (openDelimiters.includes(char) && buffer.length === 0) { // Start a new quote buffer.push(span); } else if (closeDelimiters.includes(char) && buffer.length > 0) { // End the current quote buffer.forEach(s => s.classList.add(highlightClass)); buffer = []; // Clear buffer } else if (buffer.length > 0) { // Inside a quote buffer.push(span); } } }); } /** * Helper function to color text within specified delimiters. * For non-quotation mark delimiters like parentheses. * @param {HTMLElement} container - The container element to search within. * @param {string|string[]} openDelimiter - The opening delimiter character(s). * @param {string|string[]} closeDelimiter - The closing delimiter character(s). * @param {string} highlightClass - The CSS class to apply for highlighting. * @param {boolean} isToggle - Whether to toggle highlighting (true for quotes). */ function colorTextWithinDelimiters(container, openDelimiter, closeDelimiter, highlightClass, isToggle) { const spans = container.querySelectorAll('span'); let isWithin = false; // Normalize delimiters to arrays const openDelims = Array.isArray(openDelimiter) ? openDelimiter : [openDelimiter]; const closeDelims = Array.isArray(closeDelimiter) ? closeDelimiter : [closeDelimiter]; spans.forEach(span => { const text = span.textContent; if (isToggle) { let hasOpening = false; let hasClosing = false; // Check for any closing delimiters first closeDelims.forEach(close => { if (text.includes(close)) { hasClosing = true; } }); if (hasClosing && isWithin) { // Apply highlight before closing span.classList.add(highlightClass); isWithin = false; } // Apply highlight if currently within delimiters if (isWithin) { span.classList.add(highlightClass); } // Check for any opening delimiters openDelims.forEach(open => { if (text.includes(open)) { hasOpening = true; isWithin = true; } }); if (hasOpening) { // Apply highlight for the span containing the opening delimiter span.classList.add(highlightClass); } } else { // Non-toggle: e.g., parentheses if (text.includes(openDelimiter)) { isWithin = true; } if (isWithin) { span.classList.add(highlightClass); } if (text.includes(closeDelimiter)) { isWithin = false; } } }); } // 3. Initialize the styling process function initializeStyling() { injectStyles(); styleMessageContent(); // Observe for new messages being added to the DOM const observer = new MutationObserver(mutations => { mutations.forEach(() => { styleMessageContent(); }); }); // Start observing the entire document body for changes observer.observe(document.body, { childList: true, subtree: true }); } // 4. Run the initialization initializeStyling(); })();