one 1.1.390 → 1.1.391

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.
Files changed (241) hide show
  1. package/dist/cjs/Root.cjs +6 -17
  2. package/dist/cjs/Root.js +9 -13
  3. package/dist/cjs/Root.js.map +1 -1
  4. package/dist/cjs/Root.native.js +4 -12
  5. package/dist/cjs/Root.native.js.map +1 -1
  6. package/dist/cjs/fork/NavigationContainer.cjs +49 -31
  7. package/dist/cjs/fork/NavigationContainer.js +40 -21
  8. package/dist/cjs/fork/NavigationContainer.js.map +2 -2
  9. package/dist/cjs/fork/NavigationContainer.native.js +51 -29
  10. package/dist/cjs/fork/NavigationContainer.native.js.map +2 -2
  11. package/dist/cjs/fork/createMemoryHistory.cjs +4 -3
  12. package/dist/cjs/fork/createMemoryHistory.js +3 -2
  13. package/dist/cjs/fork/createMemoryHistory.js.map +1 -1
  14. package/dist/cjs/fork/createMemoryHistory.native.js +8 -4
  15. package/dist/cjs/fork/createMemoryHistory.native.js.map +2 -2
  16. package/dist/cjs/fork/extractPathFromURL.cjs +48 -28
  17. package/dist/cjs/fork/extractPathFromURL.js +44 -21
  18. package/dist/cjs/fork/extractPathFromURL.js.map +2 -2
  19. package/dist/cjs/fork/extractPathFromURL.native.js +58 -26
  20. package/dist/cjs/fork/extractPathFromURL.native.js.map +2 -2
  21. package/dist/cjs/fork/findFocusedRoute.js.map +1 -1
  22. package/dist/cjs/fork/findFocusedRoute.native.js.map +1 -1
  23. package/dist/cjs/fork/getPathFromState-mods.cjs +65 -0
  24. package/dist/cjs/fork/getPathFromState-mods.js +56 -0
  25. package/dist/cjs/fork/getPathFromState-mods.js.map +6 -0
  26. package/dist/cjs/fork/getPathFromState-mods.native.js +70 -0
  27. package/dist/cjs/fork/getPathFromState-mods.native.js.map +6 -0
  28. package/dist/cjs/fork/getPathFromState.cjs +75 -224
  29. package/dist/cjs/fork/getPathFromState.js +68 -223
  30. package/dist/cjs/fork/getPathFromState.js.map +2 -2
  31. package/dist/cjs/fork/getPathFromState.native.js +79 -261
  32. package/dist/cjs/fork/getPathFromState.native.js.map +2 -2
  33. package/dist/cjs/fork/getStateFromPath-mods.cjs +187 -0
  34. package/dist/cjs/fork/getStateFromPath-mods.js +199 -0
  35. package/dist/cjs/fork/getStateFromPath-mods.js.map +6 -0
  36. package/dist/cjs/fork/getStateFromPath-mods.native.js +284 -0
  37. package/dist/cjs/fork/getStateFromPath-mods.native.js.map +6 -0
  38. package/dist/cjs/fork/getStateFromPath.cjs +181 -263
  39. package/dist/cjs/fork/getStateFromPath.js +148 -264
  40. package/dist/cjs/fork/getStateFromPath.js.map +2 -2
  41. package/dist/cjs/fork/getStateFromPath.native.js +164 -304
  42. package/dist/cjs/fork/getStateFromPath.native.js.map +2 -2
  43. package/dist/cjs/fork/useBackButton.js.map +1 -1
  44. package/dist/cjs/fork/useBackButton.native.js.map +1 -1
  45. package/dist/cjs/fork/useDocumentTitle.js +4 -1
  46. package/dist/cjs/fork/useDocumentTitle.js.map +1 -1
  47. package/dist/cjs/fork/useDocumentTitle.native.js +1 -1
  48. package/dist/cjs/fork/useDocumentTitle.native.js.map +2 -2
  49. package/dist/cjs/fork/useLinking.cjs +21 -24
  50. package/dist/cjs/fork/useLinking.js +21 -25
  51. package/dist/cjs/fork/useLinking.js.map +2 -2
  52. package/dist/cjs/fork/useLinking.native.js +68 -66
  53. package/dist/cjs/fork/useLinking.native.js.map +2 -2
  54. package/dist/cjs/fork/useThenable.js.map +1 -1
  55. package/dist/cjs/fork/useThenable.native.js.map +1 -1
  56. package/dist/cjs/fork/validatePathConfig.cjs +32 -11
  57. package/dist/cjs/fork/validatePathConfig.js +41 -11
  58. package/dist/cjs/fork/validatePathConfig.js.map +1 -1
  59. package/dist/cjs/fork/validatePathConfig.native.js +47 -18
  60. package/dist/cjs/fork/validatePathConfig.native.js.map +2 -2
  61. package/dist/cjs/layouts/withLayoutContext.cjs +1 -1
  62. package/dist/cjs/layouts/withLayoutContext.js +1 -1
  63. package/dist/cjs/layouts/withLayoutContext.js.map +1 -1
  64. package/dist/cjs/layouts/withLayoutContext.native.js +1 -1
  65. package/dist/cjs/layouts/withLayoutContext.native.js.map +1 -1
  66. package/dist/cjs/link/linking.cjs +4 -4
  67. package/dist/cjs/link/linking.js +3 -3
  68. package/dist/cjs/link/linking.js.map +2 -2
  69. package/dist/cjs/link/linking.native.js +3 -3
  70. package/dist/cjs/link/linking.native.js.map +1 -1
  71. package/dist/cjs/link/useLinkTo.cjs +2 -2
  72. package/dist/cjs/link/useLinkTo.js +2 -2
  73. package/dist/cjs/link/useLinkTo.js.map +1 -1
  74. package/dist/cjs/link/useLinkTo.native.js +2 -2
  75. package/dist/cjs/link/useLinkTo.native.js.map +1 -1
  76. package/dist/cjs/router/getNormalizedStatePath.cjs +2 -2
  77. package/dist/cjs/router/getNormalizedStatePath.js +2 -2
  78. package/dist/cjs/router/getNormalizedStatePath.js.map +1 -1
  79. package/dist/cjs/router/getNormalizedStatePath.native.js +2 -2
  80. package/dist/cjs/router/getNormalizedStatePath.native.js.map +1 -1
  81. package/dist/cjs/router/router.cjs +19 -3
  82. package/dist/cjs/router/router.js +25 -3
  83. package/dist/cjs/router/router.js.map +1 -1
  84. package/dist/cjs/router/router.native.js +39 -3
  85. package/dist/cjs/router/router.native.js.map +2 -2
  86. package/dist/esm/Root.js +6 -2
  87. package/dist/esm/Root.js.map +1 -1
  88. package/dist/esm/Root.mjs +1 -1
  89. package/dist/esm/Root.mjs.map +1 -1
  90. package/dist/esm/Root.native.js +1 -1
  91. package/dist/esm/Root.native.js.map +2 -2
  92. package/dist/esm/fork/NavigationContainer.js +43 -20
  93. package/dist/esm/fork/NavigationContainer.js.map +1 -1
  94. package/dist/esm/fork/NavigationContainer.mjs +42 -24
  95. package/dist/esm/fork/NavigationContainer.mjs.map +1 -1
  96. package/dist/esm/fork/NavigationContainer.native.js +44 -24
  97. package/dist/esm/fork/NavigationContainer.native.js.map +2 -2
  98. package/dist/esm/fork/createMemoryHistory.js +3 -2
  99. package/dist/esm/fork/createMemoryHistory.js.map +1 -1
  100. package/dist/esm/fork/createMemoryHistory.mjs +4 -3
  101. package/dist/esm/fork/createMemoryHistory.mjs.map +1 -1
  102. package/dist/esm/fork/createMemoryHistory.native.js +4 -4
  103. package/dist/esm/fork/createMemoryHistory.native.js.map +2 -2
  104. package/dist/esm/fork/extractPathFromURL.js +42 -11
  105. package/dist/esm/fork/extractPathFromURL.js.map +1 -1
  106. package/dist/esm/fork/extractPathFromURL.mjs +39 -11
  107. package/dist/esm/fork/extractPathFromURL.mjs.map +1 -1
  108. package/dist/esm/fork/extractPathFromURL.native.js +52 -15
  109. package/dist/esm/fork/extractPathFromURL.native.js.map +2 -2
  110. package/dist/esm/fork/findFocusedRoute.js.map +1 -1
  111. package/dist/esm/fork/findFocusedRoute.mjs.map +1 -1
  112. package/dist/esm/fork/findFocusedRoute.native.js.map +1 -1
  113. package/dist/esm/fork/getPathFromState-mods.js +40 -0
  114. package/dist/esm/fork/getPathFromState-mods.js.map +6 -0
  115. package/dist/esm/fork/getPathFromState-mods.mjs +40 -0
  116. package/dist/esm/fork/getPathFromState-mods.mjs.map +1 -0
  117. package/dist/esm/fork/getPathFromState-mods.native.js +47 -0
  118. package/dist/esm/fork/getPathFromState-mods.native.js.map +6 -0
  119. package/dist/esm/fork/getPathFromState.js +71 -228
  120. package/dist/esm/fork/getPathFromState.js.map +2 -2
  121. package/dist/esm/fork/getPathFromState.mjs +73 -221
  122. package/dist/esm/fork/getPathFromState.mjs.map +1 -1
  123. package/dist/esm/fork/getPathFromState.native.js +79 -260
  124. package/dist/esm/fork/getPathFromState.native.js.map +2 -2
  125. package/dist/esm/fork/getStateFromPath-mods.js +176 -0
  126. package/dist/esm/fork/getStateFromPath-mods.js.map +6 -0
  127. package/dist/esm/fork/getStateFromPath-mods.mjs +143 -0
  128. package/dist/esm/fork/getStateFromPath-mods.mjs.map +1 -0
  129. package/dist/esm/fork/getStateFromPath-mods.native.js +246 -0
  130. package/dist/esm/fork/getStateFromPath-mods.native.js.map +6 -0
  131. package/dist/esm/fork/getStateFromPath.js +160 -265
  132. package/dist/esm/fork/getStateFromPath.js.map +2 -2
  133. package/dist/esm/fork/getStateFromPath.mjs +181 -260
  134. package/dist/esm/fork/getStateFromPath.mjs.map +1 -1
  135. package/dist/esm/fork/getStateFromPath.native.js +164 -302
  136. package/dist/esm/fork/getStateFromPath.native.js.map +2 -2
  137. package/dist/esm/fork/useBackButton.js.map +1 -1
  138. package/dist/esm/fork/useBackButton.mjs.map +1 -1
  139. package/dist/esm/fork/useBackButton.native.js.map +1 -1
  140. package/dist/esm/fork/useDocumentTitle.js +4 -1
  141. package/dist/esm/fork/useDocumentTitle.js.map +1 -1
  142. package/dist/esm/fork/useDocumentTitle.mjs.map +1 -1
  143. package/dist/esm/fork/useDocumentTitle.native.js +1 -1
  144. package/dist/esm/fork/useDocumentTitle.native.js.map +2 -2
  145. package/dist/esm/fork/useLinking.js +22 -26
  146. package/dist/esm/fork/useLinking.js.map +1 -1
  147. package/dist/esm/fork/useLinking.mjs +20 -23
  148. package/dist/esm/fork/useLinking.mjs.map +1 -1
  149. package/dist/esm/fork/useLinking.native.js +65 -67
  150. package/dist/esm/fork/useLinking.native.js.map +2 -2
  151. package/dist/esm/fork/useThenable.js.map +1 -1
  152. package/dist/esm/fork/useThenable.mjs.map +1 -1
  153. package/dist/esm/fork/useThenable.native.js.map +1 -1
  154. package/dist/esm/fork/validatePathConfig.js +41 -11
  155. package/dist/esm/fork/validatePathConfig.js.map +1 -1
  156. package/dist/esm/fork/validatePathConfig.mjs +32 -11
  157. package/dist/esm/fork/validatePathConfig.mjs.map +1 -1
  158. package/dist/esm/fork/validatePathConfig.native.js +43 -18
  159. package/dist/esm/fork/validatePathConfig.native.js.map +2 -2
  160. package/dist/esm/layouts/withLayoutContext.js +1 -1
  161. package/dist/esm/layouts/withLayoutContext.js.map +1 -1
  162. package/dist/esm/layouts/withLayoutContext.mjs +1 -1
  163. package/dist/esm/layouts/withLayoutContext.mjs.map +1 -1
  164. package/dist/esm/layouts/withLayoutContext.native.js +1 -1
  165. package/dist/esm/layouts/withLayoutContext.native.js.map +1 -1
  166. package/dist/esm/link/linking.js +2 -2
  167. package/dist/esm/link/linking.js.map +1 -1
  168. package/dist/esm/link/linking.mjs +2 -2
  169. package/dist/esm/link/linking.mjs.map +1 -1
  170. package/dist/esm/link/linking.native.js +2 -2
  171. package/dist/esm/link/linking.native.js.map +1 -1
  172. package/dist/esm/link/useLinkTo.js +1 -1
  173. package/dist/esm/link/useLinkTo.mjs +1 -1
  174. package/dist/esm/link/useLinkTo.native.js +1 -1
  175. package/dist/esm/router/getNormalizedStatePath.js +1 -1
  176. package/dist/esm/router/getNormalizedStatePath.mjs +1 -1
  177. package/dist/esm/router/getNormalizedStatePath.native.js +1 -1
  178. package/dist/esm/router/router.js +24 -2
  179. package/dist/esm/router/router.js.map +1 -1
  180. package/dist/esm/router/router.mjs +18 -2
  181. package/dist/esm/router/router.mjs.map +1 -1
  182. package/dist/esm/router/router.native.js +38 -2
  183. package/dist/esm/router/router.native.js.map +2 -2
  184. package/package.json +8 -9
  185. package/src/Root.tsx +6 -2
  186. package/src/fork/NavigationContainer.tsx +101 -39
  187. package/src/fork/createMemoryHistory.tsx +15 -13
  188. package/src/fork/extractPathFromURL.ts +85 -40
  189. package/src/fork/findFocusedRoute.tsx +9 -1
  190. package/src/fork/getPathFromState-mods.ts +142 -0
  191. package/src/fork/getPathFromState.ts +244 -501
  192. package/src/fork/getStateFromPath-mods.ts +400 -0
  193. package/src/fork/getStateFromPath.ts +447 -538
  194. package/src/fork/useBackButton.native.tsx +16 -2
  195. package/src/fork/useBackButton.tsx +11 -2
  196. package/src/fork/useDocumentTitle.native.tsx +9 -4
  197. package/src/fork/useDocumentTitle.tsx +12 -7
  198. package/src/fork/useLinking.native.ts +71 -63
  199. package/src/fork/useLinking.ts +75 -40
  200. package/src/fork/useThenable.tsx +7 -1
  201. package/src/fork/validatePathConfig.ts +64 -12
  202. package/src/layouts/withLayoutContext.tsx +1 -1
  203. package/src/link/linking.ts +2 -2
  204. package/src/link/useLinkTo.tsx +1 -1
  205. package/src/router/getNormalizedStatePath.tsx +1 -1
  206. package/src/router/router.ts +41 -2
  207. package/types/Root.d.ts.map +1 -1
  208. package/types/fork/NavigationContainer.d.ts +19 -8
  209. package/types/fork/NavigationContainer.d.ts.map +1 -1
  210. package/types/fork/createMemoryHistory.d.ts +10 -1
  211. package/types/fork/createMemoryHistory.d.ts.map +1 -1
  212. package/types/fork/extractPathFromURL.d.ts +7 -1
  213. package/types/fork/extractPathFromURL.d.ts.map +1 -1
  214. package/types/fork/findFocusedRoute.d.ts +9 -0
  215. package/types/fork/findFocusedRoute.d.ts.map +1 -1
  216. package/types/fork/getPathFromState-mods.d.ts +23 -0
  217. package/types/fork/getPathFromState-mods.d.ts.map +1 -0
  218. package/types/fork/getPathFromState.d.ts +15 -14
  219. package/types/fork/getPathFromState.d.ts.map +1 -1
  220. package/types/fork/getStateFromPath-mods.d.ts +58 -0
  221. package/types/fork/getStateFromPath-mods.d.ts.map +1 -0
  222. package/types/fork/getStateFromPath.d.ts +28 -29
  223. package/types/fork/getStateFromPath.d.ts.map +1 -1
  224. package/types/fork/useBackButton.d.ts +6 -0
  225. package/types/fork/useBackButton.d.ts.map +1 -1
  226. package/types/fork/useBackButton.native.d.ts +9 -1
  227. package/types/fork/useBackButton.native.d.ts.map +1 -1
  228. package/types/fork/useDocumentTitle.d.ts +8 -6
  229. package/types/fork/useDocumentTitle.d.ts.map +1 -1
  230. package/types/fork/useDocumentTitle.native.d.ts +5 -2
  231. package/types/fork/useDocumentTitle.native.d.ts.map +1 -1
  232. package/types/fork/useLinking.d.ts +8 -1
  233. package/types/fork/useLinking.d.ts.map +1 -1
  234. package/types/fork/useLinking.native.d.ts +9 -2
  235. package/types/fork/useLinking.native.d.ts.map +1 -1
  236. package/types/fork/useThenable.d.ts +6 -0
  237. package/types/fork/useThenable.d.ts.map +1 -1
  238. package/types/fork/validatePathConfig.d.ts +8 -1
  239. package/types/fork/validatePathConfig.d.ts.map +1 -1
  240. package/types/link/linking.d.ts +2 -2
  241. package/types/link/linking.d.ts.map +1 -1
@@ -0,0 +1,400 @@
1
+ /**
2
+ * This file exports things that will be used to modify the forked code in `getStateFromPath.ts`.
3
+ *
4
+ * The purpose of keeping things in this separated file is to keep changes to the copied code as little as possible, making merging upstream updates easier.
5
+ */
6
+
7
+ import escape_ from 'escape-string-regexp'
8
+ import { matchGroupName, stripGroupSegmentsFromPath } from '../router/matchers'
9
+ import type { RouteConfig, ParsedRoute, InitialRouteConfig } from './getStateFromPath'
10
+
11
+ export type AdditionalRouteConfig = {
12
+ type: 'static' | 'dynamic' | 'layout'
13
+ userReadableName: string
14
+ isIndex: boolean
15
+ isInitial?: boolean
16
+ hasChildren: boolean
17
+ expandedRouteNames: string[]
18
+ parts: string[]
19
+ }
20
+
21
+ export function getUrlWithReactNavigationConcessions(
22
+ path: string,
23
+ baseUrl: string | undefined = process.env.EXPO_BASE_URL
24
+ ) {
25
+ let parsed: URL
26
+ try {
27
+ parsed = new URL(path, 'https://phony.example')
28
+ } catch {
29
+ // Do nothing with invalid URLs.
30
+ return {
31
+ path,
32
+ cleanUrl: '',
33
+ nonstandardPathname: '',
34
+ url: new URL('https://phony.example'),
35
+ }
36
+ }
37
+
38
+ const pathname = parsed.pathname
39
+ const withoutBaseUrl = stripBaseUrl(pathname, baseUrl)
40
+ const pathWithoutGroups = stripGroupSegmentsFromPath(stripBaseUrl(path, baseUrl))
41
+
42
+ // Make sure there is a trailing slash
43
+ return {
44
+ // The slashes are at the end, not the beginning
45
+ path,
46
+ nonstandardPathname: withoutBaseUrl.replace(/^\/+/g, '').replace(/\/+$/g, '') + '/',
47
+ url: parsed,
48
+ pathWithoutGroups,
49
+ }
50
+ }
51
+
52
+ export function matchForEmptyPath(configs: RouteConfig[]) {
53
+ // We need to add special handling of empty path so navigation to empty path also works
54
+ // When handling empty path, we should only look at the root level config
55
+
56
+ // NOTE: We only care about matching leaf nodes.
57
+ const leafNodes = configs
58
+ .filter((config) => !config.hasChildren)
59
+ .map((value) => {
60
+ return {
61
+ ...value,
62
+ // Collapse all levels of group segments before testing.
63
+ // This enables `app/(one)/(two)/index.js` to be matched.
64
+ path: stripGroupSegmentsFromPath(value.path),
65
+ }
66
+ })
67
+
68
+ const match =
69
+ leafNodes.find(
70
+ (config) =>
71
+ // NOTE: Test leaf node index routes that either don't have a regex or match an empty string.
72
+ config.path === '' && (!config.regex || config.regex.test(''))
73
+ ) ??
74
+ leafNodes.find(
75
+ (config) =>
76
+ // NOTE: Test leaf node dynamic routes that match an empty string.
77
+ config.path.startsWith(':') && config.regex!.test('')
78
+ ) ??
79
+ // NOTE: Test leaf node deep dynamic routes that match a slash.
80
+ // This should be done last to enable dynamic routes having a higher priority.
81
+ leafNodes.find((config) => config.path.startsWith('*') && config.regex!.test('/'))
82
+
83
+ return match
84
+ }
85
+
86
+ export function appendIsInitial(initialRoutes: InitialRouteConfig[]) {
87
+ const resolvedInitialPatterns = initialRoutes.map((route) =>
88
+ joinPaths(...route.parentScreens, route.initialRouteName)
89
+ )
90
+
91
+ return (config: RouteConfig) => {
92
+ // TODO: Probably a safer way to do this
93
+ // Mark initial routes to give them potential priority over other routes that match.
94
+ config.isInitial = resolvedInitialPatterns.includes(config.routeNames.join('/'))
95
+ return config
96
+ }
97
+ }
98
+
99
+ const joinPaths = (...paths: string[]): string =>
100
+ ([] as string[])
101
+ .concat(...paths.map((p) => p.split('/')))
102
+ .filter(Boolean)
103
+ .join('/')
104
+
105
+ export function getRouteConfigSorter(previousSegments: string[] = []) {
106
+ return function sortConfigs(a: RouteConfig, b: RouteConfig) {
107
+ // Sort config so that:
108
+ // - the most exhaustive ones are always at the beginning
109
+ // - patterns with wildcard are always at the end
110
+
111
+ // If 2 patterns are same, move the one with less route names up
112
+ // This is an error state, so it's only useful for consistent error messages
113
+ if (a.pattern === b.pattern) {
114
+ return b.routeNames.join('>').localeCompare(a.routeNames.join('>'))
115
+ }
116
+
117
+ /*
118
+ * If one of the patterns starts with the other, it is earlier in the config sorting.
119
+ * However, configs are a mix of route configs and layout configs
120
+ * e.g There will be a config for `/(group)`, but maybe there isn't a `/(group)/index.tsx`
121
+ *
122
+ * This is because you can navigate to a directory and its navigator will determine the route
123
+ * These routes should be later in the config sorting, as their patterns are very open
124
+ * and will prevent routes from being matched
125
+ *
126
+ * Therefore before we compare segment parts, we force these layout configs later in the sorting
127
+ *
128
+ * NOTE: Is this a feature we want? I'm unsure if this is a gimmick or a feature.
129
+ */
130
+ if (a.pattern.startsWith(b.pattern) && !b.isIndex) {
131
+ return -1
132
+ }
133
+
134
+ if (b.pattern.startsWith(a.pattern) && !a.isIndex) {
135
+ return 1
136
+ }
137
+
138
+ /*
139
+ * Static routes should always be higher than dynamic and layout routes.
140
+ */
141
+ if (a.type === 'static' && b.type !== 'static') {
142
+ return -1
143
+ }
144
+ if (a.type !== 'static' && b.type === 'static') {
145
+ return 1
146
+ }
147
+
148
+ /*
149
+ * If both are static/dynamic or a layout file, then we check group similarity
150
+ */
151
+ const similarToPreviousA = previousSegments.filter((value, index) => {
152
+ return value === a.expandedRouteNames[index] && value.startsWith('(') && value.endsWith(')')
153
+ })
154
+
155
+ const similarToPreviousB = previousSegments.filter((value, index) => {
156
+ return value === b.expandedRouteNames[index] && value.startsWith('(') && value.endsWith(')')
157
+ })
158
+
159
+ if (
160
+ (similarToPreviousA.length > 0 || similarToPreviousB.length > 0) &&
161
+ similarToPreviousA.length !== similarToPreviousB.length
162
+ ) {
163
+ // One matches more than the other, so pick the one that matches more
164
+ return similarToPreviousB.length - similarToPreviousA.length
165
+ }
166
+
167
+ /*
168
+ * If there is not difference in similarity, then each non-group segment is compared against each other
169
+ */
170
+ for (let i = 0; i < Math.max(a.parts.length, b.parts.length); i++) {
171
+ // if b is longer, b get higher priority
172
+ if (a.parts[i] == null) {
173
+ return 1
174
+ }
175
+ // if a is longer, a get higher priority
176
+ if (b.parts[i] == null) {
177
+ return -1
178
+ }
179
+
180
+ const aWildCard = a.parts[i].startsWith('*')
181
+ const bWildCard = b.parts[i].startsWith('*')
182
+ // if both are wildcard we compare next component
183
+ if (aWildCard && bWildCard) {
184
+ const aNotFound = a.parts[i].match(/^[*]not-found$/)
185
+ const bNotFound = b.parts[i].match(/^[*]not-found$/)
186
+
187
+ if (aNotFound && bNotFound) {
188
+ continue
189
+ }
190
+ if (aNotFound) {
191
+ return 1
192
+ }
193
+ if (bNotFound) {
194
+ return -1
195
+ }
196
+ continue
197
+ }
198
+ // if only a is wild card, b get higher priority
199
+ if (aWildCard) {
200
+ return 1
201
+ }
202
+ // if only b is wild card, a get higher priority
203
+ if (bWildCard) {
204
+ return -1
205
+ }
206
+
207
+ const aSlug = a.parts[i].startsWith(':')
208
+ const bSlug = b.parts[i].startsWith(':')
209
+ // if both are wildcard we compare next component
210
+ if (aSlug && bSlug) {
211
+ const aNotFound = a.parts[i].match(/^[*]not-found$/)
212
+ const bNotFound = b.parts[i].match(/^[*]not-found$/)
213
+
214
+ if (aNotFound && bNotFound) {
215
+ continue
216
+ }
217
+ if (aNotFound) {
218
+ return 1
219
+ }
220
+ if (bNotFound) {
221
+ return -1
222
+ }
223
+
224
+ continue
225
+ }
226
+ // if only a is wild card, b get higher priority
227
+ if (aSlug) {
228
+ return 1
229
+ }
230
+ // if only b is wild card, a get higher priority
231
+ if (bSlug) {
232
+ return -1
233
+ }
234
+ }
235
+
236
+ /*
237
+ * Both configs are identical in specificity and segments count/type
238
+ * Try and sort by initial instead.
239
+ *
240
+ * TODO: We don't differentiate between the default initialRoute and group specific default routes
241
+ *
242
+ * const unstable_settings = {
243
+ * "group": {
244
+ * initialRouteName: "article"
245
+ * }
246
+ * }
247
+ *
248
+ * "article" will be ranked higher because its an initialRoute for a group - even if not your not currently in
249
+ * that group. The current work around is to ways provide initialRouteName for all groups
250
+ */
251
+ if (a.isInitial && !b.isInitial) {
252
+ return -1
253
+ }
254
+ if (!a.isInitial && b.isInitial) {
255
+ return 1
256
+ }
257
+
258
+ return b.parts.length - a.parts.length
259
+ }
260
+ }
261
+
262
+ export function formatRegexPattern(it: string): string {
263
+ // Allow spaces in file path names.
264
+ it = it.replace(' ', '%20')
265
+
266
+ if (it.startsWith(':')) {
267
+ // TODO: Remove unused match group
268
+ return `(([^/]+\\/)${it.endsWith('?') ? '?' : ''})`
269
+ }
270
+
271
+ if (it.startsWith('*')) {
272
+ return `((.*\\/)${it.endsWith('?') ? '?' : ''})`
273
+ }
274
+
275
+ // Strip groups from the matcher
276
+ if (matchGroupName(it) != null) {
277
+ // Groups are optional segments
278
+ // this enables us to match `/bar` and `/(foo)/bar` for the same route
279
+ // NOTE(EvanBacon): Ignore this match in the regex to avoid capturing the group
280
+ return `(?:${escape(it)}\\/)?`
281
+ }
282
+
283
+ return escape_(it) + `\\/`
284
+ }
285
+
286
+ export function decodeURIComponentSafe(str: string) {
287
+ try {
288
+ return decodeURIComponent(str)
289
+ } catch {
290
+ return str
291
+ }
292
+ }
293
+
294
+ export function getParamValue(p: string, value: string) {
295
+ if (p.startsWith('*')) {
296
+ const values = value.split('/').filter((v) => v !== '')
297
+ return values.length === 0 && p.endsWith('?') ? undefined : values
298
+ }
299
+
300
+ return value
301
+ }
302
+
303
+ /**
304
+ * In One, the params are available at all levels of the routing config
305
+ */
306
+ export function populateParams(routes?: ParsedRoute[], params?: Record<string, any>) {
307
+ if (!routes || !params || Object.keys(params).length === 0) return
308
+
309
+ for (const route of routes) {
310
+ Object.assign(route, { params })
311
+ }
312
+
313
+ return routes
314
+ }
315
+
316
+ export function createConfigItemAdditionalProperties(
317
+ screen: string,
318
+ pattern: string,
319
+ routeNames: string[],
320
+ config: Record<string, any> = {}
321
+ ): Omit<AdditionalRouteConfig, 'isInitial'> {
322
+ const parts: string[] = []
323
+ let isDynamic = false
324
+ const isIndex = screen === 'index' || screen.endsWith('/index')
325
+
326
+ for (const part of pattern.split('/')) {
327
+ if (part) {
328
+ // If any part is dynamic, then the route is dynamic
329
+ isDynamic ||= part.startsWith(':') || part.startsWith('*') || part.includes('*not-found')
330
+
331
+ if (!matchGroupName(part)) {
332
+ parts.push(part)
333
+ }
334
+ }
335
+ }
336
+
337
+ const hasChildren = config.screens ? !!Object.keys(config.screens)?.length : false
338
+ const type = hasChildren ? 'layout' : isDynamic ? 'dynamic' : 'static'
339
+
340
+ if (isIndex) {
341
+ parts.push('index')
342
+ }
343
+
344
+ return {
345
+ type,
346
+ isIndex,
347
+ hasChildren,
348
+ parts,
349
+ userReadableName: [...routeNames.slice(0, -1), config.path || screen].join('/'),
350
+ expandedRouteNames: routeNames.flatMap((name) => {
351
+ return name.split('/')
352
+ }),
353
+ }
354
+ }
355
+
356
+ export function parseQueryParamsExtended(
357
+ path: string,
358
+ route: ParsedRoute,
359
+ parseConfig?: Record<string, (value: string) => any>,
360
+ hash?: string
361
+ ) {
362
+ const searchParams = new URL(path, 'https://phony.example').searchParams
363
+ const params: Record<string, string | string[]> = Object.create(null)
364
+
365
+ if (hash) {
366
+ params['#'] = hash.slice(1)
367
+ }
368
+
369
+ for (const name of searchParams.keys()) {
370
+ if (route.params?.[name]) {
371
+ if (process.env.NODE_ENV !== 'production') {
372
+ console.warn(
373
+ `Route '/${route.name}' with param '${name}' was specified both in the path and as a param, removing from path`
374
+ )
375
+ }
376
+ } else {
377
+ const values = parseConfig?.hasOwnProperty(name)
378
+ ? searchParams.getAll(name).map((value) => parseConfig[name](value))
379
+ : searchParams.getAll(name)
380
+
381
+ // searchParams.getAll returns an array.
382
+ // if we only have a single value, and its not an array param, we need to extract the value
383
+ params[name] = values.length === 1 ? values[0] : values
384
+ }
385
+ }
386
+
387
+ return Object.keys(params).length ? params : undefined
388
+ }
389
+
390
+ export function stripBaseUrl(
391
+ path: string,
392
+ baseUrl: string | undefined = process.env.EXPO_BASE_URL
393
+ ) {
394
+ if (process.env.NODE_ENV !== 'development') {
395
+ if (baseUrl) {
396
+ return path.replace(/^\/+/g, '/').replace(new RegExp(`^\\/?${escape(baseUrl)}`, 'g'), '')
397
+ }
398
+ }
399
+ return path
400
+ }