@tanstack/router-core 1.120.4-alpha.19 → 1.120.4
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/cjs/fileRoute.d.cts +2 -6
- package/dist/cjs/index.cjs +0 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +6 -6
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +1 -18
- package/dist/cjs/path.cjs +16 -130
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +0 -17
- package/dist/cjs/redirect.cjs +14 -17
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/redirect.d.cts +7 -13
- package/dist/cjs/route.cjs +1 -12
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +14 -15
- package/dist/cjs/router.cjs +155 -231
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -46
- package/dist/cjs/scroll-restoration.cjs +23 -12
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.d.cts +1 -1
- package/dist/cjs/typePrimitives.d.cts +2 -2
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +0 -2
- package/dist/esm/fileRoute.d.ts +2 -6
- package/dist/esm/index.d.ts +6 -6
- package/dist/esm/index.js +2 -5
- package/dist/esm/link.d.ts +1 -18
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/path.d.ts +0 -17
- package/dist/esm/path.js +16 -130
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/redirect.d.ts +7 -13
- package/dist/esm/redirect.js +14 -17
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/route.d.ts +14 -15
- package/dist/esm/route.js +1 -12
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +3 -46
- package/dist/esm/router.js +158 -234
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +1 -1
- package/dist/esm/scroll-restoration.js +23 -12
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/typePrimitives.d.ts +2 -2
- package/dist/esm/utils.d.ts +0 -2
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/fileRoute.ts +1 -90
- package/src/index.ts +6 -14
- package/src/link.ts +11 -97
- package/src/path.ts +16 -181
- package/src/redirect.ts +22 -37
- package/src/route.ts +35 -104
- package/src/router.ts +209 -332
- package/src/scroll-restoration.ts +44 -27
- package/src/typePrimitives.ts +2 -2
- package/src/utils.ts +0 -14
package/dist/esm/link.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sources":["../../src/link.ts"],"sourcesContent":["import type { HistoryState, ParsedHistoryState } from '@tanstack/history'\nimport type {\n AllParams,\n CatchAllPaths,\n CurrentPath,\n FullSearchSchema,\n FullSearchSchemaInput,\n ParentPath,\n RouteByPath,\n RouteByToPath,\n RoutePaths,\n RouteToPath,\n ToPath,\n} from './routeInfo'\nimport type {\n AnyRouter,\n RegisteredRouter,\n ViewTransitionOptions,\n} from './router'\nimport type {\n ConstrainLiteral,\n Expand,\n MakeDifferenceOptional,\n NoInfer,\n NonNullableUpdater,\n Updater,\n} from './utils'\nimport type { ParsedLocation } from './location'\n\nexport type IsRequiredParams<TParams> =\n Record<never, never> extends TParams ? never : true\n\nexport interface ParsePathParamsResult<\n in out TRequired,\n in out TOptional,\n in out TRest,\n> {\n required: TRequired\n optional: TOptional\n rest: TRest\n}\n\nexport type AnyParsePathParamsResult = ParsePathParamsResult<\n string,\n string,\n string\n>\n\nexport type ParsePathParamsBoundaryStart<T extends string> =\n T extends `${infer TLeft}{-${infer TRight}`\n ? ParsePathParamsResult<\n ParsePathParams<TLeft>['required'],\n | ParsePathParams<TLeft>['optional']\n | ParsePathParams<TRight>['required']\n | ParsePathParams<TRight>['optional'],\n ParsePathParams<TRight>['rest']\n >\n : T extends `${infer TLeft}{${infer TRight}`\n ? ParsePathParamsResult<\n | ParsePathParams<TLeft>['required']\n | ParsePathParams<TRight>['required'],\n | ParsePathParams<TLeft>['optional']\n | ParsePathParams<TRight>['optional'],\n ParsePathParams<TRight>['rest']\n >\n : never\n\nexport type ParsePathParamsSymbol<T extends string> =\n T extends `${string}$${infer TRight}`\n ? TRight extends `${string}/${string}`\n ? TRight extends `${infer TParam}/${infer TRest}`\n ? TParam extends ''\n ? ParsePathParamsResult<\n ParsePathParams<TRest>['required'],\n '_splat' | ParsePathParams<TRest>['optional'],\n ParsePathParams<TRest>['rest']\n >\n : ParsePathParamsResult<\n TParam | ParsePathParams<TRest>['required'],\n ParsePathParams<TRest>['optional'],\n ParsePathParams<TRest>['rest']\n >\n : never\n : TRight extends ''\n ? ParsePathParamsResult<never, '_splat', never>\n : ParsePathParamsResult<TRight, never, never>\n : never\n\nexport type ParsePathParamsBoundaryEnd<T extends string> =\n T extends `${infer TLeft}}${infer TRight}`\n ? ParsePathParamsResult<\n | ParsePathParams<TLeft>['required']\n | ParsePathParams<TRight>['required'],\n | ParsePathParams<TLeft>['optional']\n | ParsePathParams<TRight>['optional'],\n ParsePathParams<TRight>['rest']\n >\n : never\n\nexport type ParsePathParamsEscapeStart<T extends string> =\n T extends `${infer TLeft}[${infer TRight}`\n ? ParsePathParamsResult<\n | ParsePathParams<TLeft>['required']\n | ParsePathParams<TRight>['required'],\n | ParsePathParams<TLeft>['optional']\n | ParsePathParams<TRight>['optional'],\n ParsePathParams<TRight>['rest']\n >\n : never\n\nexport type ParsePathParamsEscapeEnd<T extends string> =\n T extends `${string}]${infer TRight}` ? ParsePathParams<TRight> : never\n\nexport type ParsePathParams<T extends string> = T extends `${string}[${string}`\n ? ParsePathParamsEscapeStart<T>\n : T extends `${string}]${string}`\n ? ParsePathParamsEscapeEnd<T>\n : T extends `${string}}${string}`\n ? ParsePathParamsBoundaryEnd<T>\n : T extends `${string}{${string}`\n ? ParsePathParamsBoundaryStart<T>\n : T extends `${string}$${string}`\n ? ParsePathParamsSymbol<T>\n : never\n\nexport type AddTrailingSlash<T> = T extends `${string}/` ? T : `${T & string}/`\n\nexport type RemoveTrailingSlashes<T> = T & `${string}/` extends never\n ? T\n : T extends `${infer R}/`\n ? R\n : T\n\nexport type AddLeadingSlash<T> = T & `/${string}` extends never\n ? `/${T & string}`\n : T\n\nexport type RemoveLeadingSlashes<T> = T & `/${string}` extends never\n ? T\n : T extends `/${infer R}`\n ? R\n : T\n\ntype JoinPath<TLeft extends string, TRight extends string> = TRight extends ''\n ? TLeft\n : TLeft extends ''\n ? TRight\n : `${RemoveTrailingSlashes<TLeft>}/${RemoveLeadingSlashes<TRight>}`\n\ntype RemoveLastSegment<\n T extends string,\n TAcc extends string = '',\n> = T extends `${infer TSegment}/${infer TRest}`\n ? TRest & `${string}/${string}` extends never\n ? TRest extends ''\n ? TAcc\n : `${TAcc}${TSegment}`\n : RemoveLastSegment<TRest, `${TAcc}${TSegment}/`>\n : TAcc\n\nexport type ResolveCurrentPath<\n TFrom extends string,\n TTo extends string,\n> = TTo extends '.'\n ? TFrom\n : TTo extends './'\n ? AddTrailingSlash<TFrom>\n : TTo & `./${string}` extends never\n ? never\n : TTo extends `./${infer TRest}`\n ? AddLeadingSlash<JoinPath<TFrom, TRest>>\n : never\n\nexport type ResolveParentPath<\n TFrom extends string,\n TTo extends string,\n> = TTo extends '../' | '..'\n ? TFrom extends '' | '/'\n ? never\n : AddLeadingSlash<RemoveLastSegment<TFrom>>\n : TTo & `../${string}` extends never\n ? AddLeadingSlash<JoinPath<TFrom, TTo>>\n : TFrom extends '' | '/'\n ? never\n : TTo extends `../${infer ToRest}`\n ? ResolveParentPath<RemoveLastSegment<TFrom>, ToRest>\n : AddLeadingSlash<JoinPath<TFrom, TTo>>\n\nexport type ResolveRelativePath<TFrom, TTo = '.'> = string extends TFrom\n ? TTo\n : string extends TTo\n ? TFrom\n : undefined extends TTo\n ? TFrom\n : TTo extends string\n ? TFrom extends string\n ? TTo extends `/${string}`\n ? TTo\n : TTo extends `..${string}`\n ? ResolveParentPath<TFrom, TTo>\n : TTo extends `.${string}`\n ? ResolveCurrentPath<TFrom, TTo>\n : AddLeadingSlash<JoinPath<TFrom, TTo>>\n : never\n : never\n\nexport type FindDescendantToPaths<\n TRouter extends AnyRouter,\n TPrefix extends string,\n> = `${TPrefix}/${string}` & RouteToPath<TRouter>\n\nexport type InferDescendantToPaths<\n TRouter extends AnyRouter,\n TPrefix extends string,\n TPaths = FindDescendantToPaths<TRouter, TPrefix>,\n> = TPaths extends `${TPrefix}/`\n ? never\n : TPaths extends `${TPrefix}/${infer TRest}`\n ? TRest\n : never\n\nexport type RelativeToPath<\n TRouter extends AnyRouter,\n TTo extends string,\n TResolvedPath extends string,\n> =\n | (TResolvedPath & RouteToPath<TRouter> extends never\n ? never\n : ToPath<TRouter, TTo>)\n | `${RemoveTrailingSlashes<TTo>}/${InferDescendantToPaths<TRouter, RemoveTrailingSlashes<TResolvedPath>>}`\n\nexport type RelativeToParentPath<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n TResolvedPath extends string = ResolveRelativePath<TFrom, TTo>,\n> =\n | RelativeToPath<TRouter, TTo, TResolvedPath>\n | (TTo extends `${string}..` | `${string}../`\n ? TResolvedPath extends '/' | ''\n ? never\n : FindDescendantToPaths<\n TRouter,\n RemoveTrailingSlashes<TResolvedPath>\n > extends never\n ? never\n : `${RemoveTrailingSlashes<TTo>}/${ParentPath<TRouter>}`\n : never)\n\nexport type RelativeToCurrentPath<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n TResolvedPath extends string = ResolveRelativePath<TFrom, TTo>,\n> = RelativeToPath<TRouter, TTo, TResolvedPath> | CurrentPath<TRouter>\n\nexport type AbsoluteToPath<TRouter extends AnyRouter, TFrom extends string> =\n | (string extends TFrom\n ? CurrentPath<TRouter>\n : TFrom extends `/`\n ? never\n : CurrentPath<TRouter>)\n | (string extends TFrom\n ? ParentPath<TRouter>\n : TFrom extends `/`\n ? never\n : ParentPath<TRouter>)\n | RouteToPath<TRouter>\n | (TFrom extends '/'\n ? never\n : string extends TFrom\n ? never\n : InferDescendantToPaths<TRouter, RemoveTrailingSlashes<TFrom>>)\n\nexport type RelativeToPathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n> = string extends TTo\n ? string\n : string extends TFrom\n ? AbsoluteToPath<TRouter, TFrom>\n : TTo & `..${string}` extends never\n ? TTo & `.${string}` extends never\n ? AbsoluteToPath<TRouter, TFrom>\n : RelativeToCurrentPath<TRouter, TFrom, TTo>\n : RelativeToParentPath<TRouter, TFrom, TTo>\n\nexport type NavigateOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & NavigateOptionProps\n\n/**\n * The NavigateOptions type is used to describe the options that can be used when describing a navigation action in TanStack Router.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType)\n */\nexport interface NavigateOptionProps {\n /**\n * If set to `true`, the router will scroll the element with an id matching the hash into view with default `ScrollIntoViewOptions`.\n * If set to `false`, the router will not scroll the element with an id matching the hash into view.\n * If set to `ScrollIntoViewOptions`, the router will scroll the element with an id matching the hash into view with the provided options.\n * @default true\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#hashscrollintoview)\n * @see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)\n */\n hashScrollIntoView?: boolean | ScrollIntoViewOptions\n /**\n * `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.\n * @default false\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#replace)\n */\n replace?: boolean\n /**\n * Defaults to `true` so that the scroll position will be reset to 0,0 after the location is committed to the browser history.\n * If `false`, the scroll position will not be reset to 0,0 after the location is committed to history.\n * @default true\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#resetscroll)\n */\n resetScroll?: boolean\n /** @deprecated All navigations now use startTransition under the hood */\n startTransition?: boolean\n /**\n * If set to `true`, the router will wrap the resulting navigation in a `document.startViewTransition()` call.\n * If `ViewTransitionOptions`, route navigations will be called using `document.startViewTransition({update, types})`\n * where `types` will be the strings array passed with `ViewTransitionOptions[\"types\"]`.\n * If the browser does not support viewTransition types, the navigation will fall back to normal `document.startTransition()`, same as if `true` was passed.\n *\n * If the browser does not support this api, this option will be ignored.\n * @default false\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#viewtransition)\n * @see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition)\n * @see [Google](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#view-transition-types)\n */\n viewTransition?: boolean | ViewTransitionOptions\n /**\n * If `true`, navigation will ignore any blockers that might prevent it.\n * @default false\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#ignoreblocker)\n */\n ignoreBlocker?: boolean\n /**\n * If `true`, navigation to a route inside of router will trigger a full page load instead of the traditional SPA navigation.\n * @default false\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#reloaddocument)\n */\n reloadDocument?: boolean\n /**\n * This can be used instead of `to` to navigate to a fully built href, e.g. pointing to an external target.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#href)\n */\n href?: string\n}\n\nexport type ToOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = ToSubOptions<TRouter, TFrom, TTo> & MaskOptions<TRouter, TMaskFrom, TMaskTo>\n\nexport interface MaskOptions<\n in out TRouter extends AnyRouter,\n in out TMaskFrom extends string,\n in out TMaskTo extends string,\n> {\n _fromLocation?: ParsedLocation\n mask?: ToMaskOptions<TRouter, TMaskFrom, TMaskTo>\n}\n\nexport type ToMaskOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TMaskFrom extends string = string,\n TMaskTo extends string = '.',\n> = ToSubOptions<TRouter, TMaskFrom, TMaskTo> & {\n unmaskOnReload?: boolean\n}\n\nexport type ToSubOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n> = ToSubOptionsProps<TRouter, TFrom, TTo> &\n SearchParamOptions<TRouter, TFrom, TTo> &\n PathParamOptions<TRouter, TFrom, TTo>\n\nexport interface RequiredToOptions<\n in out TRouter extends AnyRouter,\n in out TFrom extends string,\n in out TTo extends string | undefined,\n> {\n to: ToPathOption<TRouter, TFrom, TTo> & {}\n}\n\nexport interface OptionalToOptions<\n in out TRouter extends AnyRouter,\n in out TFrom extends string,\n in out TTo extends string | undefined,\n> {\n to?: ToPathOption<TRouter, TFrom, TTo> & {}\n}\n\nexport type MakeToRequired<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string | undefined,\n> = string extends TFrom\n ? string extends TTo\n ? OptionalToOptions<TRouter, TFrom, TTo>\n : TTo & CatchAllPaths<TRouter> extends never\n ? RequiredToOptions<TRouter, TFrom, TTo>\n : OptionalToOptions<TRouter, TFrom, TTo>\n : OptionalToOptions<TRouter, TFrom, TTo>\n\nexport type ToSubOptionsProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string | undefined = '.',\n> = MakeToRequired<TRouter, TFrom, TTo> & {\n hash?: true | Updater<string>\n state?: true | NonNullableUpdater<ParsedHistoryState, HistoryState>\n from?: FromPathOption<TRouter, TFrom> & {}\n relative?: 'route' | 'path'\n}\n\nexport type ParamsReducerFn<\n in out TRouter extends AnyRouter,\n in out TParamVariant extends ParamVariant,\n in out TFrom,\n in out TTo,\n> = (\n current: Expand<ResolveFromParams<TRouter, TParamVariant, TFrom>>,\n) => Expand<ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>>\n\ntype ParamsReducer<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n | Expand<ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>>\n | (ParamsReducerFn<TRouter, TParamVariant, TFrom, TTo> & {})\n\ntype ParamVariant = 'PATH' | 'SEARCH'\n\nexport type ResolveRoute<\n TRouter extends AnyRouter,\n TFrom,\n TTo,\n TPath = ResolveRelativePath<TFrom, TTo>,\n> = TPath extends string\n ? TFrom extends TPath\n ? RouteByPath<TRouter['routeTree'], TPath>\n : RouteByToPath<TRouter, TPath>\n : never\n\ntype ResolveFromParamType<TParamVariant extends ParamVariant> =\n TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchema'\n\ntype ResolveFromAllParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n> = TParamVariant extends 'PATH'\n ? AllParams<TRouter['routeTree']>\n : FullSearchSchema<TRouter['routeTree']>\n\ntype ResolveFromParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n> = string extends TFrom\n ? ResolveFromAllParams<TRouter, TParamVariant>\n : RouteByPath<\n TRouter['routeTree'],\n TFrom\n >['types'][ResolveFromParamType<TParamVariant>]\n\ntype ResolveToParamType<TParamVariant extends ParamVariant> =\n TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchemaInput'\n\ntype ResolveAllToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n> = TParamVariant extends 'PATH'\n ? AllParams<TRouter['routeTree']>\n : FullSearchSchemaInput<TRouter['routeTree']>\n\nexport type ResolveToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n ResolveRelativePath<TFrom, TTo> extends infer TPath\n ? undefined extends TPath\n ? never\n : string extends TPath\n ? ResolveAllToParams<TRouter, TParamVariant>\n : TPath extends CatchAllPaths<TRouter>\n ? ResolveAllToParams<TRouter, TParamVariant>\n : ResolveRoute<\n TRouter,\n TFrom,\n TTo\n >['types'][ResolveToParamType<TParamVariant>]\n : never\n\ntype ResolveRelativeToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n TToParams = ResolveToParams<TRouter, TParamVariant, TFrom, TTo>,\n> = TParamVariant extends 'SEARCH'\n ? TToParams\n : string extends TFrom\n ? TToParams\n : MakeDifferenceOptional<\n ResolveFromParams<TRouter, TParamVariant, TFrom>,\n TToParams\n >\n\nexport interface MakeOptionalSearchParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n search?: true | (ParamsReducer<TRouter, 'SEARCH', TFrom, TTo> & {})\n}\n\nexport interface MakeOptionalPathParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n params?: true | (ParamsReducer<TRouter, 'PATH', TFrom, TTo> & {})\n}\n\ntype MakeRequiredParamsReducer<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n | (string extends TFrom\n ? never\n : ResolveFromParams<\n TRouter,\n TParamVariant,\n TFrom\n > extends ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>\n ? true\n : never)\n | (ParamsReducer<TRouter, TParamVariant, TFrom, TTo> & {})\n\nexport interface MakeRequiredPathParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n params: MakeRequiredParamsReducer<TRouter, 'PATH', TFrom, TTo> & {}\n}\n\nexport interface MakeRequiredSearchParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n search: MakeRequiredParamsReducer<TRouter, 'SEARCH', TFrom, TTo> & {}\n}\n\nexport type IsRequired<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n ResolveRelativePath<TFrom, TTo> extends infer TPath\n ? undefined extends TPath\n ? never\n : TPath extends CatchAllPaths<TRouter>\n ? never\n : IsRequiredParams<\n ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>\n >\n : never\n\nexport type SearchParamOptions<TRouter extends AnyRouter, TFrom, TTo> =\n IsRequired<TRouter, 'SEARCH', TFrom, TTo> extends never\n ? MakeOptionalSearchParams<TRouter, TFrom, TTo>\n : MakeRequiredSearchParams<TRouter, TFrom, TTo>\n\nexport type PathParamOptions<TRouter extends AnyRouter, TFrom, TTo> =\n IsRequired<TRouter, 'PATH', TFrom, TTo> extends never\n ? MakeOptionalPathParams<TRouter, TFrom, TTo>\n : MakeRequiredPathParams<TRouter, TFrom, TTo>\n\nexport type ToPathOption<\n TRouter extends AnyRouter = AnyRouter,\n TFrom extends string = string,\n TTo extends string | undefined = string,\n> = ConstrainLiteral<\n TTo,\n RelativeToPathAutoComplete<\n TRouter,\n NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',\n NoInfer<TTo> & string\n >\n>\n\nexport type FromPathOption<TRouter extends AnyRouter, TFrom> = ConstrainLiteral<\n TFrom,\n RoutePaths<TRouter['routeTree']>\n>\n\n/**\n * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/navigation#active-options)\n */\nexport interface ActiveOptions {\n /**\n * If true, the link will be active if the current route matches the `to` route path exactly (no children routes)\n * @default false\n */\n exact?: boolean\n /**\n * If true, the link will only be active if the current URL hash matches the `hash` prop\n * @default false\n */\n includeHash?: boolean\n /**\n * If true, the link will only be active if the current URL search params inclusively match the `search` prop\n * @default true\n */\n includeSearch?: boolean\n /**\n * This modifies the `includeSearch` behavior.\n * If true, properties in `search` that are explicitly `undefined` must NOT be present in the current URL search params for the link to be active.\n * @default false\n */\n explicitUndefined?: boolean\n}\n\nexport interface LinkOptionsProps {\n /**\n * The standard anchor tag target attribute\n */\n target?: HTMLAnchorElement['target']\n /**\n * Configurable options to determine if the link should be considered active or not\n * @default {exact:true,includeHash:true}\n */\n activeOptions?: ActiveOptions\n /**\n * The preloading strategy for this link\n * - `false` - No preloading\n * - `'intent'` - Preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.\n * - `'viewport'` - Preload the linked route when it enters the viewport\n */\n preload?: false | 'intent' | 'viewport' | 'render'\n /**\n * When a preload strategy is set, this delays the preload by this many milliseconds.\n * If the user exits the link before this delay, the preload will be cancelled.\n */\n preloadDelay?: number\n /**\n * Control whether the link should be disabled or not\n * If set to `true`, the link will be rendered without an `href` attribute\n * @default false\n */\n disabled?: boolean\n /**\n * When the preload strategy is set to `intent`, this controls the proximity of the link to the cursor before it is preloaded.\n * If the user exits this proximity before this delay, the preload will be cancelled.\n */\n preloadIntentProximity?: number\n}\n\nexport type LinkOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & LinkOptionsProps\n\nexport type LinkCurrentTargetElement = {\n preloadTimeout?: null | ReturnType<typeof setTimeout>\n}\n\nexport const preloadWarning = 'Error preloading route! ☝️'\n"],"names":[],"mappings":"AAqrBO,MAAM,iBAAiB;"}
|
|
1
|
+
{"version":3,"file":"link.js","sources":["../../src/link.ts"],"sourcesContent":["import type { HistoryState, ParsedHistoryState } from '@tanstack/history'\nimport type {\n AllParams,\n CatchAllPaths,\n CurrentPath,\n FullSearchSchema,\n FullSearchSchemaInput,\n ParentPath,\n RouteByPath,\n RouteByToPath,\n RoutePaths,\n RouteToPath,\n ToPath,\n} from './routeInfo'\nimport type {\n AnyRouter,\n RegisteredRouter,\n ViewTransitionOptions,\n} from './router'\nimport type {\n ConstrainLiteral,\n Expand,\n MakeDifferenceOptional,\n NoInfer,\n NonNullableUpdater,\n Updater,\n} from './utils'\nimport type { ParsedLocation } from './location'\n\nexport type IsRequiredParams<TParams> =\n Record<never, never> extends TParams ? never : true\n\nexport type ParsePathParams<T extends string, TAcc = never> = T &\n `${string}$${string}` extends never\n ? TAcc\n : T extends `${string}$${infer TPossiblyParam}`\n ? TPossiblyParam extends ''\n ? TAcc\n : TPossiblyParam & `${string}/${string}` extends never\n ? TPossiblyParam | TAcc\n : TPossiblyParam extends `${infer TParam}/${infer TRest}`\n ? ParsePathParams<TRest, TParam extends '' ? TAcc : TParam | TAcc>\n : never\n : TAcc\n\nexport type AddTrailingSlash<T> = T extends `${string}/` ? T : `${T & string}/`\n\nexport type RemoveTrailingSlashes<T> = T & `${string}/` extends never\n ? T\n : T extends `${infer R}/`\n ? R\n : T\n\nexport type AddLeadingSlash<T> = T & `/${string}` extends never\n ? `/${T & string}`\n : T\n\nexport type RemoveLeadingSlashes<T> = T & `/${string}` extends never\n ? T\n : T extends `/${infer R}`\n ? R\n : T\n\ntype JoinPath<TLeft extends string, TRight extends string> = TRight extends ''\n ? TLeft\n : TLeft extends ''\n ? TRight\n : `${RemoveTrailingSlashes<TLeft>}/${RemoveLeadingSlashes<TRight>}`\n\ntype RemoveLastSegment<\n T extends string,\n TAcc extends string = '',\n> = T extends `${infer TSegment}/${infer TRest}`\n ? TRest & `${string}/${string}` extends never\n ? TRest extends ''\n ? TAcc\n : `${TAcc}${TSegment}`\n : RemoveLastSegment<TRest, `${TAcc}${TSegment}/`>\n : TAcc\n\nexport type ResolveCurrentPath<\n TFrom extends string,\n TTo extends string,\n> = TTo extends '.'\n ? TFrom\n : TTo extends './'\n ? AddTrailingSlash<TFrom>\n : TTo & `./${string}` extends never\n ? never\n : TTo extends `./${infer TRest}`\n ? AddLeadingSlash<JoinPath<TFrom, TRest>>\n : never\n\nexport type ResolveParentPath<\n TFrom extends string,\n TTo extends string,\n> = TTo extends '../' | '..'\n ? TFrom extends '' | '/'\n ? never\n : AddLeadingSlash<RemoveLastSegment<TFrom>>\n : TTo & `../${string}` extends never\n ? AddLeadingSlash<JoinPath<TFrom, TTo>>\n : TFrom extends '' | '/'\n ? never\n : TTo extends `../${infer ToRest}`\n ? ResolveParentPath<RemoveLastSegment<TFrom>, ToRest>\n : AddLeadingSlash<JoinPath<TFrom, TTo>>\n\nexport type ResolveRelativePath<TFrom, TTo = '.'> = string extends TFrom\n ? TTo\n : string extends TTo\n ? TFrom\n : undefined extends TTo\n ? TFrom\n : TTo extends string\n ? TFrom extends string\n ? TTo extends `/${string}`\n ? TTo\n : TTo extends `..${string}`\n ? ResolveParentPath<TFrom, TTo>\n : TTo extends `.${string}`\n ? ResolveCurrentPath<TFrom, TTo>\n : AddLeadingSlash<JoinPath<TFrom, TTo>>\n : never\n : never\n\nexport type FindDescendantToPaths<\n TRouter extends AnyRouter,\n TPrefix extends string,\n> = `${TPrefix}/${string}` & RouteToPath<TRouter>\n\nexport type InferDescendantToPaths<\n TRouter extends AnyRouter,\n TPrefix extends string,\n TPaths = FindDescendantToPaths<TRouter, TPrefix>,\n> = TPaths extends `${TPrefix}/`\n ? never\n : TPaths extends `${TPrefix}/${infer TRest}`\n ? TRest\n : never\n\nexport type RelativeToPath<\n TRouter extends AnyRouter,\n TTo extends string,\n TResolvedPath extends string,\n> =\n | (TResolvedPath & RouteToPath<TRouter> extends never\n ? never\n : ToPath<TRouter, TTo>)\n | `${RemoveTrailingSlashes<TTo>}/${InferDescendantToPaths<TRouter, RemoveTrailingSlashes<TResolvedPath>>}`\n\nexport type RelativeToParentPath<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n TResolvedPath extends string = ResolveRelativePath<TFrom, TTo>,\n> =\n | RelativeToPath<TRouter, TTo, TResolvedPath>\n | (TTo extends `${string}..` | `${string}../`\n ? TResolvedPath extends '/' | ''\n ? never\n : FindDescendantToPaths<\n TRouter,\n RemoveTrailingSlashes<TResolvedPath>\n > extends never\n ? never\n : `${RemoveTrailingSlashes<TTo>}/${ParentPath<TRouter>}`\n : never)\n\nexport type RelativeToCurrentPath<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n TResolvedPath extends string = ResolveRelativePath<TFrom, TTo>,\n> = RelativeToPath<TRouter, TTo, TResolvedPath> | CurrentPath<TRouter>\n\nexport type AbsoluteToPath<TRouter extends AnyRouter, TFrom extends string> =\n | (string extends TFrom\n ? CurrentPath<TRouter>\n : TFrom extends `/`\n ? never\n : CurrentPath<TRouter>)\n | (string extends TFrom\n ? ParentPath<TRouter>\n : TFrom extends `/`\n ? never\n : ParentPath<TRouter>)\n | RouteToPath<TRouter>\n | (TFrom extends '/'\n ? never\n : string extends TFrom\n ? never\n : InferDescendantToPaths<TRouter, RemoveTrailingSlashes<TFrom>>)\n\nexport type RelativeToPathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n> = string extends TTo\n ? string\n : string extends TFrom\n ? AbsoluteToPath<TRouter, TFrom>\n : TTo & `..${string}` extends never\n ? TTo & `.${string}` extends never\n ? AbsoluteToPath<TRouter, TFrom>\n : RelativeToCurrentPath<TRouter, TFrom, TTo>\n : RelativeToParentPath<TRouter, TFrom, TTo>\n\nexport type NavigateOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & NavigateOptionProps\n\n/**\n * The NavigateOptions type is used to describe the options that can be used when describing a navigation action in TanStack Router.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType)\n */\nexport interface NavigateOptionProps {\n /**\n * If set to `true`, the router will scroll the element with an id matching the hash into view with default `ScrollIntoViewOptions`.\n * If set to `false`, the router will not scroll the element with an id matching the hash into view.\n * If set to `ScrollIntoViewOptions`, the router will scroll the element with an id matching the hash into view with the provided options.\n * @default true\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#hashscrollintoview)\n * @see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)\n */\n hashScrollIntoView?: boolean | ScrollIntoViewOptions\n /**\n * `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.\n * @default false\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#replace)\n */\n replace?: boolean\n /**\n * Defaults to `true` so that the scroll position will be reset to 0,0 after the location is committed to the browser history.\n * If `false`, the scroll position will not be reset to 0,0 after the location is committed to history.\n * @default true\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#resetscroll)\n */\n resetScroll?: boolean\n /** @deprecated All navigations now use startTransition under the hood */\n startTransition?: boolean\n /**\n * If set to `true`, the router will wrap the resulting navigation in a `document.startViewTransition()` call.\n * If `ViewTransitionOptions`, route navigations will be called using `document.startViewTransition({update, types})`\n * where `types` will be the strings array passed with `ViewTransitionOptions[\"types\"]`.\n * If the browser does not support viewTransition types, the navigation will fall back to normal `document.startTransition()`, same as if `true` was passed.\n *\n * If the browser does not support this api, this option will be ignored.\n * @default false\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#viewtransition)\n * @see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition)\n * @see [Google](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#view-transition-types)\n */\n viewTransition?: boolean | ViewTransitionOptions\n /**\n * If `true`, navigation will ignore any blockers that might prevent it.\n * @default false\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#ignoreblocker)\n */\n ignoreBlocker?: boolean\n /**\n * If `true`, navigation to a route inside of router will trigger a full page load instead of the traditional SPA navigation.\n * @default false\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#reloaddocument)\n */\n reloadDocument?: boolean\n /**\n * This can be used instead of `to` to navigate to a fully built href, e.g. pointing to an external target.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#href)\n */\n href?: string\n}\n\nexport type ToOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = ToSubOptions<TRouter, TFrom, TTo> & MaskOptions<TRouter, TMaskFrom, TMaskTo>\n\nexport interface MaskOptions<\n in out TRouter extends AnyRouter,\n in out TMaskFrom extends string,\n in out TMaskTo extends string,\n> {\n _fromLocation?: ParsedLocation\n mask?: ToMaskOptions<TRouter, TMaskFrom, TMaskTo>\n}\n\nexport type ToMaskOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TMaskFrom extends string = string,\n TMaskTo extends string = '.',\n> = ToSubOptions<TRouter, TMaskFrom, TMaskTo> & {\n unmaskOnReload?: boolean\n}\n\nexport type ToSubOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n> = ToSubOptionsProps<TRouter, TFrom, TTo> &\n SearchParamOptions<TRouter, TFrom, TTo> &\n PathParamOptions<TRouter, TFrom, TTo>\n\nexport interface RequiredToOptions<\n in out TRouter extends AnyRouter,\n in out TFrom extends string,\n in out TTo extends string | undefined,\n> {\n to: ToPathOption<TRouter, TFrom, TTo> & {}\n}\n\nexport interface OptionalToOptions<\n in out TRouter extends AnyRouter,\n in out TFrom extends string,\n in out TTo extends string | undefined,\n> {\n to?: ToPathOption<TRouter, TFrom, TTo> & {}\n}\n\nexport type MakeToRequired<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string | undefined,\n> = string extends TFrom\n ? string extends TTo\n ? OptionalToOptions<TRouter, TFrom, TTo>\n : TTo & CatchAllPaths<TRouter> extends never\n ? RequiredToOptions<TRouter, TFrom, TTo>\n : OptionalToOptions<TRouter, TFrom, TTo>\n : OptionalToOptions<TRouter, TFrom, TTo>\n\nexport type ToSubOptionsProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string | undefined = '.',\n> = MakeToRequired<TRouter, TFrom, TTo> & {\n hash?: true | Updater<string>\n state?: true | NonNullableUpdater<ParsedHistoryState, HistoryState>\n from?: FromPathOption<TRouter, TFrom> & {}\n}\n\nexport type ParamsReducerFn<\n in out TRouter extends AnyRouter,\n in out TParamVariant extends ParamVariant,\n in out TFrom,\n in out TTo,\n> = (\n current: Expand<ResolveFromParams<TRouter, TParamVariant, TFrom>>,\n) => Expand<ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>>\n\ntype ParamsReducer<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n | Expand<ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>>\n | (ParamsReducerFn<TRouter, TParamVariant, TFrom, TTo> & {})\n\ntype ParamVariant = 'PATH' | 'SEARCH'\n\nexport type ResolveRoute<\n TRouter extends AnyRouter,\n TFrom,\n TTo,\n TPath = ResolveRelativePath<TFrom, TTo>,\n> = TPath extends string\n ? TFrom extends TPath\n ? RouteByPath<TRouter['routeTree'], TPath>\n : RouteByToPath<TRouter, TPath>\n : never\n\ntype ResolveFromParamType<TParamVariant extends ParamVariant> =\n TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchema'\n\ntype ResolveFromAllParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n> = TParamVariant extends 'PATH'\n ? AllParams<TRouter['routeTree']>\n : FullSearchSchema<TRouter['routeTree']>\n\ntype ResolveFromParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n> = string extends TFrom\n ? ResolveFromAllParams<TRouter, TParamVariant>\n : RouteByPath<\n TRouter['routeTree'],\n TFrom\n >['types'][ResolveFromParamType<TParamVariant>]\n\ntype ResolveToParamType<TParamVariant extends ParamVariant> =\n TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchemaInput'\n\ntype ResolveAllToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n> = TParamVariant extends 'PATH'\n ? AllParams<TRouter['routeTree']>\n : FullSearchSchemaInput<TRouter['routeTree']>\n\nexport type ResolveToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n ResolveRelativePath<TFrom, TTo> extends infer TPath\n ? undefined extends TPath\n ? never\n : string extends TPath\n ? ResolveAllToParams<TRouter, TParamVariant>\n : TPath extends CatchAllPaths<TRouter>\n ? ResolveAllToParams<TRouter, TParamVariant>\n : ResolveRoute<\n TRouter,\n TFrom,\n TTo\n >['types'][ResolveToParamType<TParamVariant>]\n : never\n\ntype ResolveRelativeToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n TToParams = ResolveToParams<TRouter, TParamVariant, TFrom, TTo>,\n> = TParamVariant extends 'SEARCH'\n ? TToParams\n : string extends TFrom\n ? TToParams\n : MakeDifferenceOptional<\n ResolveFromParams<TRouter, TParamVariant, TFrom>,\n TToParams\n >\n\nexport interface MakeOptionalSearchParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n search?: true | (ParamsReducer<TRouter, 'SEARCH', TFrom, TTo> & {})\n}\n\nexport interface MakeOptionalPathParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n params?: true | (ParamsReducer<TRouter, 'PATH', TFrom, TTo> & {})\n}\n\ntype MakeRequiredParamsReducer<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n | (string extends TFrom\n ? never\n : ResolveFromParams<\n TRouter,\n TParamVariant,\n TFrom\n > extends ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>\n ? true\n : never)\n | (ParamsReducer<TRouter, TParamVariant, TFrom, TTo> & {})\n\nexport interface MakeRequiredPathParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n params: MakeRequiredParamsReducer<TRouter, 'PATH', TFrom, TTo> & {}\n}\n\nexport interface MakeRequiredSearchParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n search: MakeRequiredParamsReducer<TRouter, 'SEARCH', TFrom, TTo> & {}\n}\n\nexport type IsRequired<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n ResolveRelativePath<TFrom, TTo> extends infer TPath\n ? undefined extends TPath\n ? never\n : TPath extends CatchAllPaths<TRouter>\n ? never\n : IsRequiredParams<\n ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>\n >\n : never\n\nexport type SearchParamOptions<TRouter extends AnyRouter, TFrom, TTo> =\n IsRequired<TRouter, 'SEARCH', TFrom, TTo> extends never\n ? MakeOptionalSearchParams<TRouter, TFrom, TTo>\n : MakeRequiredSearchParams<TRouter, TFrom, TTo>\n\nexport type PathParamOptions<TRouter extends AnyRouter, TFrom, TTo> =\n IsRequired<TRouter, 'PATH', TFrom, TTo> extends never\n ? MakeOptionalPathParams<TRouter, TFrom, TTo>\n : MakeRequiredPathParams<TRouter, TFrom, TTo>\n\nexport type ToPathOption<\n TRouter extends AnyRouter = AnyRouter,\n TFrom extends string = string,\n TTo extends string | undefined = string,\n> = ConstrainLiteral<\n TTo,\n RelativeToPathAutoComplete<\n TRouter,\n NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',\n NoInfer<TTo> & string\n >\n>\n\nexport type FromPathOption<TRouter extends AnyRouter, TFrom> = ConstrainLiteral<\n TFrom,\n RoutePaths<TRouter['routeTree']>\n>\n\n/**\n * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/navigation#active-options)\n */\nexport interface ActiveOptions {\n /**\n * If true, the link will be active if the current route matches the `to` route path exactly (no children routes)\n * @default false\n */\n exact?: boolean\n /**\n * If true, the link will only be active if the current URL hash matches the `hash` prop\n * @default false\n */\n includeHash?: boolean\n /**\n * If true, the link will only be active if the current URL search params inclusively match the `search` prop\n * @default true\n */\n includeSearch?: boolean\n /**\n * This modifies the `includeSearch` behavior.\n * If true, properties in `search` that are explicitly `undefined` must NOT be present in the current URL search params for the link to be active.\n * @default false\n */\n explicitUndefined?: boolean\n}\n\nexport interface LinkOptionsProps {\n /**\n * The standard anchor tag target attribute\n */\n target?: HTMLAnchorElement['target']\n /**\n * Configurable options to determine if the link should be considered active or not\n * @default {exact:true,includeHash:true}\n */\n activeOptions?: ActiveOptions\n /**\n * The preloading strategy for this link\n * - `false` - No preloading\n * - `'intent'` - Preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.\n * - `'viewport'` - Preload the linked route when it enters the viewport\n */\n preload?: false | 'intent' | 'viewport' | 'render'\n /**\n * When a preload strategy is set, this delays the preload by this many milliseconds.\n * If the user exits the link before this delay, the preload will be cancelled.\n */\n preloadDelay?: number\n /**\n * Control whether the link should be disabled or not\n * If set to `true`, the link will be rendered without an `href` attribute\n * @default false\n */\n disabled?: boolean\n}\n\nexport type LinkOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & LinkOptionsProps\n\nexport type LinkCurrentTargetElement = {\n preloadTimeout?: null | ReturnType<typeof setTimeout>\n}\n\nexport const preloadWarning = 'Error preloading route! ☝️'\n"],"names":[],"mappings":"AA+lBO,MAAM,iBAAiB;"}
|
package/dist/esm/path.d.ts
CHANGED
|
@@ -3,8 +3,6 @@ import { AnyPathParams } from './route.js';
|
|
|
3
3
|
export interface Segment {
|
|
4
4
|
type: 'pathname' | 'param' | 'wildcard';
|
|
5
5
|
value: string;
|
|
6
|
-
prefixSegment?: string;
|
|
7
|
-
suffixSegment?: string;
|
|
8
6
|
}
|
|
9
7
|
export declare function joinPaths(paths: Array<string | undefined>): string;
|
|
10
8
|
export declare function cleanPath(path: string): string;
|
|
@@ -21,21 +19,6 @@ interface ResolvePathOptions {
|
|
|
21
19
|
caseSensitive?: boolean;
|
|
22
20
|
}
|
|
23
21
|
export declare function resolvePath({ basepath, base, to, trailingSlash, caseSensitive, }: ResolvePathOptions): string;
|
|
24
|
-
/**
|
|
25
|
-
* Required: `/foo/$bar` ✅
|
|
26
|
-
* Prefix and Suffix: `/foo/prefix${bar}suffix` ✅
|
|
27
|
-
* Wildcard: `/foo/$` ✅
|
|
28
|
-
* Wildcard with Prefix and Suffix: `/foo/prefix{$}suffix` ✅
|
|
29
|
-
*
|
|
30
|
-
* Future:
|
|
31
|
-
* Optional: `/foo/{-bar}`
|
|
32
|
-
* Optional named segment: `/foo/{bar}`
|
|
33
|
-
* Optional named segment with Prefix and Suffix: `/foo/prefix{-bar}suffix`
|
|
34
|
-
* Escape special characters:
|
|
35
|
-
* - `/foo/[$]` - Static route
|
|
36
|
-
* - `/foo/[$]{$foo} - Dynamic route with a static prefix of `$`
|
|
37
|
-
* - `/foo/{$foo}[$]` - Dynamic route with a static suffix of `$`
|
|
38
|
-
*/
|
|
39
22
|
export declare function parsePathname(pathname?: string): Array<Segment>;
|
|
40
23
|
interface InterpolatePathOptions {
|
|
41
24
|
path?: string;
|
package/dist/esm/path.js
CHANGED
|
@@ -65,35 +65,9 @@ function resolvePath({
|
|
|
65
65
|
baseSegments.push({ type: "pathname", value: "/" });
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
const
|
|
69
|
-
if (segment.type === "param") {
|
|
70
|
-
const param = segment.value.substring(1);
|
|
71
|
-
if (segment.prefixSegment && segment.suffixSegment) {
|
|
72
|
-
return `${segment.prefixSegment}{$${param}}${segment.suffixSegment}`;
|
|
73
|
-
} else if (segment.prefixSegment) {
|
|
74
|
-
return `${segment.prefixSegment}{$${param}}`;
|
|
75
|
-
} else if (segment.suffixSegment) {
|
|
76
|
-
return `{$${param}}${segment.suffixSegment}`;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (segment.type === "wildcard") {
|
|
80
|
-
if (segment.prefixSegment && segment.suffixSegment) {
|
|
81
|
-
return `${segment.prefixSegment}{$}${segment.suffixSegment}`;
|
|
82
|
-
} else if (segment.prefixSegment) {
|
|
83
|
-
return `${segment.prefixSegment}{$}`;
|
|
84
|
-
} else if (segment.suffixSegment) {
|
|
85
|
-
return `{$}${segment.suffixSegment}`;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return segment.value;
|
|
89
|
-
});
|
|
90
|
-
const joined = joinPaths([basepath, ...segmentValues]);
|
|
68
|
+
const joined = joinPaths([basepath, ...baseSegments.map((d) => d.value)]);
|
|
91
69
|
return cleanPath(joined);
|
|
92
70
|
}
|
|
93
|
-
const PARAM_RE = /^\$.{1,}$/;
|
|
94
|
-
const PARAM_W_CURLY_BRACES_RE = /^(.*?)\{(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/;
|
|
95
|
-
const WILDCARD_RE = /^\$$/;
|
|
96
|
-
const WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\{\$\}(.*)$/;
|
|
97
71
|
function parsePathname(pathname) {
|
|
98
72
|
if (!pathname) {
|
|
99
73
|
return [];
|
|
@@ -113,44 +87,16 @@ function parsePathname(pathname) {
|
|
|
113
87
|
const split = pathname.split("/").filter(Boolean);
|
|
114
88
|
segments.push(
|
|
115
89
|
...split.map((part) => {
|
|
116
|
-
|
|
117
|
-
if (wildcardBracesMatch) {
|
|
118
|
-
const prefix = wildcardBracesMatch[1];
|
|
119
|
-
const suffix = wildcardBracesMatch[2];
|
|
90
|
+
if (part === "$" || part === "*") {
|
|
120
91
|
return {
|
|
121
92
|
type: "wildcard",
|
|
122
|
-
value:
|
|
123
|
-
prefixSegment: prefix || void 0,
|
|
124
|
-
suffixSegment: suffix || void 0
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
const paramBracesMatch = part.match(PARAM_W_CURLY_BRACES_RE);
|
|
128
|
-
if (paramBracesMatch) {
|
|
129
|
-
const prefix = paramBracesMatch[1];
|
|
130
|
-
const paramName = paramBracesMatch[2];
|
|
131
|
-
const suffix = paramBracesMatch[3];
|
|
132
|
-
return {
|
|
133
|
-
type: "param",
|
|
134
|
-
value: "" + paramName,
|
|
135
|
-
prefixSegment: prefix || void 0,
|
|
136
|
-
suffixSegment: suffix || void 0
|
|
93
|
+
value: part
|
|
137
94
|
};
|
|
138
95
|
}
|
|
139
|
-
if (
|
|
140
|
-
const paramName = part.substring(1);
|
|
96
|
+
if (part.charAt(0) === "$") {
|
|
141
97
|
return {
|
|
142
98
|
type: "param",
|
|
143
|
-
value:
|
|
144
|
-
prefixSegment: void 0,
|
|
145
|
-
suffixSegment: void 0
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
if (WILDCARD_RE.test(part)) {
|
|
149
|
-
return {
|
|
150
|
-
type: "wildcard",
|
|
151
|
-
value: "$",
|
|
152
|
-
prefixSegment: void 0,
|
|
153
|
-
suffixSegment: void 0
|
|
99
|
+
value: part
|
|
154
100
|
};
|
|
155
101
|
}
|
|
156
102
|
return {
|
|
@@ -191,13 +137,9 @@ function interpolatePath({
|
|
|
191
137
|
interpolatedPathSegments.map((segment) => {
|
|
192
138
|
if (segment.type === "wildcard") {
|
|
193
139
|
usedParams._splat = params._splat;
|
|
194
|
-
const segmentPrefix = segment.prefixSegment || "";
|
|
195
|
-
const segmentSuffix = segment.suffixSegment || "";
|
|
196
140
|
const value = encodeParam("_splat");
|
|
197
|
-
if (leaveWildcards) {
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
return `${segmentPrefix}${value}${segmentSuffix}`;
|
|
141
|
+
if (leaveWildcards) return `${segment.value}${value ?? ""}`;
|
|
142
|
+
return value;
|
|
201
143
|
}
|
|
202
144
|
if (segment.type === "param") {
|
|
203
145
|
const key = segment.value.substring(1);
|
|
@@ -205,13 +147,11 @@ function interpolatePath({
|
|
|
205
147
|
isMissingParams = true;
|
|
206
148
|
}
|
|
207
149
|
usedParams[key] = params[key];
|
|
208
|
-
const segmentPrefix = segment.prefixSegment || "";
|
|
209
|
-
const segmentSuffix = segment.suffixSegment || "";
|
|
210
150
|
if (leaveParams) {
|
|
211
151
|
const value = encodeParam(segment.value);
|
|
212
|
-
return `${
|
|
152
|
+
return `${segment.value}${value ?? ""}`;
|
|
213
153
|
}
|
|
214
|
-
return
|
|
154
|
+
return encodeParam(key) ?? "undefined";
|
|
215
155
|
}
|
|
216
156
|
return segment.value;
|
|
217
157
|
})
|
|
@@ -289,7 +229,6 @@ function matchByPath(basepath, from, matchLocation) {
|
|
|
289
229
|
}
|
|
290
230
|
const params = {};
|
|
291
231
|
const isMatch = (() => {
|
|
292
|
-
var _a;
|
|
293
232
|
for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
|
|
294
233
|
const baseSegment = baseSegments[i];
|
|
295
234
|
const routeSegment = routeSegments[i];
|
|
@@ -297,41 +236,9 @@ function matchByPath(basepath, from, matchLocation) {
|
|
|
297
236
|
const isLastRouteSegment = i >= routeSegments.length - 1;
|
|
298
237
|
if (routeSegment) {
|
|
299
238
|
if (routeSegment.type === "wildcard") {
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
if (!baseSegment) return false;
|
|
304
|
-
const prefix = routeSegment.prefixSegment || "";
|
|
305
|
-
const suffix = routeSegment.suffixSegment || "";
|
|
306
|
-
const baseValue = baseSegment.value;
|
|
307
|
-
if ("prefixSegment" in routeSegment) {
|
|
308
|
-
if (!baseValue.startsWith(prefix)) {
|
|
309
|
-
return false;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if ("suffixSegment" in routeSegment) {
|
|
313
|
-
if (!((_a = baseSegments[baseSegments.length - 1]) == null ? void 0 : _a.value.endsWith(suffix))) {
|
|
314
|
-
return false;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
let rejoinedSplat = decodeURI(
|
|
318
|
-
joinPaths(remainingBaseSegments.map((d) => d.value))
|
|
319
|
-
);
|
|
320
|
-
if (prefix && rejoinedSplat.startsWith(prefix)) {
|
|
321
|
-
rejoinedSplat = rejoinedSplat.slice(prefix.length);
|
|
322
|
-
}
|
|
323
|
-
if (suffix && rejoinedSplat.endsWith(suffix)) {
|
|
324
|
-
rejoinedSplat = rejoinedSplat.slice(
|
|
325
|
-
0,
|
|
326
|
-
rejoinedSplat.length - suffix.length
|
|
327
|
-
);
|
|
328
|
-
}
|
|
329
|
-
_splat = rejoinedSplat;
|
|
330
|
-
} else {
|
|
331
|
-
_splat = decodeURI(
|
|
332
|
-
joinPaths(remainingBaseSegments.map((d) => d.value))
|
|
333
|
-
);
|
|
334
|
-
}
|
|
239
|
+
const _splat = decodeURI(
|
|
240
|
+
joinPaths(baseSegments.slice(i).map((d) => d.value))
|
|
241
|
+
);
|
|
335
242
|
params["*"] = _splat;
|
|
336
243
|
params["_splat"] = _splat;
|
|
337
244
|
return true;
|
|
@@ -357,32 +264,11 @@ function matchByPath(basepath, from, matchLocation) {
|
|
|
357
264
|
if (baseSegment.value === "/") {
|
|
358
265
|
return false;
|
|
359
266
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const baseValue = baseSegment.value;
|
|
365
|
-
if (prefix && !baseValue.startsWith(prefix)) {
|
|
366
|
-
return false;
|
|
367
|
-
}
|
|
368
|
-
if (suffix && !baseValue.endsWith(suffix)) {
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
|
-
let paramValue = baseValue;
|
|
372
|
-
if (prefix && paramValue.startsWith(prefix)) {
|
|
373
|
-
paramValue = paramValue.slice(prefix.length);
|
|
374
|
-
}
|
|
375
|
-
if (suffix && paramValue.endsWith(suffix)) {
|
|
376
|
-
paramValue = paramValue.slice(
|
|
377
|
-
0,
|
|
378
|
-
paramValue.length - suffix.length
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
_paramValue = decodeURIComponent(paramValue);
|
|
382
|
-
} else {
|
|
383
|
-
_paramValue = decodeURIComponent(baseSegment.value);
|
|
267
|
+
if (baseSegment.value.charAt(0) !== "$") {
|
|
268
|
+
params[routeSegment.value.substring(1)] = decodeURIComponent(
|
|
269
|
+
baseSegment.value
|
|
270
|
+
);
|
|
384
271
|
}
|
|
385
|
-
params[routeSegment.value.substring(1)] = _paramValue;
|
|
386
272
|
}
|
|
387
273
|
}
|
|
388
274
|
if (!isLastBaseSegment && isLastRouteSegment) {
|
package/dist/esm/path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\nimport type { MatchLocation } from './RouterProvider'\nimport type { AnyPathParams } from './route'\n\nexport interface Segment {\n type: 'pathname' | 'param' | 'wildcard'\n value: string\n // Add a new property to store the static segment if present\n prefixSegment?: string\n suffixSegment?: string\n}\n\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value?.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n basepath: string\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n caseSensitive?: boolean\n}\n\nexport function resolvePath({\n basepath,\n base,\n to,\n trailingSlash = 'never',\n caseSensitive,\n}: ResolvePathOptions) {\n base = removeBasepath(basepath, base, caseSensitive)\n to = removeBasepath(basepath, to, caseSensitive)\n\n let baseSegments = parsePathname(base)\n const toSegments = parsePathname(to)\n\n if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {\n baseSegments.pop()\n }\n\n toSegments.forEach((toSegment, index) => {\n if (toSegment.value === '/') {\n if (!index) {\n // Leading slash\n baseSegments = [toSegment]\n } else if (index === toSegments.length - 1) {\n // Trailing Slash\n baseSegments.push(toSegment)\n } else {\n // ignore inter-slashes\n }\n } else if (toSegment.value === '..') {\n baseSegments.pop()\n } else if (toSegment.value === '.') {\n // ignore\n } else {\n baseSegments.push(toSegment)\n }\n })\n\n if (baseSegments.length > 1) {\n if (last(baseSegments)?.value === '/') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push({ type: 'pathname', value: '/' })\n }\n }\n\n const segmentValues = baseSegments.map((segment) => {\n if (segment.type === 'param') {\n const param = segment.value.substring(1)\n if (segment.prefixSegment && segment.suffixSegment) {\n return `${segment.prefixSegment}{$${param}}${segment.suffixSegment}`\n } else if (segment.prefixSegment) {\n return `${segment.prefixSegment}{$${param}}`\n } else if (segment.suffixSegment) {\n return `{$${param}}${segment.suffixSegment}`\n }\n }\n if (segment.type === 'wildcard') {\n if (segment.prefixSegment && segment.suffixSegment) {\n return `${segment.prefixSegment}{$}${segment.suffixSegment}`\n } else if (segment.prefixSegment) {\n return `${segment.prefixSegment}{$}`\n } else if (segment.suffixSegment) {\n return `{$}${segment.suffixSegment}`\n }\n }\n return segment.value\n })\n const joined = joinPaths([basepath, ...segmentValues])\n return cleanPath(joined)\n}\n\nconst PARAM_RE = /^\\$.{1,}$/ // $paramName\nconst PARAM_W_CURLY_BRACES_RE = /^(.*?)\\{(\\$[a-zA-Z_$][a-zA-Z0-9_$]*)\\}(.*)$/ // prefix{$paramName}suffix\nconst WILDCARD_RE = /^\\$$/ // $\nconst WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\\{\\$\\}(.*)$/ // prefix{$}suffix\n\n/**\n * Required: `/foo/$bar` ✅\n * Prefix and Suffix: `/foo/prefix${bar}suffix` ✅\n * Wildcard: `/foo/$` ✅\n * Wildcard with Prefix and Suffix: `/foo/prefix{$}suffix` ✅\n *\n * Future:\n * Optional: `/foo/{-bar}`\n * Optional named segment: `/foo/{bar}`\n * Optional named segment with Prefix and Suffix: `/foo/prefix{-bar}suffix`\n * Escape special characters:\n * - `/foo/[$]` - Static route\n * - `/foo/[$]{$foo} - Dynamic route with a static prefix of `$`\n * - `/foo/{$foo}[$]` - Dynamic route with a static suffix of `$`\n */\nexport function parsePathname(pathname?: string): Array<Segment> {\n if (!pathname) {\n return []\n }\n\n pathname = cleanPath(pathname)\n\n const segments: Array<Segment> = []\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!pathname) {\n return segments\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean)\n\n segments.push(\n ...split.map((part): Segment => {\n // Check for wildcard with curly braces: prefix{$}suffix\n const wildcardBracesMatch = part.match(WILDCARD_W_CURLY_BRACES_RE)\n if (wildcardBracesMatch) {\n const prefix = wildcardBracesMatch[1]\n const suffix = wildcardBracesMatch[2]\n return {\n type: 'wildcard',\n value: '$',\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for the new parameter format: prefix{$paramName}suffix\n const paramBracesMatch = part.match(PARAM_W_CURLY_BRACES_RE)\n if (paramBracesMatch) {\n const prefix = paramBracesMatch[1]\n const paramName = paramBracesMatch[2]\n const suffix = paramBracesMatch[3]\n return {\n type: 'param',\n value: '' + paramName,\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for bare parameter format: $paramName (without curly braces)\n if (PARAM_RE.test(part)) {\n const paramName = part.substring(1)\n return {\n type: 'param',\n value: '$' + paramName,\n prefixSegment: undefined,\n suffixSegment: undefined,\n }\n }\n\n // Check for bare wildcard: $ (without curly braces)\n if (WILDCARD_RE.test(part)) {\n return {\n type: 'wildcard',\n value: '$',\n prefixSegment: undefined,\n suffixSegment: undefined,\n }\n }\n\n // Handle regular pathname segment\n return {\n type: 'pathname',\n value: part.includes('%25')\n ? part\n .split('%25')\n .map((segment) => decodeURI(segment))\n .join('%25')\n : decodeURI(part),\n }\n }),\n )\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n return segments\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n leaveWildcards?: boolean\n leaveParams?: boolean\n // Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params\n decodeCharMap?: Map<string, string>\n}\n\ntype InterPolatePathResult = {\n interpolatedPath: string\n usedParams: Record<string, unknown>\n isMissingParams: boolean // true if any params were not available when being looked up in the params object\n}\nexport function interpolatePath({\n path,\n params,\n leaveWildcards,\n leaveParams,\n decodeCharMap,\n}: InterpolatePathOptions): InterPolatePathResult {\n const interpolatedPathSegments = parsePathname(path)\n\n function encodeParam(key: string): any {\n const value = params[key]\n const isValueString = typeof value === 'string'\n\n if (['*', '_splat'].includes(key)) {\n // the splat/catch-all routes shouldn't have the '/' encoded out\n return isValueString ? encodeURI(value) : value\n } else {\n return isValueString ? encodePathParam(value, decodeCharMap) : value\n }\n }\n\n // Tracking if any params are missing in the `params` object\n // when interpolating the path\n let isMissingParams = false\n\n const usedParams: Record<string, unknown> = {}\n const interpolatedPath = joinPaths(\n interpolatedPathSegments.map((segment) => {\n if (segment.type === 'wildcard') {\n usedParams._splat = params._splat\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n const value = encodeParam('_splat')\n if (leaveWildcards) {\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${value}${segmentSuffix}`\n }\n\n if (segment.type === 'param') {\n const key = segment.value.substring(1)\n if (!isMissingParams && !(key in params)) {\n isMissingParams = true\n }\n usedParams[key] = params[key]\n\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n if (leaveParams) {\n const value = encodeParam(segment.value)\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${encodeParam(key) ?? 'undefined'}${segmentSuffix}`\n }\n\n return segment.value\n }),\n )\n return { usedParams, interpolatedPath, isMissingParams }\n}\n\nfunction encodePathParam(value: string, decodeCharMap?: Map<string, string>) {\n let encoded = encodeURIComponent(value)\n if (decodeCharMap) {\n for (const [encodedChar, char] of decodeCharMap) {\n encoded = encoded.replaceAll(encodedChar, char)\n }\n }\n return encoded\n}\n\nexport function matchPathname(\n basepath: string,\n currentPathname: string,\n matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,\n): AnyPathParams | undefined {\n const pathParams = matchByPath(basepath, currentPathname, matchLocation)\n // const searchMatched = matchBySearch(location.search, matchLocation)\n\n if (matchLocation.to && !pathParams) {\n return\n }\n\n return pathParams ?? {}\n}\n\nexport function removeBasepath(\n basepath: string,\n pathname: string,\n caseSensitive: boolean = false,\n) {\n // normalize basepath and pathname for case-insensitive comparison if needed\n const normalizedBasepath = caseSensitive ? basepath : basepath.toLowerCase()\n const normalizedPathname = caseSensitive ? pathname : pathname.toLowerCase()\n\n switch (true) {\n // default behaviour is to serve app from the root - pathname\n // left untouched\n case normalizedBasepath === '/':\n return pathname\n\n // shortcut for removing the basepath if it matches the pathname\n case normalizedPathname === normalizedBasepath:\n return ''\n\n // in case pathname is shorter than basepath - there is\n // nothing to remove\n case pathname.length < basepath.length:\n return pathname\n\n // avoid matching partial segments - strict equality handled\n // earlier, otherwise, basepath separated from pathname with\n // separator, therefore lack of separator means partial\n // segment match (`/app` should not match `/application`)\n case normalizedPathname[normalizedBasepath.length] !== '/':\n return pathname\n\n // remove the basepath from the pathname if it starts with it\n case normalizedPathname.startsWith(normalizedBasepath):\n return pathname.slice(basepath.length)\n\n // otherwise, return the pathname as is\n default:\n return pathname\n }\n}\n\nexport function matchByPath(\n basepath: string,\n from: string,\n matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,\n): Record<string, string> | undefined {\n // check basepath first\n if (basepath !== '/' && !from.startsWith(basepath)) {\n return undefined\n }\n // Remove the base path from the pathname\n from = removeBasepath(basepath, from, matchLocation.caseSensitive)\n // Default to to $ (wildcard)\n const to = removeBasepath(\n basepath,\n `${matchLocation.to ?? '$'}`,\n matchLocation.caseSensitive,\n )\n\n // Parse the from and to\n const baseSegments = parsePathname(from)\n const routeSegments = parsePathname(to)\n\n if (!from.startsWith('/')) {\n baseSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!to.startsWith('/')) {\n routeSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n const params: Record<string, string> = {}\n\n const isMatch = (() => {\n for (\n let i = 0;\n i < Math.max(baseSegments.length, routeSegments.length);\n i++\n ) {\n const baseSegment = baseSegments[i]\n const routeSegment = routeSegments[i]\n\n const isLastBaseSegment = i >= baseSegments.length - 1\n const isLastRouteSegment = i >= routeSegments.length - 1\n\n if (routeSegment) {\n if (routeSegment.type === 'wildcard') {\n // Capture all remaining segments for a wildcard\n const remainingBaseSegments = baseSegments.slice(i)\n\n let _splat: string\n\n // If this is a wildcard with prefix/suffix, we need to handle the first segment specially\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n if (!baseSegment) return false\n\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if ('prefixSegment' in routeSegment) {\n if (!baseValue.startsWith(prefix)) {\n return false\n }\n }\n if ('suffixSegment' in routeSegment) {\n if (\n !baseSegments[baseSegments.length - 1]?.value.endsWith(suffix)\n ) {\n return false\n }\n }\n\n let rejoinedSplat = decodeURI(\n joinPaths(remainingBaseSegments.map((d) => d.value)),\n )\n\n // Remove the prefix and suffix from the rejoined splat\n if (prefix && rejoinedSplat.startsWith(prefix)) {\n rejoinedSplat = rejoinedSplat.slice(prefix.length)\n }\n\n if (suffix && rejoinedSplat.endsWith(suffix)) {\n rejoinedSplat = rejoinedSplat.slice(\n 0,\n rejoinedSplat.length - suffix.length,\n )\n }\n\n _splat = rejoinedSplat\n } else {\n // If no prefix/suffix, just rejoin the remaining segments\n _splat = decodeURI(\n joinPaths(remainingBaseSegments.map((d) => d.value)),\n )\n }\n\n // TODO: Deprecate *\n params['*'] = _splat\n params['_splat'] = _splat\n return true\n }\n\n if (routeSegment.type === 'pathname') {\n if (routeSegment.value === '/' && !baseSegment?.value) {\n return true\n }\n\n if (baseSegment) {\n if (matchLocation.caseSensitive) {\n if (routeSegment.value !== baseSegment.value) {\n return false\n }\n } else if (\n routeSegment.value.toLowerCase() !==\n baseSegment.value.toLowerCase()\n ) {\n return false\n }\n }\n }\n\n if (!baseSegment) {\n return false\n }\n\n if (routeSegment.type === 'param') {\n if (baseSegment.value === '/') {\n return false\n }\n\n let _paramValue: string\n\n // If this param has prefix/suffix, we need to extract the actual parameter value\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if (prefix && !baseValue.startsWith(prefix)) {\n return false\n }\n if (suffix && !baseValue.endsWith(suffix)) {\n return false\n }\n\n let paramValue = baseValue\n if (prefix && paramValue.startsWith(prefix)) {\n paramValue = paramValue.slice(prefix.length)\n }\n if (suffix && paramValue.endsWith(suffix)) {\n paramValue = paramValue.slice(\n 0,\n paramValue.length - suffix.length,\n )\n }\n\n _paramValue = decodeURIComponent(paramValue)\n } else {\n // If no prefix/suffix, just decode the base segment value\n _paramValue = decodeURIComponent(baseSegment.value)\n }\n\n params[routeSegment.value.substring(1)] = _paramValue\n }\n }\n\n if (!isLastBaseSegment && isLastRouteSegment) {\n params['**'] = joinPaths(baseSegments.slice(i + 1).map((d) => d.value))\n return !!matchLocation.fuzzy && routeSegment?.value !== '/'\n }\n }\n\n return true\n })()\n\n return isMatch ? params : undefined\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\nimport type { MatchLocation } from './RouterProvider'\nimport type { AnyPathParams } from './route'\n\nexport interface Segment {\n type: 'pathname' | 'param' | 'wildcard'\n value: string\n}\n\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value?.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n basepath: string\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n caseSensitive?: boolean\n}\n\nexport function resolvePath({\n basepath,\n base,\n to,\n trailingSlash = 'never',\n caseSensitive,\n}: ResolvePathOptions) {\n base = removeBasepath(basepath, base, caseSensitive)\n to = removeBasepath(basepath, to, caseSensitive)\n\n let baseSegments = parsePathname(base)\n const toSegments = parsePathname(to)\n\n if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {\n baseSegments.pop()\n }\n\n toSegments.forEach((toSegment, index) => {\n if (toSegment.value === '/') {\n if (!index) {\n // Leading slash\n baseSegments = [toSegment]\n } else if (index === toSegments.length - 1) {\n // Trailing Slash\n baseSegments.push(toSegment)\n } else {\n // ignore inter-slashes\n }\n } else if (toSegment.value === '..') {\n baseSegments.pop()\n } else if (toSegment.value === '.') {\n // ignore\n } else {\n baseSegments.push(toSegment)\n }\n })\n\n if (baseSegments.length > 1) {\n if (last(baseSegments)?.value === '/') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push({ type: 'pathname', value: '/' })\n }\n }\n\n const joined = joinPaths([basepath, ...baseSegments.map((d) => d.value)])\n return cleanPath(joined)\n}\n\nexport function parsePathname(pathname?: string): Array<Segment> {\n if (!pathname) {\n return []\n }\n\n pathname = cleanPath(pathname)\n\n const segments: Array<Segment> = []\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!pathname) {\n return segments\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean)\n\n segments.push(\n ...split.map((part): Segment => {\n if (part === '$' || part === '*') {\n return {\n type: 'wildcard',\n value: part,\n }\n }\n\n if (part.charAt(0) === '$') {\n return {\n type: 'param',\n value: part,\n }\n }\n\n return {\n type: 'pathname',\n value: part.includes('%25')\n ? part\n .split('%25')\n .map((segment) => decodeURI(segment))\n .join('%25')\n : decodeURI(part),\n }\n }),\n )\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n return segments\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n leaveWildcards?: boolean\n leaveParams?: boolean\n // Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params\n decodeCharMap?: Map<string, string>\n}\n\ntype InterPolatePathResult = {\n interpolatedPath: string\n usedParams: Record<string, unknown>\n isMissingParams: boolean // true if any params were not available when being looked up in the params object\n}\nexport function interpolatePath({\n path,\n params,\n leaveWildcards,\n leaveParams,\n decodeCharMap,\n}: InterpolatePathOptions): InterPolatePathResult {\n const interpolatedPathSegments = parsePathname(path)\n\n function encodeParam(key: string): any {\n const value = params[key]\n const isValueString = typeof value === 'string'\n\n if (['*', '_splat'].includes(key)) {\n // the splat/catch-all routes shouldn't have the '/' encoded out\n return isValueString ? encodeURI(value) : value\n } else {\n return isValueString ? encodePathParam(value, decodeCharMap) : value\n }\n }\n\n // Tracking if any params are missing in the `params` object\n // when interpolating the path\n let isMissingParams = false\n\n const usedParams: Record<string, unknown> = {}\n const interpolatedPath = joinPaths(\n interpolatedPathSegments.map((segment) => {\n if (segment.type === 'wildcard') {\n usedParams._splat = params._splat\n const value = encodeParam('_splat')\n if (leaveWildcards) return `${segment.value}${value ?? ''}`\n return value\n }\n\n if (segment.type === 'param') {\n const key = segment.value.substring(1)\n if (!isMissingParams && !(key in params)) {\n isMissingParams = true\n }\n usedParams[key] = params[key]\n if (leaveParams) {\n const value = encodeParam(segment.value)\n return `${segment.value}${value ?? ''}`\n }\n return encodeParam(key) ?? 'undefined'\n }\n\n return segment.value\n }),\n )\n return { usedParams, interpolatedPath, isMissingParams }\n}\n\nfunction encodePathParam(value: string, decodeCharMap?: Map<string, string>) {\n let encoded = encodeURIComponent(value)\n if (decodeCharMap) {\n for (const [encodedChar, char] of decodeCharMap) {\n encoded = encoded.replaceAll(encodedChar, char)\n }\n }\n return encoded\n}\n\nexport function matchPathname(\n basepath: string,\n currentPathname: string,\n matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,\n): AnyPathParams | undefined {\n const pathParams = matchByPath(basepath, currentPathname, matchLocation)\n // const searchMatched = matchBySearch(location.search, matchLocation)\n\n if (matchLocation.to && !pathParams) {\n return\n }\n\n return pathParams ?? {}\n}\n\nexport function removeBasepath(\n basepath: string,\n pathname: string,\n caseSensitive: boolean = false,\n) {\n // normalize basepath and pathname for case-insensitive comparison if needed\n const normalizedBasepath = caseSensitive ? basepath : basepath.toLowerCase()\n const normalizedPathname = caseSensitive ? pathname : pathname.toLowerCase()\n\n switch (true) {\n // default behaviour is to serve app from the root - pathname\n // left untouched\n case normalizedBasepath === '/':\n return pathname\n\n // shortcut for removing the basepath if it matches the pathname\n case normalizedPathname === normalizedBasepath:\n return ''\n\n // in case pathname is shorter than basepath - there is\n // nothing to remove\n case pathname.length < basepath.length:\n return pathname\n\n // avoid matching partial segments - strict equality handled\n // earlier, otherwise, basepath separated from pathname with\n // separator, therefore lack of separator means partial\n // segment match (`/app` should not match `/application`)\n case normalizedPathname[normalizedBasepath.length] !== '/':\n return pathname\n\n // remove the basepath from the pathname if it starts with it\n case normalizedPathname.startsWith(normalizedBasepath):\n return pathname.slice(basepath.length)\n\n // otherwise, return the pathname as is\n default:\n return pathname\n }\n}\n\nexport function matchByPath(\n basepath: string,\n from: string,\n matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,\n): Record<string, string> | undefined {\n // check basepath first\n if (basepath !== '/' && !from.startsWith(basepath)) {\n return undefined\n }\n // Remove the base path from the pathname\n from = removeBasepath(basepath, from, matchLocation.caseSensitive)\n // Default to to $ (wildcard)\n const to = removeBasepath(\n basepath,\n `${matchLocation.to ?? '$'}`,\n matchLocation.caseSensitive,\n )\n\n // Parse the from and to\n const baseSegments = parsePathname(from)\n const routeSegments = parsePathname(to)\n\n if (!from.startsWith('/')) {\n baseSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!to.startsWith('/')) {\n routeSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n const params: Record<string, string> = {}\n\n const isMatch = (() => {\n for (\n let i = 0;\n i < Math.max(baseSegments.length, routeSegments.length);\n i++\n ) {\n const baseSegment = baseSegments[i]\n const routeSegment = routeSegments[i]\n\n const isLastBaseSegment = i >= baseSegments.length - 1\n const isLastRouteSegment = i >= routeSegments.length - 1\n\n if (routeSegment) {\n if (routeSegment.type === 'wildcard') {\n const _splat = decodeURI(\n joinPaths(baseSegments.slice(i).map((d) => d.value)),\n )\n // TODO: Deprecate *\n params['*'] = _splat\n params['_splat'] = _splat\n return true\n }\n\n if (routeSegment.type === 'pathname') {\n if (routeSegment.value === '/' && !baseSegment?.value) {\n return true\n }\n\n if (baseSegment) {\n if (matchLocation.caseSensitive) {\n if (routeSegment.value !== baseSegment.value) {\n return false\n }\n } else if (\n routeSegment.value.toLowerCase() !==\n baseSegment.value.toLowerCase()\n ) {\n return false\n }\n }\n }\n\n if (!baseSegment) {\n return false\n }\n\n if (routeSegment.type === 'param') {\n if (baseSegment.value === '/') {\n return false\n }\n if (baseSegment.value.charAt(0) !== '$') {\n params[routeSegment.value.substring(1)] = decodeURIComponent(\n baseSegment.value,\n )\n }\n }\n }\n\n if (!isLastBaseSegment && isLastRouteSegment) {\n params['**'] = joinPaths(baseSegments.slice(i + 1).map((d) => d.value))\n return !!matchLocation.fuzzy && routeSegment?.value !== '/'\n }\n }\n\n return true\n })()\n\n return isMatch ? params : undefined\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/redirect.d.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { NavigateOptions } from './link.js';
|
|
2
2
|
import { AnyRouter, RegisteredRouter } from './router.js';
|
|
3
|
+
import { PickAsRequired } from './utils.js';
|
|
3
4
|
export type AnyRedirect = Redirect<any, any, any, any, any>;
|
|
4
5
|
/**
|
|
5
6
|
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)
|
|
6
7
|
*/
|
|
7
|
-
export type Redirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = undefined, TMaskFrom extends string = TFrom, TMaskTo extends string = '.'> =
|
|
8
|
-
options: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
9
|
-
redirectHandled?: boolean;
|
|
10
|
-
};
|
|
11
|
-
export type RedirectOptions<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = undefined, TMaskFrom extends string = TFrom, TMaskTo extends string = '.'> = {
|
|
8
|
+
export type Redirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = undefined, TMaskFrom extends string = TFrom, TMaskTo extends string = '.'> = {
|
|
12
9
|
href?: string;
|
|
13
10
|
/**
|
|
14
11
|
* @deprecated Use `statusCode` instead
|
|
@@ -30,12 +27,9 @@ export type RedirectOptions<TRouter extends AnyRouter = RegisteredRouter, TFrom
|
|
|
30
27
|
*/
|
|
31
28
|
headers?: HeadersInit;
|
|
32
29
|
} & NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
33
|
-
export type ResolvedRedirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string = '', TMaskFrom extends string = TFrom, TMaskTo extends string = ''> = Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo
|
|
34
|
-
|
|
35
|
-
export declare function isRedirect(obj: any): obj is AnyRedirect;
|
|
36
|
-
export declare function isResolvedRedirect(obj: any): obj is AnyRedirect & {
|
|
37
|
-
options: {
|
|
38
|
-
href: string;
|
|
39
|
-
};
|
|
30
|
+
export type ResolvedRedirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string = '', TMaskFrom extends string = TFrom, TMaskTo extends string = ''> = PickAsRequired<Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>, 'code' | 'statusCode' | 'headers'> & {
|
|
31
|
+
href: string;
|
|
40
32
|
};
|
|
41
|
-
export declare function
|
|
33
|
+
export declare function redirect<TRouter extends AnyRouter = RegisteredRouter, const TTo extends string | undefined = '.', const TFrom extends string = string, const TMaskFrom extends string = TFrom, const TMaskTo extends string = ''>(opts: Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
34
|
+
export declare function isRedirect(obj: any): obj is AnyRedirect;
|
|
35
|
+
export declare function isResolvedRedirect(obj: any): obj is ResolvedRedirect;
|
package/dist/esm/redirect.js
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
1
|
function redirect(opts) {
|
|
2
|
+
opts.isRedirect = true;
|
|
2
3
|
opts.statusCode = opts.statusCode || opts.code || 307;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
opts.headers = opts.headers || {};
|
|
5
|
+
if (!opts.reloadDocument) {
|
|
6
|
+
opts.reloadDocument = false;
|
|
7
|
+
try {
|
|
8
|
+
new URL(`${opts.href}`);
|
|
9
|
+
opts.reloadDocument = true;
|
|
10
|
+
} catch {
|
|
11
|
+
}
|
|
12
|
+
}
|
|
9
13
|
if (opts.throw) {
|
|
10
|
-
throw
|
|
14
|
+
throw opts;
|
|
11
15
|
}
|
|
12
|
-
return
|
|
16
|
+
return opts;
|
|
13
17
|
}
|
|
14
18
|
function isRedirect(obj) {
|
|
15
|
-
return obj
|
|
19
|
+
return !!(obj == null ? void 0 : obj.isRedirect);
|
|
16
20
|
}
|
|
17
21
|
function isResolvedRedirect(obj) {
|
|
18
|
-
return
|
|
19
|
-
}
|
|
20
|
-
function parseRedirect(obj) {
|
|
21
|
-
if (typeof obj === "object" && obj.isSerializedRedirect) {
|
|
22
|
-
return redirect(obj);
|
|
23
|
-
}
|
|
24
|
-
return void 0;
|
|
22
|
+
return !!(obj == null ? void 0 : obj.isRedirect) && obj.href;
|
|
25
23
|
}
|
|
26
24
|
export {
|
|
27
25
|
isRedirect,
|
|
28
26
|
isResolvedRedirect,
|
|
29
|
-
parseRedirect,
|
|
30
27
|
redirect
|
|
31
28
|
};
|
|
32
29
|
//# sourceMappingURL=redirect.js.map
|
package/dist/esm/redirect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect.js","sources":["../../src/redirect.ts"],"sourcesContent":["import type { NavigateOptions } from './link'\nimport type { AnyRouter, RegisteredRouter } from './router'\n\nexport type AnyRedirect = Redirect<any, any, any, any, any>\n\n/**\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)\n */\nexport type Redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> =
|
|
1
|
+
{"version":3,"file":"redirect.js","sources":["../../src/redirect.ts"],"sourcesContent":["import type { NavigateOptions } from './link'\nimport type { AnyRouter, RegisteredRouter } from './router'\nimport type { PickAsRequired } from './utils'\n\nexport type AnyRedirect = Redirect<any, any, any, any, any>\n\n/**\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)\n */\nexport type Redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = {\n href?: string\n /**\n * @deprecated Use `statusCode` instead\n **/\n code?: number\n /**\n * The HTTP status code to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#statuscode-property)\n */\n statusCode?: number\n /**\n * If provided, will throw the redirect object instead of returning it. This can be useful in places where `throwing` in a function might cause it to have a return type of `never`. In that case, you can use `redirect({ throw: true })` to throw the redirect object instead of returning it.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#throw-property)\n */\n throw?: any\n /**\n * The HTTP headers to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#headers-property)\n */\n headers?: HeadersInit\n} & NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type ResolvedRedirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = PickAsRequired<\n Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n 'code' | 'statusCode' | 'headers'\n> & {\n href: string\n}\n\nexport function redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n const TTo extends string | undefined = '.',\n const TFrom extends string = string,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n opts: Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> {\n ;(opts as any).isRedirect = true\n opts.statusCode = opts.statusCode || opts.code || 307\n opts.headers = opts.headers || {}\n if (!opts.reloadDocument) {\n opts.reloadDocument = false\n try {\n new URL(`${opts.href}`)\n opts.reloadDocument = true\n } catch {}\n }\n\n if (opts.throw) {\n throw opts\n }\n\n return opts\n}\n\nexport function isRedirect(obj: any): obj is AnyRedirect {\n return !!obj?.isRedirect\n}\n\nexport function isResolvedRedirect(obj: any): obj is ResolvedRedirect {\n return !!obj?.isRedirect && obj.href\n}\n"],"names":[],"mappings":"AAmDO,SAAS,SAOd,MACmD;AACjD,OAAa,aAAa;AAC5B,OAAK,aAAa,KAAK,cAAc,KAAK,QAAQ;AAC7C,OAAA,UAAU,KAAK,WAAW,CAAC;AAC5B,MAAA,CAAC,KAAK,gBAAgB;AACxB,SAAK,iBAAiB;AAClB,QAAA;AACF,UAAI,IAAI,GAAG,KAAK,IAAI,EAAE;AACtB,WAAK,iBAAiB;AAAA,IAAA,QAChB;AAAA,IAAA;AAAA,EAAC;AAGX,MAAI,KAAK,OAAO;AACR,UAAA;AAAA,EAAA;AAGD,SAAA;AACT;AAEO,SAAS,WAAW,KAA8B;AAChD,SAAA,CAAC,EAAC,2BAAK;AAChB;AAEO,SAAS,mBAAmB,KAAmC;AACpE,SAAO,CAAC,EAAC,2BAAK,eAAc,IAAI;AAClC;"}
|