@remix-run/router 0.0.0-experimental-8bb3ffdf → 0.0.0-experimental-d90c8fb3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remix-run/router",
3
- "version": "0.0.0-experimental-8bb3ffdf",
3
+ "version": "0.0.0-experimental-d90c8fb3",
4
4
  "description": "Nested/Data-driven/Framework-agnostic Routing",
5
5
  "keywords": [
6
6
  "remix",
package/router.ts CHANGED
@@ -4098,7 +4098,11 @@ async function callLoaderOrAction(
4098
4098
  // Check between word boundaries instead of startsWith() due to the last
4099
4099
  // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
4100
4100
  if (contentType && /\bapplication\/json\b/.test(contentType)) {
4101
- data = await result.json();
4101
+ if (result.body == null) {
4102
+ data = null;
4103
+ } else {
4104
+ data = await result.json();
4105
+ }
4102
4106
  } else {
4103
4107
  data = await result.text();
4104
4108
  }
package/utils.ts CHANGED
@@ -485,16 +485,14 @@ export function matchRoutes<
485
485
 
486
486
  let matches = null;
487
487
  for (let i = 0; matches == null && i < branches.length; ++i) {
488
- matches = matchRouteBranch<string, RouteObjectType>(
489
- branches[i],
490
- // Incoming pathnames are generally encoded from either window.location
491
- // or from router.navigate, but we want to match against the unencoded
492
- // paths in the route definitions. Memory router locations won't be
493
- // encoded here but there also shouldn't be anything to decode so this
494
- // should be a safe operation. This avoids needing matchRoutes to be
495
- // history-aware.
496
- safelyDecodeURI(pathname)
497
- );
488
+ // Incoming pathnames are generally encoded from either window.location
489
+ // or from router.navigate, but we want to match against the unencoded
490
+ // paths in the route definitions. Memory router locations won't be
491
+ // encoded here but there also shouldn't be anything to decode so this
492
+ // should be a safe operation. This avoids needing matchRoutes to be
493
+ // history-aware.
494
+ let decoded = decodePath(pathname);
495
+ matches = matchRouteBranch<string, RouteObjectType>(branches[i], decoded);
498
496
  }
499
497
 
500
498
  return matches;
@@ -685,7 +683,7 @@ function rankRouteBranches(branches: RouteBranch[]): void {
685
683
  );
686
684
  }
687
685
 
688
- const paramRe = /^:\w+$/;
686
+ const paramRe = /^:[\w-]+$/;
689
687
  const dynamicSegmentValue = 3;
690
688
  const indexRouteValue = 2;
691
689
  const emptySegmentValue = 1;
@@ -822,7 +820,7 @@ export function generatePath<Path extends string>(
822
820
  return stringify(params[star]);
823
821
  }
824
822
 
825
- const keyMatch = segment.match(/^:(\w+)(\??)$/);
823
+ const keyMatch = segment.match(/^:([\w-]+)(\??)$/);
826
824
  if (keyMatch) {
827
825
  const [, key, optional] = keyMatch;
828
826
  let param = params[key as PathParam<Path>];
@@ -930,7 +928,7 @@ export function matchPath<
930
928
  if (isOptional && !value) {
931
929
  memo[paramName] = undefined;
932
930
  } else {
933
- memo[paramName] = safelyDecodeURIComponent(value || "", paramName);
931
+ memo[paramName] = (value || "").replace(/%2F/g, "/");
934
932
  }
935
933
  return memo;
936
934
  },
@@ -967,10 +965,13 @@ function compilePath(
967
965
  .replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
968
966
  .replace(/^\/*/, "/") // Make sure it has a leading /
969
967
  .replace(/[\\.*+^${}|()[\]]/g, "\\$&") // Escape special regex chars
970
- .replace(/\/:(\w+)(\?)?/g, (_: string, paramName: string, isOptional) => {
971
- params.push({ paramName, isOptional: isOptional != null });
972
- return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
973
- });
968
+ .replace(
969
+ /\/:([\w-]+)(\?)?/g,
970
+ (_: string, paramName: string, isOptional) => {
971
+ params.push({ paramName, isOptional: isOptional != null });
972
+ return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
973
+ }
974
+ );
974
975
 
975
976
  if (path.endsWith("*")) {
976
977
  params.push({ paramName: "*" });
@@ -999,9 +1000,12 @@ function compilePath(
999
1000
  return [matcher, params];
1000
1001
  }
1001
1002
 
1002
- function safelyDecodeURI(value: string) {
1003
+ function decodePath(value: string) {
1003
1004
  try {
1004
- return decodeURI(value);
1005
+ return value
1006
+ .split("/")
1007
+ .map((v) => decodeURIComponent(v).replace(/\//g, "%2F"))
1008
+ .join("/");
1005
1009
  } catch (error) {
1006
1010
  warning(
1007
1011
  false,
@@ -1014,21 +1018,6 @@ function safelyDecodeURI(value: string) {
1014
1018
  }
1015
1019
  }
1016
1020
 
1017
- function safelyDecodeURIComponent(value: string, paramName: string) {
1018
- try {
1019
- return decodeURIComponent(value);
1020
- } catch (error) {
1021
- warning(
1022
- false,
1023
- `The value for the URL param "${paramName}" will not be decoded because` +
1024
- ` the string "${value}" is a malformed URL segment. This is probably` +
1025
- ` due to a bad percent encoding (${error}).`
1026
- );
1027
-
1028
- return value;
1029
- }
1030
- }
1031
-
1032
1021
  /**
1033
1022
  * @private
1034
1023
  */