Skip to content

Commit

Permalink
wip: it works!
Browse files Browse the repository at this point in the history
need to clean up the tests
  • Loading branch information
pcattori committed Dec 6, 2022
1 parent 56bdb30 commit 9d5a7d9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 105 deletions.
15 changes: 14 additions & 1 deletion packages/react-router/__tests__/path-matching-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,20 @@ function pickPathsAndParams(routes: RouteObject[], pathname: string) {
let matches = matchRoutes(routes, pathname);
return (
matches &&
matches.map((match) => ({ path: match.route.path, params: match.params }))
matches.map((match) => {
let { path } = match.route

// filter params to only include params for the current (relative) route path
let paramNames = path?.split('/')
.filter(seg => seg.startsWith(':'))
.map(paramSeg => paramSeg.replace(/^:/, "").replace(/\?$/, ""))
let params = Object.fromEntries(Object.entries(match.params).filter(([k,v]) => paramNames?.includes(k)))

return {
path: match.route.path,
params,
}
})
);
}

Expand Down
120 changes: 16 additions & 104 deletions packages/router/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,42 +327,7 @@ export function matchRoutes<
return null;
}

// routes
let branches = flattenRoutes(routes);

let explodedBranches = branches.flatMap((branch) => {
if (!branch.path.includes("?")) return [branch];

let explodedBranches = [];
for (let explodedPath of explodeOptionalSegments(branch.path)) {
console.log(`explodedPath: ${explodedPath}`);
let segments = explodedPath.split("/");
let newRoutesMeta: typeof branch.routesMeta = [];
for (let routeMeta of branch.routesMeta) {
console.log(`routeMeta.relativePath: ${routeMeta.relativePath}`);
console.log(`route.path: ${routeMeta.route.path}`);
let newRouteMeta = {
...routeMeta,
relativePath: routeMeta.relativePath
.split("/")
.map((x) => x.replace(/\?$/, ""))
.join("/"),
};
console.log(`newRouteMeta.relativePath: ${newRouteMeta.relativePath}`);
newRoutesMeta.push(newRouteMeta);
}
explodedBranches.push({
...branch,
path: explodedPath,
score: computeScore(
explodedPath,
newRoutesMeta.slice(-1)[0].route.index
),
routesMeta: newRoutesMeta,
});
}
return explodedBranches;
});
rankRouteBranches(branches);

let matches = null;
Expand Down Expand Up @@ -407,9 +372,13 @@ function flattenRoutes<
parentsMeta: RouteMeta<RouteObjectType>[] = [],
parentPath = ""
): RouteBranch<RouteObjectType>[] {
routes.forEach((route, index) => {
let flattenRoute = (
route: RouteObjectType,
index: number,
relativePath?: string
) => {
let meta: RouteMeta<RouteObjectType> = {
relativePath: route.path || "",
relativePath: relativePath || route.path || "",
caseSensitive: route.caseSensitive === true,
childrenIndex: index,
route,
Expand Down Expand Up @@ -450,82 +419,25 @@ function flattenRoutes<
return;
}

// let hasOptionalSegments = path.includes("?");
// if (!hasOptionalSegments) {
// branches.push({
// path,
// score: computeScore(path, route.index),
// routesMeta,
// });
// return;
// }

// // Handle option path segments like `/one/two?/three/:four?` where trailing `?` denotes an optional segment.
// // The goal is to emulate users manually exploding a path with optional segments.

// // Explode path with optional segments into the equivalent set of paths _without_ optional segments.
// // For each of the exploded paths, we'll need to patch the last item in `routesMeta` (the one that corresponds to this relative path).
// // Specifically, we want to update `relativePath` to be consistent with the exploded path,
// // **BUT** we want to keep `routesMeta.route.path` as-is so that it refers to the original path _with_ optional segments.
// // That way, whenever we report paths to the user, we will always report the path the user authored and not leak these internal, exploded paths to the user.
// for (let explodedPath of explodeOptionalSegments(path)) {
// let [explodedRoutesMeta, last] = tail(routesMeta);
// let relativePath = explodedPath.slice(parentPath.length);
// if (last !== undefined) {
// explodedRoutesMeta.push({
// ...last,
// relativePath,
// });
// }
// branches.push({
// path: relativePath,
// score: computeScore(explodedPath, route.index),
// routesMeta: explodedRoutesMeta,
// });
// }
branches.push({
path,
score: computeScore(path, route.index),
routesMeta,
});
};
routes.forEach((route, index) => {
if (route.path === "" || !route.path?.includes("?")) {
flattenRoute(route, index);
} else {
for (let exploded of explodeOptionalSegments(route.path)) {
flattenRoute(route, index, exploded);
}
}
});

return branches;
}

function tail<Item>(arr: Item[]): [Item[], Item | undefined] {
return [arr.slice(0, -1), arr.at(-1)];
}

// /**
// * Given a route path with optional segments,
// * produces the equivalent combinations of paths _without_ optionals.
// *
// * For example, exploding `/one/two?/three/four?` produces:
// * - `/one/three`
// * - `/one/two/three`
// * - `/one/three/four`
// * - `/one/two/three/four`
// */
// function explode(path: string): string[] {
// let segments = path.split("/");
// if (segments.length === 0) return [];

// let [first, ...rest] = segments;
// let isOptional = first.endsWith("?");
// let segment = isOptional ? first.slice(0, -1) : first;

// if (rest.length === 0) {
// if (!isOptional) return [segment];
// return ["", segment];
// }

// let restExploded = explode(rest.join("/"));
// let exploded = restExploded.map((x) => segment + "/" + x);
// if (isOptional) exploded = [...exploded, ...restExploded];
// return exploded;
// }

/**
* Computes all combinations of optional path segments for a given path.
*
Expand Down Expand Up @@ -604,7 +516,7 @@ let explodeOptionalSegments = function* (path: string) {
if (dynamicHashes.has(hash)) continue;

dynamicHashes.add(hash);
yield exploded === "" ? "/" : exploded;
yield exploded;
}
};

Expand Down

0 comments on commit 9d5a7d9

Please sign in to comment.