next
Version:
The React Framework
196 lines (195 loc) • 7.77 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
PARAMETER_PATTERN: null,
getDynamicParam: null,
interpolateParallelRouteParams: null,
parseMatchedParameter: null,
parseParameter: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
PARAMETER_PATTERN: function() {
return PARAMETER_PATTERN;
},
getDynamicParam: function() {
return getDynamicParam;
},
interpolateParallelRouteParams: function() {
return interpolateParallelRouteParams;
},
parseMatchedParameter: function() {
return parseMatchedParameter;
},
parseParameter: function() {
return parseParameter;
}
});
const _invarianterror = require("../../invariant-error");
const _parseloadertree = require("./parse-loader-tree");
const _getsegmentparam = require("./get-segment-param");
/**
* Gets the value of a param from the params object. This correctly handles the
* case where the param is a fallback route param and encodes the resulting
* value.
*
* @param interpolatedParams - The params object.
* @param segmentKey - The key of the segment.
* @param fallbackRouteParams - The fallback route params.
* @returns The value of the param.
*/ function getParamValue(interpolatedParams, segmentKey, fallbackRouteParams) {
let value = interpolatedParams[segmentKey];
if (fallbackRouteParams?.has(segmentKey)) {
// We know that the fallback route params has the segment key because we
// checked that above.
const [searchValue] = fallbackRouteParams.get(segmentKey);
value = searchValue;
} else if (Array.isArray(value)) {
value = value.map((i)=>encodeURIComponent(i));
} else if (typeof value === 'string') {
value = encodeURIComponent(value);
}
return value;
}
function interpolateParallelRouteParams(loaderTree, params, pagePath, fallbackRouteParams) {
const interpolated = structuredClone(params);
// Stack-based traversal with depth tracking
const stack = [
{
tree: loaderTree,
depth: 0
}
];
// Derive value from pagePath based on depth and parameter type
const pathSegments = pagePath.split('/').slice(1) // Remove first empty string
;
while(stack.length > 0){
const { tree, depth } = stack.pop();
const { segment, parallelRoutes } = (0, _parseloadertree.parseLoaderTree)(tree);
// Check if current segment contains a parameter
const segmentParam = (0, _getsegmentparam.getSegmentParam)(segment);
if (segmentParam && !interpolated.hasOwnProperty(segmentParam.param) && // If the param is in the fallback route params, we don't need to
// interpolate it because it's already marked as being unknown.
!fallbackRouteParams?.has(segmentParam.param)) {
switch(segmentParam.type){
case 'catchall':
case 'optional-catchall':
case 'catchall-intercepted-(..)(..)':
case 'catchall-intercepted-(.)':
case 'catchall-intercepted-(..)':
case 'catchall-intercepted-(...)':
// For catchall parameters, take all remaining segments from this depth
const remainingSegments = pathSegments.slice(depth);
// Process each segment to handle any dynamic params
const processedSegments = remainingSegments.flatMap((pathSegment)=>{
const param = (0, _getsegmentparam.getSegmentParam)(pathSegment);
// If the segment matches a param, return the param value otherwise,
// it's a static segment, so just return that. We don't use the
// `getParamValue` function here because we don't want the values to
// be encoded, that's handled on get by the `getDynamicParam`
// function.
return param ? interpolated[param.param] : pathSegment;
}).filter((s)=>s !== undefined);
if (processedSegments.length > 0) {
interpolated[segmentParam.param] = processedSegments;
}
break;
case 'dynamic':
case 'dynamic-intercepted-(..)(..)':
case 'dynamic-intercepted-(.)':
case 'dynamic-intercepted-(..)':
case 'dynamic-intercepted-(...)':
// For regular dynamic parameters, take the segment at this depth
if (depth < pathSegments.length) {
const pathSegment = pathSegments[depth];
const param = (0, _getsegmentparam.getSegmentParam)(pathSegment);
interpolated[segmentParam.param] = param ? interpolated[param.param] : pathSegment;
}
break;
default:
segmentParam.type;
}
}
// Calculate next depth - increment if this is not a route group and not empty
let nextDepth = depth;
const isRouteGroup = segment.startsWith('(') && segment.endsWith(')');
if (!isRouteGroup && segment !== '') {
nextDepth++;
}
// Add all parallel routes to the stack for processing
for (const route of Object.values(parallelRoutes)){
stack.push({
tree: route,
depth: nextDepth
});
}
}
return interpolated;
}
function getDynamicParam(interpolatedParams, segmentKey, dynamicParamType, fallbackRouteParams) {
let value = getParamValue(interpolatedParams, segmentKey, fallbackRouteParams);
// handle the case where an optional catchall does not have a value,
// e.g. `/dashboard/[[...slug]]` when requesting `/dashboard`
if (!value || value.length === 0) {
if (dynamicParamType === 'oc') {
return {
param: segmentKey,
value: null,
type: dynamicParamType,
treeSegment: [
segmentKey,
'',
dynamicParamType
]
};
}
throw Object.defineProperty(new _invarianterror.InvariantError(`Missing value for segment key: "${segmentKey}" with dynamic param type: ${dynamicParamType}`), "__NEXT_ERROR_CODE", {
value: "E864",
enumerable: false,
configurable: true
});
}
return {
param: segmentKey,
// The value that is passed to user code.
value,
// The value that is rendered in the router tree.
treeSegment: [
segmentKey,
Array.isArray(value) ? value.join('/') : value,
dynamicParamType
],
type: dynamicParamType
};
}
const PARAMETER_PATTERN = /^([^[]*)\[((?:\[[^\]]*\])|[^\]]+)\](.*)$/;
function parseParameter(param) {
const match = param.match(PARAMETER_PATTERN);
if (!match) {
return parseMatchedParameter(param);
}
return parseMatchedParameter(match[2]);
}
function parseMatchedParameter(param) {
const optional = param.startsWith('[') && param.endsWith(']');
if (optional) {
param = param.slice(1, -1);
}
const repeat = param.startsWith('...');
if (repeat) {
param = param.slice(3);
}
return {
key: param,
repeat,
optional
};
}
//# sourceMappingURL=get-dynamic-param.js.map