summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--background.js61
-rw-r--r--data-viewer/data-viewer.js27
-rw-r--r--inject-css.js220
-rw-r--r--popup/popup.js42
4 files changed, 99 insertions, 251 deletions
diff --git a/background.js b/background.js
index a3f6e43..9b4ba51 100644
--- a/background.js
+++ b/background.js
@@ -92,20 +92,36 @@ browser.runtime.onMessage.addListener(async (message, sender) => {
// Get appropriate styles for a hostname based on all rules
async function getStylesForHostname(hostname, settings) {
- // Check for exact matches
+ console.log("DEBUG: Finding styles for hostname:", hostname);
+
+ // Check for exact matches first (highest priority)
if (cssCache.has(hostname)) {
+ console.log("DEBUG: Found exact hostname match in cache");
return cssCache.get(hostname);
} else if (cssCache.has(`www.${hostname}`)) {
+ console.log("DEBUG: Found www prefix match in cache");
return cssCache.get(`www.${hostname}`);
} else {
// Check for wildcard matches (+domain.com)
for (const [cachedSite, cachedCSS] of cssCache.entries()) {
if (cachedSite.startsWith("+")) {
const baseSite = cachedSite.slice(1);
- if (hostname.endsWith(baseSite)) {
+ // Ensure we're matching with proper domain boundary (dot or exact match)
+ if (hostname === baseSite || hostname.endsWith(`.${baseSite}`)) {
+ console.log(
+ `DEBUG: Found wildcard match: ${cachedSite} for ${hostname}`
+ );
return cachedCSS;
}
- } else if (hostname.endsWith(cachedSite)) {
+ } else if (
+ cachedSite !== hostname &&
+ cachedSite !== `www.${hostname}` &&
+ hostname.endsWith(`.${cachedSite}`)
+ ) {
+ // Only match subdomains, not partial domain names
+ console.log(
+ `DEBUG: Found subdomain match: ${cachedSite} for ${hostname}`
+ );
return cachedCSS;
}
}
@@ -197,35 +213,48 @@ async function applyCSSToTab(tab) {
// Find the best matching CSS file
let bestMatch = null;
let bestMatchLength = 0;
+ let matchType = "none";
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}`) {
+ bestMatch = key;
+ matchType = "exact";
+ console.log("DEBUG: Found exact match:", key);
+ break;
+ }
+
+ // Then check wildcard matches
if (siteName.startsWith("+")) {
- const baseSiteName = siteName.slice(1);
+ const baseSite = siteName.slice(1);
+ // Ensure we're matching with proper domain boundary
if (
- hostname.endsWith(baseSiteName) &&
- baseSiteName.length > bestMatchLength
+ (hostname === baseSite || hostname.endsWith(`.${baseSite}`)) &&
+ baseSite.length > bestMatchLength
) {
bestMatch = key;
- bestMatchLength = baseSiteName.length;
+ bestMatchLength = baseSite.length;
+ matchType = "wildcard";
console.log(
"DEBUG: Found wildcard match:",
key,
"with length",
- baseSiteName.length
+ baseSite.length
);
}
- } else if (hostname === siteName || hostname === `www.${siteName}`) {
- // Exact match has priority
- bestMatch = key;
- console.log("DEBUG: Found exact match:", key);
- break;
- } else if (
- hostname.endsWith(siteName) &&
+ }
+ // Last, check subdomain matches with proper domain boundary
+ else if (
+ hostname !== siteName &&
+ hostname !== `www.${siteName}` &&
+ hostname.endsWith(`.${siteName}`) &&
siteName.length > bestMatchLength
) {
bestMatch = key;
bestMatchLength = siteName.length;
+ matchType = "subdomain";
console.log(
"DEBUG: Found domain suffix match:",
key,
@@ -237,7 +266,7 @@ async function applyCSSToTab(tab) {
// If we found a direct match, use it
if (bestMatch) {
- console.log("DEBUG: Using direct match:", bestMatch);
+ console.log("DEBUG: Using match:", bestMatch, "of type:", matchType);
await applyCSS(tab.id, hostname, data.styles.website[bestMatch]);
return;
} else {
diff --git a/data-viewer/data-viewer.js b/data-viewer/data-viewer.js
index d38f53f..f6dd566 100644
--- a/data-viewer/data-viewer.js
+++ b/data-viewer/data-viewer.js
@@ -334,11 +334,28 @@ document.addEventListener("DOMContentLoaded", function () {
// Get site settings if available
const siteName = website.replace(".css", "");
- const domainName = siteName.startsWith("+")
- ? siteName.slice(1)
- : siteName;
- const settingsData =
- siteSettings[domainName] || siteSettings[`www.${domainName}`] || {};
+ let domainName;
+ // Declare settingsData at a higher scope so it's accessible throughout the function
+ let settingsData = {};
+
+ // Handle wildcard sites correctly
+ if (siteName.startsWith("+")) {
+ domainName = siteName.slice(1);
+ // For wildcard sites, we need to find any matching domain in settings
+ const matchingDomains = Object.keys(siteSettings).filter(
+ (domain) => domain === domainName || domain.endsWith(`.${domainName}`)
+ );
+
+ // Use the first matching domain's settings if any found
+ const settingsKey =
+ matchingDomains.length > 0 ? matchingDomains[0] : null;
+ settingsData = settingsKey ? siteSettings[settingsKey] : {};
+ } else {
+ // For direct domains, just check the domain and www.domain
+ domainName = siteName;
+ settingsData =
+ siteSettings[domainName] || siteSettings[`www.${domainName}`] || {};
+ }
header.innerHTML = `
<div class="website-header-content">
diff --git a/inject-css.js b/inject-css.js
deleted file mode 100644
index 27b4ecc..0000000
--- a/inject-css.js
+++ /dev/null
@@ -1,220 +0,0 @@
-import { SKIP_FORCE_THEMING_KEY } from "./shared/constants.js";
-
-let logging = false;
-
-if (logging) console.log("inject-css.js script loaded");
-
-// Run as early as possible in the document lifecycle
-const implementImmediateInjection = () => {
- // Create a style element immediately to avoid any delay - do this before anything else
- const styleElement = document.createElement("style");
- styleElement.id = "zen-internet-styles";
-
- // Set highest priority
- styleElement.setAttribute("data-priority", "highest");
-
- // Add !important to all rules to override any existing styles
- styleElement.innerHTML = `
- /* Prevent FOUC - temporarily hide content until styles are applied */
- body { opacity: 0 !important; transition: opacity 0.1s ease-in !important; }
- `;
-
- // Insert as the first element of head if possible
- if (document.head) {
- document.head.insertBefore(styleElement, document.head.firstChild);
- } else {
- // If head isn't ready yet (very early execution), add to documentElement
- document.documentElement.appendChild(styleElement);
-
- // Set up mutation observer to move it to head when head becomes available
- new MutationObserver((mutations, observer) => {
- if (document.head) {
- if (styleElement.parentNode !== document.head) {
- document.head.insertBefore(styleElement, document.head.firstChild);
- }
- observer.disconnect();
- }
- }).observe(document.documentElement, { childList: true });
- }
-
- return styleElement;
-};
-
-// Create style element immediately
-const styleElement = implementImmediateInjection();
-
-// Function to apply styles immediately when available
-function applyStyles(css) {
- if (!css) return;
-
- // Add the CSS
- try {
- // For immediate application, directly set textContent
- // as this is more reliably applied in early document stages
- styleElement.textContent =
- css.trim() +
- `
-/* Remove FOUC prevention once styles are loaded */
-body { opacity: 1 !important; }`;
-
- // After a very short delay (to ensure CSS application), ensure body is visible
- setTimeout(() => {
- if (document.body) {
- document.body.style.opacity = "1";
- }
- }, 10);
-
- if (logging) console.log("Styles applied:", css.length, "bytes");
- } catch (e) {
- console.error("Error applying styles:", e);
- }
-}
-
-// Listen for style data from background script for immediate injection
-browser.runtime.onMessage.addListener((message) => {
- if (message.action === "applyStyles" && message.css) {
- applyStyles(message.css);
- return true;
- }
-});
-
-// Send hostname to background script as early as possible
-browser.runtime
- .sendMessage({
- action: "contentScriptReady",
- hostname: window.location.hostname,
- url: window.location.href,
- })
- .catch((err) => {
- if (logging) console.log("Background script not ready yet:", err);
- });
-
-// Main function - but we don't wait for this before applying styles
-// This is just a backup in case background script injection fails
-(async () => {
- try {
- const settings = await browser.storage.local.get("transparentZenSettings");
- if (logging) console.log("Settings loaded", settings);
-
- if (!settings.transparentZenSettings?.enableStyling) {
- if (logging) console.log("Styling is disabled");
- return;
- }
-
- if (logging) console.log("Styling is enabled");
-
- // Tell background script we're ready and what page we're on
- browser.runtime.sendMessage({
- action: "contentScriptReady",
- hostname: window.location.hostname,
- });
-
- const data = await browser.storage.local.get("styles");
- if (!data.styles) {
- if (logging) console.log("No styles data available");
- return;
- }
-
- if (logging) console.log("Styles data loaded", data);
-
- const currentUrl = window.location.hostname;
- if (logging) console.log("Current URL hostname", currentUrl);
-
- // Find the best matching CSS file
- let bestMatch = null;
- let bestMatchLength = 0;
-
- for (const key of Object.keys(data.styles?.website || {})) {
- const siteName = key.replace(".css", "");
- if (siteName.startsWith("+")) {
- const baseSiteName = siteName.slice(1);
- if (
- currentUrl.endsWith(baseSiteName) &&
- baseSiteName.length > bestMatchLength
- ) {
- bestMatch = key;
- bestMatchLength = baseSiteName.length;
- }
- } else if (currentUrl === siteName || currentUrl === `www.${siteName}`) {
- // Exact match has priority
- bestMatch = key;
- break;
- } else if (
- currentUrl.endsWith(siteName) &&
- siteName.length > bestMatchLength
- ) {
- bestMatch = key;
- bestMatchLength = siteName.length;
- }
- }
-
- // If a direct match was found, use it
- if (bestMatch) {
- await injectCSS(currentUrl, data.styles.website[bestMatch]);
- return;
- }
-
- // If no direct match was found and force styling is enabled, check whitelist/blacklist mode
- if (settings.transparentZenSettings?.forceStyling) {
- const skipListData = await browser.storage.local.get(
- SKIP_FORCE_THEMING_KEY
- );
- const siteList = skipListData[SKIP_FORCE_THEMING_KEY] || [];
- const isWhitelistMode =
- settings.transparentZenSettings?.whitelistMode || false;
- const siteInList = siteList.includes(currentUrl);
-
- // In whitelist mode: apply only if site is in the list
- // In blacklist mode: apply only if site is NOT in the list
- if (
- (isWhitelistMode && siteInList) ||
- (!isWhitelistMode && !siteInList)
- ) {
- await injectCSS(currentUrl, data.styles.website["example.com.css"]);
- } else {
- if (logging)
- console.log(
- `Styling skipped due to ${
- isWhitelistMode ? "whitelist" : "blacklist"
- } mode settings`
- );
- }
- } else {
- if (logging) console.log("No CSS file found for current site");
- }
- } catch (error) {
- console.error("Error injecting CSS:", error);
- }
-})();
-
-async function injectCSS(hostname, features) {
- if (!features) return;
-
- const siteKey = `transparentZenSettings.${hostname}`;
- const settings = await browser.storage.local.get("transparentZenSettings");
- const globalSettings = settings.transparentZenSettings || {};
- const siteData = await browser.storage.local.get(siteKey);
- const featureSettings = siteData[siteKey] || {};
-
- let combinedCSS = "";
- for (const [feature, css] of Object.entries(features)) {
- // Skip any transparency feature if disableTransparency is enabled globally
- if (
- globalSettings.disableTransparency &&
- feature.toLowerCase().includes("transparency")
- ) {
- if (logging) console.log(`Skipping transparency feature: ${feature}`);
- continue;
- }
-
- // Apply the feature if it's not explicitly disabled
- if (featureSettings[feature] !== false) {
- combinedCSS += css + "\n";
- }
- }
-
- if (combinedCSS) {
- applyStyles(combinedCSS);
- if (logging) console.log(`Injected custom CSS for ${hostname}`);
- }
-}
diff --git a/popup/popup.js b/popup/popup.js
index 37d1ab2..7b00bb5 100644
--- a/popup/popup.js
+++ b/popup/popup.js
@@ -331,12 +331,21 @@ new (class ExtensionPopup {
isCurrentSite(siteName) {
if (logging) console.log("isCurrentSite called with", siteName);
if (!this.currentSiteHostname) return false;
+
+ // Exact match has priority
+ if (this.currentSiteHostname === siteName) return true;
+ if (this.currentSiteHostname === `www.${siteName}`) return true;
+
+ // Wildcard match (with proper domain boundary)
if (siteName.startsWith("+")) {
const baseSiteName = siteName.slice(1);
- return this.currentSiteHostname.endsWith(baseSiteName);
+ return (
+ this.currentSiteHostname === baseSiteName ||
+ this.currentSiteHostname.endsWith(`.${baseSiteName}`)
+ );
}
- if (this.currentSiteHostname === siteName) return true;
- if (this.currentSiteHostname === `www.${siteName}`) return true;
+
+ // Don't match partial domain names
return false;
}
@@ -413,25 +422,38 @@ new (class ExtensionPopup {
for (const site of Object.keys(styles)) {
const siteName = site.replace(/\.css$/, "");
+
+ // Exact match has highest priority
+ if (hostname === siteName || hostname === `www.${siteName}`) {
+ bestMatch = site;
+ if (logging) console.log("Popup: Found exact match:", site);
+ break;
+ }
+
+ // Then check wildcard matches
if (siteName.startsWith("+")) {
const baseSiteName = siteName.slice(1);
+ // Ensure we're matching with proper domain boundary
if (
- hostname.endsWith(baseSiteName) &&
+ (hostname === baseSiteName ||
+ hostname.endsWith(`.${baseSiteName}`)) &&
baseSiteName.length > bestMatchLength
) {
bestMatch = site;
bestMatchLength = baseSiteName.length;
+ if (logging) console.log("Popup: Found wildcard match:", site);
}
- } else if (hostname === siteName || hostname === `www.${siteName}`) {
- // Exact match has priority
- bestMatch = site;
- break;
- } else if (
- hostname.endsWith(siteName) &&
+ }
+ // Last, check subdomain matches with proper domain boundary
+ else if (
+ hostname !== siteName &&
+ hostname !== `www.${siteName}` &&
+ hostname.endsWith(`.${siteName}`) &&
siteName.length > bestMatchLength
) {
bestMatch = site;
bestMatchLength = siteName.length;
+ if (logging) console.log("Popup: Found subdomain match:", site);
}
}