@jsenv/navi 0.15.7 → 0.15.8

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.
@@ -7365,7 +7365,10 @@ const buildRouteRelativeUrl = (
7365
7365
  // When a parameter is wrapped with rawUrlPart(), it bypasses encoding and is
7366
7366
  // inserted as-is into the URL. This allows including pre-encoded values or
7367
7367
  // special characters that should not be percent-encoded.
7368
- const encodeParamValue = (value) => {
7368
+ //
7369
+ // For wildcard parameters (isWildcard=true), we preserve slashes as path separators.
7370
+ // For named parameters and search params (isWildcard=false), we encode slashes.
7371
+ const encodeParamValue = (value, isWildcard = false) => {
7369
7372
  if (value && value[rawUrlPartSymbol]) {
7370
7373
  const rawValue = value.value;
7371
7374
  // Check if raw value contains invalid URL characters
@@ -7374,15 +7377,54 @@ const buildRouteRelativeUrl = (
7374
7377
  }
7375
7378
  return rawValue;
7376
7379
  }
7380
+
7381
+ if (isWildcard) {
7382
+ // For wildcards, only encode characters that are invalid in URL paths,
7383
+ // but preserve slashes as they are path separators
7384
+ return value
7385
+ ? value.replace(/[^a-zA-Z0-9\-._~!$&'()*+,;=:@/]/g, (char) => {
7386
+ return encodeURIComponent(char);
7387
+ })
7388
+ : value;
7389
+ }
7390
+
7391
+ // For named parameters and search params, encode everything including slashes
7377
7392
  return encodeURIComponent(value);
7378
7393
  };
7379
7394
  const extraParamMap = new Map();
7395
+ let wildcardIndex = 0; // Declare wildcard index in the main scope
7396
+
7380
7397
  if (params) {
7381
7398
  const keys = Object.keys(params);
7399
+
7400
+ // First, handle special case: optional groups immediately followed by wildcards
7401
+ // This handles patterns like {/}?* where the optional part should be included when wildcard has content
7402
+ relativeUrl = relativeUrl.replace(/\{([^}]*)\}\?\*/g, (match, group) => {
7403
+ const paramKey = wildcardIndex.toString();
7404
+ const paramValue = params[paramKey];
7405
+
7406
+ if (paramValue) {
7407
+ // Don't add to extraParamMap since we're processing it here
7408
+ // For wildcards, preserve slashes as path separators
7409
+ const wildcardValue = encodeParamValue(paramValue, true);
7410
+ wildcardIndex++;
7411
+ // Include the optional group content when wildcard has value
7412
+ return group + wildcardValue;
7413
+ }
7414
+ wildcardIndex++;
7415
+ // Remove the optional group and wildcard when no value
7416
+ return "";
7417
+ });
7418
+
7382
7419
  // Replace named parameters (:param and {param}) and remove optional markers
7383
7420
  for (const key of keys) {
7421
+ // Skip numeric keys (wildcards) if they were already processed
7422
+ if (!isNaN(key) && parseInt(key) < wildcardIndex) {
7423
+ continue;
7424
+ }
7425
+
7384
7426
  const value = params[key];
7385
- const encodedValue = encodeParamValue(value);
7427
+ const encodedValue = encodeParamValue(value, false); // Named parameters should encode slashes
7386
7428
  const beforeReplace = relativeUrl;
7387
7429
 
7388
7430
  // Replace parameter and remove optional marker if present
@@ -7405,7 +7447,7 @@ const buildRouteRelativeUrl = (
7405
7447
  // Check if any parameters in the group were provided
7406
7448
  for (const key of keys) {
7407
7449
  if (params[key] !== undefined) {
7408
- const encodedValue = encodeParamValue(params[key]);
7450
+ const encodedValue = encodeParamValue(params[key], false); // Named parameters encode slashes
7409
7451
  const paramPattern = new RegExp(`:${key}\\b`);
7410
7452
  if (paramPattern.test(processedGroup)) {
7411
7453
  processedGroup = processedGroup.replace(paramPattern, encodedValue);
@@ -7418,7 +7460,7 @@ const buildRouteRelativeUrl = (
7418
7460
  // Also check for literal parts that match parameter names (like /time where time is a param)
7419
7461
  for (const key of keys) {
7420
7462
  if (params[key] !== undefined) {
7421
- const encodedValue = encodeParamValue(params[key]);
7463
+ const encodedValue = encodeParamValue(params[key], false); // Named parameters encode slashes
7422
7464
  // Check for literal parts like /time that match parameter names
7423
7465
  const literalPattern = new RegExp(`\\/${key}\\b`);
7424
7466
  if (literalPattern.test(processedGroup)) {
@@ -7441,18 +7483,19 @@ const buildRouteRelativeUrl = (
7441
7483
  // Clean up any double slashes or trailing slashes that might result
7442
7484
  relativeUrl = relativeUrl.replace(/\/+/g, "/").replace(/\/$/, "");
7443
7485
 
7444
- // Handle remaining wildcards
7486
+ // Handle remaining wildcards (those not processed by optional group + wildcard above)
7445
7487
  if (params) {
7446
- let wildcardIndex = 0;
7447
7488
  relativeUrl = relativeUrl.replace(/\*/g, () => {
7448
7489
  const paramKey = wildcardIndex.toString();
7449
7490
  const paramValue = params[paramKey];
7450
7491
  if (paramValue) {
7451
7492
  extraParamMap.delete(paramKey);
7493
+ const replacement = encodeParamValue(paramValue, true); // Wildcards preserve slashes
7494
+ wildcardIndex++;
7495
+ return replacement;
7452
7496
  }
7453
- const replacement = paramValue ? encodeParamValue(paramValue) : "*";
7454
7497
  wildcardIndex++;
7455
- return replacement;
7498
+ return "*";
7456
7499
  });
7457
7500
  }
7458
7501
 
@@ -7481,7 +7524,7 @@ const buildRouteRelativeUrl = (
7481
7524
  if (value === true) {
7482
7525
  searchParamPairs.push(encodedKey);
7483
7526
  } else {
7484
- const encodedValue = encodeParamValue(value);
7527
+ const encodedValue = encodeParamValue(value, false); // Search params encode slashes
7485
7528
  searchParamPairs.push(`${encodedKey}=${encodedValue}`);
7486
7529
  }
7487
7530
  }