one 1.1.390 → 1.1.392
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/Root.cjs +6 -17
- package/dist/cjs/Root.js +9 -13
- package/dist/cjs/Root.js.map +1 -1
- package/dist/cjs/Root.native.js +4 -12
- package/dist/cjs/Root.native.js.map +1 -1
- package/dist/cjs/cli/build.cjs +2 -3
- package/dist/cjs/cli/build.js +2 -3
- package/dist/cjs/cli/build.js.map +1 -1
- package/dist/cjs/cli/build.native.js +2 -3
- package/dist/cjs/cli/build.native.js.map +2 -2
- package/dist/cjs/constants.cjs +9 -1
- package/dist/cjs/constants.js +7 -1
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/constants.native.js +9 -1
- package/dist/cjs/constants.native.js.map +2 -2
- package/dist/cjs/fork/NavigationContainer.cjs +49 -31
- package/dist/cjs/fork/NavigationContainer.js +40 -21
- package/dist/cjs/fork/NavigationContainer.js.map +2 -2
- package/dist/cjs/fork/NavigationContainer.native.js +51 -29
- package/dist/cjs/fork/NavigationContainer.native.js.map +2 -2
- package/dist/cjs/fork/createMemoryHistory.cjs +4 -3
- package/dist/cjs/fork/createMemoryHistory.js +3 -2
- package/dist/cjs/fork/createMemoryHistory.js.map +1 -1
- package/dist/cjs/fork/createMemoryHistory.native.js +8 -4
- package/dist/cjs/fork/createMemoryHistory.native.js.map +2 -2
- package/dist/cjs/fork/extractPathFromURL.cjs +48 -28
- package/dist/cjs/fork/extractPathFromURL.js +44 -21
- package/dist/cjs/fork/extractPathFromURL.js.map +2 -2
- package/dist/cjs/fork/extractPathFromURL.native.js +58 -26
- package/dist/cjs/fork/extractPathFromURL.native.js.map +2 -2
- package/dist/cjs/fork/findFocusedRoute.js.map +1 -1
- package/dist/cjs/fork/findFocusedRoute.native.js.map +1 -1
- package/dist/cjs/fork/getPathFromState-mods.cjs +65 -0
- package/dist/cjs/fork/getPathFromState-mods.js +56 -0
- package/dist/cjs/fork/getPathFromState-mods.js.map +6 -0
- package/dist/cjs/fork/getPathFromState-mods.native.js +70 -0
- package/dist/cjs/fork/getPathFromState-mods.native.js.map +6 -0
- package/dist/cjs/fork/getPathFromState.cjs +75 -224
- package/dist/cjs/fork/getPathFromState.js +68 -223
- package/dist/cjs/fork/getPathFromState.js.map +2 -2
- package/dist/cjs/fork/getPathFromState.native.js +79 -261
- package/dist/cjs/fork/getPathFromState.native.js.map +2 -2
- package/dist/cjs/fork/getStateFromPath-mods.cjs +187 -0
- package/dist/cjs/fork/getStateFromPath-mods.js +199 -0
- package/dist/cjs/fork/getStateFromPath-mods.js.map +6 -0
- package/dist/cjs/fork/getStateFromPath-mods.native.js +284 -0
- package/dist/cjs/fork/getStateFromPath-mods.native.js.map +6 -0
- package/dist/cjs/fork/getStateFromPath.cjs +181 -263
- package/dist/cjs/fork/getStateFromPath.js +148 -264
- package/dist/cjs/fork/getStateFromPath.js.map +2 -2
- package/dist/cjs/fork/getStateFromPath.native.js +164 -304
- package/dist/cjs/fork/getStateFromPath.native.js.map +2 -2
- package/dist/cjs/fork/useBackButton.js.map +1 -1
- package/dist/cjs/fork/useBackButton.native.js.map +1 -1
- package/dist/cjs/fork/useDocumentTitle.js +4 -1
- package/dist/cjs/fork/useDocumentTitle.js.map +1 -1
- package/dist/cjs/fork/useDocumentTitle.native.js +1 -1
- package/dist/cjs/fork/useDocumentTitle.native.js.map +2 -2
- package/dist/cjs/fork/useLinking.cjs +21 -24
- package/dist/cjs/fork/useLinking.js +21 -25
- package/dist/cjs/fork/useLinking.js.map +2 -2
- package/dist/cjs/fork/useLinking.native.js +68 -66
- package/dist/cjs/fork/useLinking.native.js.map +2 -2
- package/dist/cjs/fork/useThenable.js.map +1 -1
- package/dist/cjs/fork/useThenable.native.js.map +1 -1
- package/dist/cjs/fork/validatePathConfig.cjs +32 -11
- package/dist/cjs/fork/validatePathConfig.js +41 -11
- package/dist/cjs/fork/validatePathConfig.js.map +1 -1
- package/dist/cjs/fork/validatePathConfig.native.js +47 -18
- package/dist/cjs/fork/validatePathConfig.native.js.map +2 -2
- package/dist/cjs/layouts/withLayoutContext.cjs +1 -1
- package/dist/cjs/layouts/withLayoutContext.js +1 -1
- package/dist/cjs/layouts/withLayoutContext.js.map +1 -1
- package/dist/cjs/layouts/withLayoutContext.native.js +1 -1
- package/dist/cjs/layouts/withLayoutContext.native.js.map +1 -1
- package/dist/cjs/link/linking.cjs +4 -4
- package/dist/cjs/link/linking.js +3 -3
- package/dist/cjs/link/linking.js.map +2 -2
- package/dist/cjs/link/linking.native.js +3 -3
- package/dist/cjs/link/linking.native.js.map +1 -1
- package/dist/cjs/link/useLinkTo.cjs +2 -2
- package/dist/cjs/link/useLinkTo.js +2 -2
- package/dist/cjs/link/useLinkTo.js.map +1 -1
- package/dist/cjs/link/useLinkTo.native.js +2 -2
- package/dist/cjs/link/useLinkTo.native.js.map +1 -1
- package/dist/cjs/router/getNormalizedStatePath.cjs +2 -2
- package/dist/cjs/router/getNormalizedStatePath.js +2 -2
- package/dist/cjs/router/getNormalizedStatePath.js.map +1 -1
- package/dist/cjs/router/getNormalizedStatePath.native.js +2 -2
- package/dist/cjs/router/getNormalizedStatePath.native.js.map +1 -1
- package/dist/cjs/router/router.cjs +19 -3
- package/dist/cjs/router/router.js +25 -3
- package/dist/cjs/router/router.js.map +1 -1
- package/dist/cjs/router/router.native.js +39 -3
- package/dist/cjs/router/router.native.js.map +2 -2
- package/dist/cjs/utils/serverContext.cjs +7 -7
- package/dist/cjs/utils/serverContext.js +7 -7
- package/dist/cjs/utils/serverContext.js.map +1 -1
- package/dist/cjs/utils/serverContext.native.js +5 -5
- package/dist/cjs/utils/serverContext.native.js.map +2 -2
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.cjs +6 -6
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js +3 -4
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js.map +2 -2
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js +3 -4
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +2 -2
- package/dist/esm/Root.js +6 -2
- package/dist/esm/Root.js.map +1 -1
- package/dist/esm/Root.mjs +1 -1
- package/dist/esm/Root.mjs.map +1 -1
- package/dist/esm/Root.native.js +1 -1
- package/dist/esm/Root.native.js.map +2 -2
- package/dist/esm/cli/build.js +2 -3
- package/dist/esm/cli/build.js.map +1 -1
- package/dist/esm/cli/build.mjs +2 -3
- package/dist/esm/cli/build.mjs.map +1 -1
- package/dist/esm/cli/build.native.js +2 -3
- package/dist/esm/cli/build.native.js.map +2 -2
- package/dist/esm/constants.js +7 -1
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/constants.mjs +8 -2
- package/dist/esm/constants.mjs.map +1 -1
- package/dist/esm/constants.native.js +7 -1
- package/dist/esm/constants.native.js.map +2 -2
- package/dist/esm/fork/NavigationContainer.js +43 -20
- package/dist/esm/fork/NavigationContainer.js.map +1 -1
- package/dist/esm/fork/NavigationContainer.mjs +42 -24
- package/dist/esm/fork/NavigationContainer.mjs.map +1 -1
- package/dist/esm/fork/NavigationContainer.native.js +44 -24
- package/dist/esm/fork/NavigationContainer.native.js.map +2 -2
- package/dist/esm/fork/createMemoryHistory.js +3 -2
- package/dist/esm/fork/createMemoryHistory.js.map +1 -1
- package/dist/esm/fork/createMemoryHistory.mjs +4 -3
- package/dist/esm/fork/createMemoryHistory.mjs.map +1 -1
- package/dist/esm/fork/createMemoryHistory.native.js +4 -4
- package/dist/esm/fork/createMemoryHistory.native.js.map +2 -2
- package/dist/esm/fork/extractPathFromURL.js +42 -11
- package/dist/esm/fork/extractPathFromURL.js.map +1 -1
- package/dist/esm/fork/extractPathFromURL.mjs +39 -11
- package/dist/esm/fork/extractPathFromURL.mjs.map +1 -1
- package/dist/esm/fork/extractPathFromURL.native.js +52 -15
- package/dist/esm/fork/extractPathFromURL.native.js.map +2 -2
- package/dist/esm/fork/findFocusedRoute.js.map +1 -1
- package/dist/esm/fork/findFocusedRoute.mjs.map +1 -1
- package/dist/esm/fork/findFocusedRoute.native.js.map +1 -1
- package/dist/esm/fork/getPathFromState-mods.js +40 -0
- package/dist/esm/fork/getPathFromState-mods.js.map +6 -0
- package/dist/esm/fork/getPathFromState-mods.mjs +40 -0
- package/dist/esm/fork/getPathFromState-mods.mjs.map +1 -0
- package/dist/esm/fork/getPathFromState-mods.native.js +47 -0
- package/dist/esm/fork/getPathFromState-mods.native.js.map +6 -0
- package/dist/esm/fork/getPathFromState.js +71 -228
- package/dist/esm/fork/getPathFromState.js.map +2 -2
- package/dist/esm/fork/getPathFromState.mjs +73 -221
- package/dist/esm/fork/getPathFromState.mjs.map +1 -1
- package/dist/esm/fork/getPathFromState.native.js +79 -260
- package/dist/esm/fork/getPathFromState.native.js.map +2 -2
- package/dist/esm/fork/getStateFromPath-mods.js +176 -0
- package/dist/esm/fork/getStateFromPath-mods.js.map +6 -0
- package/dist/esm/fork/getStateFromPath-mods.mjs +143 -0
- package/dist/esm/fork/getStateFromPath-mods.mjs.map +1 -0
- package/dist/esm/fork/getStateFromPath-mods.native.js +246 -0
- package/dist/esm/fork/getStateFromPath-mods.native.js.map +6 -0
- package/dist/esm/fork/getStateFromPath.js +160 -265
- package/dist/esm/fork/getStateFromPath.js.map +2 -2
- package/dist/esm/fork/getStateFromPath.mjs +181 -260
- package/dist/esm/fork/getStateFromPath.mjs.map +1 -1
- package/dist/esm/fork/getStateFromPath.native.js +164 -302
- package/dist/esm/fork/getStateFromPath.native.js.map +2 -2
- package/dist/esm/fork/useBackButton.js.map +1 -1
- package/dist/esm/fork/useBackButton.mjs.map +1 -1
- package/dist/esm/fork/useBackButton.native.js.map +1 -1
- package/dist/esm/fork/useDocumentTitle.js +4 -1
- package/dist/esm/fork/useDocumentTitle.js.map +1 -1
- package/dist/esm/fork/useDocumentTitle.mjs.map +1 -1
- package/dist/esm/fork/useDocumentTitle.native.js +1 -1
- package/dist/esm/fork/useDocumentTitle.native.js.map +2 -2
- package/dist/esm/fork/useLinking.js +22 -26
- package/dist/esm/fork/useLinking.js.map +1 -1
- package/dist/esm/fork/useLinking.mjs +20 -23
- package/dist/esm/fork/useLinking.mjs.map +1 -1
- package/dist/esm/fork/useLinking.native.js +65 -67
- package/dist/esm/fork/useLinking.native.js.map +2 -2
- package/dist/esm/fork/useThenable.js.map +1 -1
- package/dist/esm/fork/useThenable.mjs.map +1 -1
- package/dist/esm/fork/useThenable.native.js.map +1 -1
- package/dist/esm/fork/validatePathConfig.js +41 -11
- package/dist/esm/fork/validatePathConfig.js.map +1 -1
- package/dist/esm/fork/validatePathConfig.mjs +32 -11
- package/dist/esm/fork/validatePathConfig.mjs.map +1 -1
- package/dist/esm/fork/validatePathConfig.native.js +43 -18
- package/dist/esm/fork/validatePathConfig.native.js.map +2 -2
- package/dist/esm/layouts/withLayoutContext.js +1 -1
- package/dist/esm/layouts/withLayoutContext.js.map +1 -1
- package/dist/esm/layouts/withLayoutContext.mjs +1 -1
- package/dist/esm/layouts/withLayoutContext.mjs.map +1 -1
- package/dist/esm/layouts/withLayoutContext.native.js +1 -1
- package/dist/esm/layouts/withLayoutContext.native.js.map +1 -1
- package/dist/esm/link/linking.js +2 -2
- package/dist/esm/link/linking.js.map +1 -1
- package/dist/esm/link/linking.mjs +2 -2
- package/dist/esm/link/linking.mjs.map +1 -1
- package/dist/esm/link/linking.native.js +2 -2
- package/dist/esm/link/linking.native.js.map +1 -1
- package/dist/esm/link/useLinkTo.js +1 -1
- package/dist/esm/link/useLinkTo.mjs +1 -1
- package/dist/esm/link/useLinkTo.native.js +1 -1
- package/dist/esm/router/getNormalizedStatePath.js +1 -1
- package/dist/esm/router/getNormalizedStatePath.mjs +1 -1
- package/dist/esm/router/getNormalizedStatePath.native.js +1 -1
- package/dist/esm/router/router.js +24 -2
- package/dist/esm/router/router.js.map +1 -1
- package/dist/esm/router/router.mjs +18 -2
- package/dist/esm/router/router.mjs.map +1 -1
- package/dist/esm/router/router.native.js +38 -2
- package/dist/esm/router/router.native.js.map +2 -2
- package/dist/esm/utils/serverContext.js +2 -1
- package/dist/esm/utils/serverContext.js.map +1 -1
- package/dist/esm/utils/serverContext.mjs +1 -1
- package/dist/esm/utils/serverContext.mjs.map +1 -1
- package/dist/esm/utils/serverContext.native.js +2 -1
- package/dist/esm/utils/serverContext.native.js.map +2 -2
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.js +3 -3
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs +3 -3
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js +3 -3
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +2 -2
- package/package.json +8 -9
- package/src/Root.tsx +6 -2
- package/src/cli/build.ts +2 -3
- package/src/constants.ts +8 -0
- package/src/fork/NavigationContainer.tsx +101 -39
- package/src/fork/createMemoryHistory.tsx +15 -13
- package/src/fork/extractPathFromURL.ts +85 -40
- package/src/fork/findFocusedRoute.tsx +9 -1
- package/src/fork/getPathFromState-mods.ts +142 -0
- package/src/fork/getPathFromState.ts +244 -501
- package/src/fork/getStateFromPath-mods.ts +400 -0
- package/src/fork/getStateFromPath.ts +447 -538
- package/src/fork/useBackButton.native.tsx +16 -2
- package/src/fork/useBackButton.tsx +11 -2
- package/src/fork/useDocumentTitle.native.tsx +9 -4
- package/src/fork/useDocumentTitle.tsx +12 -7
- package/src/fork/useLinking.native.ts +71 -63
- package/src/fork/useLinking.ts +75 -40
- package/src/fork/useThenable.tsx +7 -1
- package/src/fork/validatePathConfig.ts +64 -12
- package/src/layouts/withLayoutContext.tsx +1 -1
- package/src/link/linking.ts +2 -2
- package/src/link/useLinkTo.tsx +1 -1
- package/src/router/getNormalizedStatePath.tsx +1 -1
- package/src/router/router.ts +41 -2
- package/src/utils/serverContext.tsx +3 -1
- package/src/vite/plugins/fileSystemRouterPlugin.tsx +3 -3
- package/types/Root.d.ts.map +1 -1
- package/types/cli/build.d.ts.map +1 -1
- package/types/constants.d.ts +2 -0
- package/types/constants.d.ts.map +1 -1
- package/types/fork/NavigationContainer.d.ts +19 -8
- package/types/fork/NavigationContainer.d.ts.map +1 -1
- package/types/fork/createMemoryHistory.d.ts +10 -1
- package/types/fork/createMemoryHistory.d.ts.map +1 -1
- package/types/fork/extractPathFromURL.d.ts +7 -1
- package/types/fork/extractPathFromURL.d.ts.map +1 -1
- package/types/fork/findFocusedRoute.d.ts +9 -0
- package/types/fork/findFocusedRoute.d.ts.map +1 -1
- package/types/fork/getPathFromState-mods.d.ts +23 -0
- package/types/fork/getPathFromState-mods.d.ts.map +1 -0
- package/types/fork/getPathFromState.d.ts +15 -14
- package/types/fork/getPathFromState.d.ts.map +1 -1
- package/types/fork/getStateFromPath-mods.d.ts +58 -0
- package/types/fork/getStateFromPath-mods.d.ts.map +1 -0
- package/types/fork/getStateFromPath.d.ts +28 -29
- package/types/fork/getStateFromPath.d.ts.map +1 -1
- package/types/fork/useBackButton.d.ts +6 -0
- package/types/fork/useBackButton.d.ts.map +1 -1
- package/types/fork/useBackButton.native.d.ts +9 -1
- package/types/fork/useBackButton.native.d.ts.map +1 -1
- package/types/fork/useDocumentTitle.d.ts +8 -6
- package/types/fork/useDocumentTitle.d.ts.map +1 -1
- package/types/fork/useDocumentTitle.native.d.ts +5 -2
- package/types/fork/useDocumentTitle.native.d.ts.map +1 -1
- package/types/fork/useLinking.d.ts +8 -1
- package/types/fork/useLinking.d.ts.map +1 -1
- package/types/fork/useLinking.native.d.ts +9 -2
- package/types/fork/useLinking.native.d.ts.map +1 -1
- package/types/fork/useThenable.d.ts +6 -0
- package/types/fork/useThenable.d.ts.map +1 -1
- package/types/fork/validatePathConfig.d.ts +8 -1
- package/types/fork/validatePathConfig.d.ts.map +1 -1
- package/types/link/linking.d.ts +2 -2
- package/types/link/linking.d.ts.map +1 -1
- package/types/utils/serverContext.d.ts.map +1 -1
- package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
@@ -1,70 +1,72 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
/**
|
2
|
+
* This file is copied from the react-navigation repo:
|
3
|
+
* https://github.com/react-navigation/react-navigation/blob/%40react-navigation/core%407.1.2/packages/core/src/getStateFromPath.tsx
|
4
|
+
*
|
5
|
+
* Please refrain from making changes to this file, as it will make merging updates from the upstream harder.
|
6
|
+
* All modifications except formatting should be marked with `// @modified` comment.
|
7
|
+
*/
|
8
|
+
|
9
|
+
import type { InitialState, NavigationState, PartialState } from '@react-navigation/routers'
|
10
|
+
// biome-ignore lint/suspicious/noShadowRestrictedNames: ignore from forked code // @modified
|
4
11
|
import escape from 'escape-string-regexp'
|
5
|
-
import
|
6
|
-
import { matchGroupName, stripGroupSegmentsFromPath } from '../router/matchers'
|
7
|
-
import { findFocusedRoute } from './findFocusedRoute'
|
8
|
-
import validatePathConfig from './validatePathConfig'
|
9
|
-
import type { OneRouter } from '../interfaces/router'
|
12
|
+
// import * as queryString from 'query-string'
|
10
13
|
|
11
|
-
|
14
|
+
import { findFocusedRoute } from './findFocusedRoute'
|
15
|
+
import type { PathConfigMap } from '@react-navigation/core' // @modified
|
16
|
+
import { validatePathConfig } from './validatePathConfig'
|
17
|
+
import {
|
18
|
+
type AdditionalRouteConfig,
|
19
|
+
appendIsInitial,
|
20
|
+
createConfigItemAdditionalProperties,
|
21
|
+
decodeURIComponentSafe,
|
22
|
+
formatRegexPattern,
|
23
|
+
getParamValue,
|
24
|
+
getRouteConfigSorter,
|
25
|
+
getUrlWithReactNavigationConcessions,
|
26
|
+
matchForEmptyPath,
|
27
|
+
parseQueryParamsExtended,
|
28
|
+
populateParams,
|
29
|
+
} from './getStateFromPath-mods'
|
30
|
+
|
31
|
+
type Options<ParamList extends {}> = {
|
32
|
+
path?: string
|
12
33
|
initialRouteName?: string
|
13
34
|
screens: PathConfigMap<ParamList>
|
14
35
|
}
|
15
36
|
|
16
37
|
type ParseConfig = Record<string, (value: string) => any>
|
17
38
|
|
18
|
-
|
19
|
-
|
39
|
+
// @modified: add export
|
40
|
+
export type RouteConfig = {
|
20
41
|
screen: string
|
21
42
|
regex?: RegExp
|
22
43
|
path: string
|
23
44
|
pattern: string
|
24
45
|
routeNames: string[]
|
25
46
|
parse?: ParseConfig
|
26
|
-
|
27
|
-
userReadableName: string
|
28
|
-
_route?: RouteNode
|
29
|
-
}
|
47
|
+
} & AdditionalRouteConfig // @modified: union with AdditionalRouteConfig
|
30
48
|
|
31
|
-
|
49
|
+
// @modified: add export
|
50
|
+
export type InitialRouteConfig = {
|
32
51
|
initialRouteName: string
|
33
52
|
parentScreens: string[]
|
34
53
|
}
|
35
54
|
|
36
|
-
type
|
55
|
+
type ResultState = PartialState<NavigationState> & {
|
56
|
+
state?: ResultState
|
57
|
+
}
|
58
|
+
|
59
|
+
// @modified: add export
|
60
|
+
export type ParsedRoute = {
|
37
61
|
name: string
|
38
62
|
path?: string
|
39
|
-
params?: Record<string, any>
|
63
|
+
params?: Record<string, any> | undefined
|
40
64
|
}
|
41
65
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
let parsed: URL
|
47
|
-
try {
|
48
|
-
parsed = new URL(path, baseUrl || 'http://phony.example')
|
49
|
-
} catch (err) {
|
50
|
-
console.warn(`Error parsing url ${path}: ${err?.['message']}`)
|
51
|
-
// Do nothing with invalid URLs.
|
52
|
-
return {
|
53
|
-
nonstandardPathname: path,
|
54
|
-
inputPathnameWithoutHash: path.replace(/#.*$/g, ''),
|
55
|
-
url: null,
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
const pathname = parsed.pathname
|
60
|
-
|
61
|
-
// Make sure there is a trailing slash
|
62
|
-
return {
|
63
|
-
// The slashes are at the end, not the beginning
|
64
|
-
nonstandardPathname:
|
65
|
-
stripBaseUrl(pathname, baseUrl).replace(/^\/+/g, '').replace(/\/+$/g, '') + '/',
|
66
|
-
url: parsed,
|
67
|
-
}
|
66
|
+
type ConfigResources = {
|
67
|
+
initialRoutes: InitialRouteConfig[]
|
68
|
+
configs: RouteConfig[]
|
69
|
+
configWithRegexes: RouteConfig[]
|
68
70
|
}
|
69
71
|
|
70
72
|
/**
|
@@ -88,322 +90,276 @@ export function getUrlWithReactNavigationConcessions(
|
|
88
90
|
* @param path Path string to parse and convert, e.g. /foo/bar?count=42.
|
89
91
|
* @param options Extra options to fine-tune how to parse the path.
|
90
92
|
*/
|
91
|
-
export
|
93
|
+
export function getStateFromPath<ParamList extends {}>(
|
92
94
|
path: string,
|
93
95
|
options?: Options<ParamList>
|
94
|
-
):
|
95
|
-
const { initialRoutes, configs } =
|
96
|
-
return getStateFromPathWithConfigs(path, configs, initialRoutes)
|
97
|
-
}
|
98
|
-
|
99
|
-
export function getMatchableRouteConfigs<ParamList extends object>(options?: Options<ParamList>) {
|
100
|
-
if (options) {
|
101
|
-
validatePathConfig(options)
|
102
|
-
}
|
96
|
+
): ResultState | undefined {
|
97
|
+
const { initialRoutes, configs, configWithRegexes } = getConfigResources(options)
|
103
98
|
|
104
99
|
const screens = options?.screens
|
105
|
-
// One disallows usage without a linking config.
|
106
|
-
if (!screens) {
|
107
|
-
throw Error("You must pass a 'screens' object to 'getStateFromPath' to generate a path.")
|
108
|
-
}
|
109
100
|
|
110
|
-
//
|
111
|
-
const
|
101
|
+
// @modified - start
|
102
|
+
const pathData = getUrlWithReactNavigationConcessions(path)
|
103
|
+
// @modified - end
|
112
104
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
})
|
118
|
-
}
|
105
|
+
let remaining = pathData.nonstandardPathname // @modified: use `pathData.nonstandardPathname` instead of `path`
|
106
|
+
.replace(/\/+/g, '/') // Replace multiple slash (//) with single ones
|
107
|
+
.replace(/^\//, '') // Remove extra leading slash
|
108
|
+
.replace(/\?.*$/, '') // Remove query params which we will handle later
|
119
109
|
|
120
|
-
//
|
121
|
-
|
122
|
-
.flatMap((key) => createNormalizedConfigs(key, screens, [], initialRoutes))
|
123
|
-
.flat()
|
124
|
-
|
125
|
-
const resolvedInitialPatterns = initialRoutes.map((route) =>
|
126
|
-
joinPaths(...route.parentScreens, route.initialRouteName)
|
127
|
-
)
|
110
|
+
// Make sure there is a trailing slash
|
111
|
+
remaining = remaining.endsWith('/') ? remaining : `${remaining}/`
|
128
112
|
|
129
|
-
const
|
130
|
-
...config,
|
131
|
-
// TODO: Probably a safer way to do this
|
132
|
-
// Mark initial routes to give them potential priority over other routes that match.
|
133
|
-
isInitial: resolvedInitialPatterns.includes(config.routeNames.join('/')),
|
134
|
-
}))
|
113
|
+
const prefix = options?.path?.replace(/^\//, '') // Remove extra leading slash
|
135
114
|
|
136
|
-
|
137
|
-
|
115
|
+
if (prefix) {
|
116
|
+
// Make sure there is a trailing slash
|
117
|
+
const normalizedPrefix = prefix.endsWith('/') ? prefix : `${prefix}/`
|
138
118
|
|
139
|
-
|
140
|
-
|
119
|
+
// If the path doesn't start with the prefix, it's not a match
|
120
|
+
if (!remaining.startsWith(normalizedPrefix)) {
|
121
|
+
return undefined
|
122
|
+
}
|
141
123
|
|
142
|
-
|
143
|
-
|
124
|
+
// Remove the prefix from the path
|
125
|
+
remaining = remaining.replace(normalizedPrefix, '')
|
126
|
+
}
|
144
127
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
128
|
+
if (screens === undefined) {
|
129
|
+
// When no config is specified, use the path segments as route names
|
130
|
+
const routes = remaining
|
131
|
+
.split('/')
|
132
|
+
.filter(Boolean)
|
133
|
+
.map((segment) => {
|
134
|
+
const name = decodeURIComponent(segment)
|
135
|
+
return { name }
|
136
|
+
})
|
151
137
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
138
|
+
if (routes.length) {
|
139
|
+
// @modified - start
|
140
|
+
// return createNestedStateObject(path, routes, initialRoutes)
|
141
|
+
return createNestedStateObject(pathData, routes, initialRoutes, [], pathData.url.hash)
|
142
|
+
// @modified - end
|
143
|
+
}
|
156
144
|
|
157
|
-
|
158
|
-
|
159
|
-
const intersects =
|
160
|
-
a.length > b.length ? b.every((it, i) => a[i] === it) : a.every((it, i) => b[i] === it)
|
145
|
+
return undefined
|
146
|
+
}
|
161
147
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
148
|
+
if (remaining === '/') {
|
149
|
+
// We need to add special handling of empty path so navigation to empty path also works
|
150
|
+
// When handling empty path, we should only look at the root level config
|
151
|
+
// @modified - start
|
152
|
+
// const match = configs.find(
|
153
|
+
// (config) =>
|
154
|
+
// config.path === '' &&
|
155
|
+
// config.routeNames.every(
|
156
|
+
// // Make sure that none of the parent configs have a non-empty path defined
|
157
|
+
// (name) => !configs.find((c) => c.screen === name)?.path
|
158
|
+
// )
|
159
|
+
// )
|
160
|
+
const match = matchForEmptyPath(configWithRegexes)
|
161
|
+
// @modified - end
|
162
|
+
|
163
|
+
if (match) {
|
164
|
+
return createNestedStateObject(
|
165
|
+
pathData, // @modified: pass pathData instead of path
|
166
|
+
match.routeNames.map((name) => ({ name })),
|
167
|
+
initialRoutes,
|
168
|
+
configs
|
169
|
+
)
|
183
170
|
}
|
184
171
|
|
185
|
-
return
|
186
|
-
|
187
|
-
})
|
188
|
-
}, {})
|
189
|
-
}
|
172
|
+
return undefined
|
173
|
+
}
|
190
174
|
|
191
|
-
|
192
|
-
|
193
|
-
// - the most exhaustive ones are always at the beginning
|
194
|
-
// - patterns with wildcard are always at the end
|
175
|
+
let result: PartialState<NavigationState> | undefined
|
176
|
+
let current: PartialState<NavigationState> | undefined
|
195
177
|
|
196
|
-
//
|
197
|
-
// This
|
198
|
-
|
199
|
-
return b.routeNames.join('>').localeCompare(a.routeNames.join('>'))
|
200
|
-
}
|
178
|
+
// We match the whole path against the regex instead of segments
|
179
|
+
// This makes sure matches such as wildcard will catch any unmatched routes, even if nested
|
180
|
+
const { routes, remainingPath } = matchAgainstConfigs(remaining, configWithRegexes)
|
201
181
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
) {
|
209
|
-
return -1
|
182
|
+
if (routes !== undefined) {
|
183
|
+
// This will always be empty if full path matched
|
184
|
+
// @modified: pass pathData instead of path
|
185
|
+
current = createNestedStateObject(pathData, routes, initialRoutes, configs)
|
186
|
+
remaining = remainingPath
|
187
|
+
result = current
|
210
188
|
}
|
211
189
|
|
212
|
-
if (
|
213
|
-
return
|
190
|
+
if (current == null || result == null) {
|
191
|
+
return undefined
|
214
192
|
}
|
215
193
|
|
216
|
-
|
217
|
-
|
218
|
-
// This is so we can compare the length of the pattern, e.g. `foo/*` > `foo` vs `*` < ``.
|
219
|
-
const aParts = a.pattern
|
220
|
-
.split('/')
|
221
|
-
// Strip out group names to ensure they don't affect the priority.
|
222
|
-
.filter((part) => matchGroupName(part) == null)
|
223
|
-
if (a.screen === 'index' || a.screen.match(/\/index$/)) {
|
224
|
-
aParts.push('index')
|
225
|
-
}
|
194
|
+
return result
|
195
|
+
}
|
226
196
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
197
|
+
/**
|
198
|
+
* Reference to the last used config resources. This is used to avoid recomputing the config resources when the options are the same.
|
199
|
+
*/
|
200
|
+
const cachedConfigResources = new WeakMap<Options<{}>, ConfigResources>()
|
231
201
|
|
232
|
-
|
233
|
-
|
234
|
-
if (aParts[i] == null) {
|
235
|
-
return 1
|
236
|
-
}
|
237
|
-
// if a is longer, a get higher priority
|
238
|
-
if (bParts[i] == null) {
|
239
|
-
return -1
|
240
|
-
}
|
202
|
+
function getConfigResources<ParamList extends {}>(options: Options<ParamList> | undefined) {
|
203
|
+
if (!options) return prepareConfigResources()
|
241
204
|
|
242
|
-
|
243
|
-
const bWildCard = bParts[i].startsWith('*')
|
244
|
-
// if both are wildcard we compare next component
|
245
|
-
if (aWildCard && bWildCard) {
|
246
|
-
const aNotFound = aParts[i].match(/^[*]not-found$/)
|
247
|
-
const bNotFound = bParts[i].match(/^[*]not-found$/)
|
205
|
+
const cached = cachedConfigResources.get(options)
|
248
206
|
|
249
|
-
|
250
|
-
continue
|
251
|
-
}
|
252
|
-
if (aNotFound) {
|
253
|
-
return 1
|
254
|
-
}
|
255
|
-
if (bNotFound) {
|
256
|
-
return -1
|
257
|
-
}
|
258
|
-
continue
|
259
|
-
}
|
260
|
-
// if only a is wild card, b get higher priority
|
261
|
-
if (aWildCard) {
|
262
|
-
return 1
|
263
|
-
}
|
264
|
-
// if only b is wild card, a get higher priority
|
265
|
-
if (bWildCard) {
|
266
|
-
return -1
|
267
|
-
}
|
207
|
+
if (cached) return cached
|
268
208
|
|
269
|
-
|
270
|
-
const bSlug = bParts[i].startsWith(':')
|
209
|
+
const resources = prepareConfigResources(options)
|
271
210
|
|
272
|
-
|
273
|
-
if (aSlug && bSlug) {
|
274
|
-
const aNotFound = aParts[i].match(/^[*]not-found$/)
|
275
|
-
const bNotFound = bParts[i].match(/^[*]not-found$/)
|
211
|
+
cachedConfigResources.set(options, resources)
|
276
212
|
|
277
|
-
|
278
|
-
|
279
|
-
}
|
280
|
-
if (aNotFound) {
|
281
|
-
return 1
|
282
|
-
}
|
283
|
-
if (bNotFound) {
|
284
|
-
return -1
|
285
|
-
}
|
213
|
+
return resources
|
214
|
+
}
|
286
215
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
return 1
|
292
|
-
}
|
293
|
-
// if only b is wild card, a get higher priority
|
294
|
-
if (bSlug) {
|
295
|
-
return -1
|
296
|
-
}
|
216
|
+
// @modified: add previousSegments parameter
|
217
|
+
function prepareConfigResources(options?: Options<{}>, previousSegments?: string[]) {
|
218
|
+
if (options) {
|
219
|
+
validatePathConfig(options)
|
297
220
|
}
|
298
221
|
|
299
|
-
|
300
|
-
// this ensures shared routes go to the shortest path.
|
301
|
-
if (a.isInitial && !b.isInitial) {
|
302
|
-
return -1
|
303
|
-
}
|
304
|
-
if (!a.isInitial && b.isInitial) {
|
305
|
-
return 1
|
306
|
-
}
|
222
|
+
const initialRoutes = getInitialRoutes(options)
|
307
223
|
|
308
|
-
|
309
|
-
|
224
|
+
// @modified: pass previousSegments
|
225
|
+
const configs = getNormalizedConfigs(initialRoutes, options?.screens, previousSegments)
|
310
226
|
|
311
|
-
|
312
|
-
path: string,
|
313
|
-
hash: string,
|
314
|
-
configs: RouteConfig[],
|
315
|
-
initialRoutes: InitialRouteConfig[]
|
316
|
-
): OneRouter.ResultState | undefined {
|
317
|
-
// We need to add special handling of empty path so navigation to empty path also works
|
318
|
-
// When handling empty path, we should only look at the root level config
|
319
|
-
|
320
|
-
// NOTE: We only care about matching leaf nodes.
|
321
|
-
const leafNodes = configs
|
322
|
-
.filter((config) => !config.hasChildren)
|
323
|
-
.map((value) => {
|
324
|
-
return {
|
325
|
-
...value,
|
326
|
-
// Collapse all levels of group segments before testing.
|
327
|
-
// This enables `app/(one)/(two)/index.js` to be matched.
|
328
|
-
path: stripGroupSegmentsFromPath(value.path),
|
329
|
-
}
|
330
|
-
})
|
227
|
+
checkForDuplicatedConfigs(configs)
|
331
228
|
|
332
|
-
const
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
leafNodes.find(
|
339
|
-
(config) =>
|
340
|
-
// NOTE: Test leaf node dynamic routes that match an empty string.
|
341
|
-
config.path.startsWith(':') && config.regex!.test('')
|
342
|
-
) ??
|
343
|
-
// NOTE: Test leaf node deep dynamic routes that match a slash.
|
344
|
-
// This should be done last to enable dynamic routes having a higher priority.
|
345
|
-
leafNodes.find((config) => config.path.startsWith('*') && config.regex!.test('/'))
|
346
|
-
|
347
|
-
if (!match) {
|
348
|
-
return undefined
|
229
|
+
const configWithRegexes = getConfigsWithRegexes(configs)
|
230
|
+
|
231
|
+
return {
|
232
|
+
initialRoutes,
|
233
|
+
configs,
|
234
|
+
configWithRegexes,
|
349
235
|
}
|
236
|
+
}
|
350
237
|
|
351
|
-
|
352
|
-
|
353
|
-
return { name }
|
354
|
-
}
|
355
|
-
return {
|
356
|
-
name,
|
357
|
-
_route: match._route,
|
358
|
-
}
|
359
|
-
})
|
238
|
+
function getInitialRoutes(options?: Options<{}>) {
|
239
|
+
const initialRoutes: InitialRouteConfig[] = []
|
360
240
|
|
361
|
-
|
241
|
+
if (options?.initialRouteName) {
|
242
|
+
initialRoutes.push({
|
243
|
+
initialRouteName: options.initialRouteName,
|
244
|
+
parentScreens: [],
|
245
|
+
})
|
246
|
+
}
|
247
|
+
|
248
|
+
return initialRoutes
|
362
249
|
}
|
363
250
|
|
364
|
-
function
|
365
|
-
path: string,
|
366
|
-
configs: RouteConfig[],
|
251
|
+
function getNormalizedConfigs(
|
367
252
|
initialRoutes: InitialRouteConfig[],
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
253
|
+
screens: PathConfigMap<object> = {},
|
254
|
+
// @modified - start
|
255
|
+
previousSegments?: string[]
|
256
|
+
// @modified - end
|
257
|
+
) {
|
258
|
+
// Create a normalized configs array which will be easier to use
|
259
|
+
return (
|
260
|
+
([] as RouteConfig[])
|
261
|
+
.concat(
|
262
|
+
...Object.keys(screens).map((key) =>
|
263
|
+
createNormalizedConfigs(key, screens as PathConfigMap<object>, [], initialRoutes, [])
|
264
|
+
)
|
265
|
+
)
|
266
|
+
/* @modified - start */
|
267
|
+
// .sort((a, b) => {
|
268
|
+
// // Sort config so that:
|
269
|
+
// // - the most exhaustive ones are always at the beginning
|
270
|
+
// // - patterns with wildcard are always at the end
|
271
|
+
|
272
|
+
// // If 2 patterns are same, move the one with less route names up
|
273
|
+
// // This is an error state, so it's only useful for consistent error messages
|
274
|
+
// if (a.pattern === b.pattern) {
|
275
|
+
// return b.routeNames.join('>').localeCompare(a.routeNames.join('>'))
|
276
|
+
// }
|
277
|
+
|
278
|
+
// // If one of the patterns starts with the other, it's more exhaustive
|
279
|
+
// // So move it up
|
280
|
+
// if (a.pattern.startsWith(b.pattern)) {
|
281
|
+
// return -1
|
282
|
+
// }
|
283
|
+
|
284
|
+
// if (b.pattern.startsWith(a.pattern)) {
|
285
|
+
// return 1
|
286
|
+
// }
|
287
|
+
|
288
|
+
// const aParts = a.pattern.split('/')
|
289
|
+
// const bParts = b.pattern.split('/')
|
290
|
+
|
291
|
+
// for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
292
|
+
// // if b is longer, b get higher priority
|
293
|
+
// if (aParts[i] == null) {
|
294
|
+
// return 1
|
295
|
+
// }
|
296
|
+
// // if a is longer, a get higher priority
|
297
|
+
// if (bParts[i] == null) {
|
298
|
+
// return -1
|
299
|
+
// }
|
300
|
+
// const aWildCard = aParts[i] === '*' || aParts[i].startsWith(':')
|
301
|
+
// const bWildCard = bParts[i] === '*' || bParts[i].startsWith(':')
|
302
|
+
// // if both are wildcard we compare next component
|
303
|
+
// if (aWildCard && bWildCard) {
|
304
|
+
// continue
|
305
|
+
// }
|
306
|
+
// // if only a is wild card, b get higher priority
|
307
|
+
// if (aWildCard) {
|
308
|
+
// return 1
|
309
|
+
// }
|
310
|
+
// // if only b is wild card, a get higher priority
|
311
|
+
// if (bWildCard) {
|
312
|
+
// return -1
|
313
|
+
// }
|
314
|
+
// }
|
315
|
+
// return bParts.length - aParts.length
|
316
|
+
// })
|
317
|
+
.map(appendIsInitial(initialRoutes))
|
318
|
+
.sort(getRouteConfigSorter(previousSegments))
|
319
|
+
/* @modified - end */
|
320
|
+
)
|
321
|
+
}
|
376
322
|
|
377
|
-
|
378
|
-
|
379
|
-
|
323
|
+
function checkForDuplicatedConfigs(configs: RouteConfig[]) {
|
324
|
+
// Check for duplicate patterns in the config
|
325
|
+
configs.reduce<Record<string, RouteConfig>>((acc, config) => {
|
326
|
+
if (acc[config.pattern]) {
|
327
|
+
const a = acc[config.pattern].routeNames
|
328
|
+
const b = config.routeNames
|
380
329
|
|
381
|
-
|
330
|
+
// It's not a problem if the path string omitted from a inner most screen
|
331
|
+
// For example, it's ok if a path resolves to `A > B > C` or `A > B`
|
332
|
+
const intersects =
|
333
|
+
a.length > b.length ? b.every((it, i) => a[i] === it) : a.every((it, i) => b[i] === it)
|
382
334
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
335
|
+
if (!intersects) {
|
336
|
+
throw new Error(
|
337
|
+
`Found conflicting screens with the same pattern. The pattern '${
|
338
|
+
config.pattern
|
339
|
+
}' resolves to both '${a.join(' > ')}' and '${b.join(
|
340
|
+
' > '
|
341
|
+
)}'. Patterns must be unique and cannot resolve to more than one screen.`
|
342
|
+
)
|
343
|
+
}
|
344
|
+
}
|
391
345
|
|
392
|
-
|
393
|
-
|
394
|
-
|
346
|
+
return Object.assign(acc, {
|
347
|
+
[config.pattern]: config,
|
348
|
+
})
|
349
|
+
}, {})
|
350
|
+
}
|
395
351
|
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
)
|
352
|
+
function getConfigsWithRegexes(configs: RouteConfig[]) {
|
353
|
+
return configs.map((c) => ({
|
354
|
+
...c,
|
355
|
+
// Add `$` to the regex to make sure it matches till end of the path and not just beginning
|
356
|
+
// @modified - start
|
357
|
+
// regex: c.regex ? new RegExp(c.regex.source + '$') : undefined,
|
358
|
+
regex: c.pattern
|
359
|
+
? new RegExp(`^(${c.pattern.split('/').map(formatRegexPattern).join('')})$`)
|
360
|
+
: undefined,
|
361
|
+
// @modified - end
|
362
|
+
}))
|
407
363
|
}
|
408
364
|
|
409
365
|
const joinPaths = (...paths: string[]): string =>
|
@@ -412,10 +368,14 @@ const joinPaths = (...paths: string[]): string =>
|
|
412
368
|
.filter(Boolean)
|
413
369
|
.join('/')
|
414
370
|
|
415
|
-
|
371
|
+
const matchAgainstConfigs = (remaining: string, configs: RouteConfig[]) => {
|
416
372
|
let routes: ParsedRoute[] | undefined
|
417
373
|
let remainingPath = remaining
|
418
374
|
|
375
|
+
// @modified - start
|
376
|
+
const allParams = Object.create(null)
|
377
|
+
// @modified - end
|
378
|
+
|
419
379
|
// Go through all configs, and see if the next path segment matches our regex
|
420
380
|
for (const config of configs) {
|
421
381
|
if (!config.regex) {
|
@@ -425,112 +385,104 @@ function matchAgainstConfigs(remaining: string, configs: RouteConfig[]): ParsedR
|
|
425
385
|
const match = remainingPath.match(config.regex)
|
426
386
|
|
427
387
|
// If our regex matches, we need to extract params from the path
|
428
|
-
if (
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
.reduce<Record<string, any>>((acc, p, i) => {
|
437
|
-
if (p.match(/^\*/)) {
|
438
|
-
return {
|
439
|
-
...acc,
|
440
|
-
[p]: match![(i + 1) * 2], //?.replace(/\//, ""),
|
388
|
+
if (match) {
|
389
|
+
const matchResult = config.pattern?.split('/').reduce<{
|
390
|
+
pos: number // Position of the current path param segment in the path (e.g in pattern `a/:b/:c`, `:a` is 0 and `:b` is 1)
|
391
|
+
matchedParams: Record<string, Record<string, string>> // The extracted params
|
392
|
+
}>(
|
393
|
+
(acc, p, index) => {
|
394
|
+
if (!p.startsWith(':')) {
|
395
|
+
return acc
|
441
396
|
}
|
442
|
-
}
|
443
|
-
return Object.assign(acc, {
|
444
|
-
// The param segments appear every second item starting from 2 in the regex match result.
|
445
|
-
// This will only work if we ensure groups aren't included in the match.
|
446
|
-
[p]: match![(i + 1) * 2]?.replace(/\//, ''),
|
447
|
-
})
|
448
|
-
}, {})
|
449
397
|
|
450
|
-
|
451
|
-
|
452
|
-
if (!config?.path) {
|
453
|
-
return { name }
|
454
|
-
}
|
398
|
+
// Path parameter so increment position for the segment
|
399
|
+
acc.pos += 1
|
455
400
|
|
456
|
-
|
401
|
+
const decodedParamSegment = decodeURIComponentSafe(
|
402
|
+
// @modified: use decodeURIComponent**Safe**
|
403
|
+
// The param segments appear every second item starting from 2 in the regex match result
|
404
|
+
match![(acc.pos + 1) * 2]
|
405
|
+
// Remove trailing slash
|
406
|
+
.replace(/\/$/, '')
|
407
|
+
)
|
457
408
|
|
458
|
-
|
409
|
+
Object.assign(acc.matchedParams, {
|
410
|
+
[p]: Object.assign(acc.matchedParams[p] || {}, {
|
411
|
+
[index]: decodedParamSegment,
|
412
|
+
}),
|
413
|
+
})
|
459
414
|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
if (value) {
|
465
|
-
if (p.match(/^\*/)) {
|
466
|
-
// Convert to an array before providing as a route.
|
467
|
-
value = value?.split('/').filter(Boolean)
|
468
|
-
}
|
415
|
+
return acc
|
416
|
+
},
|
417
|
+
{ pos: -1, matchedParams: {} }
|
418
|
+
)
|
469
419
|
|
470
|
-
|
471
|
-
|
472
|
-
|
420
|
+
const matchedParams = matchResult.matchedParams || {}
|
421
|
+
|
422
|
+
routes = config.routeNames.map((name) => {
|
423
|
+
const routeConfig = configs.find((c) => {
|
424
|
+
// Check matching name AND pattern in case same screen is used at different levels in config
|
425
|
+
return c.screen === name && config.pattern.startsWith(c.pattern)
|
473
426
|
})
|
474
427
|
|
475
|
-
|
476
|
-
|
477
|
-
}
|
428
|
+
// Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.
|
429
|
+
const normalizedPath = routeConfig?.path.split('/').filter(Boolean).join('/')
|
478
430
|
|
479
|
-
|
480
|
-
|
431
|
+
// Get the number of segments in the initial pattern
|
432
|
+
const numInitialSegments = routeConfig?.pattern
|
433
|
+
// Extract the prefix from the pattern by removing the ending path pattern (e.g pattern=`a/b/c/d` and normalizedPath=`c/d` becomes `a/b`)
|
434
|
+
.replace(new RegExp(`${escape(normalizedPath!)}$`), '')
|
435
|
+
?.split('/').length
|
481
436
|
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
_route: config._route,
|
489
|
-
}
|
490
|
-
})
|
491
|
-
|
492
|
-
// TODO: Maybe we should warn / assert if multiple slugs use the same param name.
|
493
|
-
const combinedParams = routes.reduce<Record<string, any>>(
|
494
|
-
(acc, r) => Object.assign(acc, r.params),
|
495
|
-
{}
|
496
|
-
)
|
437
|
+
const params = normalizedPath
|
438
|
+
?.split('/')
|
439
|
+
.reduce<Record<string, unknown>>((acc, p, index) => {
|
440
|
+
if (!p.startsWith(':')) {
|
441
|
+
return acc
|
442
|
+
}
|
497
443
|
|
498
|
-
|
444
|
+
// Get the real index of the path parameter in the matched path
|
445
|
+
// by offsetting by the number of segments in the initial pattern
|
446
|
+
const offset = numInitialSegments ? numInitialSegments - 1 : 0
|
447
|
+
// @modified - start
|
448
|
+
// const value = matchedParams[p]?.[index + offset]
|
449
|
+
const value = getParamValue(p, matchedParams[p]?.[index + offset])
|
450
|
+
// @modified - end
|
451
|
+
|
452
|
+
if (value) {
|
453
|
+
const key = p.replace(/^:/, '').replace(/\?$/, '')
|
454
|
+
acc[key] = routeConfig?.parse?.[key] ? routeConfig.parse[key](value as any) : value
|
455
|
+
}
|
499
456
|
|
500
|
-
|
501
|
-
|
502
|
-
if (hasCombinedParams) {
|
503
|
-
r.params = combinedParams
|
504
|
-
}
|
505
|
-
return r
|
506
|
-
})
|
457
|
+
return acc
|
458
|
+
}, {})
|
507
459
|
|
508
|
-
|
460
|
+
if (params && Object.keys(params).length) {
|
461
|
+
return { name, params }
|
462
|
+
}
|
509
463
|
|
510
|
-
|
511
|
-
|
464
|
+
return { name }
|
465
|
+
})
|
512
466
|
|
513
|
-
|
514
|
-
}
|
467
|
+
remainingPath = remainingPath.replace(match[1], '')
|
515
468
|
|
516
|
-
|
517
|
-
if (a.length !== b.length) {
|
518
|
-
return false
|
519
|
-
}
|
520
|
-
for (let i = 0; i < a.length; i++) {
|
521
|
-
if (a[i].localeCompare(b[i]) !== 0) {
|
522
|
-
return false
|
469
|
+
break
|
523
470
|
}
|
524
471
|
}
|
525
|
-
|
472
|
+
|
473
|
+
// @modified - start
|
474
|
+
populateParams(routes, allParams)
|
475
|
+
// @modified - end
|
476
|
+
|
477
|
+
return { routes, remainingPath }
|
526
478
|
}
|
527
479
|
|
528
480
|
const createNormalizedConfigs = (
|
529
481
|
screen: string,
|
530
482
|
routeConfig: PathConfigMap<object>,
|
531
483
|
routeNames: string[] = [],
|
532
|
-
initials: InitialRouteConfig[]
|
533
|
-
parentScreens: string[]
|
484
|
+
initials: InitialRouteConfig[],
|
485
|
+
parentScreens: string[],
|
534
486
|
parentPattern?: string
|
535
487
|
): RouteConfig[] => {
|
536
488
|
const configs: RouteConfig[] = []
|
@@ -539,19 +491,16 @@ const createNormalizedConfigs = (
|
|
539
491
|
|
540
492
|
parentScreens.push(screen)
|
541
493
|
|
542
|
-
const config =
|
494
|
+
const config = routeConfig[screen]
|
543
495
|
|
544
496
|
if (typeof config === 'string') {
|
545
|
-
// TODO: This should never happen with the addition of `_route`
|
546
|
-
|
547
497
|
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
|
548
498
|
const pattern = parentPattern ? joinPaths(parentPattern, config) : config
|
549
499
|
|
550
|
-
configs.push(createConfigItem(screen, routeNames, pattern, config
|
500
|
+
configs.push(createConfigItem(screen, routeNames, pattern, config))
|
551
501
|
} else if (typeof config === 'object') {
|
552
502
|
let pattern: string | undefined
|
553
503
|
|
554
|
-
const { _route } = config
|
555
504
|
// if an object is specified as the value (e.g. Foo: { ... }),
|
556
505
|
// it can have `path` property and
|
557
506
|
// it could have `screens` prop which has nested configs
|
@@ -567,17 +516,12 @@ const createNormalizedConfigs = (
|
|
567
516
|
? joinPaths(parentPattern || '', config.path || '')
|
568
517
|
: config.path || ''
|
569
518
|
|
519
|
+
// @modified - start
|
520
|
+
// configs.push(createConfigItem(screen, routeNames, pattern!, config.path, config.parse))
|
570
521
|
configs.push(
|
571
|
-
createConfigItem(
|
572
|
-
screen,
|
573
|
-
routeNames,
|
574
|
-
pattern!,
|
575
|
-
config.path,
|
576
|
-
config.screens ? !!Object.keys(config.screens)?.length : false,
|
577
|
-
config.parse,
|
578
|
-
_route
|
579
|
-
)
|
522
|
+
createConfigItem(screen, routeNames, pattern!, config.path, config.parse, config)
|
580
523
|
)
|
524
|
+
// @modified - end
|
581
525
|
}
|
582
526
|
|
583
527
|
if (config.screens) {
|
@@ -609,44 +553,32 @@ const createNormalizedConfigs = (
|
|
609
553
|
return configs
|
610
554
|
}
|
611
555
|
|
612
|
-
function formatRegexPattern(it: string): string {
|
613
|
-
// Allow spaces in file path names.
|
614
|
-
it = it.replace(' ', '%20')
|
615
|
-
|
616
|
-
if (it.startsWith(':')) {
|
617
|
-
// TODO: Remove unused match group
|
618
|
-
return `(([^/]+\\/)${it.endsWith('?') ? '?' : ''})`
|
619
|
-
}
|
620
|
-
|
621
|
-
if (it.startsWith('*')) {
|
622
|
-
return `((.*\\/)${it.endsWith('?') ? '?' : ''})`
|
623
|
-
}
|
624
|
-
|
625
|
-
// Strip groups from the matcher
|
626
|
-
if (matchGroupName(it) != null) {
|
627
|
-
// Groups are optional segments
|
628
|
-
// this enables us to match `/bar` and `/(foo)/bar` for the same route
|
629
|
-
// NOTE: Ignore this match in the regex to avoid capturing the group
|
630
|
-
return `(?:${escape(it)}\\/)?`
|
631
|
-
}
|
632
|
-
|
633
|
-
return escape(it) + `\\/`
|
634
|
-
}
|
635
|
-
|
636
556
|
const createConfigItem = (
|
637
557
|
screen: string,
|
638
558
|
routeNames: string[],
|
639
559
|
pattern: string,
|
640
560
|
path: string,
|
641
|
-
|
642
|
-
|
643
|
-
|
561
|
+
parse: ParseConfig | undefined = undefined,
|
562
|
+
// @modified - start
|
563
|
+
config: Record<string, any> = {}
|
564
|
+
// @modified - end
|
644
565
|
): RouteConfig => {
|
645
566
|
// Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.
|
646
567
|
pattern = pattern.split('/').filter(Boolean).join('/')
|
647
568
|
|
648
569
|
const regex = pattern
|
649
|
-
? new RegExp(
|
570
|
+
? new RegExp(
|
571
|
+
`^(${pattern
|
572
|
+
.split('/')
|
573
|
+
.map((it) => {
|
574
|
+
if (it.startsWith(':')) {
|
575
|
+
return `(([^/]+\\/)${it.endsWith('?') ? '?' : ''})`
|
576
|
+
}
|
577
|
+
|
578
|
+
return `${it === '*' ? '.*' : escape(it)}\\/`
|
579
|
+
})
|
580
|
+
.join('')})`
|
581
|
+
)
|
650
582
|
: undefined
|
651
583
|
|
652
584
|
return {
|
@@ -657,17 +589,17 @@ const createConfigItem = (
|
|
657
589
|
// The routeNames array is mutated, so copy it to keep the current state
|
658
590
|
routeNames: [...routeNames],
|
659
591
|
parse,
|
660
|
-
|
661
|
-
|
662
|
-
|
592
|
+
// @modified - start
|
593
|
+
...createConfigItemAdditionalProperties(screen, pattern, routeNames, config),
|
594
|
+
// @modified - end
|
663
595
|
}
|
664
596
|
}
|
665
597
|
|
666
598
|
const findParseConfigForRoute = (
|
667
599
|
routeName: string,
|
668
|
-
|
600
|
+
flatConfig: RouteConfig[]
|
669
601
|
): ParseConfig | undefined => {
|
670
|
-
for (const config of
|
602
|
+
for (const config of flatConfig) {
|
671
603
|
if (routeName === config.routeNames[config.routeNames.length - 1]) {
|
672
604
|
return config.parse
|
673
605
|
}
|
@@ -683,10 +615,17 @@ const findInitialRoute = (
|
|
683
615
|
initialRoutes: InitialRouteConfig[]
|
684
616
|
): string | undefined => {
|
685
617
|
for (const config of initialRoutes) {
|
686
|
-
if (
|
687
|
-
|
688
|
-
|
689
|
-
|
618
|
+
if (parentScreens.length === config.parentScreens.length) {
|
619
|
+
let sameParents = true
|
620
|
+
for (let i = 0; i < parentScreens.length; i++) {
|
621
|
+
if (parentScreens[i].localeCompare(config.parentScreens[i]) !== 0) {
|
622
|
+
sameParents = false
|
623
|
+
break
|
624
|
+
}
|
625
|
+
}
|
626
|
+
if (sameParents) {
|
627
|
+
return routeName !== config.initialRouteName ? config.initialRouteName : undefined
|
628
|
+
}
|
690
629
|
}
|
691
630
|
}
|
692
631
|
return undefined
|
@@ -695,9 +634,9 @@ const findInitialRoute = (
|
|
695
634
|
// returns state object with values depending on whether
|
696
635
|
// it is the end of state and if there is initialRoute for this level
|
697
636
|
const createStateObject = (
|
637
|
+
initialRoute: string | undefined,
|
698
638
|
route: ParsedRoute,
|
699
|
-
isEmpty: boolean
|
700
|
-
initialRoute?: string
|
639
|
+
isEmpty: boolean
|
701
640
|
): InitialState => {
|
702
641
|
if (isEmpty) {
|
703
642
|
if (initialRoute) {
|
@@ -705,29 +644,37 @@ const createStateObject = (
|
|
705
644
|
index: 1,
|
706
645
|
routes: [{ name: initialRoute }, route],
|
707
646
|
}
|
647
|
+
// biome-ignore lint/style/noUselessElse: not changing forked code
|
648
|
+
} else {
|
649
|
+
return {
|
650
|
+
routes: [route],
|
651
|
+
}
|
708
652
|
}
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
653
|
+
// biome-ignore lint/style/noUselessElse: not changing forked code
|
654
|
+
} else {
|
655
|
+
if (initialRoute) {
|
656
|
+
return {
|
657
|
+
index: 1,
|
658
|
+
routes: [{ name: initialRoute }, { ...route, state: { routes: [] } }],
|
659
|
+
}
|
660
|
+
// biome-ignore lint/style/noUselessElse: not changing forked code
|
661
|
+
} else {
|
662
|
+
return {
|
663
|
+
routes: [{ ...route, state: { routes: [] } }],
|
664
|
+
}
|
718
665
|
}
|
719
666
|
}
|
720
|
-
return {
|
721
|
-
routes: [{ ...route, state: { routes: [] } }],
|
722
|
-
}
|
723
667
|
}
|
724
668
|
|
725
669
|
const createNestedStateObject = (
|
726
|
-
|
727
|
-
|
670
|
+
// @modified - start
|
671
|
+
// path: string,
|
672
|
+
{ path, ...restPathData }: ReturnType<typeof getUrlWithReactNavigationConcessions>,
|
673
|
+
// @modified - end
|
728
674
|
routes: ParsedRoute[],
|
729
|
-
|
730
|
-
|
675
|
+
initialRoutes: InitialRouteConfig[],
|
676
|
+
flatConfig?: RouteConfig[],
|
677
|
+
hash?: string // @modified: added
|
731
678
|
) => {
|
732
679
|
let route = routes.shift() as ParsedRoute
|
733
680
|
const parentScreens: string[] = []
|
@@ -736,7 +683,7 @@ const createNestedStateObject = (
|
|
736
683
|
|
737
684
|
parentScreens.push(route.name)
|
738
685
|
|
739
|
-
const state: InitialState = createStateObject(route, routes.length === 0
|
686
|
+
const state: InitialState = createStateObject(initialRoute, route, routes.length === 0)
|
740
687
|
|
741
688
|
if (routes.length > 0) {
|
742
689
|
let nestedState = state
|
@@ -747,9 +694,9 @@ const createNestedStateObject = (
|
|
747
694
|
const nestedStateIndex = nestedState.index || nestedState.routes.length - 1
|
748
695
|
|
749
696
|
nestedState.routes[nestedStateIndex].state = createStateObject(
|
697
|
+
initialRoute,
|
750
698
|
route,
|
751
|
-
routes.length === 0
|
752
|
-
initialRoute
|
699
|
+
routes.length === 0
|
753
700
|
)
|
754
701
|
|
755
702
|
if (routes.length > 0) {
|
@@ -761,81 +708,43 @@ const createNestedStateObject = (
|
|
761
708
|
}
|
762
709
|
|
763
710
|
route = findFocusedRoute(state) as ParsedRoute
|
764
|
-
|
765
|
-
//
|
766
|
-
route.path =
|
767
|
-
|
768
|
-
|
711
|
+
// @modified - start
|
712
|
+
// route.path = path
|
713
|
+
route.path = restPathData.pathWithoutGroups
|
714
|
+
// @modified - end
|
715
|
+
|
716
|
+
// @modified - start
|
717
|
+
// const params = parseQueryParams(
|
718
|
+
// path,
|
719
|
+
// flatConfig ? findParseConfigForRoute(route.name, flatConfig) : undefined
|
720
|
+
// )
|
721
|
+
const params = parseQueryParamsExtended(
|
722
|
+
path,
|
723
|
+
route,
|
724
|
+
flatConfig ? findParseConfigForRoute(route.name, flatConfig) : undefined,
|
725
|
+
hash
|
726
|
+
)
|
727
|
+
// @modified - end
|
769
728
|
|
770
729
|
if (params) {
|
771
|
-
route.params =
|
772
|
-
for (const [name, value] of Object.entries(params)) {
|
773
|
-
if (route.params?.[name]) {
|
774
|
-
if (process.env.NODE_ENV !== 'production') {
|
775
|
-
console.warn(
|
776
|
-
`Route '/${route.name}' with param '${name}' was specified both in the path and as a param, removing from path`
|
777
|
-
)
|
778
|
-
}
|
779
|
-
}
|
780
|
-
|
781
|
-
if (!route.params?.[name]) {
|
782
|
-
route.params[name] = value
|
783
|
-
continue
|
784
|
-
}
|
785
|
-
}
|
786
|
-
|
787
|
-
if (Object.keys(route.params).length === 0) {
|
788
|
-
delete route.params
|
789
|
-
}
|
790
|
-
}
|
791
|
-
|
792
|
-
if (hash) {
|
793
|
-
route.params = Object.assign(Object.create(null), route.params) as Record<string, any>
|
794
|
-
route.params['#'] = hash
|
730
|
+
route.params = { ...route.params, ...params }
|
795
731
|
}
|
796
732
|
|
797
733
|
return state
|
798
734
|
}
|
799
735
|
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
return Object.keys(params).length ? params : undefined
|
817
|
-
}
|
818
|
-
|
819
|
-
const baseUrlCache = new Map<string, RegExp>()
|
820
|
-
|
821
|
-
function getBaseUrlRegex(baseUrl: string) {
|
822
|
-
if (baseUrlCache.has(baseUrl)) {
|
823
|
-
return baseUrlCache.get(baseUrl)!
|
824
|
-
}
|
825
|
-
const regex = new RegExp(`^\\/?${escape(baseUrl)}`, 'g')
|
826
|
-
baseUrlCache.set(baseUrl, regex)
|
827
|
-
return regex
|
828
|
-
}
|
829
|
-
|
830
|
-
export function stripBaseUrl(
|
831
|
-
path: string,
|
832
|
-
baseUrl: string | undefined = process.env.EXPO_BASE_URL
|
833
|
-
) {
|
834
|
-
if (process.env.NODE_ENV !== 'development') {
|
835
|
-
if (baseUrl) {
|
836
|
-
const reg = getBaseUrlRegex(baseUrl)
|
837
|
-
return path.replace(/^\/+/g, '/').replace(reg, '')
|
838
|
-
}
|
839
|
-
}
|
840
|
-
return path
|
841
|
-
}
|
736
|
+
// @modified: commenting out unused code
|
737
|
+
// const parseQueryParams = (path: string, parseConfig?: Record<string, (value: string) => any>) => {
|
738
|
+
// const query = path.split('?')[1]
|
739
|
+
// const params = queryString.parse(query)
|
740
|
+
|
741
|
+
// if (parseConfig) {
|
742
|
+
// Object.keys(params).forEach((name) => {
|
743
|
+
// if (Object.hasOwnProperty.call(parseConfig, name) && typeof params[name] === 'string') {
|
744
|
+
// params[name] = parseConfig[name](params[name] as string)
|
745
|
+
// }
|
746
|
+
// })
|
747
|
+
// }
|
748
|
+
|
749
|
+
// return Object.keys(params).length ? params : undefined
|
750
|
+
// }
|