diff --git a/src/components/badge.ts b/src/components/badge.ts index e1cba9c..7f78640 100644 --- a/src/components/badge.ts +++ b/src/components/badge.ts @@ -5,6 +5,7 @@ import { colors } from "~/modules/badge" export enum BadgeWeight { Primary, Secondary, + Tertiary, None, } @@ -12,8 +13,10 @@ export const mapURLMatchToBadgeWeight = (urlMatch: URLMatch): BadgeWeight => { switch (urlMatch) { case URLMatch.Exact: return BadgeWeight.Primary - case URLMatch.Domain: + case URLMatch.Path: return BadgeWeight.Secondary + case URLMatch.Domain: + return BadgeWeight.Tertiary default: return BadgeWeight.None } @@ -36,6 +39,8 @@ const Badge = styled.span` case BadgeWeight.Primary: return colors[URLMatch.Exact] case BadgeWeight.Secondary: + return colors[URLMatch.Path] + case BadgeWeight.Tertiary: return colors[URLMatch.Domain] case BadgeWeight.None: return "transparent" diff --git a/src/modules/badge.ts b/src/modules/badge.ts index cf29f82..9228993 100644 --- a/src/modules/badge.ts +++ b/src/modules/badge.ts @@ -33,6 +33,7 @@ const disableBadge: IO = () => { export const colors = { [URLMatch.Exact]: "#4286f4", + [URLMatch.Path]: "#71a5f8", [URLMatch.Domain]: "#a0c4ff", } @@ -102,6 +103,10 @@ const updateBadge = ( runIO(setBadge(colors[URLMatch.Exact])(text)) break + case URLMatch.Path: + runIO(setBadge(colors[URLMatch.Path])(text)) + break + case URLMatch.Domain: runIO(setBadge(colors[URLMatch.Domain])(text)) break diff --git a/src/modules/compare-urls.test.ts b/src/modules/compare-urls.test.ts index d531879..c420cc2 100644 --- a/src/modules/compare-urls.test.ts +++ b/src/modules/compare-urls.test.ts @@ -9,10 +9,22 @@ describe("~/modules/compare-urls", () => { expect(match(url1)(url2)).toBe(URLMatch.Exact) }) - test("matches exact URL even if HTTP(S) protocol differs", () => { + test("matches host and path if query differs", () => { + const url1 = new URL("https://samhh.com/path?foo=bar#baz") + const url2 = new URL("https://samhh.com/path?foo=baz#baz") + expect(match(url1)(url2)).toBe(URLMatch.Path) + }) + + test("matches host and path if hash differs", () => { + const url1 = new URL("https://samhh.com/path?foo=bar#baz") + const url2 = new URL("https://samhh.com/path?foo=bar#bar") + expect(match(url1)(url2)).toBe(URLMatch.Path) + }) + + test("matches host and path even if HTTP(S) protocol differs", () => { const url1 = new URL("https://samhh.com") const url2 = new URL("http://samhh.com/") - expect(match(url1)(url2)).toBe(URLMatch.Exact) + expect(match(url1)(url2)).toBe(URLMatch.Path) }) test("matches domain", () => { @@ -52,7 +64,8 @@ describe("~/modules/compare-urls", () => { test("ordURLMatch", () => { expect(ordNumber.compare(10, 5)).toBe(1) // for reference - expect(ordURLMatch.compare(URLMatch.Exact, URLMatch.Domain)).toBe(1) + expect(ordURLMatch.compare(URLMatch.Exact, URLMatch.Path)).toBe(1) + expect(ordURLMatch.compare(URLMatch.Path, URLMatch.Domain)).toBe(1) expect(ordURLMatch.compare(URLMatch.Domain, URLMatch.None)).toBe(1) expect(ordURLMatch.compare(URLMatch.None, URLMatch.Exact)).toBe(-1) }) diff --git a/src/modules/compare-urls.ts b/src/modules/compare-urls.ts index 9245738..eda6583 100644 --- a/src/modules/compare-urls.ts +++ b/src/modules/compare-urls.ts @@ -3,16 +3,18 @@ import { ordNumber, contramap } from "fp-ts/lib/Ord" import { eqString } from "fp-ts/lib/Eq" import { equal, mapBoth } from "~/modules/tuple" import * as A from "fp-ts/Array" -import { hrefSansProtocol, isHttpOrHttps, domain } from "~/modules/url" +import { hostAndPath, isHttpOrHttps, domain } from "~/modules/url" export enum URLMatch { Exact = "exact", + Path = "path", Domain = "domain", None = "none", } const eqS = equal(eqString) -const eqHref = flow(mapBoth(hrefSansProtocol), eqS) +const eqUrl = flow(mapBoth(String), eqS) +const eqPath = flow(mapBoth(hostAndPath), eqS) const eqDomain = flow(mapBoth(domain), eqS) /** @@ -24,8 +26,11 @@ export const match = (x: URL) => (y: URL): URLMatch => { // Never match URLs with non-HTTP(S) protocols if (A.some(not(isHttpOrHttps))(zs)) return URLMatch.None - // Match URLs as exact irrespective of protocol equality - if (eqHref(zs)) return URLMatch.Exact + // Match URLs as exact if they're exactly identical + if (eqUrl(zs)) return URLMatch.Exact + + // Check equality of hostname and path (ignoring protocol(s)) + if (eqPath(zs)) return URLMatch.Path // Check equality of domain (ignoring subdomain(s)) if (eqDomain(zs)) return URLMatch.Domain @@ -36,6 +41,8 @@ export const match = (x: URL) => (y: URL): URLMatch => { export const ordURLMatch = contramap(x => { switch (x) { case URLMatch.Exact: + return 3 + case URLMatch.Path: return 2 case URLMatch.Domain: return 1 diff --git a/src/modules/url.test.ts b/src/modules/url.test.ts index a4fad0a..199f519 100644 --- a/src/modules/url.test.ts +++ b/src/modules/url.test.ts @@ -1,4 +1,4 @@ -import { domain, hrefSansProtocol } from "~/modules/url" +import { domain, hostAndPath } from "~/modules/url" describe("~/modules/url", () => { test("domain", () => { @@ -7,13 +7,16 @@ describe("~/modules/url", () => { expect(domain(new URL("http://samhh.com/abc"))).toEqual("samhh.com") }) - test("hrefSansProtocol", () => { - expect(hrefSansProtocol(new URL("https://samhh.com"))).toEqual("samhh.com/") - expect(hrefSansProtocol(new URL("http://samhh.com/a/path.html"))).toEqual( + test("hostAndPath", () => { + expect(hostAndPath(new URL("https://samhh.com"))).toEqual("samhh.com/") + expect(hostAndPath(new URL("http://samhh.com/a/path.html"))).toEqual( "samhh.com/a/path.html", ) expect( - hrefSansProtocol(new URL("https://subdomain.samhh.com/some/other/path")), + hostAndPath(new URL("https://subdomain.samhh.com/some/other/path")), ).toEqual("subdomain.samhh.com/some/other/path") + expect( + hostAndPath(new URL("https://subdomain.samhh.com/path?foo=bar#baz")), + ).toEqual("subdomain.samhh.com/path") }) }) diff --git a/src/modules/url.ts b/src/modules/url.ts index f66ad3c..340357b 100644 --- a/src/modules/url.ts +++ b/src/modules/url.ts @@ -25,7 +25,7 @@ export const pathname = Lens.fromProp()("pathname") export const domain = (x: URL): string => pipe(host.get(x), S.split("."), A.takeRight(2), join(".")) -export const hrefSansProtocol = (x: URL): string => +export const hostAndPath = (x: URL): string => host.get(x) + pathname.get(x) export const isHttpOrHttps: Predicate = flow(