Skip to content

Commit

Permalink
feat!: support mixed params in same path segment (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 authored Oct 4, 2023
1 parent 0202d4c commit 130c4b8
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 4 deletions.
27 changes: 23 additions & 4 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ function lookup(ctx: RadixRouterContext, path: string): MatchedRoute {
if (node === null) {
break;
} else {
params[node.paramName] = section;
if (node.type === NODE_TYPES.MIXED && node.paramMatcher) {
const matches = section.match(node.paramMatcher);
Object.assign(params, matches.groups);
} else {
params[node.paramName] = section;
}
paramsFound = true;
}
} else {
Expand Down Expand Up @@ -116,8 +121,22 @@ function insert(ctx: RadixRouterContext, path: string, data: any) {
node.children.set(section, childNode);

if (type === NODE_TYPES.PLACEHOLDER) {
childNode.paramName =
section === "*" ? `_${_unnamedPlaceholderCtr++}` : section.slice(1);
if (section === "*") {
childNode.paramName = `_${_unnamedPlaceholderCtr++}`;
} else {
const PARAMS_RE = /:\w+|[^:]+/g;
const params = [...section.matchAll(PARAMS_RE)].map((i) => i[0]);
if (params.length === 1) {
childNode.paramName = params[0].slice(1);
} else {
childNode.type = NODE_TYPES.MIXED;
const sectionRegexString = section.replace(
/:(\w+)/g,
(_, id) => `(?<${id}>\\w+)`,
);
childNode.paramMatcher = new RegExp(`^${sectionRegexString}$`);
}
}
node.placeholderChildNode = childNode;
isStaticRoute = false;
} else if (type === NODE_TYPES.WILDCARD) {
Expand Down Expand Up @@ -185,7 +204,7 @@ function getNodeType(str: string) {
if (str.startsWith("**")) {
return NODE_TYPES.WILDCARD;
}
if (str[0] === ":" || str === "*") {
if (str.includes(":") || str === "*") {
return NODE_TYPES.PLACEHOLDER;
}
return NODE_TYPES.NORMAL;
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const NODE_TYPES = {
NORMAL: 0 as const,
WILDCARD: 1 as const,
PLACEHOLDER: 2 as const,
MIXED: 3 as const,
};

type _NODE_TYPES = typeof NODE_TYPES;
Expand All @@ -22,6 +23,7 @@ export interface RadixNode<T extends RadixNodeData = RadixNodeData> {
children: Map<string, RadixNode<T>>;
data: RadixNodeData | null;
paramName: string | null;
paramMatcher?: string | RegExp;
wildcardChildNode: RadixNode<T> | null;
placeholderChildNode: RadixNode<T> | null;
}
Expand Down
10 changes: 10 additions & 0 deletions tests/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ describe("Router lookup", function () {
});
});

describe("mixed params in same segemnt", function () {
const mixedPath = "/files/:category/:id,name=:name.txt";
testRouter([mixedPath], {
"/files/test/123,name=foobar.txt": {
path: mixedPath,
params: { category: "test", id: "123", name: "foobar" },
},
});
});

describe("should be able to match routes with trailing slash", function () {
testRouter(["route/without/trailing/slash", "route/with/trailing/slash/"], {
"route/without/trailing/slash": { path: "route/without/trailing/slash" },
Expand Down

0 comments on commit 130c4b8

Please sign in to comment.