let isDarkMode = false; // Track current mode (light or dark) // Color Palette for Dark Mode const darkModeStyles = { backgroundColor: '#121212', // Dark background for general elements color: '#e0e0e0', // General text color linkColor: '#bb86fc', // Link color for dark mode activeLinkColor: '#ff79c6', // Active link color buttonBackground: '#333333', // Button background color for dark mode buttonTextColor: '#e0e0e0', // Button text color inputBackground: '#333333', // Input background color for dark mode inputTextColor: '#e0e0e0', // Input text color codeBackground: '#1e1e1e', // Code block background color for dark mode borderColor: '#444444', // Border color for inputs, buttons, etc. containerBackground: '#181818', // Even darker shade for containers like .s-topbar siteSpecificHeaderFooterBackground: '#eeeeee', // Light background color for certain headers }; // Function to apply dark mode via JavaScript only (without using CSS) function applyDarkMode() { // Apply the general background and text color to the body document.body.style.backgroundColor = darkModeStyles.backgroundColor; document.body.style.color = darkModeStyles.color; // 1. Loop through all elements to find light background colors and change them const allElements = document.querySelectorAll('*'); allElements.forEach(el => { const computedBackgroundColor = window.getComputedStyle(el).backgroundColor; const computedBackgroundImage = window.getComputedStyle(el).backgroundImage; // Check for light backgrounds (RGB or hex-based light colors) and ignore background images if (isLightBackground(computedBackgroundColor) && computedBackgroundImage === 'none') { el.style.backgroundColor = darkModeStyles.backgroundColor; // Set to dark mode color } else if (computedBackgroundImage && (computedBackgroundImage.includes('linear-gradient') || computedBackgroundImage.includes('radial-gradient'))) { // Handle gradients with pure white or light colors el.style.backgroundImage = adjustLightGradients(computedBackgroundImage); } // Apply text color to all elements except code blocks and pre blocks if (el.tagName !== 'CODE' && el.tagName !== 'PRE') { el.style.color = darkModeStyles.color; } // Handle padding and margin issues by checking padding area background handlePaddingAndMarginBackground(el); }); // 2. Handle site-specific elements such as headers and footers (e.g., Craigslist, MDN, etc.) const siteSpecificElements = document.querySelectorAll('header, footer, .header, .footer'); siteSpecificElements.forEach(el => { const bgColor = window.getComputedStyle(el).backgroundColor; if (bgColor === 'rgb(238, 238, 238)' || bgColor === 'rgba(238, 238, 238, 1)') { el.style.backgroundColor = darkModeStyles.siteSpecificHeaderFooterBackground; } }); // 3. Handle other specific elements like buttons, inputs, code blocks, etc. handleFormElements(); handleCodeBlocks(); handleLinks(); } // Helper function to determine if a background color is light function isLightBackground(rgbColor) { if (!rgbColor) return false; // If there's no color or invalid color, return false const rgb = rgbColor.match(/^rgba?\((\d+), (\d+), (\d+)/); // Match rgb values if (rgb) { const r = parseInt(rgb[1], 10); const g = parseInt(rgb[2], 10); const b = parseInt(rgb[3], 10); // Simple luminance calculation to detect light colors const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b; return luminance > 150; // Threshold for light background } return false; // If it's not an RGB value, assume it's not light } // Function to adjust light colors in a gradient (specifically pure white or light colors) function adjustLightGradients(gradient) { const gradientRegex = /(linear-gradient|radial-gradient)\((.*?)\)/; return gradient.replace(gradientRegex, (match, type, gradientContent) => { // Regex to match rgb or rgba color values in the gradient const lightColorRegex = /rgba?\((\d+), (\d+), (\d+)(?:, (\d*\.?\d+))?\)/g; // Replace each light color (e.g., rgb(255, 255, 255)) with a darker color const adjustedGradient = gradientContent.replace(lightColorRegex, (colorMatch, r, g, b, a) => { // Calculate luminance for detecting light colors const luminance = 0.2126 * parseInt(r, 10) + 0.7152 * parseInt(g, 10) + 0.0722 * parseInt(b, 10); // If the luminance is higher than a threshold (200), it's a light color if (luminance > 200) { // Replace light colors with a dark background color (e.g., #282828 or similar) return `rgb(40, 40, 40)`; // Dark theme color } return colorMatch; // Keep dark colors unchanged }); // Return the updated gradient return `${type}(${adjustedGradient})`; }); } // Function to ensure padding and margin background colors are applied function handlePaddingAndMarginBackground(el) { const padding = window.getComputedStyle(el).padding; const margin = window.getComputedStyle(el).margin; const bgColor = window.getComputedStyle(el).backgroundColor; // Check if the element has padding or margin and is missing a background if ((padding !== '0px' || margin !== '0px') && (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent')) { el.style.backgroundColor = darkModeStyles.backgroundColor; // Ensure padding area has a background color } } // Function to handle links with dark mode styling function handleLinks() { const links = document.querySelectorAll('a'); links.forEach(link => { link.style.color = darkModeStyles.linkColor; if (link.hasAttribute('aria-selected') && link.getAttribute('aria-selected') === 'true') { link.style.color = darkModeStyles.activeLinkColor; // Active state color for links } }); } // Function to handle form elements (buttons, inputs) function handleFormElements() { const buttons = document.querySelectorAll('button'); buttons.forEach(button => { button.style.backgroundColor = darkModeStyles.buttonBackground; button.style.color = darkModeStyles.buttonTextColor; button.style.borderColor = darkModeStyles.borderColor; if (button.hasAttribute('aria-pressed') && button.getAttribute('aria-pressed') === 'true') { button.style.backgroundColor = darkModeStyles.activeLinkColor; // Active state for buttons } }); const inputs = document.querySelectorAll('input, textarea, select'); inputs.forEach(input => { input.style.backgroundColor = darkModeStyles.inputBackground; input.style.color = darkModeStyles.inputTextColor; input.style.borderColor = darkModeStyles.borderColor; }); } // Function to handle code blocks with dark mode styling function handleCodeBlocks() { const codeBlocks = document.querySelectorAll('code, pre'); codeBlocks.forEach(code => { code.style.backgroundColor = darkModeStyles.codeBackground; code.style.color = darkModeStyles.color; // Use the dark text color for code }); } // Function to revert to light mode (optional) function revertLightMode() { // Reset all styles document.body.style.backgroundColor = ''; document.body.style.color = ''; const allElements = document.querySelectorAll('*'); allElements.forEach(el => { el.style.backgroundColor = ''; el.style.backgroundImage = ''; el.style.color = ''; }); } // Listen for the toggle dark mode action chrome.runtime.onMessage.addListener((message) => { if (message.action === 'toggleDarkMode') { if (isDarkMode) { revertLightMode(); } else { applyDarkMode(); } isDarkMode = !isDarkMode; } }); // Apply dark mode on page load if (isDarkMode) { applyDarkMode(); } else { revertLightMode(); }