@tanstack/history
Advanced tools
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["// While the public API was clearly inspired by the \"history\" npm package,\n// This implementation attempts to be more lightweight by\n// making assumptions about the way TanStack Router works\n\nexport interface NavigateOptions {\n ignoreBlocker?: boolean\n}\n\ntype SubscriberHistoryAction =\n | {\n type: Exclude<HistoryAction, 'GO'>\n }\n | {\n type: 'GO'\n index: number\n }\n\ntype SubscriberArgs = {\n location: HistoryLocation\n action: SubscriberHistoryAction\n}\n\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: SubscriberArgs) => void>\n subscribe: (cb: (opts: SubscriberArgs) => void) => () => void\n push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n go: (index: number, navigateOpts?: NavigateOptions) => void\n back: (navigateOpts?: NavigateOptions) => void\n forward: (navigateOpts?: NavigateOptions) => void\n canGoBack: () => boolean\n createHref: (href: string) => string\n block: (blocker: NavigationBlocker) => () => void\n flush: () => void\n destroy: () => void\n notify: (action: SubscriberHistoryAction) => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: ParsedHistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {}\n\nexport type ParsedHistoryState = HistoryState & {\n key?: string // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key?: string\n __TSR_index: number\n}\n\ntype ShouldAllowNavigation = any\n\nexport type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO'\n\nexport type BlockerFnArgs = {\n currentLocation: HistoryLocation\n nextLocation: HistoryLocation\n action: HistoryAction\n}\n\nexport type BlockerFn = (\n args: BlockerFnArgs,\n) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation\n\nexport type NavigationBlocker = {\n blockerFn: BlockerFn\n enableBeforeUnload?: (() => boolean) | boolean\n}\n\ntype TryNavigateArgs = {\n task: () => void\n type: 'PUSH' | 'REPLACE' | 'BACK' | 'FORWARD' | 'GO'\n navigateOpts?: NavigateOptions\n} & (\n | {\n type: 'PUSH' | 'REPLACE'\n path: string\n state: any\n }\n | {\n type: 'BACK' | 'FORWARD' | 'GO'\n }\n)\n\nconst stateIndexKey = '__TSR_index'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nexport function createHistory(opts: {\n getLocation: () => HistoryLocation\n getLength: () => number\n pushState: (path: string, state: any) => void\n replaceState: (path: string, state: any) => void\n go: (n: number) => void\n back: (ignoreBlocker: boolean) => void\n forward: (ignoreBlocker: boolean) => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: () => void\n getBlockers?: () => Array<NavigationBlocker>\n setBlockers?: (blockers: Array<NavigationBlocker>) => void\n // Avoid notifying on forward/back/go, used for browser history as we already get notified by the popstate event\n notifyOnIndexChange?: boolean\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: SubscriberArgs) => void>()\n\n const notify = (action: SubscriberHistoryAction) => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location, action }))\n }\n\n const handleIndexChange = (action: SubscriberHistoryAction) => {\n if (opts.notifyOnIndexChange ?? true) notify(action)\n else location = opts.getLocation()\n }\n\n const tryNavigation = async ({\n task,\n navigateOpts,\n ...actionInfo\n }: TryNavigateArgs) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (ignoreBlocker) {\n task()\n return\n }\n\n const blockers = opts.getBlockers?.() ?? []\n const isPushOrReplace =\n actionInfo.type === 'PUSH' || actionInfo.type === 'REPLACE'\n if (typeof document !== 'undefined' && blockers.length && isPushOrReplace) {\n for (const blocker of blockers) {\n const nextLocation = parseHref(actionInfo.path, actionInfo.state)\n const isBlocked = await blocker.blockerFn({\n currentLocation: location,\n nextLocation,\n action: actionInfo.type,\n })\n if (isBlocked) {\n opts.onBlocked?.()\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n get length() {\n return opts.getLength()\n },\n subscribers,\n subscribe: (cb: (opts: SubscriberArgs) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex + 1, state)\n tryNavigation({\n task: () => {\n opts.pushState(path, state)\n notify({ type: 'PUSH' })\n },\n navigateOpts,\n type: 'PUSH',\n path,\n state,\n })\n },\n replace: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex, state)\n tryNavigation({\n task: () => {\n opts.replaceState(path, state)\n notify({ type: 'REPLACE' })\n },\n navigateOpts,\n type: 'REPLACE',\n path,\n state,\n })\n },\n go: (index, navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.go(index)\n handleIndexChange({ type: 'GO', index })\n },\n navigateOpts,\n type: 'GO',\n })\n },\n back: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.back(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'BACK' })\n },\n navigateOpts,\n type: 'BACK',\n })\n },\n forward: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.forward(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'FORWARD' })\n },\n navigateOpts,\n type: 'FORWARD',\n })\n },\n canGoBack: () => location.state[stateIndexKey] !== 0,\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n if (!opts.setBlockers) return () => {}\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers([...blockers, blocker])\n\n return () => {\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers?.(blockers.filter((b) => b !== blocker))\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKeyAndIndex(index: number, state: HistoryState | undefined) {\n if (!state) {\n state = {} as HistoryState\n }\n const key = createRandomKey()\n return {\n ...state,\n key, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: key,\n [stateIndexKey]: index,\n } as ParsedHistoryState\n}\n\n/**\n * Creates a history object that can be used to interact with the browser's\n * navigation. This is a lightweight API wrapping the browser's native methods.\n * It is designed to work with TanStack Router, but could be used as a standalone API as well.\n * IMPORTANT: This API implements history throttling via a microtask to prevent\n * excessive calls to the history API. In some browsers, calling history.pushState or\n * history.replaceState in quick succession can cause the browser to ignore subsequent\n * calls. This API smooths out those differences and ensures that your application\n * state will *eventually* match the browser state. In most cases, this is not a problem,\n * but if you need to ensure that the browser state is up to date, you can use the\n * `history.flush` method to immediately flush all pending state changes to the browser URL.\n * @param opts\n * @param opts.getHref A function that returns the current href (path + search + hash)\n * @param opts.createHref A function that takes a path and returns a href (path + search + hash)\n * @returns A history instance\n */\nexport function createBrowserHistory(opts?: {\n parseLocation?: () => HistoryLocation\n createHref?: (path: string) => string\n window?: any\n}): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n\n const originalPushState = win.history.pushState\n const originalReplaceState = win.history.replaceState\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n const createHref = opts?.createHref ?? ((path) => path)\n const parseLocation =\n opts?.parseLocation ??\n (() =>\n parseHref(\n `${win.location.pathname}${win.location.search}${win.location.hash}`,\n win.history.state,\n ))\n\n // Ensure there is always a key to start\n if (!win.history.state?.__TSR_key && !win.history.state?.key) {\n const addedKey = createRandomKey()\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: addedKey, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: addedKey,\n },\n '',\n )\n }\n\n let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\n\n let nextPopIsGo = false\n let ignoreNextPop = false\n let skipBlockerNextPop = false\n let ignoreNextBeforeUnload = false\n\n const getLocation = () => currentLocation\n\n let next:\n | undefined\n | {\n // This is the latest location that we were attempting to push/replace\n href: string\n // This is the latest state that we were attempting to push/replace\n state: any\n // This is the latest type that we were attempting to push/replace\n isPush: boolean\n }\n\n // We need to track the current scheduled update to prevent\n // multiple updates from being scheduled at the same time.\n let scheduled: Promise<void> | undefined\n\n // This function flushes the next update to the browser history\n const flush = () => {\n if (!next) {\n return\n }\n\n // We need to ignore any updates to the subscribers while we update the browser history\n history._ignoreSubscribers = true\n\n // Update the browser history\n ;(next.isPush ? win.history.pushState : win.history.replaceState)(\n next.state,\n '',\n next.href,\n )\n\n // Stop ignoring subscriber updates\n history._ignoreSubscribers = false\n\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n }\n\n // This function queues up a call to update the browser history\n const queueHistoryAction = (\n type: 'push' | 'replace',\n destHref: string,\n state: any,\n ) => {\n const href = createHref(destHref)\n\n if (!scheduled) {\n rollbackLocation = currentLocation\n }\n\n // Update the location in memory\n currentLocation = parseHref(destHref, state)\n\n // Keep track of the next location we need to flush to the URL\n next = {\n href,\n state,\n isPush: next?.isPush || type === 'push',\n }\n\n if (!scheduled) {\n // Schedule an update to the browser history\n scheduled = Promise.resolve().then(() => flush())\n }\n }\n\n // NOTE: this function can probably be removed\n const onPushPop = (type: 'PUSH' | 'REPLACE') => {\n currentLocation = parseLocation()\n history.notify({ type })\n }\n\n const onPushPopEvent = async () => {\n if (ignoreNextPop) {\n ignoreNextPop = false\n return\n }\n\n const nextLocation = parseLocation()\n const delta =\n nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey]\n const isForward = delta === 1\n const isBack = delta === -1\n const isGo = (!isForward && !isBack) || nextPopIsGo\n nextPopIsGo = false\n\n const action = isGo ? 'GO' : isBack ? 'BACK' : 'FORWARD'\n const notify: SubscriberHistoryAction = isGo\n ? {\n type: 'GO',\n index: delta,\n }\n : {\n type: isBack ? 'BACK' : 'FORWARD',\n }\n\n if (skipBlockerNextPop) {\n skipBlockerNextPop = false\n } else {\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const isBlocked = await blocker.blockerFn({\n currentLocation,\n nextLocation,\n action,\n })\n if (isBlocked) {\n ignoreNextPop = true\n win.history.go(1)\n history.notify(notify)\n return\n }\n }\n }\n }\n\n currentLocation = parseLocation()\n history.notify(notify)\n }\n\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (ignoreNextBeforeUnload) {\n ignoreNextBeforeUnload = false\n return\n }\n\n let shouldBlock = false\n\n // If one blocker has a non-disabled beforeUnload, we should block\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true\n if (shouldHaveBeforeUnload === true) {\n shouldBlock = true\n break\n }\n\n if (\n typeof shouldHaveBeforeUnload === 'function' &&\n shouldHaveBeforeUnload() === true\n ) {\n shouldBlock = true\n break\n }\n }\n }\n\n if (shouldBlock) {\n e.preventDefault()\n return (e.returnValue = '')\n }\n return\n }\n\n const history = createHistory({\n getLocation,\n getLength: () => win.history.length,\n pushState: (href, state) => queueHistoryAction('push', href, state),\n replaceState: (href, state) => queueHistoryAction('replace', href, state),\n back: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n return win.history.back()\n },\n forward: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n win.history.forward()\n },\n go: (n) => {\n nextPopIsGo = true\n win.history.go(n)\n },\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {\n capture: true,\n })\n win.removeEventListener(popStateEvent, onPushPopEvent)\n },\n onBlocked: () => {\n // If a navigation is blocked, we need to rollback the location\n // that we optimistically updated in memory.\n if (rollbackLocation && currentLocation !== rollbackLocation) {\n currentLocation = rollbackLocation\n }\n },\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n notifyOnIndexChange: false,\n })\n\n win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true })\n win.addEventListener(popStateEvent, onPushPopEvent)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('PUSH')\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('REPLACE')\n return res\n }\n\n return history\n}\n\n/**\n * Create a hash-based history implementation.\n * Useful for static hosts or environments without server URL rewriting.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/history-types\n */\nexport function createHashHistory(opts?: { window?: any }): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n return createBrowserHistory({\n window: win,\n parseLocation: () => {\n const hashSplit = win.location.hash.split('#').slice(1)\n const pathPart = hashSplit[0] ?? '/'\n const searchPart = win.location.search\n const hashEntries = hashSplit.slice(1)\n const hashPart =\n hashEntries.length === 0 ? '' : `#${hashEntries.join('#')}`\n const hashHref = `${pathPart}${searchPart}${hashPart}`\n return parseHref(hashHref, win.history.state)\n },\n createHref: (href) =>\n `${win.location.pathname}${win.location.search}#${href}`,\n })\n}\n\n/**\n * Create an in-memory history implementation.\n * Ideal for server rendering, tests, and non-DOM environments.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/history-types\n */\nexport function createMemoryHistory(\n opts: {\n initialEntries: Array<string>\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex\n ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)\n : entries.length - 1\n const states = entries.map((_entry, index) =>\n assignKeyAndIndex(index, undefined),\n )\n\n const getLocation = () => parseHref(entries[index]!, states[index])\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n return createHistory({\n getLocation,\n getLength: () => entries.length,\n pushState: (path, state) => {\n // Removes all subsequent entries after the current index to start a new branch\n if (index < entries.length - 1) {\n entries.splice(index + 1)\n states.splice(index + 1)\n }\n states.push(state)\n entries.push(path)\n index = Math.max(entries.length - 1, 0)\n },\n replaceState: (path, state) => {\n states[index] = state\n entries[index] = path\n },\n back: () => {\n index = Math.max(index - 1, 0)\n },\n forward: () => {\n index = Math.min(index + 1, entries.length - 1)\n },\n go: (n) => {\n index = Math.min(Math.max(index + n, 0), entries.length - 1)\n },\n createHref: (path) => path,\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n })\n}\n\n/**\n * Sanitize a path to prevent open redirect vulnerabilities.\n * Removes control characters and collapses leading double slashes.\n */\nfunction sanitizePath(path: string): string {\n // Remove ASCII control characters (0x00-0x1F) and DEL (0x7F)\n // These include CR (\\r = 0x0D), LF (\\n = 0x0A), and other potentially dangerous characters\n // eslint-disable-next-line no-control-regex\n let sanitized = path.replace(/[\\x00-\\x1f\\x7f]/g, '')\n\n // Prevent open redirect via protocol-relative URLs (e.g. \"//evil.com\")\n // Collapse leading double slashes to a single slash\n if (sanitized.startsWith('//')) {\n sanitized = '/' + sanitized.replace(/^\\/+/, '')\n }\n\n return sanitized\n}\n\nexport function parseHref(\n href: string,\n state: ParsedHistoryState | undefined,\n): HistoryLocation {\n const sanitizedHref = sanitizePath(href)\n const hashIndex = sanitizedHref.indexOf('#')\n const searchIndex = sanitizedHref.indexOf('?')\n\n const addedKey = createRandomKey()\n\n return {\n href: sanitizedHref,\n pathname: sanitizedHref.substring(\n 0,\n hashIndex > 0\n ? searchIndex > 0\n ? Math.min(hashIndex, searchIndex)\n : hashIndex\n : searchIndex > 0\n ? searchIndex\n : sanitizedHref.length,\n ),\n hash: hashIndex > -1 ? sanitizedHref.substring(hashIndex) : '',\n search:\n searchIndex > -1\n ? sanitizedHref.slice(\n searchIndex,\n hashIndex === -1 ? undefined : hashIndex,\n )\n : '',\n state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":["blockers","index"],"mappings":"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"} | ||
| {"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["// While the public API was clearly inspired by the \"history\" npm package,\n// This implementation attempts to be more lightweight by\n// making assumptions about the way TanStack Router works\n\nexport interface NavigateOptions {\n ignoreBlocker?: boolean\n}\n\ntype SubscriberHistoryAction =\n | {\n type: Exclude<HistoryAction, 'GO'>\n }\n | {\n type: 'GO'\n index: number\n }\n\ntype SubscriberArgs = {\n location: HistoryLocation\n action: SubscriberHistoryAction\n}\n\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: SubscriberArgs) => void>\n subscribe: (cb: (opts: SubscriberArgs) => void) => () => void\n push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n go: (index: number, navigateOpts?: NavigateOptions) => void\n back: (navigateOpts?: NavigateOptions) => void\n forward: (navigateOpts?: NavigateOptions) => void\n canGoBack: () => boolean\n createHref: (href: string) => string\n block: (blocker: NavigationBlocker) => () => void\n flush: () => void\n destroy: () => void\n notify: (action: SubscriberHistoryAction) => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: ParsedHistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {}\n\nexport type ParsedHistoryState = HistoryState & {\n key?: string // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key?: string\n __TSR_index: number\n}\n\ntype ShouldAllowNavigation = any\n\nexport type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO'\n\nexport type BlockerFnArgs = {\n currentLocation: HistoryLocation\n nextLocation: HistoryLocation\n action: HistoryAction\n}\n\nexport type BlockerFn = (\n args: BlockerFnArgs,\n) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation\n\nexport type NavigationBlocker = {\n blockerFn: BlockerFn\n enableBeforeUnload?: (() => boolean) | boolean\n}\n\ntype TryNavigateArgs = {\n task: () => void\n type: 'PUSH' | 'REPLACE' | 'BACK' | 'FORWARD' | 'GO'\n navigateOpts?: NavigateOptions\n} & (\n | {\n type: 'PUSH' | 'REPLACE'\n path: string\n state: any\n }\n | {\n type: 'BACK' | 'FORWARD' | 'GO'\n }\n)\n\nconst stateIndexKey = '__TSR_index'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nexport function createHistory(opts: {\n getLocation: () => HistoryLocation\n getLength: () => number\n pushState: (path: string, state: any) => void\n replaceState: (path: string, state: any) => void\n go: (n: number) => void\n back: (ignoreBlocker: boolean) => void\n forward: (ignoreBlocker: boolean) => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: () => void\n getBlockers?: () => Array<NavigationBlocker>\n setBlockers?: (blockers: Array<NavigationBlocker>) => void\n // Avoid notifying on forward/back/go, used for browser history as we already get notified by the popstate event\n notifyOnIndexChange?: boolean\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: SubscriberArgs) => void>()\n\n const notify = (action: SubscriberHistoryAction) => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location, action }))\n }\n\n const handleIndexChange = (action: SubscriberHistoryAction) => {\n if (opts.notifyOnIndexChange ?? true) notify(action)\n else location = opts.getLocation()\n }\n\n const tryNavigation = async ({\n task,\n navigateOpts,\n ...actionInfo\n }: TryNavigateArgs) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (ignoreBlocker) {\n task()\n return\n }\n\n const blockers = opts.getBlockers?.() ?? []\n const isPushOrReplace =\n actionInfo.type === 'PUSH' || actionInfo.type === 'REPLACE'\n if (typeof document !== 'undefined' && blockers.length && isPushOrReplace) {\n for (const blocker of blockers) {\n const nextLocation = parseHref(actionInfo.path, actionInfo.state)\n const isBlocked = await blocker.blockerFn({\n currentLocation: location,\n nextLocation,\n action: actionInfo.type,\n })\n if (isBlocked) {\n opts.onBlocked?.()\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n get length() {\n return opts.getLength()\n },\n subscribers,\n subscribe: (cb: (opts: SubscriberArgs) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex + 1, state)\n tryNavigation({\n task: () => {\n opts.pushState(path, state)\n notify({ type: 'PUSH' })\n },\n navigateOpts,\n type: 'PUSH',\n path,\n state,\n })\n },\n replace: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex, state)\n tryNavigation({\n task: () => {\n opts.replaceState(path, state)\n notify({ type: 'REPLACE' })\n },\n navigateOpts,\n type: 'REPLACE',\n path,\n state,\n })\n },\n go: (index, navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.go(index)\n handleIndexChange({ type: 'GO', index })\n },\n navigateOpts,\n type: 'GO',\n })\n },\n back: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.back(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'BACK' })\n },\n navigateOpts,\n type: 'BACK',\n })\n },\n forward: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.forward(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'FORWARD' })\n },\n navigateOpts,\n type: 'FORWARD',\n })\n },\n canGoBack: () => location.state[stateIndexKey] !== 0,\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n if (!opts.setBlockers) return () => {}\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers([...blockers, blocker])\n\n return () => {\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers?.(blockers.filter((b) => b !== blocker))\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKeyAndIndex(index: number, state: HistoryState | undefined) {\n if (!state) {\n state = {}\n }\n const key = createRandomKey()\n return {\n ...state,\n key, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: key,\n [stateIndexKey]: index,\n } as ParsedHistoryState\n}\n\n/**\n * Creates a history object that can be used to interact with the browser's\n * navigation. This is a lightweight API wrapping the browser's native methods.\n * It is designed to work with TanStack Router, but could be used as a standalone API as well.\n * IMPORTANT: This API implements history throttling via a microtask to prevent\n * excessive calls to the history API. In some browsers, calling history.pushState or\n * history.replaceState in quick succession can cause the browser to ignore subsequent\n * calls. This API smooths out those differences and ensures that your application\n * state will *eventually* match the browser state. In most cases, this is not a problem,\n * but if you need to ensure that the browser state is up to date, you can use the\n * `history.flush` method to immediately flush all pending state changes to the browser URL.\n * @param opts\n * @param opts.getHref A function that returns the current href (path + search + hash)\n * @param opts.createHref A function that takes a path and returns a href (path + search + hash)\n * @returns A history instance\n */\nexport function createBrowserHistory(opts?: {\n parseLocation?: () => HistoryLocation\n createHref?: (path: string) => string\n window?: any\n}): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n\n const originalPushState = win.history.pushState\n const originalReplaceState = win.history.replaceState\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n const createHref = opts?.createHref ?? ((path) => path)\n const parseLocation =\n opts?.parseLocation ??\n (() =>\n parseHref(\n `${win.location.pathname}${win.location.search}${win.location.hash}`,\n win.history.state,\n ))\n\n // Ensure there is always a key to start\n if (!win.history.state?.__TSR_key && !win.history.state?.key) {\n const addedKey = createRandomKey()\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: addedKey, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: addedKey,\n },\n '',\n )\n }\n\n let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\n\n let nextPopIsGo = false\n let ignoreNextPop = false\n let skipBlockerNextPop = false\n let ignoreNextBeforeUnload = false\n\n const getLocation = () => currentLocation\n\n let next:\n | undefined\n | {\n // This is the latest location that we were attempting to push/replace\n href: string\n // This is the latest state that we were attempting to push/replace\n state: any\n // This is the latest type that we were attempting to push/replace\n isPush: boolean\n }\n\n // We need to track the current scheduled update to prevent\n // multiple updates from being scheduled at the same time.\n let scheduled: Promise<void> | undefined\n\n // This function flushes the next update to the browser history\n const flush = () => {\n if (!next) {\n return\n }\n\n // We need to ignore any updates to the subscribers while we update the browser history\n history._ignoreSubscribers = true\n\n // Update the browser history\n ;(next.isPush ? win.history.pushState : win.history.replaceState)(\n next.state,\n '',\n next.href,\n )\n\n // Stop ignoring subscriber updates\n history._ignoreSubscribers = false\n\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n }\n\n // This function queues up a call to update the browser history\n const queueHistoryAction = (\n type: 'push' | 'replace',\n destHref: string,\n state: any,\n ) => {\n const href = createHref(destHref)\n\n if (!scheduled) {\n rollbackLocation = currentLocation\n }\n\n // Update the location in memory\n currentLocation = parseHref(destHref, state)\n\n // Keep track of the next location we need to flush to the URL\n next = {\n href,\n state,\n isPush: next?.isPush || type === 'push',\n }\n\n if (!scheduled) {\n // Schedule an update to the browser history\n scheduled = Promise.resolve().then(() => flush())\n }\n }\n\n // NOTE: this function can probably be removed\n const onPushPop = (type: 'PUSH' | 'REPLACE') => {\n currentLocation = parseLocation()\n history.notify({ type })\n }\n\n const onPushPopEvent = async () => {\n if (ignoreNextPop) {\n ignoreNextPop = false\n return\n }\n\n const nextLocation = parseLocation()\n const delta =\n nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey]\n const isForward = delta === 1\n const isBack = delta === -1\n const isGo = (!isForward && !isBack) || nextPopIsGo\n nextPopIsGo = false\n\n const action = isGo ? 'GO' : isBack ? 'BACK' : 'FORWARD'\n const notify: SubscriberHistoryAction = isGo\n ? {\n type: 'GO',\n index: delta,\n }\n : {\n type: isBack ? 'BACK' : 'FORWARD',\n }\n\n if (skipBlockerNextPop) {\n skipBlockerNextPop = false\n } else {\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const isBlocked = await blocker.blockerFn({\n currentLocation,\n nextLocation,\n action,\n })\n if (isBlocked) {\n ignoreNextPop = true\n win.history.go(1)\n history.notify(notify)\n return\n }\n }\n }\n }\n\n currentLocation = parseLocation()\n history.notify(notify)\n }\n\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (ignoreNextBeforeUnload) {\n ignoreNextBeforeUnload = false\n return\n }\n\n let shouldBlock = false\n\n // If one blocker has a non-disabled beforeUnload, we should block\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true\n if (shouldHaveBeforeUnload === true) {\n shouldBlock = true\n break\n }\n\n if (\n typeof shouldHaveBeforeUnload === 'function' &&\n shouldHaveBeforeUnload() === true\n ) {\n shouldBlock = true\n break\n }\n }\n }\n\n if (shouldBlock) {\n e.preventDefault()\n return (e.returnValue = '')\n }\n return\n }\n\n const history = createHistory({\n getLocation,\n getLength: () => win.history.length,\n pushState: (href, state) => queueHistoryAction('push', href, state),\n replaceState: (href, state) => queueHistoryAction('replace', href, state),\n back: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n return win.history.back()\n },\n forward: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n win.history.forward()\n },\n go: (n) => {\n nextPopIsGo = true\n win.history.go(n)\n },\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {\n capture: true,\n })\n win.removeEventListener(popStateEvent, onPushPopEvent)\n },\n onBlocked: () => {\n // If a navigation is blocked, we need to rollback the location\n // that we optimistically updated in memory.\n if (rollbackLocation && currentLocation !== rollbackLocation) {\n currentLocation = rollbackLocation\n }\n },\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n notifyOnIndexChange: false,\n })\n\n win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true })\n win.addEventListener(popStateEvent, onPushPopEvent)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('PUSH')\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('REPLACE')\n return res\n }\n\n return history\n}\n\n/**\n * Create a hash-based history implementation.\n * Useful for static hosts or environments without server URL rewriting.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/history-types\n */\nexport function createHashHistory(opts?: { window?: any }): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n return createBrowserHistory({\n window: win,\n parseLocation: () => {\n const hashSplit = win.location.hash.split('#').slice(1)\n const pathPart = hashSplit[0] ?? '/'\n const searchPart = win.location.search\n const hashEntries = hashSplit.slice(1)\n const hashPart =\n hashEntries.length === 0 ? '' : `#${hashEntries.join('#')}`\n const hashHref = `${pathPart}${searchPart}${hashPart}`\n return parseHref(hashHref, win.history.state)\n },\n createHref: (href) =>\n `${win.location.pathname}${win.location.search}#${href}`,\n })\n}\n\n/**\n * Create an in-memory history implementation.\n * Ideal for server rendering, tests, and non-DOM environments.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/history-types\n */\nexport function createMemoryHistory(\n opts: {\n initialEntries: Array<string>\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex\n ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)\n : entries.length - 1\n const states = entries.map((_entry, index) =>\n assignKeyAndIndex(index, undefined),\n )\n\n const getLocation = () => parseHref(entries[index]!, states[index])\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n return createHistory({\n getLocation,\n getLength: () => entries.length,\n pushState: (path, state) => {\n // Removes all subsequent entries after the current index to start a new branch\n if (index < entries.length - 1) {\n entries.splice(index + 1)\n states.splice(index + 1)\n }\n states.push(state)\n entries.push(path)\n index = Math.max(entries.length - 1, 0)\n },\n replaceState: (path, state) => {\n states[index] = state\n entries[index] = path\n },\n back: () => {\n index = Math.max(index - 1, 0)\n },\n forward: () => {\n index = Math.min(index + 1, entries.length - 1)\n },\n go: (n) => {\n index = Math.min(Math.max(index + n, 0), entries.length - 1)\n },\n createHref: (path) => path,\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n })\n}\n\n/**\n * Sanitize a path to prevent open redirect vulnerabilities.\n * Removes control characters and collapses leading double slashes.\n */\nfunction sanitizePath(path: string): string {\n // Remove ASCII control characters (0x00-0x1F) and DEL (0x7F)\n // These include CR (\\r = 0x0D), LF (\\n = 0x0A), and other potentially dangerous characters\n // eslint-disable-next-line no-control-regex\n let sanitized = path.replace(/[\\x00-\\x1f\\x7f]/g, '')\n\n // Prevent open redirect via protocol-relative URLs (e.g. \"//evil.com\")\n // Collapse leading double slashes to a single slash\n if (sanitized.startsWith('//')) {\n sanitized = '/' + sanitized.replace(/^\\/+/, '')\n }\n\n return sanitized\n}\n\nexport function parseHref(\n href: string,\n state: ParsedHistoryState | undefined,\n): HistoryLocation {\n const sanitizedHref = sanitizePath(href)\n const hashIndex = sanitizedHref.indexOf('#')\n const searchIndex = sanitizedHref.indexOf('?')\n\n const addedKey = createRandomKey()\n\n return {\n href: sanitizedHref,\n pathname: sanitizedHref.substring(\n 0,\n hashIndex > 0\n ? searchIndex > 0\n ? Math.min(hashIndex, searchIndex)\n : hashIndex\n : searchIndex > 0\n ? searchIndex\n : sanitizedHref.length,\n ),\n hash: hashIndex > -1 ? sanitizedHref.substring(hashIndex) : '',\n search:\n searchIndex > -1\n ? sanitizedHref.slice(\n searchIndex,\n hashIndex === -1 ? undefined : hashIndex,\n )\n : '',\n state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":["blockers","index"],"mappings":"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"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["// While the public API was clearly inspired by the \"history\" npm package,\n// This implementation attempts to be more lightweight by\n// making assumptions about the way TanStack Router works\n\nexport interface NavigateOptions {\n ignoreBlocker?: boolean\n}\n\ntype SubscriberHistoryAction =\n | {\n type: Exclude<HistoryAction, 'GO'>\n }\n | {\n type: 'GO'\n index: number\n }\n\ntype SubscriberArgs = {\n location: HistoryLocation\n action: SubscriberHistoryAction\n}\n\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: SubscriberArgs) => void>\n subscribe: (cb: (opts: SubscriberArgs) => void) => () => void\n push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n go: (index: number, navigateOpts?: NavigateOptions) => void\n back: (navigateOpts?: NavigateOptions) => void\n forward: (navigateOpts?: NavigateOptions) => void\n canGoBack: () => boolean\n createHref: (href: string) => string\n block: (blocker: NavigationBlocker) => () => void\n flush: () => void\n destroy: () => void\n notify: (action: SubscriberHistoryAction) => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: ParsedHistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {}\n\nexport type ParsedHistoryState = HistoryState & {\n key?: string // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key?: string\n __TSR_index: number\n}\n\ntype ShouldAllowNavigation = any\n\nexport type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO'\n\nexport type BlockerFnArgs = {\n currentLocation: HistoryLocation\n nextLocation: HistoryLocation\n action: HistoryAction\n}\n\nexport type BlockerFn = (\n args: BlockerFnArgs,\n) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation\n\nexport type NavigationBlocker = {\n blockerFn: BlockerFn\n enableBeforeUnload?: (() => boolean) | boolean\n}\n\ntype TryNavigateArgs = {\n task: () => void\n type: 'PUSH' | 'REPLACE' | 'BACK' | 'FORWARD' | 'GO'\n navigateOpts?: NavigateOptions\n} & (\n | {\n type: 'PUSH' | 'REPLACE'\n path: string\n state: any\n }\n | {\n type: 'BACK' | 'FORWARD' | 'GO'\n }\n)\n\nconst stateIndexKey = '__TSR_index'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nexport function createHistory(opts: {\n getLocation: () => HistoryLocation\n getLength: () => number\n pushState: (path: string, state: any) => void\n replaceState: (path: string, state: any) => void\n go: (n: number) => void\n back: (ignoreBlocker: boolean) => void\n forward: (ignoreBlocker: boolean) => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: () => void\n getBlockers?: () => Array<NavigationBlocker>\n setBlockers?: (blockers: Array<NavigationBlocker>) => void\n // Avoid notifying on forward/back/go, used for browser history as we already get notified by the popstate event\n notifyOnIndexChange?: boolean\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: SubscriberArgs) => void>()\n\n const notify = (action: SubscriberHistoryAction) => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location, action }))\n }\n\n const handleIndexChange = (action: SubscriberHistoryAction) => {\n if (opts.notifyOnIndexChange ?? true) notify(action)\n else location = opts.getLocation()\n }\n\n const tryNavigation = async ({\n task,\n navigateOpts,\n ...actionInfo\n }: TryNavigateArgs) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (ignoreBlocker) {\n task()\n return\n }\n\n const blockers = opts.getBlockers?.() ?? []\n const isPushOrReplace =\n actionInfo.type === 'PUSH' || actionInfo.type === 'REPLACE'\n if (typeof document !== 'undefined' && blockers.length && isPushOrReplace) {\n for (const blocker of blockers) {\n const nextLocation = parseHref(actionInfo.path, actionInfo.state)\n const isBlocked = await blocker.blockerFn({\n currentLocation: location,\n nextLocation,\n action: actionInfo.type,\n })\n if (isBlocked) {\n opts.onBlocked?.()\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n get length() {\n return opts.getLength()\n },\n subscribers,\n subscribe: (cb: (opts: SubscriberArgs) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex + 1, state)\n tryNavigation({\n task: () => {\n opts.pushState(path, state)\n notify({ type: 'PUSH' })\n },\n navigateOpts,\n type: 'PUSH',\n path,\n state,\n })\n },\n replace: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex, state)\n tryNavigation({\n task: () => {\n opts.replaceState(path, state)\n notify({ type: 'REPLACE' })\n },\n navigateOpts,\n type: 'REPLACE',\n path,\n state,\n })\n },\n go: (index, navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.go(index)\n handleIndexChange({ type: 'GO', index })\n },\n navigateOpts,\n type: 'GO',\n })\n },\n back: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.back(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'BACK' })\n },\n navigateOpts,\n type: 'BACK',\n })\n },\n forward: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.forward(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'FORWARD' })\n },\n navigateOpts,\n type: 'FORWARD',\n })\n },\n canGoBack: () => location.state[stateIndexKey] !== 0,\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n if (!opts.setBlockers) return () => {}\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers([...blockers, blocker])\n\n return () => {\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers?.(blockers.filter((b) => b !== blocker))\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKeyAndIndex(index: number, state: HistoryState | undefined) {\n if (!state) {\n state = {} as HistoryState\n }\n const key = createRandomKey()\n return {\n ...state,\n key, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: key,\n [stateIndexKey]: index,\n } as ParsedHistoryState\n}\n\n/**\n * Creates a history object that can be used to interact with the browser's\n * navigation. This is a lightweight API wrapping the browser's native methods.\n * It is designed to work with TanStack Router, but could be used as a standalone API as well.\n * IMPORTANT: This API implements history throttling via a microtask to prevent\n * excessive calls to the history API. In some browsers, calling history.pushState or\n * history.replaceState in quick succession can cause the browser to ignore subsequent\n * calls. This API smooths out those differences and ensures that your application\n * state will *eventually* match the browser state. In most cases, this is not a problem,\n * but if you need to ensure that the browser state is up to date, you can use the\n * `history.flush` method to immediately flush all pending state changes to the browser URL.\n * @param opts\n * @param opts.getHref A function that returns the current href (path + search + hash)\n * @param opts.createHref A function that takes a path and returns a href (path + search + hash)\n * @returns A history instance\n */\nexport function createBrowserHistory(opts?: {\n parseLocation?: () => HistoryLocation\n createHref?: (path: string) => string\n window?: any\n}): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n\n const originalPushState = win.history.pushState\n const originalReplaceState = win.history.replaceState\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n const createHref = opts?.createHref ?? ((path) => path)\n const parseLocation =\n opts?.parseLocation ??\n (() =>\n parseHref(\n `${win.location.pathname}${win.location.search}${win.location.hash}`,\n win.history.state,\n ))\n\n // Ensure there is always a key to start\n if (!win.history.state?.__TSR_key && !win.history.state?.key) {\n const addedKey = createRandomKey()\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: addedKey, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: addedKey,\n },\n '',\n )\n }\n\n let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\n\n let nextPopIsGo = false\n let ignoreNextPop = false\n let skipBlockerNextPop = false\n let ignoreNextBeforeUnload = false\n\n const getLocation = () => currentLocation\n\n let next:\n | undefined\n | {\n // This is the latest location that we were attempting to push/replace\n href: string\n // This is the latest state that we were attempting to push/replace\n state: any\n // This is the latest type that we were attempting to push/replace\n isPush: boolean\n }\n\n // We need to track the current scheduled update to prevent\n // multiple updates from being scheduled at the same time.\n let scheduled: Promise<void> | undefined\n\n // This function flushes the next update to the browser history\n const flush = () => {\n if (!next) {\n return\n }\n\n // We need to ignore any updates to the subscribers while we update the browser history\n history._ignoreSubscribers = true\n\n // Update the browser history\n ;(next.isPush ? win.history.pushState : win.history.replaceState)(\n next.state,\n '',\n next.href,\n )\n\n // Stop ignoring subscriber updates\n history._ignoreSubscribers = false\n\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n }\n\n // This function queues up a call to update the browser history\n const queueHistoryAction = (\n type: 'push' | 'replace',\n destHref: string,\n state: any,\n ) => {\n const href = createHref(destHref)\n\n if (!scheduled) {\n rollbackLocation = currentLocation\n }\n\n // Update the location in memory\n currentLocation = parseHref(destHref, state)\n\n // Keep track of the next location we need to flush to the URL\n next = {\n href,\n state,\n isPush: next?.isPush || type === 'push',\n }\n\n if (!scheduled) {\n // Schedule an update to the browser history\n scheduled = Promise.resolve().then(() => flush())\n }\n }\n\n // NOTE: this function can probably be removed\n const onPushPop = (type: 'PUSH' | 'REPLACE') => {\n currentLocation = parseLocation()\n history.notify({ type })\n }\n\n const onPushPopEvent = async () => {\n if (ignoreNextPop) {\n ignoreNextPop = false\n return\n }\n\n const nextLocation = parseLocation()\n const delta =\n nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey]\n const isForward = delta === 1\n const isBack = delta === -1\n const isGo = (!isForward && !isBack) || nextPopIsGo\n nextPopIsGo = false\n\n const action = isGo ? 'GO' : isBack ? 'BACK' : 'FORWARD'\n const notify: SubscriberHistoryAction = isGo\n ? {\n type: 'GO',\n index: delta,\n }\n : {\n type: isBack ? 'BACK' : 'FORWARD',\n }\n\n if (skipBlockerNextPop) {\n skipBlockerNextPop = false\n } else {\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const isBlocked = await blocker.blockerFn({\n currentLocation,\n nextLocation,\n action,\n })\n if (isBlocked) {\n ignoreNextPop = true\n win.history.go(1)\n history.notify(notify)\n return\n }\n }\n }\n }\n\n currentLocation = parseLocation()\n history.notify(notify)\n }\n\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (ignoreNextBeforeUnload) {\n ignoreNextBeforeUnload = false\n return\n }\n\n let shouldBlock = false\n\n // If one blocker has a non-disabled beforeUnload, we should block\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true\n if (shouldHaveBeforeUnload === true) {\n shouldBlock = true\n break\n }\n\n if (\n typeof shouldHaveBeforeUnload === 'function' &&\n shouldHaveBeforeUnload() === true\n ) {\n shouldBlock = true\n break\n }\n }\n }\n\n if (shouldBlock) {\n e.preventDefault()\n return (e.returnValue = '')\n }\n return\n }\n\n const history = createHistory({\n getLocation,\n getLength: () => win.history.length,\n pushState: (href, state) => queueHistoryAction('push', href, state),\n replaceState: (href, state) => queueHistoryAction('replace', href, state),\n back: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n return win.history.back()\n },\n forward: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n win.history.forward()\n },\n go: (n) => {\n nextPopIsGo = true\n win.history.go(n)\n },\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {\n capture: true,\n })\n win.removeEventListener(popStateEvent, onPushPopEvent)\n },\n onBlocked: () => {\n // If a navigation is blocked, we need to rollback the location\n // that we optimistically updated in memory.\n if (rollbackLocation && currentLocation !== rollbackLocation) {\n currentLocation = rollbackLocation\n }\n },\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n notifyOnIndexChange: false,\n })\n\n win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true })\n win.addEventListener(popStateEvent, onPushPopEvent)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('PUSH')\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('REPLACE')\n return res\n }\n\n return history\n}\n\n/**\n * Create a hash-based history implementation.\n * Useful for static hosts or environments without server URL rewriting.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/history-types\n */\nexport function createHashHistory(opts?: { window?: any }): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n return createBrowserHistory({\n window: win,\n parseLocation: () => {\n const hashSplit = win.location.hash.split('#').slice(1)\n const pathPart = hashSplit[0] ?? '/'\n const searchPart = win.location.search\n const hashEntries = hashSplit.slice(1)\n const hashPart =\n hashEntries.length === 0 ? '' : `#${hashEntries.join('#')}`\n const hashHref = `${pathPart}${searchPart}${hashPart}`\n return parseHref(hashHref, win.history.state)\n },\n createHref: (href) =>\n `${win.location.pathname}${win.location.search}#${href}`,\n })\n}\n\n/**\n * Create an in-memory history implementation.\n * Ideal for server rendering, tests, and non-DOM environments.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/history-types\n */\nexport function createMemoryHistory(\n opts: {\n initialEntries: Array<string>\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex\n ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)\n : entries.length - 1\n const states = entries.map((_entry, index) =>\n assignKeyAndIndex(index, undefined),\n )\n\n const getLocation = () => parseHref(entries[index]!, states[index])\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n return createHistory({\n getLocation,\n getLength: () => entries.length,\n pushState: (path, state) => {\n // Removes all subsequent entries after the current index to start a new branch\n if (index < entries.length - 1) {\n entries.splice(index + 1)\n states.splice(index + 1)\n }\n states.push(state)\n entries.push(path)\n index = Math.max(entries.length - 1, 0)\n },\n replaceState: (path, state) => {\n states[index] = state\n entries[index] = path\n },\n back: () => {\n index = Math.max(index - 1, 0)\n },\n forward: () => {\n index = Math.min(index + 1, entries.length - 1)\n },\n go: (n) => {\n index = Math.min(Math.max(index + n, 0), entries.length - 1)\n },\n createHref: (path) => path,\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n })\n}\n\n/**\n * Sanitize a path to prevent open redirect vulnerabilities.\n * Removes control characters and collapses leading double slashes.\n */\nfunction sanitizePath(path: string): string {\n // Remove ASCII control characters (0x00-0x1F) and DEL (0x7F)\n // These include CR (\\r = 0x0D), LF (\\n = 0x0A), and other potentially dangerous characters\n // eslint-disable-next-line no-control-regex\n let sanitized = path.replace(/[\\x00-\\x1f\\x7f]/g, '')\n\n // Prevent open redirect via protocol-relative URLs (e.g. \"//evil.com\")\n // Collapse leading double slashes to a single slash\n if (sanitized.startsWith('//')) {\n sanitized = '/' + sanitized.replace(/^\\/+/, '')\n }\n\n return sanitized\n}\n\nexport function parseHref(\n href: string,\n state: ParsedHistoryState | undefined,\n): HistoryLocation {\n const sanitizedHref = sanitizePath(href)\n const hashIndex = sanitizedHref.indexOf('#')\n const searchIndex = sanitizedHref.indexOf('?')\n\n const addedKey = createRandomKey()\n\n return {\n href: sanitizedHref,\n pathname: sanitizedHref.substring(\n 0,\n hashIndex > 0\n ? searchIndex > 0\n ? Math.min(hashIndex, searchIndex)\n : hashIndex\n : searchIndex > 0\n ? searchIndex\n : sanitizedHref.length,\n ),\n hash: hashIndex > -1 ? sanitizedHref.substring(hashIndex) : '',\n search:\n searchIndex > -1\n ? sanitizedHref.slice(\n searchIndex,\n hashIndex === -1 ? undefined : hashIndex,\n )\n : '',\n state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":["blockers","index"],"mappings":"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"} | ||
| {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["// While the public API was clearly inspired by the \"history\" npm package,\n// This implementation attempts to be more lightweight by\n// making assumptions about the way TanStack Router works\n\nexport interface NavigateOptions {\n ignoreBlocker?: boolean\n}\n\ntype SubscriberHistoryAction =\n | {\n type: Exclude<HistoryAction, 'GO'>\n }\n | {\n type: 'GO'\n index: number\n }\n\ntype SubscriberArgs = {\n location: HistoryLocation\n action: SubscriberHistoryAction\n}\n\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: SubscriberArgs) => void>\n subscribe: (cb: (opts: SubscriberArgs) => void) => () => void\n push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n go: (index: number, navigateOpts?: NavigateOptions) => void\n back: (navigateOpts?: NavigateOptions) => void\n forward: (navigateOpts?: NavigateOptions) => void\n canGoBack: () => boolean\n createHref: (href: string) => string\n block: (blocker: NavigationBlocker) => () => void\n flush: () => void\n destroy: () => void\n notify: (action: SubscriberHistoryAction) => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: ParsedHistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {}\n\nexport type ParsedHistoryState = HistoryState & {\n key?: string // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key?: string\n __TSR_index: number\n}\n\ntype ShouldAllowNavigation = any\n\nexport type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO'\n\nexport type BlockerFnArgs = {\n currentLocation: HistoryLocation\n nextLocation: HistoryLocation\n action: HistoryAction\n}\n\nexport type BlockerFn = (\n args: BlockerFnArgs,\n) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation\n\nexport type NavigationBlocker = {\n blockerFn: BlockerFn\n enableBeforeUnload?: (() => boolean) | boolean\n}\n\ntype TryNavigateArgs = {\n task: () => void\n type: 'PUSH' | 'REPLACE' | 'BACK' | 'FORWARD' | 'GO'\n navigateOpts?: NavigateOptions\n} & (\n | {\n type: 'PUSH' | 'REPLACE'\n path: string\n state: any\n }\n | {\n type: 'BACK' | 'FORWARD' | 'GO'\n }\n)\n\nconst stateIndexKey = '__TSR_index'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nexport function createHistory(opts: {\n getLocation: () => HistoryLocation\n getLength: () => number\n pushState: (path: string, state: any) => void\n replaceState: (path: string, state: any) => void\n go: (n: number) => void\n back: (ignoreBlocker: boolean) => void\n forward: (ignoreBlocker: boolean) => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: () => void\n getBlockers?: () => Array<NavigationBlocker>\n setBlockers?: (blockers: Array<NavigationBlocker>) => void\n // Avoid notifying on forward/back/go, used for browser history as we already get notified by the popstate event\n notifyOnIndexChange?: boolean\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: SubscriberArgs) => void>()\n\n const notify = (action: SubscriberHistoryAction) => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location, action }))\n }\n\n const handleIndexChange = (action: SubscriberHistoryAction) => {\n if (opts.notifyOnIndexChange ?? true) notify(action)\n else location = opts.getLocation()\n }\n\n const tryNavigation = async ({\n task,\n navigateOpts,\n ...actionInfo\n }: TryNavigateArgs) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (ignoreBlocker) {\n task()\n return\n }\n\n const blockers = opts.getBlockers?.() ?? []\n const isPushOrReplace =\n actionInfo.type === 'PUSH' || actionInfo.type === 'REPLACE'\n if (typeof document !== 'undefined' && blockers.length && isPushOrReplace) {\n for (const blocker of blockers) {\n const nextLocation = parseHref(actionInfo.path, actionInfo.state)\n const isBlocked = await blocker.blockerFn({\n currentLocation: location,\n nextLocation,\n action: actionInfo.type,\n })\n if (isBlocked) {\n opts.onBlocked?.()\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n get length() {\n return opts.getLength()\n },\n subscribers,\n subscribe: (cb: (opts: SubscriberArgs) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex + 1, state)\n tryNavigation({\n task: () => {\n opts.pushState(path, state)\n notify({ type: 'PUSH' })\n },\n navigateOpts,\n type: 'PUSH',\n path,\n state,\n })\n },\n replace: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex, state)\n tryNavigation({\n task: () => {\n opts.replaceState(path, state)\n notify({ type: 'REPLACE' })\n },\n navigateOpts,\n type: 'REPLACE',\n path,\n state,\n })\n },\n go: (index, navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.go(index)\n handleIndexChange({ type: 'GO', index })\n },\n navigateOpts,\n type: 'GO',\n })\n },\n back: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.back(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'BACK' })\n },\n navigateOpts,\n type: 'BACK',\n })\n },\n forward: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.forward(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'FORWARD' })\n },\n navigateOpts,\n type: 'FORWARD',\n })\n },\n canGoBack: () => location.state[stateIndexKey] !== 0,\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n if (!opts.setBlockers) return () => {}\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers([...blockers, blocker])\n\n return () => {\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers?.(blockers.filter((b) => b !== blocker))\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKeyAndIndex(index: number, state: HistoryState | undefined) {\n if (!state) {\n state = {}\n }\n const key = createRandomKey()\n return {\n ...state,\n key, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: key,\n [stateIndexKey]: index,\n } as ParsedHistoryState\n}\n\n/**\n * Creates a history object that can be used to interact with the browser's\n * navigation. This is a lightweight API wrapping the browser's native methods.\n * It is designed to work with TanStack Router, but could be used as a standalone API as well.\n * IMPORTANT: This API implements history throttling via a microtask to prevent\n * excessive calls to the history API. In some browsers, calling history.pushState or\n * history.replaceState in quick succession can cause the browser to ignore subsequent\n * calls. This API smooths out those differences and ensures that your application\n * state will *eventually* match the browser state. In most cases, this is not a problem,\n * but if you need to ensure that the browser state is up to date, you can use the\n * `history.flush` method to immediately flush all pending state changes to the browser URL.\n * @param opts\n * @param opts.getHref A function that returns the current href (path + search + hash)\n * @param opts.createHref A function that takes a path and returns a href (path + search + hash)\n * @returns A history instance\n */\nexport function createBrowserHistory(opts?: {\n parseLocation?: () => HistoryLocation\n createHref?: (path: string) => string\n window?: any\n}): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n\n const originalPushState = win.history.pushState\n const originalReplaceState = win.history.replaceState\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n const createHref = opts?.createHref ?? ((path) => path)\n const parseLocation =\n opts?.parseLocation ??\n (() =>\n parseHref(\n `${win.location.pathname}${win.location.search}${win.location.hash}`,\n win.history.state,\n ))\n\n // Ensure there is always a key to start\n if (!win.history.state?.__TSR_key && !win.history.state?.key) {\n const addedKey = createRandomKey()\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: addedKey, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: addedKey,\n },\n '',\n )\n }\n\n let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\n\n let nextPopIsGo = false\n let ignoreNextPop = false\n let skipBlockerNextPop = false\n let ignoreNextBeforeUnload = false\n\n const getLocation = () => currentLocation\n\n let next:\n | undefined\n | {\n // This is the latest location that we were attempting to push/replace\n href: string\n // This is the latest state that we were attempting to push/replace\n state: any\n // This is the latest type that we were attempting to push/replace\n isPush: boolean\n }\n\n // We need to track the current scheduled update to prevent\n // multiple updates from being scheduled at the same time.\n let scheduled: Promise<void> | undefined\n\n // This function flushes the next update to the browser history\n const flush = () => {\n if (!next) {\n return\n }\n\n // We need to ignore any updates to the subscribers while we update the browser history\n history._ignoreSubscribers = true\n\n // Update the browser history\n ;(next.isPush ? win.history.pushState : win.history.replaceState)(\n next.state,\n '',\n next.href,\n )\n\n // Stop ignoring subscriber updates\n history._ignoreSubscribers = false\n\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n }\n\n // This function queues up a call to update the browser history\n const queueHistoryAction = (\n type: 'push' | 'replace',\n destHref: string,\n state: any,\n ) => {\n const href = createHref(destHref)\n\n if (!scheduled) {\n rollbackLocation = currentLocation\n }\n\n // Update the location in memory\n currentLocation = parseHref(destHref, state)\n\n // Keep track of the next location we need to flush to the URL\n next = {\n href,\n state,\n isPush: next?.isPush || type === 'push',\n }\n\n if (!scheduled) {\n // Schedule an update to the browser history\n scheduled = Promise.resolve().then(() => flush())\n }\n }\n\n // NOTE: this function can probably be removed\n const onPushPop = (type: 'PUSH' | 'REPLACE') => {\n currentLocation = parseLocation()\n history.notify({ type })\n }\n\n const onPushPopEvent = async () => {\n if (ignoreNextPop) {\n ignoreNextPop = false\n return\n }\n\n const nextLocation = parseLocation()\n const delta =\n nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey]\n const isForward = delta === 1\n const isBack = delta === -1\n const isGo = (!isForward && !isBack) || nextPopIsGo\n nextPopIsGo = false\n\n const action = isGo ? 'GO' : isBack ? 'BACK' : 'FORWARD'\n const notify: SubscriberHistoryAction = isGo\n ? {\n type: 'GO',\n index: delta,\n }\n : {\n type: isBack ? 'BACK' : 'FORWARD',\n }\n\n if (skipBlockerNextPop) {\n skipBlockerNextPop = false\n } else {\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const isBlocked = await blocker.blockerFn({\n currentLocation,\n nextLocation,\n action,\n })\n if (isBlocked) {\n ignoreNextPop = true\n win.history.go(1)\n history.notify(notify)\n return\n }\n }\n }\n }\n\n currentLocation = parseLocation()\n history.notify(notify)\n }\n\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (ignoreNextBeforeUnload) {\n ignoreNextBeforeUnload = false\n return\n }\n\n let shouldBlock = false\n\n // If one blocker has a non-disabled beforeUnload, we should block\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true\n if (shouldHaveBeforeUnload === true) {\n shouldBlock = true\n break\n }\n\n if (\n typeof shouldHaveBeforeUnload === 'function' &&\n shouldHaveBeforeUnload() === true\n ) {\n shouldBlock = true\n break\n }\n }\n }\n\n if (shouldBlock) {\n e.preventDefault()\n return (e.returnValue = '')\n }\n return\n }\n\n const history = createHistory({\n getLocation,\n getLength: () => win.history.length,\n pushState: (href, state) => queueHistoryAction('push', href, state),\n replaceState: (href, state) => queueHistoryAction('replace', href, state),\n back: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n return win.history.back()\n },\n forward: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n win.history.forward()\n },\n go: (n) => {\n nextPopIsGo = true\n win.history.go(n)\n },\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {\n capture: true,\n })\n win.removeEventListener(popStateEvent, onPushPopEvent)\n },\n onBlocked: () => {\n // If a navigation is blocked, we need to rollback the location\n // that we optimistically updated in memory.\n if (rollbackLocation && currentLocation !== rollbackLocation) {\n currentLocation = rollbackLocation\n }\n },\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n notifyOnIndexChange: false,\n })\n\n win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true })\n win.addEventListener(popStateEvent, onPushPopEvent)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('PUSH')\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('REPLACE')\n return res\n }\n\n return history\n}\n\n/**\n * Create a hash-based history implementation.\n * Useful for static hosts or environments without server URL rewriting.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/history-types\n */\nexport function createHashHistory(opts?: { window?: any }): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n return createBrowserHistory({\n window: win,\n parseLocation: () => {\n const hashSplit = win.location.hash.split('#').slice(1)\n const pathPart = hashSplit[0] ?? '/'\n const searchPart = win.location.search\n const hashEntries = hashSplit.slice(1)\n const hashPart =\n hashEntries.length === 0 ? '' : `#${hashEntries.join('#')}`\n const hashHref = `${pathPart}${searchPart}${hashPart}`\n return parseHref(hashHref, win.history.state)\n },\n createHref: (href) =>\n `${win.location.pathname}${win.location.search}#${href}`,\n })\n}\n\n/**\n * Create an in-memory history implementation.\n * Ideal for server rendering, tests, and non-DOM environments.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/history-types\n */\nexport function createMemoryHistory(\n opts: {\n initialEntries: Array<string>\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex\n ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)\n : entries.length - 1\n const states = entries.map((_entry, index) =>\n assignKeyAndIndex(index, undefined),\n )\n\n const getLocation = () => parseHref(entries[index]!, states[index])\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n return createHistory({\n getLocation,\n getLength: () => entries.length,\n pushState: (path, state) => {\n // Removes all subsequent entries after the current index to start a new branch\n if (index < entries.length - 1) {\n entries.splice(index + 1)\n states.splice(index + 1)\n }\n states.push(state)\n entries.push(path)\n index = Math.max(entries.length - 1, 0)\n },\n replaceState: (path, state) => {\n states[index] = state\n entries[index] = path\n },\n back: () => {\n index = Math.max(index - 1, 0)\n },\n forward: () => {\n index = Math.min(index + 1, entries.length - 1)\n },\n go: (n) => {\n index = Math.min(Math.max(index + n, 0), entries.length - 1)\n },\n createHref: (path) => path,\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n })\n}\n\n/**\n * Sanitize a path to prevent open redirect vulnerabilities.\n * Removes control characters and collapses leading double slashes.\n */\nfunction sanitizePath(path: string): string {\n // Remove ASCII control characters (0x00-0x1F) and DEL (0x7F)\n // These include CR (\\r = 0x0D), LF (\\n = 0x0A), and other potentially dangerous characters\n // eslint-disable-next-line no-control-regex\n let sanitized = path.replace(/[\\x00-\\x1f\\x7f]/g, '')\n\n // Prevent open redirect via protocol-relative URLs (e.g. \"//evil.com\")\n // Collapse leading double slashes to a single slash\n if (sanitized.startsWith('//')) {\n sanitized = '/' + sanitized.replace(/^\\/+/, '')\n }\n\n return sanitized\n}\n\nexport function parseHref(\n href: string,\n state: ParsedHistoryState | undefined,\n): HistoryLocation {\n const sanitizedHref = sanitizePath(href)\n const hashIndex = sanitizedHref.indexOf('#')\n const searchIndex = sanitizedHref.indexOf('?')\n\n const addedKey = createRandomKey()\n\n return {\n href: sanitizedHref,\n pathname: sanitizedHref.substring(\n 0,\n hashIndex > 0\n ? searchIndex > 0\n ? Math.min(hashIndex, searchIndex)\n : hashIndex\n : searchIndex > 0\n ? searchIndex\n : sanitizedHref.length,\n ),\n hash: hashIndex > -1 ? sanitizedHref.substring(hashIndex) : '',\n search:\n searchIndex > -1\n ? sanitizedHref.slice(\n searchIndex,\n hashIndex === -1 ? undefined : hashIndex,\n )\n : '',\n state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":["blockers","index"],"mappings":"AA8FA,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AACtB,MAAM,oBAAoB;AAEnB,SAAS,cAAc,MAgBZ;AAChB,MAAI,WAAW,KAAK,YAAA;AACpB,QAAM,kCAAkB,IAAA;AAExB,QAAM,SAAS,CAAC,WAAoC;AAClD,eAAW,KAAK,YAAA;AAChB,gBAAY,QAAQ,CAAC,eAAe,WAAW,EAAE,UAAU,OAAA,CAAQ,CAAC;AAAA,EACtE;AAEA,QAAM,oBAAoB,CAAC,WAAoC;AAC7D,QAAI,KAAK,uBAAuB,KAAM,QAAO,MAAM;AAAA,QAC9C,YAAW,KAAK,YAAA;AAAA,EACvB;AAEA,QAAM,gBAAgB,OAAO;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,MACkB;AACrB,UAAM,gBAAgB,cAAc,iBAAiB;AACrD,QAAI,eAAe;AACjB,WAAA;AACA;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,cAAA,KAAmB,CAAA;AACzC,UAAM,kBACJ,WAAW,SAAS,UAAU,WAAW,SAAS;AACpD,QAAI,OAAO,aAAa,eAAe,SAAS,UAAU,iBAAiB;AACzE,iBAAW,WAAW,UAAU;AAC9B,cAAM,eAAe,UAAU,WAAW,MAAM,WAAW,KAAK;AAChE,cAAM,YAAY,MAAM,QAAQ,UAAU;AAAA,UACxC,iBAAiB;AAAA,UACjB;AAAA,UACA,QAAQ,WAAW;AAAA,QAAA,CACpB;AACD,YAAI,WAAW;AACb,eAAK,YAAA;AACL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,IAAI,WAAW;AACb,aAAO;AAAA,IACT;AAAA,IACA,IAAI,SAAS;AACX,aAAO,KAAK,UAAA;AAAA,IACd;AAAA,IACA;AAAA,IACA,WAAW,CAAC,OAAuC;AACjD,kBAAY,IAAI,EAAE;AAElB,aAAO,MAAM;AACX,oBAAY,OAAO,EAAE;AAAA,MACvB;AAAA,IACF;AAAA,IACA,MAAM,CAAC,MAAM,OAAO,iBAAiB;AACnC,YAAM,eAAe,SAAS,MAAM,aAAa;AACjD,cAAQ,kBAAkB,eAAe,GAAG,KAAK;AACjD,oBAAc;AAAA,QACZ,MAAM,MAAM;AACV,eAAK,UAAU,MAAM,KAAK;AAC1B,iBAAO,EAAE,MAAM,QAAQ;AAAA,QACzB;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,SAAS,CAAC,MAAM,OAAO,iBAAiB;AACtC,YAAM,eAAe,SAAS,MAAM,aAAa;AACjD,cAAQ,kBAAkB,cAAc,KAAK;AAC7C,oBAAc;AAAA,QACZ,MAAM,MAAM;AACV,eAAK,aAAa,MAAM,KAAK;AAC7B,iBAAO,EAAE,MAAM,WAAW;AAAA,QAC5B;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,IAAI,CAAC,OAAO,iBAAiB;AAC3B,oBAAc;AAAA,QACZ,MAAM,MAAM;AACV,eAAK,GAAG,KAAK;AACb,4BAAkB,EAAE,MAAM,MAAM,MAAA,CAAO;AAAA,QACzC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,MAAM,CAAC,iBAAiB;AACtB,oBAAc;AAAA,QACZ,MAAM,MAAM;AACV,eAAK,KAAK,cAAc,iBAAiB,KAAK;AAC9C,4BAAkB,EAAE,MAAM,QAAQ;AAAA,QACpC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,SAAS,CAAC,iBAAiB;AACzB,oBAAc;AAAA,QACZ,MAAM,MAAM;AACV,eAAK,QAAQ,cAAc,iBAAiB,KAAK;AACjD,4BAAkB,EAAE,MAAM,WAAW;AAAA,QACvC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,WAAW,MAAM,SAAS,MAAM,aAAa,MAAM;AAAA,IACnD,YAAY,CAAC,QAAQ,KAAK,WAAW,GAAG;AAAA,IACxC,OAAO,CAAC,YAAY;AAClB,UAAI,CAAC,KAAK,YAAa,QAAO,MAAM;AAAA,MAAC;AACrC,YAAM,WAAW,KAAK,cAAA,KAAmB,CAAA;AACzC,WAAK,YAAY,CAAC,GAAG,UAAU,OAAO,CAAC;AAEvC,aAAO,MAAM;AACX,cAAMA,YAAW,KAAK,cAAA,KAAmB,CAAA;AACzC,aAAK,cAAcA,UAAS,OAAO,CAAC,MAAM,MAAM,OAAO,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,IACA,OAAO,MAAM,KAAK,QAAA;AAAA,IAClB,SAAS,MAAM,KAAK,UAAA;AAAA,IACpB;AAAA,EAAA;AAEJ;AAEA,SAAS,kBAAkB,OAAe,OAAiC;AACzE,MAAI,CAAC,OAAO;AACV,YAAQ,CAAA;AAAA,EACV;AACA,QAAM,MAAM,gBAAA;AACZ,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA;AAAA,IACA,WAAW;AAAA,IACX,CAAC,aAAa,GAAG;AAAA,EAAA;AAErB;AAkBO,SAAS,qBAAqB,MAInB;AAChB,QAAM,MACJ,MAAM,WACL,OAAO,aAAa,cAAc,SAAU;AAE/C,QAAM,oBAAoB,IAAI,QAAQ;AACtC,QAAM,uBAAuB,IAAI,QAAQ;AAEzC,MAAI,WAAqC,CAAA;AACzC,QAAM,eAAe,MAAM;AAC3B,QAAM,eAAe,CAAC,gBACnB,WAAW;AAEd,QAAM,aAAa,MAAM,eAAe,CAAC,SAAS;AAClD,QAAM,gBACJ,MAAM,kBACL,MACC;AAAA,IACE,GAAG,IAAI,SAAS,QAAQ,GAAG,IAAI,SAAS,MAAM,GAAG,IAAI,SAAS,IAAI;AAAA,IAClE,IAAI,QAAQ;AAAA,EAAA;AAIlB,MAAI,CAAC,IAAI,QAAQ,OAAO,aAAa,CAAC,IAAI,QAAQ,OAAO,KAAK;AAC5D,UAAM,WAAW,gBAAA;AACjB,QAAI,QAAQ;AAAA,MACV;AAAA,QACE,CAAC,aAAa,GAAG;AAAA,QACjB,KAAK;AAAA;AAAA,QACL,WAAW;AAAA,MAAA;AAAA,MAEb;AAAA,IAAA;AAAA,EAEJ;AAEA,MAAI,kBAAkB,cAAA;AACtB,MAAI;AAEJ,MAAI,cAAc;AAClB,MAAI,gBAAgB;AACpB,MAAI,qBAAqB;AACzB,MAAI,yBAAyB;AAE7B,QAAM,cAAc,MAAM;AAE1B,MAAI;AAaJ,MAAI;AAGJ,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AAGA,YAAQ,qBAAqB;AAG5B,KAAC,KAAK,SAAS,IAAI,QAAQ,YAAY,IAAI,QAAQ;AAAA,MAClD,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,IAAA;AAIP,YAAQ,qBAAqB;AAG7B,WAAO;AACP,gBAAY;AACZ,uBAAmB;AAAA,EACrB;AAGA,QAAM,qBAAqB,CACzB,MACA,UACA,UACG;AACH,UAAM,OAAO,WAAW,QAAQ;AAEhC,QAAI,CAAC,WAAW;AACd,yBAAmB;AAAA,IACrB;AAGA,sBAAkB,UAAU,UAAU,KAAK;AAG3C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,QAAQ,MAAM,UAAU,SAAS;AAAA,IAAA;AAGnC,QAAI,CAAC,WAAW;AAEd,kBAAY,QAAQ,QAAA,EAAU,KAAK,MAAM,OAAO;AAAA,IAClD;AAAA,EACF;AAGA,QAAM,YAAY,CAAC,SAA6B;AAC9C,sBAAkB,cAAA;AAClB,YAAQ,OAAO,EAAE,MAAM;AAAA,EACzB;AAEA,QAAM,iBAAiB,YAAY;AACjC,QAAI,eAAe;AACjB,sBAAgB;AAChB;AAAA,IACF;AAEA,UAAM,eAAe,cAAA;AACrB,UAAM,QACJ,aAAa,MAAM,aAAa,IAAI,gBAAgB,MAAM,aAAa;AACzE,UAAM,YAAY,UAAU;AAC5B,UAAM,SAAS,UAAU;AACzB,UAAM,OAAQ,CAAC,aAAa,CAAC,UAAW;AACxC,kBAAc;AAEd,UAAM,SAAS,OAAO,OAAO,SAAS,SAAS;AAC/C,UAAM,SAAkC,OACpC;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,IAAA,IAET;AAAA,MACE,MAAM,SAAS,SAAS;AAAA,IAAA;AAG9B,QAAI,oBAAoB;AACtB,2BAAqB;AAAA,IACvB,OAAO;AACL,YAAMA,YAAW,aAAA;AACjB,UAAI,OAAO,aAAa,eAAeA,UAAS,QAAQ;AACtD,mBAAW,WAAWA,WAAU;AAC9B,gBAAM,YAAY,MAAM,QAAQ,UAAU;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,UAAA,CACD;AACD,cAAI,WAAW;AACb,4BAAgB;AAChB,gBAAI,QAAQ,GAAG,CAAC;AAChB,oBAAQ,OAAO,MAAM;AACrB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,sBAAkB,cAAA;AAClB,YAAQ,OAAO,MAAM;AAAA,EACvB;AAEA,QAAM,iBAAiB,CAAC,MAAyB;AAC/C,QAAI,wBAAwB;AAC1B,+BAAyB;AACzB;AAAA,IACF;AAEA,QAAI,cAAc;AAGlB,UAAMA,YAAW,aAAA;AACjB,QAAI,OAAO,aAAa,eAAeA,UAAS,QAAQ;AACtD,iBAAW,WAAWA,WAAU;AAC9B,cAAM,yBAAyB,QAAQ,sBAAsB;AAC7D,YAAI,2BAA2B,MAAM;AACnC,wBAAc;AACd;AAAA,QACF;AAEA,YACE,OAAO,2BAA2B,cAClC,uBAAA,MAA6B,MAC7B;AACA,wBAAc;AACd;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,aAAa;AACf,QAAE,eAAA;AACF,aAAQ,EAAE,cAAc;AAAA,IAC1B;AACA;AAAA,EACF;AAEA,QAAM,UAAU,cAAc;AAAA,IAC5B;AAAA,IACA,WAAW,MAAM,IAAI,QAAQ;AAAA,IAC7B,WAAW,CAAC,MAAM,UAAU,mBAAmB,QAAQ,MAAM,KAAK;AAAA,IAClE,cAAc,CAAC,MAAM,UAAU,mBAAmB,WAAW,MAAM,KAAK;AAAA,IACxE,MAAM,CAAC,kBAAkB;AACvB,UAAI,cAAe,sBAAqB;AACxC,+BAAyB;AACzB,aAAO,IAAI,QAAQ,KAAA;AAAA,IACrB;AAAA,IACA,SAAS,CAAC,kBAAkB;AAC1B,UAAI,cAAe,sBAAqB;AACxC,+BAAyB;AACzB,UAAI,QAAQ,QAAA;AAAA,IACd;AAAA,IACA,IAAI,CAAC,MAAM;AACT,oBAAc;AACd,UAAI,QAAQ,GAAG,CAAC;AAAA,IAClB;AAAA,IACA,YAAY,CAAC,SAAS,WAAW,IAAI;AAAA,IACrC;AAAA,IACA,SAAS,MAAM;AACb,UAAI,QAAQ,YAAY;AACxB,UAAI,QAAQ,eAAe;AAC3B,UAAI,oBAAoB,mBAAmB,gBAAgB;AAAA,QACzD,SAAS;AAAA,MAAA,CACV;AACD,UAAI,oBAAoB,eAAe,cAAc;AAAA,IACvD;AAAA,IACA,WAAW,MAAM;AAGf,UAAI,oBAAoB,oBAAoB,kBAAkB;AAC5D,0BAAkB;AAAA,MACpB;AAAA,IACF;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb,qBAAqB;AAAA,EAAA,CACtB;AAED,MAAI,iBAAiB,mBAAmB,gBAAgB,EAAE,SAAS,MAAM;AACzE,MAAI,iBAAiB,eAAe,cAAc;AAElD,MAAI,QAAQ,YAAY,YAAa,MAAkB;AACrD,UAAM,MAAM,kBAAkB,MAAM,IAAI,SAAS,IAAW;AAC5D,QAAI,CAAC,QAAQ,mBAAoB,WAAU,MAAM;AACjD,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,eAAe,YAAa,MAAkB;AACxD,UAAM,MAAM,qBAAqB,MAAM,IAAI,SAAS,IAAW;AAC/D,QAAI,CAAC,QAAQ,mBAAoB,WAAU,SAAS;AACpD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAOO,SAAS,kBAAkB,MAAwC;AACxE,QAAM,MACJ,MAAM,WACL,OAAO,aAAa,cAAc,SAAU;AAC/C,SAAO,qBAAqB;AAAA,IAC1B,QAAQ;AAAA,IACR,eAAe,MAAM;AACnB,YAAM,YAAY,IAAI,SAAS,KAAK,MAAM,GAAG,EAAE,MAAM,CAAC;AACtD,YAAM,WAAW,UAAU,CAAC,KAAK;AACjC,YAAM,aAAa,IAAI,SAAS;AAChC,YAAM,cAAc,UAAU,MAAM,CAAC;AACrC,YAAM,WACJ,YAAY,WAAW,IAAI,KAAK,IAAI,YAAY,KAAK,GAAG,CAAC;AAC3D,YAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ;AACpD,aAAO,UAAU,UAAU,IAAI,QAAQ,KAAK;AAAA,IAC9C;AAAA,IACA,YAAY,CAAC,SACX,GAAG,IAAI,SAAS,QAAQ,GAAG,IAAI,SAAS,MAAM,IAAI,IAAI;AAAA,EAAA,CACzD;AACH;AAOO,SAAS,oBACd,OAGI;AAAA,EACF,gBAAgB,CAAC,GAAG;AACtB,GACe;AACf,QAAM,UAAU,KAAK;AACrB,MAAI,QAAQ,KAAK,eACb,KAAK,IAAI,KAAK,IAAI,KAAK,cAAc,CAAC,GAAG,QAAQ,SAAS,CAAC,IAC3D,QAAQ,SAAS;AACrB,QAAM,SAAS,QAAQ;AAAA,IAAI,CAAC,QAAQC,WAClC,kBAAkBA,QAAO,MAAS;AAAA,EAAA;AAGpC,QAAM,cAAc,MAAM,UAAU,QAAQ,KAAK,GAAI,OAAO,KAAK,CAAC;AAElE,MAAI,WAAqC,CAAA;AACzC,QAAM,eAAe,MAAM;AAC3B,QAAM,eAAe,CAAC,gBACnB,WAAW;AAEd,SAAO,cAAc;AAAA,IACnB;AAAA,IACA,WAAW,MAAM,QAAQ;AAAA,IACzB,WAAW,CAAC,MAAM,UAAU;AAE1B,UAAI,QAAQ,QAAQ,SAAS,GAAG;AAC9B,gBAAQ,OAAO,QAAQ,CAAC;AACxB,eAAO,OAAO,QAAQ,CAAC;AAAA,MACzB;AACA,aAAO,KAAK,KAAK;AACjB,cAAQ,KAAK,IAAI;AACjB,cAAQ,KAAK,IAAI,QAAQ,SAAS,GAAG,CAAC;AAAA,IACxC;AAAA,IACA,cAAc,CAAC,MAAM,UAAU;AAC7B,aAAO,KAAK,IAAI;AAChB,cAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,IACA,MAAM,MAAM;AACV,cAAQ,KAAK,IAAI,QAAQ,GAAG,CAAC;AAAA,IAC/B;AAAA,IACA,SAAS,MAAM;AACb,cAAQ,KAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,CAAC;AAAA,IAChD;AAAA,IACA,IAAI,CAAC,MAAM;AACT,cAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,GAAG,CAAC,GAAG,QAAQ,SAAS,CAAC;AAAA,IAC7D;AAAA,IACA,YAAY,CAAC,SAAS;AAAA,IACtB,aAAa;AAAA,IACb,aAAa;AAAA,EAAA,CACd;AACH;AAMA,SAAS,aAAa,MAAsB;AAI1C,MAAI,YAAY,KAAK,QAAQ,oBAAoB,EAAE;AAInD,MAAI,UAAU,WAAW,IAAI,GAAG;AAC9B,gBAAY,MAAM,UAAU,QAAQ,QAAQ,EAAE;AAAA,EAChD;AAEA,SAAO;AACT;AAEO,SAAS,UACd,MACA,OACiB;AACjB,QAAM,gBAAgB,aAAa,IAAI;AACvC,QAAM,YAAY,cAAc,QAAQ,GAAG;AAC3C,QAAM,cAAc,cAAc,QAAQ,GAAG;AAE7C,QAAM,WAAW,gBAAA;AAEjB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,cAAc;AAAA,MACtB;AAAA,MACA,YAAY,IACR,cAAc,IACZ,KAAK,IAAI,WAAW,WAAW,IAC/B,YACF,cAAc,IACZ,cACA,cAAc;AAAA,IAAA;AAAA,IAEtB,MAAM,YAAY,KAAK,cAAc,UAAU,SAAS,IAAI;AAAA,IAC5D,QACE,cAAc,KACV,cAAc;AAAA,MACZ;AAAA,MACA,cAAc,KAAK,SAAY;AAAA,IAAA,IAEjC;AAAA,IACN,OAAO,SAAS,EAAE,CAAC,aAAa,GAAG,GAAG,KAAK,UAAU,WAAW,SAAA;AAAA,EAAS;AAE7E;AAGA,SAAS,kBAAkB;AACzB,UAAQ,KAAK,WAAW,GAAG,SAAS,EAAE,EAAE,UAAU,CAAC;AACrD;"} |
+5
-2
| { | ||
| "name": "@tanstack/history", | ||
| "version": "1.154.14", | ||
| "version": "1.161.4", | ||
| "description": "Modern and scalable routing for React applications", | ||
@@ -44,4 +44,7 @@ "author": "Tanner Linsley", | ||
| "engines": { | ||
| "node": ">=12" | ||
| "node": ">=20.19" | ||
| }, | ||
| "devDependencies": { | ||
| "vite": "*" | ||
| }, | ||
| "scripts": { | ||
@@ -48,0 +51,0 @@ "clean": "rimraf ./dist && rimraf ./coverage", |
+1
-1
@@ -254,3 +254,3 @@ // While the public API was clearly inspired by the "history" npm package, | ||
| if (!state) { | ||
| state = {} as HistoryState | ||
| state = {} | ||
| } | ||
@@ -257,0 +257,0 @@ const key = createRandomKey() |
116462
01
Infinity%