Skip to content
This repository has been archived by the owner on Sep 7, 2024. It is now read-only.

Exact URL detection #176

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/components/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import { colors } from "~/modules/badge"
export enum BadgeWeight {
Primary,
Secondary,
Tertiary,
None,
}

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
}
Expand All @@ -36,6 +39,8 @@ const Badge = styled.span<Props>`
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"
Expand Down
5 changes: 5 additions & 0 deletions src/modules/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const disableBadge: IO<void> = () => {

export const colors = {
[URLMatch.Exact]: "#4286f4",
[URLMatch.Path]: "#71a5f8",
[URLMatch.Domain]: "#a0c4ff",
}

Expand Down Expand Up @@ -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
Expand Down
19 changes: 16 additions & 3 deletions src/modules/compare-urls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down Expand Up @@ -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)
})
Expand Down
15 changes: 11 additions & 4 deletions src/modules/compare-urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)

/**
Expand All @@ -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
Expand All @@ -36,6 +41,8 @@ export const match = (x: URL) => (y: URL): URLMatch => {
export const ordURLMatch = contramap<number, URLMatch>(x => {
switch (x) {
case URLMatch.Exact:
return 3
case URLMatch.Path:
return 2
case URLMatch.Domain:
return 1
Expand Down
13 changes: 8 additions & 5 deletions src/modules/url.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { domain, hrefSansProtocol } from "~/modules/url"
import { domain, hostAndPath } from "~/modules/url"

describe("~/modules/url", () => {
test("domain", () => {
Expand All @@ -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")
})
})
2 changes: 1 addition & 1 deletion src/modules/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const pathname = Lens.fromProp<URL>()("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<URL> = flow(
Expand Down