Skip to content

Commit

Permalink
feat: isEqual utility
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed May 6, 2022
1 parent 872c873 commit 5fb8267
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
17 changes: 17 additions & 0 deletions README.md
Expand Up @@ -194,6 +194,23 @@ Removes url protocol
withoutProtocol('http://example.com')
```

### `isEqual`

Compare two URLs regardless of their slash condition or encoding:

```ts
// Result: true
isEqual('/foo', 'foo')
isEqual('foo/', 'foo')
isEqual('/foo bar', '/foo%20bar')

// Strict compare
// Result: false
isEqual('/foo', 'foo', { leadingSlash: true })
isEqual('foo/', 'foo', { trailingSlash: true })
isEqual('/foo bar', '/foo%20bar', { encoding: true })
```

## License

[MIT](./LICENSE)
Expand Down
22 changes: 22 additions & 0 deletions src/utils.ts
Expand Up @@ -155,3 +155,25 @@ export function resolveURL (base: string, ...input: string[]): string {
export function isSamePath (p1: string, p2: string) {
return decode(withoutTrailingSlash(p1)) === decode(withoutTrailingSlash(p2))
}

interface CompareURLOptions {
trailingSlash?: boolean
leadingSlash?: boolean
encoding?: boolean
}

export function isEqual (a: string, b: string, opts: CompareURLOptions = {}) {
if (!opts.trailingSlash) {
a = withTrailingSlash(a)
b = withTrailingSlash(b)
}
if (!opts.leadingSlash) {
a = withLeadingSlash(a)
b = withLeadingSlash(b)
}
if (!opts.encoding) {
a = decode(a)
b = decode(b)
}
return a === b
}
19 changes: 19 additions & 0 deletions test/utilities.test.ts
@@ -1,6 +1,7 @@
import { describe, expect, test } from 'vitest'
import {
hasProtocol,
isEqual,
isRelative,
parsePath,
stringifyParsedURL,
Expand Down Expand Up @@ -139,3 +140,21 @@ describe('withoutProtocol', () => {
})
}
})

describe('isEqual', () => {
const tests: { input: [string, string, any?], out: boolean }[] = [
{ input: ['/foo', '/foo/'], out: true },
{ input: ['foo', '/foo'], out: true },
{ input: ['foo', '/foo/'], out: true },
{ input: ['/foo%20bar/', '/foo bar'], out: true },
{ input: ['foo', '/foo', { leadingSlash: true }], out: false },
{ input: ['foo', 'foo/', { trailingSlash: true }], out: false },
{ input: ['/foo%20bar/', '/foo bar', { encoding: true }], out: false }
]

for (const t of tests) {
test(`${t.input[0]} == ${t.input[1]} ${t.input[2] ? JSON.stringify(t.input[2]) : ''}`, () => {
expect(isEqual(t.input[0], t.input[1], t.input[2])).toBe(t.out)
})
}
})

0 comments on commit 5fb8267

Please sign in to comment.