diff options
-rw-r--r-- | background.js | 112 | ||||
-rw-r--r-- | popup/popup.js | 134 |
2 files changed, 204 insertions, 42 deletions
diff --git a/background.js b/background.js index 9b4ba51..45a9346 100644 --- a/background.js +++ b/background.js @@ -5,6 +5,11 @@ let logging = true; // Enable logging for debugging const cssCache = new Map(); const activeTabs = new Map(); +// Helper function to normalize hostnames by removing www. prefix +function normalizeHostname(hostname) { + return hostname.startsWith("www.") ? hostname.substring(4) : hostname; +} + // Preload styles for faster injection async function preloadStyles() { try { @@ -44,7 +49,9 @@ browser.webNavigation.onBeforeNavigate.addListener((details) => { activeTabs.set(details.tabId, details.url); // Pre-fetch any styling needed for this URL - prepareStylesForUrl(new URL(details.url).hostname, details.tabId); + const url = new URL(details.url); + const normalizedHostname = normalizeHostname(url.hostname); + prepareStylesForUrl(normalizedHostname, details.tabId); } }); @@ -53,7 +60,7 @@ browser.runtime.onMessage.addListener(async (message, sender) => { if (message.action === "contentScriptReady" && message.hostname) { try { // Look for cached styles for this hostname or its domain match - const hostname = message.hostname; + const normalizedHostname = normalizeHostname(message.hostname); // Get settings to check if styling is enabled const settingsData = await browser.storage.local.get( @@ -63,7 +70,7 @@ browser.runtime.onMessage.addListener(async (message, sender) => { if (settings.enableStyling === false) return; - const css = await getStylesForHostname(hostname, settings); + const css = await getStylesForHostname(normalizedHostname, settings); // If we found matching CSS, send it immediately to the content script if (css) { @@ -102,8 +109,9 @@ async function getStylesForHostname(hostname, settings) { console.log("DEBUG: Found www prefix match in cache"); return cssCache.get(`www.${hostname}`); } else { - // Check for wildcard matches (+domain.com) + // Check for wildcard matches (+domain.com) and suffix matches (-domain.com) for (const [cachedSite, cachedCSS] of cssCache.entries()) { + // Handle wildcard domain prefix matches (+example.com) if (cachedSite.startsWith("+")) { const baseSite = cachedSite.slice(1); // Ensure we're matching with proper domain boundary (dot or exact match) @@ -113,10 +121,37 @@ async function getStylesForHostname(hostname, settings) { ); return cachedCSS; } - } else if ( + } + // Handle TLD suffix matches (-domain.com) + else if (cachedSite.startsWith("-")) { + const baseSite = cachedSite.slice(1); + + // Extract domain name without the TLD + // For cached site: Use everything before the last dot(s) + const cachedDomain = baseSite.split(".").slice(0, -1).join("."); + + // For hostname: Similarly extract the domain without the TLD + const hostParts = hostname.split("."); + const hostDomain = + hostParts.length > 1 ? hostParts.slice(0, -1).join(".") : hostname; + + console.log( + `DEBUG: Comparing domains - cached: ${cachedDomain}, host: ${hostDomain}` + ); + + if (cachedDomain && hostDomain && hostDomain === cachedDomain) { + console.log( + `DEBUG: Found TLD suffix match: ${cachedSite} for ${hostname}` + ); + return cachedCSS; + } + } + // Regular subdomain handling (exact match already checked above) + else if ( cachedSite !== hostname && cachedSite !== `www.${hostname}` && - hostname.endsWith(`.${cachedSite}`) + hostname.endsWith(`.${cachedSite}`) && + !cachedSite.startsWith("-") ) { // Only match subdomains, not partial domain names console.log( @@ -182,8 +217,15 @@ async function applyCSSToTab(tab) { try { const url = new URL(tab.url); - const hostname = url.hostname; - console.log("DEBUG: Processing hostname:", hostname); + const originalHostname = url.hostname; + const hostname = normalizeHostname(originalHostname); + console.log( + "DEBUG: Processing hostname:", + hostname, + "(original:", + originalHostname, + ")" + ); const settings = await browser.storage.local.get("transparentZenSettings"); const globalSettings = settings.transparentZenSettings || {}; @@ -218,8 +260,11 @@ async function applyCSSToTab(tab) { for (const key of Object.keys(data.styles?.website || {})) { const siteName = key.replace(".css", ""); - // Exact match has highest priority - if (hostname === siteName || hostname === `www.${siteName}`) { + // For site names in the styles list, also normalize by removing www. if present + const normalizedSiteName = normalizeHostname(siteName); + + // Exact match has highest priority - compare normalized hostnames + if (hostname === normalizedSiteName) { bestMatch = key; matchType = "exact"; console.log("DEBUG: Found exact match:", key); @@ -245,21 +290,56 @@ async function applyCSSToTab(tab) { ); } } + // Check TLD suffix matches (-domain.com) - fixed implementation + else if (siteName.startsWith("-")) { + const baseSite = siteName.slice(1); + + // Extract domain name without the TLD + // For cached site: Use everything before the last dot(s) + const cachedDomain = baseSite.split(".").slice(0, -1).join("."); + + // For hostname: Similarly extract the domain without the TLD + const hostParts = hostname.split("."); + const hostDomain = + hostParts.length > 1 ? hostParts.slice(0, -1).join(".") : hostname; + + console.log( + `DEBUG: Comparing domains - cached: ${cachedDomain}, host: ${hostDomain}` + ); + + // Match if the domain part (without TLD) matches + if (cachedDomain && hostDomain && hostDomain === cachedDomain) { + // Only update if it's a better match (longer domain name part) + if (cachedDomain.length > bestMatchLength) { + bestMatch = key; + bestMatchLength = cachedDomain.length; + matchType = "suffix"; + console.log( + "DEBUG: Found TLD suffix match:", + key, + "for", + hostname, + "with domain part:", + cachedDomain + ); + } + } + } // Last, check subdomain matches with proper domain boundary else if ( - hostname !== siteName && - hostname !== `www.${siteName}` && - hostname.endsWith(`.${siteName}`) && - siteName.length > bestMatchLength + hostname !== normalizedSiteName && + hostname.endsWith(`.${normalizedSiteName}`) && + !siteName.startsWith("-") && + normalizedSiteName.length > bestMatchLength ) { bestMatch = key; - bestMatchLength = siteName.length; + bestMatchLength = normalizedSiteName.length; matchType = "subdomain"; console.log( "DEBUG: Found domain suffix match:", key, "with length", - siteName.length + normalizedSiteName.length ); } } diff --git a/popup/popup.js b/popup/popup.js index 64036a9..e1c4566 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -1,6 +1,11 @@ let logging = false; let SKIP_FORCE_THEMING_KEY = "skipForceThemingList"; +// Helper function to normalize hostnames by removing www. prefix +function normalizeHostname(hostname) { + return hostname.startsWith("www.") ? hostname.substring(4) : hostname; +} + new (class ExtensionPopup { BROWSER_STORAGE_KEY = "transparentZenSettings"; globalSettings = {}; @@ -10,6 +15,7 @@ new (class ExtensionPopup { websitesList = document.getElementById("websites-list"); currentSiteFeatures = document.getElementById("current-site-toggles"); currentSiteHostname = ""; + normalizedCurrentSiteHostname = ""; autoUpdateSwitch = document.getElementById("auto-update"); lastFetchedTime = document.getElementById("last-fetched-time"); forceStylingSwitch = document.getElementById("force-styling"); @@ -86,7 +92,17 @@ new (class ExtensionPopup { if (tabs.length > 0) { const url = new URL(tabs[0].url); this.currentSiteHostname = url.hostname; - console.info("Current site hostname:", this.currentSiteHostname); + // Store normalized hostname + this.normalizedCurrentSiteHostname = normalizeHostname( + this.currentSiteHostname + ); + console.info( + "Current site hostname:", + this.currentSiteHostname, + "(normalized:", + this.normalizedCurrentSiteHostname, + ")" + ); } } catch (error) { console.error("Error getting current tab info:", error); @@ -152,9 +168,16 @@ new (class ExtensionPopup { // Load site-specific settings if on a specific site if (this.currentSiteHostname) { - const siteKey = `${this.BROWSER_STORAGE_KEY}.${this.currentSiteHostname}`; - const siteData = await browser.storage.local.get(siteKey); - this.siteSettings = siteData[siteKey] || {}; + const normalizedSiteKey = `${this.BROWSER_STORAGE_KEY}.${this.normalizedCurrentSiteHostname}`; + const originalSiteKey = `${this.BROWSER_STORAGE_KEY}.${this.currentSiteHostname}`; + + const normalizedData = await browser.storage.local.get(normalizedSiteKey); + const originalData = await browser.storage.local.get(originalSiteKey); + + this.siteSettings = + normalizedData[normalizedSiteKey] || + originalData[originalSiteKey] || + {}; await this.loadCurrentSiteFeatures(); } } @@ -402,21 +425,50 @@ new (class ExtensionPopup { isCurrentSite(siteName) { if (logging) console.log("isCurrentSite called with", siteName); - if (!this.currentSiteHostname) return false; + if (!this.normalizedCurrentSiteHostname) return false; + + // Normalize the site name too + const normalizedSiteName = normalizeHostname(siteName); // Exact match has priority - if (this.currentSiteHostname === siteName) return true; - if (this.currentSiteHostname === `www.${siteName}`) return true; + if (this.normalizedCurrentSiteHostname === normalizedSiteName) return true; - // Wildcard match (with proper domain boundary) + // TLD prefix match (match subdomain regardless of TLD) if (siteName.startsWith("+")) { const baseSiteName = siteName.slice(1); + const normalizedBaseSiteName = normalizeHostname(baseSiteName); return ( - this.currentSiteHostname === baseSiteName || - this.currentSiteHostname.endsWith(`.${baseSiteName}`) + this.normalizedCurrentSiteHostname === normalizedBaseSiteName || + this.normalizedCurrentSiteHostname.endsWith( + `.${normalizedBaseSiteName}` + ) ); } + // TLD suffix match (match domain regardless of TLD) + if (siteName.startsWith("-")) { + const baseSiteName = siteName.slice(1); + + // Extract domain name without the TLD + // For site name: Use everything before the last dot(s) + const cachedDomain = baseSiteName.split(".").slice(0, -1).join("."); + + // For current hostname: Similarly extract the domain without the TLD + const hostParts = this.currentSiteHostname.split("."); + const hostDomain = + hostParts.length > 1 + ? hostParts.slice(0, -1).join(".") + : this.currentSiteHostname; + + if (logging) + console.log( + `isCurrentSite comparing domains - cached: ${cachedDomain}, host: ${hostDomain}` + ); + + // Match if the domain part (without TLD) matches + return cachedDomain && hostDomain && hostDomain === cachedDomain; + } + // Don't match partial domain names return false; } @@ -472,6 +524,7 @@ new (class ExtensionPopup { if (logging) console.log("applyCSSToTab called with", tab); const url = new URL(tab.url); const hostname = url.hostname; + const normalizedHostname = normalizeHostname(hostname); try { // Try to remove any existing CSS first @@ -494,9 +547,10 @@ new (class ExtensionPopup { for (const site of Object.keys(styles)) { const siteName = site.replace(/\.css$/, ""); + const normalizedSiteName = normalizeHostname(siteName); // Exact match has highest priority - if (hostname === siteName || hostname === `www.${siteName}`) { + if (normalizedHostname === normalizedSiteName) { bestMatch = site; if (logging) console.log("Popup: Found exact match:", site); break; @@ -505,26 +559,54 @@ new (class ExtensionPopup { // Then check wildcard matches if (siteName.startsWith("+")) { const baseSiteName = siteName.slice(1); + const normalizedBaseSiteName = normalizeHostname(baseSiteName); // Ensure we're matching with proper domain boundary if ( - (hostname === baseSiteName || - hostname.endsWith(`.${baseSiteName}`)) && - baseSiteName.length > bestMatchLength + (normalizedHostname === normalizedBaseSiteName || + normalizedHostname.endsWith(`.${normalizedBaseSiteName}`)) && + normalizedBaseSiteName.length > bestMatchLength ) { bestMatch = site; - bestMatchLength = baseSiteName.length; + bestMatchLength = normalizedBaseSiteName.length; if (logging) console.log("Popup: Found wildcard match:", site); } } + // Check TLD suffix matches (-domain.com) + else if (siteName.startsWith("-")) { + const baseSiteName = siteName.slice(1); + + // Extract domain name without the TLD + // For site name: Use everything before the last dot(s) + const cachedDomain = baseSiteName.split(".").slice(0, -1).join("."); + + // For hostname: Similarly extract the domain without the TLD + const hostParts = hostname.split("."); + const hostDomain = + hostParts.length > 1 ? hostParts.slice(0, -1).join(".") : hostname; + + if (logging) + console.log( + `Popup comparing domains - cached: ${cachedDomain}, host: ${hostDomain}` + ); + + // Match if the domain part (without TLD) matches + if (cachedDomain && hostDomain && hostDomain === cachedDomain) { + // Use this match if it's better than what we have + if (cachedDomain.length > bestMatchLength) { + bestMatch = site; + bestMatchLength = cachedDomain.length; + if (logging) console.log("Popup: Found TLD suffix match:", site); + } + } + } // Last, check subdomain matches with proper domain boundary else if ( - hostname !== siteName && - hostname !== `www.${siteName}` && - hostname.endsWith(`.${siteName}`) && - siteName.length > bestMatchLength + normalizedHostname !== normalizedSiteName && + normalizedHostname.endsWith(`.${normalizedSiteName}`) && + normalizedSiteName.length > bestMatchLength ) { bestMatch = site; - bestMatchLength = siteName.length; + bestMatchLength = normalizedSiteName.length; if (logging) console.log("Popup: Found subdomain match:", site); } } @@ -532,9 +614,11 @@ new (class ExtensionPopup { // If we found a direct match, use it if (bestMatch) { const features = styles[bestMatch]; - const siteStorageKey = `${this.BROWSER_STORAGE_KEY}.${hostname}`; - const siteData = await browser.storage.local.get(siteStorageKey); - const featureSettings = siteData[siteStorageKey] || {}; + const normalizedSiteStorageKey = `${this.BROWSER_STORAGE_KEY}.${normalizedHostname}`; + const siteData = await browser.storage.local.get( + normalizedSiteStorageKey + ); + const featureSettings = siteData[normalizedSiteStorageKey] || {}; let combinedCSS = ""; for (const [feature, css] of Object.entries(features)) { @@ -591,9 +675,7 @@ new (class ExtensionPopup { if (logging) console.log("displayAddonVersion called"); const manifest = browser.runtime.getManifest(); const version = manifest.version; - document.getElementById( - "addon-version" - ).textContent = `v${version}`; + document.getElementById("addon-version").textContent = `v${version}`; } setupAutoUpdate() { |