Skip to content

Commit b731a53

Browse files
authored
fix(toRouteMatcher): respect non strict trailing slash (#91)
1 parent 790d0af commit b731a53

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

src/matcher.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ export interface RouteMatcher {
1919

2020
export function toRouteMatcher(router: RadixRouter): RouteMatcher {
2121
const table = _routerNodeToTable("", router.ctx.rootNode);
22-
return _createMatcher(table);
22+
return _createMatcher(table, router.ctx.options.strictTrailingSlash);
2323
}
2424

25-
function _createMatcher(table: RouteTable): RouteMatcher {
25+
function _createMatcher(
26+
table: RouteTable,
27+
strictTrailingSlash?: boolean,
28+
): RouteMatcher {
2629
return {
2730
ctx: { table },
28-
matchAll: (path) => _matchRoutes(path, table),
31+
matchAll: (path: string) => _matchRoutes(path, table, strictTrailingSlash),
2932
} satisfies RouteMatcher;
3033
}
3134

@@ -83,7 +86,16 @@ export function createMatcherFromExport(
8386
return _createMatcher(_createTableFromExport(matcherExport));
8487
}
8588

86-
function _matchRoutes(path: string, table: RouteTable): RadixNodeData[] {
89+
function _matchRoutes(
90+
path: string,
91+
table: RouteTable,
92+
strictTrailingSlash?: boolean,
93+
): RadixNodeData[] {
94+
// By default trailing slashes are not strict
95+
if (strictTrailingSlash !== true && path.endsWith("/")) {
96+
path = path.slice(0, -1) || "/";
97+
}
98+
8799
// Order should be from less specific to most specific
88100
const matches = [];
89101

tests/matcher.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ describe("Route matcher", function () {
5151
"/foo/baz",
5252
"/foo/baz/**",
5353
"/foo/*/sub",
54+
"/without-trailing",
55+
"/with-trailing/",
5456
]);
5557

5658
const router = createRouter({ routes });
@@ -88,6 +90,12 @@ describe("Route matcher", function () {
8890
"/foo/baz" => {
8991
"pattern": "/foo/baz",
9092
},
93+
"/without-trailing" => {
94+
"pattern": "/without-trailing",
95+
},
96+
"/with-trailing" => {
97+
"pattern": "/with-trailing/",
98+
},
9199
},
92100
"wildcard": Map {
93101
"/foo" => {
@@ -142,6 +150,26 @@ describe("Route matcher", function () {
142150
`);
143151
});
144152

153+
it("trailing slash", () => {
154+
// Defined with trailing slash
155+
expect(_match("/with-trailing")).to.toMatchInlineSnapshot(`
156+
[
157+
"/with-trailing/",
158+
]
159+
`);
160+
expect(_match("/with-trailing")).toMatchObject(_match("/with-trailing/"));
161+
162+
// Defined without trailing slash
163+
expect(_match("/without-trailing")).to.toMatchInlineSnapshot(`
164+
[
165+
"/without-trailing",
166+
]
167+
`);
168+
expect(_match("/without-trailing")).toMatchObject(
169+
_match("/without-trailing/"),
170+
);
171+
});
172+
145173
it("can be exported", () => {
146174
const jsonData = exportMatcher(matcher);
147175
expect(jsonData).toMatchInlineSnapshot(`
@@ -173,6 +201,12 @@ describe("Route matcher", function () {
173201
"/foo/baz": {
174202
"pattern": "/foo/baz",
175203
},
204+
"/with-trailing": {
205+
"pattern": "/with-trailing/",
206+
},
207+
"/without-trailing": {
208+
"pattern": "/without-trailing",
209+
},
176210
},
177211
"wildcard": {
178212
"/foo": {

0 commit comments

Comments
 (0)