Skip to content

Commit d2cdfa5

Browse files
Create option for isEqualPath
1 parent c2423a4 commit d2cdfa5

File tree

4 files changed

+53
-7
lines changed

4 files changed

+53
-7
lines changed

packages/minimal-shared/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# minimal-shared
22

3+
## 1.0.11
4+
5+
_May 14, 2025_
6+
7+
- Update `src/utils/url`.
8+
9+
---
10+
311
## 1.0.10
412

513
_May 12, 2025_

packages/minimal-shared/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "minimal-shared",
33
"author": "Minimals",
4-
"version": "1.0.10",
4+
"version": "1.0.11",
55
"description": "Shared hooks and utils used by Minimal UI and Zone UI.",
66
"keywords": [
77
"typescript",

packages/minimal-shared/src/utils/url/url.test.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,23 @@ describe('isEqualPath()', () => {
3939
['Match with trailing slash', '/dashboard/', '/dashboard', true],
4040
['Both paths have trailing slashes', '/dashboard/', '/dashboard/', true],
4141
['Different paths', '/dashboard', '/settings', false],
42-
];
42+
['Path with and without trailing slash', '/dashboard/params', '/dashboard/params/', true],
43+
[
44+
'Same path with query params and trailing slash',
45+
'/dashboard/params?id=123&filter=active',
46+
'/dashboard/params/?id=123&filter=active',
47+
true,
48+
],
49+
['Invalid URLs fallback to false', 'not-a-url', '/valid', false],
50+
] as const;
4351

44-
test.each(mapWithIndex(cases))('%i. %s', (_i, _desc, a, b, expected) => {
45-
expect(isEqualPath(a, b)).toBe(expected);
52+
describe.each([true, false])('deep = %s', (deep) => {
53+
test.each(cases)('%s | a: "%s", b: "%s" => %s', (description, a, b, expected) => {
54+
const result = isEqualPath(a, b, { deep });
55+
const mode = deep ? 'including params' : 'ignoring params';
56+
console.log(`[${mode}] ${description}: Comparing "${a}" and "${b}" => ${result}`);
57+
expect(result).toBe(expected);
58+
});
4659
});
4760
});
4861

packages/minimal-shared/src/utils/url/url.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import { isEqual } from 'es-toolkit';
2+
3+
// ----------------------------------------------------------------------
4+
15
/**
26
* Checks if a URL has query parameters.
37
*
@@ -41,15 +45,36 @@ export function removeLastSlash(pathname: string): string {
4145
* Checks if two paths are equal after removing trailing slashes.
4246
*
4347
* @param targetUrl - The target URL to compare.
44-
* @param pathname - The pathname to compare.
48+
* @param currentUrl - The pathname to compare.
49+
* @param options.deep - Options for deep comparison.
4550
* @returns True if the paths are equal, false otherwise.
4651
*
4752
* @example
4853
* isEqualPath('/dashboard/', '/dashboard'); // true
4954
* isEqualPath('/home', '/dashboard'); // false
5055
*/
51-
export function isEqualPath(targetUrl: string, pathname: string): boolean {
52-
return removeLastSlash(targetUrl) === removeLastSlash(pathname);
56+
export type EqualPathOptions = {
57+
deep?: boolean;
58+
};
59+
60+
export function isEqualPath(
61+
targetUrl: string,
62+
currentUrl: string,
63+
options: EqualPathOptions = {
64+
deep: true,
65+
}
66+
): boolean {
67+
const parseUrl = (url: string) => {
68+
try {
69+
const { pathname, searchParams } = new URL(url.trim(), 'http://dummy');
70+
return options.deep
71+
? { pathname: removeLastSlash(pathname), params: Object.fromEntries(searchParams) }
72+
: { pathname: removeLastSlash(pathname) };
73+
} catch {
74+
return { pathname: '' };
75+
}
76+
};
77+
return isEqual(parseUrl(currentUrl), parseUrl(targetUrl));
5378
}
5479

5580
// ----------------------------------------------------------------------

0 commit comments

Comments
 (0)