Skip to content

Commit ce4ff15

Browse files
committed
Improve background mathing.
1 parent 23057f3 commit ce4ff15

File tree

2 files changed

+112
-57
lines changed

2 files changed

+112
-57
lines changed

Public/background.js

Lines changed: 102 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -519,55 +519,116 @@ function urlMatchesPattern(url, pattern) {
519519
// Handle edge cases
520520
if (pattern === url) return true;
521521
if (!url || !pattern) return false;
522-
522+
523+
// Normalize pattern if missing scheme
524+
if (!pattern.includes("://")) {
525+
pattern = "*://" + pattern;
526+
}
527+
523528
// Extract scheme, host, and path from pattern
524-
let schemeHost, patternPath;
525-
526-
if (pattern.includes("://")) {
527-
[schemeHost, ...patternPathParts] = pattern.split("/");
528-
patternPath = patternPathParts.length > 0 ? "/" + patternPathParts.join("/") : "/*";
529-
530-
// Fix handling of the scheme/host part
531-
let [patternScheme, patternHost] = schemeHost.split("://");
532-
533-
// Create URL object for the input URL
534-
const urlObj = new URL(url);
535-
536-
// Handle scheme matching
537-
if (patternScheme !== "*" && patternScheme !== urlObj.protocol.slice(0, -1)) {
529+
let [schemeHostPart, ...patternPathParts] = pattern.split("/");
530+
let patternPath =
531+
patternPathParts.length > 0 ? "/" + patternPathParts.join("/") : "/";
532+
533+
// Fix handling of the scheme/host part
534+
let [patternScheme, ...hostParts] = schemeHostPart.split("://");
535+
let patternHost = hostParts.join("://"); // In case there's :// in the hostname (unlikely but safe)
536+
537+
// Create URL object for the input URL
538+
const urlObj = new URL(url);
539+
const urlPath = urlObj.pathname;
540+
541+
// Handle scheme matching
542+
if (
543+
patternScheme !== "*" &&
544+
patternScheme !== urlObj.protocol.slice(0, -1)
545+
) {
546+
return false;
547+
}
548+
549+
// Handle host matching with wildcards
550+
if (patternHost.startsWith("*.")) {
551+
// *.domain.com pattern - match domain or any subdomain
552+
const domain = patternHost.slice(2);
553+
if (
554+
!(urlObj.hostname === domain || urlObj.hostname.endsWith("." + domain))
555+
) {
538556
return false;
539557
}
540-
541-
// Handle host matching with wildcard
542-
if (patternHost.startsWith("*.")) {
543-
if (!urlObj.hostname.endsWith(patternHost.slice(2))) {
544-
return false;
545-
}
546-
} else if (patternHost !== "*" && patternHost !== urlObj.hostname) {
558+
} else if (patternHost.includes("*")) {
559+
// Handle other wildcards in hostname
560+
const hostRegex = new RegExp(
561+
"^" + patternHost.replace(/\./g, "\\.").replace(/\*/g, ".*") + "$"
562+
);
563+
if (!hostRegex.test(urlObj.hostname)) {
547564
return false;
548565
}
549-
550-
// Handle path matching
551-
if (patternPath === "/*") {
552-
return true; // Match any path
566+
} else if (patternHost !== "*" && patternHost !== urlObj.hostname) {
567+
// Direct hostname match
568+
return false;
569+
}
570+
571+
// If pattern path is empty or just "/" or "/*", match any path
572+
if (patternPath === "/" || patternPath === "/*") {
573+
return true;
574+
}
575+
576+
// Handle special case for /** at the end
577+
if (patternPath.endsWith("/**")) {
578+
const basePath = patternPath.slice(0, -3);
579+
return urlPath === basePath || urlPath.startsWith(basePath);
580+
}
581+
582+
// Handle path matching with both * and ** wildcards
583+
const pathSegments = patternPath
584+
.split("/")
585+
.filter((segment) => segment !== "");
586+
const urlSegments = urlPath.split("/").filter((segment) => segment !== "");
587+
588+
// Simple case: if pattern is just /* match any single-level path
589+
if (pathSegments.length === 1 && pathSegments[0] === "*") {
590+
return true;
591+
}
592+
593+
let pathRegexParts = ["^"];
594+
let i = 0;
595+
596+
for (i = 0; i < pathSegments.length; i++) {
597+
const segment = pathSegments[i];
598+
599+
// Handle ** wildcard (matches across multiple path segments)
600+
if (segment === "**") {
601+
// If this is the last segment, match anything that follows
602+
if (i === pathSegments.length - 1) {
603+
pathRegexParts.push(".*");
604+
break;
605+
}
606+
607+
// Otherwise, match anything until we find the next segment
608+
const nextSegment = pathSegments[i + 1];
609+
const nextSegmentRegex = nextSegment
610+
.replace(/\*/g, "[^/]*")
611+
.replace(/\./g, "\\.");
612+
613+
pathRegexParts.push(`(?:.*?\\/)?${nextSegmentRegex}`);
614+
i++; // Skip the next segment as we've already included it
553615
} else {
554-
// Convert pattern path to regex pattern
555-
const pathPattern = patternPath
556-
.split("/")
557-
.map(segment => {
558-
if (segment === "*") return "[^/]*";
559-
if (segment.includes("*")) return segment.replace(/\*/g, "[^/]*");
560-
return segment;
561-
})
562-
.join("/");
563-
564-
const pathRegex = new RegExp(`^${pathPattern}$`);
565-
return pathRegex.test(urlObj.pathname);
616+
// Handle regular segment with potential * wildcards
617+
const segmentRegex = segment
618+
.replace(/\*/g, "[^/]*")
619+
.replace(/\./g, "\\.");
620+
if (i === 0) {
621+
pathRegexParts.push(`\\/?${segmentRegex}`); // Make the first slash optional
622+
} else {
623+
pathRegexParts.push(`\\/${segmentRegex}`);
624+
}
566625
}
567-
} else {
568-
// Handle patterns without scheme
569-
return url.includes(pattern);
570626
}
627+
628+
pathRegexParts.push("$");
629+
const pathRegex = new RegExp(pathRegexParts.join(""));
630+
631+
return pathRegex.test(urlPath);
571632
} catch (error) {
572633
console.warn("URL matching error:", error);
573634
return false;

Public/popup.js

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,6 @@ function urlMatchesPattern(url, script) {
257257
if (!pattern) return false;
258258
if (pattern === url) return true;
259259

260-
// Handle exact match
261-
if (pattern === url) return true;
262-
263260
// Normalize pattern if missing scheme
264261
if (!pattern.includes("://")) {
265262
pattern = "*://" + pattern;
@@ -296,23 +293,20 @@ function urlMatchesPattern(url, script) {
296293
if (!(urlHost === domain || urlHost.endsWith("." + domain))) {
297294
return false;
298295
}
299-
} else if (hostPattern !== "*" && hostPattern !== urlHost) {
300-
// Handle direct hostname match or * wildcard
301-
if (hostPattern.includes("*")) {
302-
// Convert * to regex for partial host matching
303-
const hostRegex = new RegExp(
304-
"^" + hostPattern.replace(/\./g, "\\.").replace(/\*/g, ".*") + "$"
305-
);
306-
if (!hostRegex.test(urlHost)) {
307-
return false;
308-
}
309-
} else {
296+
} else if (hostPattern.includes("*")) {
297+
// Convert * to regex for partial host matching
298+
const hostRegex = new RegExp(
299+
"^" + hostPattern.replace(/\./g, "\\.").replace(/\*/g, ".*") + "$"
300+
);
301+
if (!hostRegex.test(urlHost)) {
310302
return false;
311303
}
304+
} else if (hostPattern !== "*" && hostPattern !== urlHost) {
305+
return false;
312306
}
313307

314-
// If no path in pattern but URL has path, still consider it a match
315-
if (!pathPattern) {
308+
// If no path in pattern or just wildcard, consider it a match
309+
if (!pathPattern || pathPattern === "*") {
316310
return true;
317311
}
318312

0 commit comments

Comments
 (0)