Skip to content

Commit

Permalink
Handle '/' base and escaping edge cases.
Browse files Browse the repository at this point in the history
  • Loading branch information
molefrog committed Aug 21, 2024
1 parent 9685183 commit c126f10
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 8 deletions.
6 changes: 3 additions & 3 deletions packages/wouter/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
useIsomorphicLayoutEffect,
useEvent,
} from "./react-deps.js";
import { absolutePath, relativePath, unescape, stripQm } from "./paths.js";
import { absolutePath, relativePath, sanitizeSearch } from "./paths.js";

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

export const useSearch = () => {
const router = useRouter();
return unescape(stripQm(router.searchHook(router)));
return sanitizeSearch(router.searchHook(router));
};

export const matchRoute = (parser, route, path, loose) => {
Expand Down
20 changes: 15 additions & 5 deletions packages/wouter/src/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,37 @@
* Transforms `path` into its relative `base` version
* If base isn't part of the path provided returns absolute path e.g. `~/app`
*/
export const relativePath = (base = "", path) =>
const _relativePath = (base, path) =>
!path.toLowerCase().indexOf(base.toLowerCase())
? path.slice(base.length) || "/"
: "~" + path;

export const absolutePath = (to, base = "") =>
to[0] === "~" ? to.slice(1) : base + to;
/**
* When basepath is `undefined` or '/' it is ignored (we assume it's empty string)
*/
const baseDefaults = (base = "") => (base === "/" ? "" : base);

export const absolutePath = (to, base) =>
to[0] === "~" ? to.slice(1) : baseDefaults(base) + to;

export const relativePath = (base = "", path) =>
_relativePath(unescape(baseDefaults(base)), unescape(path));

/*
* Removes leading question mark
*/
export const stripQm = (str) => (str[0] === "?" ? str.slice(1) : str);
const stripQm = (str) => (str[0] === "?" ? str.slice(1) : str);

/*
* decodes escape sequences such as %20
*/
export const unescape = (str) => {
const unescape = (str) => {
try {
return decodeURI(str);
} catch (_e) {
// fail-safe mode: if string can't be decoded do nothing
return str;
}
};

export const sanitizeSearch = (search) => unescape(stripQm(search));

0 comments on commit c126f10

Please sign in to comment.