@rangojs/router 0.0.0-experimental.59 → 0.0.0-experimental.60
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/dist/vite/index.js +1 -1
- package/package.json +1 -1
- package/src/reverse.ts +20 -1
- package/src/router/handler-context.ts +21 -1
package/dist/vite/index.js
CHANGED
|
@@ -1745,7 +1745,7 @@ import { resolve } from "node:path";
|
|
|
1745
1745
|
// package.json
|
|
1746
1746
|
var package_default = {
|
|
1747
1747
|
name: "@rangojs/router",
|
|
1748
|
-
version: "0.0.0-experimental.
|
|
1748
|
+
version: "0.0.0-experimental.60",
|
|
1749
1749
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1750
1750
|
keywords: [
|
|
1751
1751
|
"react",
|
package/package.json
CHANGED
package/src/reverse.ts
CHANGED
|
@@ -305,8 +305,22 @@ export function createReverse<TRoutes extends Record<string, string>>(
|
|
|
305
305
|
if (params) {
|
|
306
306
|
// Replace :param placeholders with actual values
|
|
307
307
|
// Strip constraint syntax: :param(a|b) -> use "param" as key
|
|
308
|
+
// Optional params (:param?) are omitted when not provided
|
|
309
|
+
let hadOmittedOptional = false;
|
|
308
310
|
result = result.replace(
|
|
309
|
-
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))
|
|
311
|
+
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(\?)/g,
|
|
312
|
+
(_, key, _constraint, optional) => {
|
|
313
|
+
const value = params[key];
|
|
314
|
+
if (value === undefined) {
|
|
315
|
+
hadOmittedOptional = true;
|
|
316
|
+
return "";
|
|
317
|
+
}
|
|
318
|
+
return encodeURIComponent(value);
|
|
319
|
+
},
|
|
320
|
+
);
|
|
321
|
+
// Second pass: required params (no trailing ?)
|
|
322
|
+
result = result.replace(
|
|
323
|
+
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(?!\?)/g,
|
|
310
324
|
(_, key) => {
|
|
311
325
|
const value = params[key];
|
|
312
326
|
if (value === undefined) {
|
|
@@ -315,6 +329,11 @@ export function createReverse<TRoutes extends Record<string, string>>(
|
|
|
315
329
|
return encodeURIComponent(value);
|
|
316
330
|
},
|
|
317
331
|
);
|
|
332
|
+
// Clean up slashes only when an optional param was actually omitted,
|
|
333
|
+
// so intentional trailing-slash patterns like "/blog/" are preserved.
|
|
334
|
+
if (hadOmittedOptional) {
|
|
335
|
+
result = result.replace(/\/\/+/g, "/").replace(/\/+$/, "") || "/";
|
|
336
|
+
}
|
|
318
337
|
}
|
|
319
338
|
|
|
320
339
|
// Append search params as query string
|
|
@@ -166,9 +166,24 @@ export function createReverseFunction(
|
|
|
166
166
|
: hrefParams;
|
|
167
167
|
|
|
168
168
|
// Substitute params (strip constraint and optional syntax: :param(a|b)? -> value)
|
|
169
|
+
// Optional params (:param?) are omitted when not provided
|
|
169
170
|
if (effectiveParams) {
|
|
171
|
+
let hadOmittedOptional = false;
|
|
172
|
+
// First pass: optional params (trailing ?)
|
|
170
173
|
result = result.replace(
|
|
171
|
-
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))
|
|
174
|
+
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(\?)/g,
|
|
175
|
+
(_, key) => {
|
|
176
|
+
const value = effectiveParams[key];
|
|
177
|
+
if (value === undefined) {
|
|
178
|
+
hadOmittedOptional = true;
|
|
179
|
+
return "";
|
|
180
|
+
}
|
|
181
|
+
return encodeURIComponent(value);
|
|
182
|
+
},
|
|
183
|
+
);
|
|
184
|
+
// Second pass: required params (no trailing ?)
|
|
185
|
+
result = result.replace(
|
|
186
|
+
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(?!\?)/g,
|
|
172
187
|
(_, key) => {
|
|
173
188
|
const value = effectiveParams[key];
|
|
174
189
|
if (value === undefined) {
|
|
@@ -177,6 +192,11 @@ export function createReverseFunction(
|
|
|
177
192
|
return encodeURIComponent(value);
|
|
178
193
|
},
|
|
179
194
|
);
|
|
195
|
+
// Clean up slashes only when an optional param was actually omitted,
|
|
196
|
+
// so intentional trailing-slash patterns like "/blog/" are preserved.
|
|
197
|
+
if (hadOmittedOptional) {
|
|
198
|
+
result = result.replace(/\/\/+/g, "/").replace(/\/+$/, "") || "/";
|
|
199
|
+
}
|
|
180
200
|
}
|
|
181
201
|
|
|
182
202
|
// Append search params as query string
|