Skip to content

Commit c126f10

Browse files
committed
Handle '/' base and escaping edge cases.
1 parent 9685183 commit c126f10

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

packages/wouter/src/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
useIsomorphicLayoutEffect,
1818
useEvent,
1919
} from "./react-deps.js";
20-
import { absolutePath, relativePath, unescape, stripQm } from "./paths.js";
20+
import { absolutePath, relativePath, sanitizeSearch } from "./paths.js";
2121

2222
/*
2323
* Router and router context. Router is a lightweight object that represents the current
@@ -67,7 +67,7 @@ const useLocationFromRouter = (router) => {
6767
// it can be passed down as an element prop without any performance concerns.
6868
// (This is achieved via `useEvent`.)
6969
return [
70-
unescape(relativePath(router.base, location)),
70+
relativePath(router.base, location),
7171
useEvent((to, navOpts) => navigate(absolutePath(to, router.base), navOpts)),
7272
];
7373
};
@@ -76,7 +76,7 @@ export const useLocation = () => useLocationFromRouter(useRouter());
7676

7777
export const useSearch = () => {
7878
const router = useRouter();
79-
return unescape(stripQm(router.searchHook(router)));
79+
return sanitizeSearch(router.searchHook(router));
8080
};
8181

8282
export const matchRoute = (parser, route, path, loose) => {

packages/wouter/src/paths.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,37 @@
22
* Transforms `path` into its relative `base` version
33
* If base isn't part of the path provided returns absolute path e.g. `~/app`
44
*/
5-
export const relativePath = (base = "", path) =>
5+
const _relativePath = (base, path) =>
66
!path.toLowerCase().indexOf(base.toLowerCase())
77
? path.slice(base.length) || "/"
88
: "~" + path;
99

10-
export const absolutePath = (to, base = "") =>
11-
to[0] === "~" ? to.slice(1) : base + to;
10+
/**
11+
* When basepath is `undefined` or '/' it is ignored (we assume it's empty string)
12+
*/
13+
const baseDefaults = (base = "") => (base === "/" ? "" : base);
14+
15+
export const absolutePath = (to, base) =>
16+
to[0] === "~" ? to.slice(1) : baseDefaults(base) + to;
17+
18+
export const relativePath = (base = "", path) =>
19+
_relativePath(unescape(baseDefaults(base)), unescape(path));
1220

1321
/*
1422
* Removes leading question mark
1523
*/
16-
export const stripQm = (str) => (str[0] === "?" ? str.slice(1) : str);
24+
const stripQm = (str) => (str[0] === "?" ? str.slice(1) : str);
1725

1826
/*
1927
* decodes escape sequences such as %20
2028
*/
21-
export const unescape = (str) => {
29+
const unescape = (str) => {
2230
try {
2331
return decodeURI(str);
2432
} catch (_e) {
2533
// fail-safe mode: if string can't be decoded do nothing
2634
return str;
2735
}
2836
};
37+
38+
export const sanitizeSearch = (search) => unescape(stripQm(search));

0 commit comments

Comments
 (0)