@remix-run/router 1.1.0-pre.0 → 1.1.0

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": "1.1.0-pre.0",
3
+ "version": "1.1.0",
4
4
  "description": "Nested/Data-driven/Framework-agnostic Routing",
5
5
  "keywords": [
6
6
  "remix",
package/utils.ts CHANGED
@@ -468,25 +468,35 @@ function explodeOptionalSegments(path: string): string[] {
468
468
  if (rest.length === 0) {
469
469
  // Intepret empty string as omitting an optional segment
470
470
  // `["one", "", "three"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`
471
- return isOptional ? ["", required] : [required];
471
+ return isOptional ? [required, ""] : [required];
472
472
  }
473
473
 
474
474
  let restExploded = explodeOptionalSegments(rest.join("/"));
475
- return restExploded
476
- .flatMap((subpath) => {
477
- // /one + / + :two/three -> /one/:two/three
478
- let requiredExploded =
479
- subpath === "" ? required : required + "/" + subpath;
480
- // For optional segments, return the exploded path _without_ current segment first (`subpath`)
481
- // and exploded path _with_ current segment later (`subpath`)
482
- // This ensures that exploded paths are emitted in priority order
483
- // `/one/three/:four` will come before `/one/three/:five`
484
- return isOptional ? [subpath, requiredExploded] : [requiredExploded];
485
- })
486
- .map((exploded) => {
487
- // for absolute paths, ensure `/` instead of empty segment
488
- return path.startsWith("/") && exploded === "" ? "/" : exploded;
489
- });
475
+
476
+ let result: string[] = [];
477
+
478
+ // All child paths with the prefix. Do this for all children before the
479
+ // optional version for all children so we get consistent ordering where the
480
+ // parent optional aspect is preferred as required. Otherwise, we can get
481
+ // child sections interspersed where deeper optional segments are higher than
482
+ // parent optional segments, where for example, /:two would explodes _earlier_
483
+ // then /:one. By always including the parent as required _for all children_
484
+ // first, we avoid this issue
485
+ result.push(
486
+ ...restExploded.map((subpath) =>
487
+ subpath === "" ? required : [required, subpath].join("/")
488
+ )
489
+ );
490
+
491
+ // Then if this is an optional value, add all child versions without
492
+ if (isOptional) {
493
+ result.push(...restExploded);
494
+ }
495
+
496
+ // for absolute paths, ensure `/` instead of empty segment
497
+ return result.map((exploded) =>
498
+ path.startsWith("/") && exploded === "" ? "/" : exploded
499
+ );
490
500
  }
491
501
 
492
502
  function rankRouteBranches(branches: RouteBranch[]): void {