@tanstack/router-core 0.0.1-beta.13 → 0.0.1-beta.145

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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/build/cjs/history.js +226 -0
  3. package/build/cjs/history.js.map +1 -0
  4. package/build/cjs/{packages/router-core/src/index.js → index.js} +33 -15
  5. package/build/cjs/{packages/router-core/src/index.js.map → index.js.map} +1 -1
  6. package/build/cjs/{packages/router-core/src/path.js → path.js} +45 -56
  7. package/build/cjs/path.js.map +1 -0
  8. package/build/cjs/{packages/router-core/src/qss.js → qss.js} +10 -16
  9. package/build/cjs/qss.js.map +1 -0
  10. package/build/cjs/route.js +147 -0
  11. package/build/cjs/route.js.map +1 -0
  12. package/build/cjs/router.js +1102 -0
  13. package/build/cjs/router.js.map +1 -0
  14. package/build/cjs/{packages/router-core/src/searchParams.js → searchParams.js} +11 -13
  15. package/build/cjs/searchParams.js.map +1 -0
  16. package/build/cjs/{packages/router-core/src/utils.js → utils.js} +54 -64
  17. package/build/cjs/utils.js.map +1 -0
  18. package/build/esm/index.js +1444 -2095
  19. package/build/esm/index.js.map +1 -1
  20. package/build/stats-html.html +59 -49
  21. package/build/stats-react.json +186 -249
  22. package/build/types/index.d.ts +559 -422
  23. package/build/umd/index.development.js +1675 -2223
  24. package/build/umd/index.development.js.map +1 -1
  25. package/build/umd/index.production.js +12 -2
  26. package/build/umd/index.production.js.map +1 -1
  27. package/package.json +11 -7
  28. package/src/history.ts +292 -0
  29. package/src/index.ts +2 -10
  30. package/src/link.ts +116 -113
  31. package/src/path.ts +37 -17
  32. package/src/qss.ts +1 -2
  33. package/src/route.ts +927 -218
  34. package/src/routeInfo.ts +121 -197
  35. package/src/router.ts +1483 -1008
  36. package/src/searchParams.ts +1 -1
  37. package/src/utils.ts +80 -49
  38. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -33
  39. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
  40. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js +0 -33
  41. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js.map +0 -1
  42. package/build/cjs/node_modules/history/index.js +0 -815
  43. package/build/cjs/node_modules/history/index.js.map +0 -1
  44. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js +0 -30
  45. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +0 -1
  46. package/build/cjs/packages/router-core/src/path.js.map +0 -1
  47. package/build/cjs/packages/router-core/src/qss.js.map +0 -1
  48. package/build/cjs/packages/router-core/src/route.js +0 -147
  49. package/build/cjs/packages/router-core/src/route.js.map +0 -1
  50. package/build/cjs/packages/router-core/src/routeConfig.js +0 -69
  51. package/build/cjs/packages/router-core/src/routeConfig.js.map +0 -1
  52. package/build/cjs/packages/router-core/src/routeMatch.js +0 -226
  53. package/build/cjs/packages/router-core/src/routeMatch.js.map +0 -1
  54. package/build/cjs/packages/router-core/src/router.js +0 -823
  55. package/build/cjs/packages/router-core/src/router.js.map +0 -1
  56. package/build/cjs/packages/router-core/src/searchParams.js.map +0 -1
  57. package/build/cjs/packages/router-core/src/utils.js.map +0 -1
  58. package/src/frameworks.ts +0 -11
  59. package/src/routeConfig.ts +0 -489
  60. package/src/routeMatch.ts +0 -312
package/src/link.ts CHANGED
@@ -1,11 +1,6 @@
1
- import { AnyPathParams } from './routeConfig'
2
- import {
3
- AnyAllRouteInfo,
4
- DefaultAllRouteInfo,
5
- RouteInfoByPath,
6
- } from './routeInfo'
7
- import { Location } from './router'
8
- import { Expand, NoInfer, PickAsRequired, PickRequired, Updater } from './utils'
1
+ import { AnyRoutesInfo, RouteByPath } from './routeInfo'
2
+ import { ParsedLocation, LocationState, RegisteredRoutesInfo } from './router'
3
+ import { NoInfer, PickRequired, UnionToIntersection, Updater } from './utils'
9
4
 
10
5
  export type LinkInfo =
11
6
  | {
@@ -14,19 +9,16 @@ export type LinkInfo =
14
9
  }
15
10
  | {
16
11
  type: 'internal'
17
- next: Location
12
+ next: ParsedLocation
18
13
  handleFocus: (e: any) => void
19
14
  handleClick: (e: any) => void
20
15
  handleEnter: (e: any) => void
21
16
  handleLeave: (e: any) => void
17
+ handleTouchStart: (e: any) => void
22
18
  isActive: boolean
23
19
  disabled?: boolean
24
20
  }
25
21
 
26
- type StartsWith<A, B> = A extends `${B extends string ? B : never}${infer _}`
27
- ? true
28
- : false
29
-
30
22
  type CleanPath<T extends string> = T extends `${infer L}//${infer R}`
31
23
  ? CleanPath<`${CleanPath<L>}/${CleanPath<R>}`>
32
24
  : T extends `${infer L}//`
@@ -58,17 +50,17 @@ export type Split<S, TIncludeTrailingSlash = true> = S extends unknown
58
50
  : never
59
51
 
60
52
  export type ParsePathParams<T extends string> = Split<T>[number] extends infer U
61
- ? U extends `:${infer V}`
53
+ ? U extends `$${infer V}`
62
54
  ? V
63
55
  : never
64
56
  : never
65
57
 
66
- type Join<T> = T extends []
58
+ type Join<T, Delimiter extends string = '/'> = T extends []
67
59
  ? ''
68
60
  : T extends [infer L extends string]
69
61
  ? L
70
62
  : T extends [infer L extends string, ...infer Tail extends [...string[]]]
71
- ? CleanPath<`${L}/${Join<Tail>}`>
63
+ ? CleanPath<`${L}${Delimiter}${Join<Tail>}`>
72
64
  : never
73
65
 
74
66
  export type RelativeToPathAutoComplete<
@@ -106,126 +98,155 @@ export type RelativeToPathAutoComplete<
106
98
  ]
107
99
  ? `${TTo}${Join<RestPath>}`
108
100
  : never
109
- : './' | '../' | AllPaths
101
+ :
102
+ | (TFrom extends `/`
103
+ ? never
104
+ : SplitPaths extends [...Split<TFrom, false>, ...infer RestPath]
105
+ ? Join<RestPath> extends { length: 0 }
106
+ ? never
107
+ : './'
108
+ : never)
109
+ | (TFrom extends `/` ? never : '../')
110
+ | AllPaths
110
111
 
111
- export type NavigateOptionsAbsolute<
112
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
113
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
114
- TTo extends string = '.',
115
- > = ToOptions<TAllRouteInfo, TFrom, TTo> & {
116
- // Whether to replace the current history stack instead of pushing a new one
112
+ export type NavigateOptions<
113
+ TRoutesInfo extends AnyRoutesInfo = RegisteredRoutesInfo,
114
+ TFrom extends TRoutesInfo['routePaths'] = '/',
115
+ TTo extends string = '',
116
+ > = ToOptions<TRoutesInfo, TFrom, TTo> & {
117
+ // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
117
118
  replace?: boolean
118
119
  }
119
120
 
120
121
  export type ToOptions<
121
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
122
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
123
- TTo extends string = '.',
122
+ TRoutesInfo extends AnyRoutesInfo = RegisteredRoutesInfo,
123
+ TFrom extends TRoutesInfo['routePaths'] = '/',
124
+ TTo extends string = '',
124
125
  TResolvedTo = ResolveRelativePath<TFrom, NoInfer<TTo>>,
125
126
  > = {
126
- to?: ToPathOption<TAllRouteInfo, TFrom, TTo>
127
+ to?: ToPathOption<TRoutesInfo, TFrom, TTo>
127
128
  // The new has string or a function to update it
128
129
  hash?: Updater<string>
130
+ // State to pass to the history stack
131
+ state?: LocationState
129
132
  // The source route path. This is automatically set when using route-level APIs, but for type-safe relative routing on the router itself, this is required
130
133
  from?: TFrom
131
134
  // // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
132
135
  // fromCurrent?: boolean
133
- } & CheckPath<TAllRouteInfo, NoInfer<TResolvedTo>, {}> &
134
- SearchParamOptions<TAllRouteInfo, TFrom, TResolvedTo> &
135
- PathParamOptions<TAllRouteInfo, TFrom, TResolvedTo>
136
+ } & CheckPath<TRoutesInfo, NoInfer<TResolvedTo>, {}> &
137
+ SearchParamOptions<TRoutesInfo, TFrom, TResolvedTo> &
138
+ PathParamOptions<TRoutesInfo, TFrom, TResolvedTo>
136
139
 
137
- type SearchParamOptions<
138
- TAllRouteInfo extends AnyAllRouteInfo,
140
+ export type SearchParamOptions<
141
+ TRoutesInfo extends AnyRoutesInfo,
139
142
  TFrom,
140
143
  TTo,
141
- TFromSchema = RouteInfoByPath<TAllRouteInfo, TFrom>['fullSearchSchema'],
142
- TToSchema = RouteInfoByPath<TAllRouteInfo, TTo>['fullSearchSchema'],
143
- > = StartsWith<TFrom, TTo> extends true // If the next route search extend or cover the from route, params will be optional
144
- ? {
145
- search?: SearchReducer<TFromSchema, TToSchema>
146
- }
147
- : // Optional search params? Allow it
148
- keyof PickRequired<TToSchema> extends never
144
+ TFromSchema = UnionToIntersection<
145
+ TRoutesInfo['fullSearchSchema'] &
146
+ RouteByPath<TRoutesInfo, TFrom> extends never
147
+ ? {}
148
+ : RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']
149
+ >,
150
+ // Find the schema for the new path, and make optional any keys
151
+ // that are already defined in the current schema
152
+ TToSchema = Partial<
153
+ RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']
154
+ > &
155
+ Omit<
156
+ RouteByPath<TRoutesInfo, TTo>['__types']['fullSearchSchema'],
157
+ keyof PickRequired<
158
+ RouteByPath<TRoutesInfo, TFrom>['__types']['fullSearchSchema']
159
+ >
160
+ >,
161
+ TFromFullSchema = UnionToIntersection<
162
+ TRoutesInfo['fullSearchSchema'] & TFromSchema
163
+ >,
164
+ TToFullSchema = UnionToIntersection<
165
+ TRoutesInfo['fullSearchSchema'] & TToSchema
166
+ >,
167
+ > = keyof PickRequired<TToSchema> extends never
149
168
  ? {
150
- search?: SearchReducer<TFromSchema, TToSchema>
169
+ search?: true | SearchReducer<TFromFullSchema, TToFullSchema>
151
170
  }
152
171
  : {
153
- // Must have required search params, enforce it
154
- search: SearchReducer<TFromSchema, TToSchema>
172
+ search: SearchReducer<TFromFullSchema, TToFullSchema>
155
173
  }
156
174
 
157
175
  type SearchReducer<TFrom, TTo> =
158
176
  | { [TKey in keyof TTo]: TTo[TKey] }
159
177
  | ((current: TFrom) => TTo)
160
178
 
161
- type PathParamOptions<
162
- TAllRouteInfo extends AnyAllRouteInfo,
179
+ export type PathParamOptions<
180
+ TRoutesInfo extends AnyRoutesInfo,
163
181
  TFrom,
164
182
  TTo,
165
- TFromParams = RouteInfoByPath<TAllRouteInfo, TFrom>['allParams'],
166
- TToParams = RouteInfoByPath<TAllRouteInfo, TTo>['allParams'],
167
- > =
168
- // If the next routes params extend or cover the from route, params will be optional
169
- StartsWith<TFrom, TTo> extends true
170
- ? {
171
- params?: ParamsReducer<TFromParams, TToParams>
172
- }
173
- : // If the next route doesn't have params, warn if any have been passed
174
- AnyPathParams extends TToParams
175
- ? {
176
- params?: ParamsReducer<TFromParams, Record<string, never>>
177
- }
178
- : // If the next route has params, enforce them
179
- {
180
- params: ParamsReducer<TFromParams, TToParams>
181
- }
183
+ TFromSchema = UnionToIntersection<
184
+ RouteByPath<TRoutesInfo, TFrom> extends never
185
+ ? {}
186
+ : RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']
187
+ >,
188
+ // Find the schema for the new path, and make optional any keys
189
+ // that are already defined in the current schema
190
+ TToSchema = Partial<RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']> &
191
+ Omit<
192
+ RouteByPath<TRoutesInfo, TTo>['__types']['allParams'],
193
+ keyof PickRequired<
194
+ RouteByPath<TRoutesInfo, TFrom>['__types']['allParams']
195
+ >
196
+ >,
197
+ TFromFullParams = UnionToIntersection<TRoutesInfo['allParams'] & TFromSchema>,
198
+ TToFullParams = UnionToIntersection<TRoutesInfo['allParams'] & TToSchema>,
199
+ > = keyof PickRequired<TToSchema> extends never
200
+ ? {
201
+ params?: ParamsReducer<TFromFullParams, TToFullParams>
202
+ }
203
+ : {
204
+ params: ParamsReducer<TFromFullParams, TToFullParams>
205
+ }
182
206
 
183
207
  type ParamsReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
184
208
 
185
209
  export type ToPathOption<
186
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
187
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
188
- TTo extends string = '.',
210
+ TRoutesInfo extends AnyRoutesInfo = RegisteredRoutesInfo,
211
+ TFrom extends TRoutesInfo['routePaths'] = '/',
212
+ TTo extends string = '',
189
213
  > =
190
214
  | TTo
191
215
  | RelativeToPathAutoComplete<
192
- TAllRouteInfo['routePaths'],
216
+ TRoutesInfo['routePaths'],
193
217
  NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
194
218
  NoInfer<TTo> & string
195
219
  >
196
220
 
197
221
  export type ToIdOption<
198
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
199
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
200
- TTo extends string = '.',
222
+ TRoutesInfo extends AnyRoutesInfo = RegisteredRoutesInfo,
223
+ TFrom extends TRoutesInfo['routePaths'] = '/',
224
+ TTo extends string = '',
201
225
  > =
202
226
  | TTo
203
227
  | RelativeToPathAutoComplete<
204
- TAllRouteInfo['routeIds'],
228
+ TRoutesInfo['routeIds'],
205
229
  NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
206
230
  NoInfer<TTo> & string
207
231
  >
208
232
 
209
- interface ActiveOptions {
233
+ export interface ActiveOptions {
210
234
  exact?: boolean
211
235
  includeHash?: boolean
236
+ includeSearch?: boolean
212
237
  }
213
238
 
214
239
  export type LinkOptions<
215
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
216
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
217
- TTo extends string = '.',
218
- > = NavigateOptionsAbsolute<TAllRouteInfo, TFrom, TTo> & {
240
+ TRoutesInfo extends AnyRoutesInfo = RegisteredRoutesInfo,
241
+ TFrom extends TRoutesInfo['routePaths'] = '/',
242
+ TTo extends string = '',
243
+ > = NavigateOptions<TRoutesInfo, TFrom, TTo> & {
219
244
  // The standard anchor tag target attribute
220
245
  target?: HTMLAnchorElement['target']
221
246
  // Defaults to `{ exact: false, includeHash: false }`
222
247
  activeOptions?: ActiveOptions
223
248
  // If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
224
249
  preload?: false | 'intent'
225
- // When preloaded, the preloaded result will be considered "fresh" for this duration in milliseconds
226
- preloadMaxAge?: number
227
- // When preloaded and subsequently inactive, the preloaded result will remain in memory for this duration in milliseconds
228
- preloadGcMaxAge?: number
229
250
  // Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
230
251
  preloadDelay?: number
231
252
  // If true, will render the link without the href attribute
@@ -233,58 +254,48 @@ export type LinkOptions<
233
254
  }
234
255
 
235
256
  export type CheckRelativePath<
236
- TAllRouteInfo extends AnyAllRouteInfo,
257
+ TRoutesInfo extends AnyRoutesInfo,
237
258
  TFrom,
238
259
  TTo,
239
260
  > = TTo extends string
240
261
  ? TFrom extends string
241
- ? ResolveRelativePath<TFrom, TTo> extends TAllRouteInfo['routePaths']
262
+ ? ResolveRelativePath<TFrom, TTo> extends TRoutesInfo['routePaths']
242
263
  ? {}
243
264
  : {
244
265
  Error: `${TFrom} + ${TTo} resolves to ${ResolveRelativePath<
245
266
  TFrom,
246
267
  TTo
247
268
  >}, which is not a valid route path.`
248
- 'Valid Route Paths': TAllRouteInfo['routePaths']
269
+ 'Valid Route Paths': TRoutesInfo['routePaths']
249
270
  }
250
271
  : {}
251
272
  : {}
252
273
 
253
274
  export type CheckPath<
254
- TAllRouteInfo extends AnyAllRouteInfo,
275
+ TRoutesInfo extends AnyRoutesInfo,
255
276
  TPath,
256
277
  TPass,
257
- > = Exclude<TPath, TAllRouteInfo['routePaths']> extends never
278
+ > = Exclude<TPath, TRoutesInfo['routePaths']> extends never
258
279
  ? TPass
259
- : CheckPathError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routePaths']>>
280
+ : CheckPathError<TRoutesInfo, Exclude<TPath, TRoutesInfo['routePaths']>>
260
281
 
261
- export type CheckPathError<
262
- TAllRouteInfo extends AnyAllRouteInfo,
263
- TInvalids,
264
- > = Expand<{
265
- Error: `${TInvalids extends string
266
- ? TInvalids
267
- : never} is not a valid route path.`
268
- 'Valid Route Paths': TAllRouteInfo['routePaths']
269
- }>
282
+ export type CheckPathError<TRoutesInfo extends AnyRoutesInfo, TInvalids> = {
283
+ to: TRoutesInfo['routePaths']
284
+ }
270
285
 
271
- export type CheckId<
272
- TAllRouteInfo extends AnyAllRouteInfo,
286
+ export type CheckId<TRoutesInfo extends AnyRoutesInfo, TPath, TPass> = Exclude<
273
287
  TPath,
274
- TPass,
275
- > = Exclude<TPath, TAllRouteInfo['routeIds']> extends never
288
+ TRoutesInfo['routeIds']
289
+ > extends never
276
290
  ? TPass
277
- : CheckIdError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routeIds']>>
291
+ : CheckIdError<TRoutesInfo, Exclude<TPath, TRoutesInfo['routeIds']>>
278
292
 
279
- export type CheckIdError<
280
- TAllRouteInfo extends AnyAllRouteInfo,
281
- TInvalids,
282
- > = Expand<{
293
+ export type CheckIdError<TRoutesInfo extends AnyRoutesInfo, TInvalids> = {
283
294
  Error: `${TInvalids extends string
284
295
  ? TInvalids
285
296
  : never} is not a valid route ID.`
286
- 'Valid Route IDs': TAllRouteInfo['routeIds']
287
- }>
297
+ 'Valid Route IDs': TRoutesInfo['routeIds']
298
+ }
288
299
 
289
300
  export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
290
301
  ? TTo extends string
@@ -309,11 +320,3 @@ export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
309
320
  : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>>
310
321
  : never
311
322
  : never
312
-
313
- export type ValidFromPath<
314
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
315
- > =
316
- | undefined
317
- | (string extends TAllRouteInfo['routePaths']
318
- ? string
319
- : TAllRouteInfo['routePaths'])
package/src/path.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AnyPathParams } from './routeConfig'
1
+ import { AnyPathParams } from './route'
2
2
  import { MatchLocation } from './router'
3
3
  import { last } from './utils'
4
4
 
@@ -90,14 +90,14 @@ export function parsePathname(pathname?: string): Segment[] {
90
90
 
91
91
  segments.push(
92
92
  ...split.map((part): Segment => {
93
- if (part.startsWith('*')) {
93
+ if (part === '$' || part === '*') {
94
94
  return {
95
95
  type: 'wildcard',
96
96
  value: part,
97
97
  }
98
98
  }
99
99
 
100
- if (part.charAt(0) === ':') {
100
+ if (part.charAt(0) === '$') {
101
101
  return {
102
102
  type: 'param',
103
103
  value: part,
@@ -125,14 +125,16 @@ export function parsePathname(pathname?: string): Segment[] {
125
125
  export function interpolatePath(
126
126
  path: string | undefined,
127
127
  params: any,
128
- leaveWildcard?: boolean,
128
+ leaveWildcards: boolean = false,
129
129
  ) {
130
130
  const interpolatedPathSegments = parsePathname(path)
131
131
 
132
132
  return joinPaths(
133
133
  interpolatedPathSegments.map((segment) => {
134
- if (segment.value === '*' && !leaveWildcard) {
135
- return ''
134
+ if (segment.type === 'wildcard') {
135
+ const value = params[segment.value]
136
+ if (leaveWildcards) return `${segment.value}${value ?? ''}`
137
+ return value
136
138
  }
137
139
 
138
140
  if (segment.type === 'param') {
@@ -145,29 +147,46 @@ export function interpolatePath(
145
147
  }
146
148
 
147
149
  export function matchPathname(
150
+ basepath: string,
148
151
  currentPathname: string,
149
152
  matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,
150
153
  ): AnyPathParams | undefined {
151
- const pathParams = matchByPath(currentPathname, matchLocation)
152
- // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
154
+ const pathParams = matchByPath(basepath, currentPathname, matchLocation)
155
+ // const searchMatched = matchBySearch(location.search, matchLocation)
153
156
 
154
157
  if (matchLocation.to && !pathParams) {
155
158
  return
156
159
  }
157
160
 
158
- // if (matchLocation.search && !searchMatched) {
159
- // return
160
- // }
161
-
162
161
  return pathParams ?? {}
163
162
  }
164
163
 
165
164
  export function matchByPath(
165
+ basepath: string,
166
166
  from: string,
167
167
  matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,
168
168
  ): Record<string, string> | undefined {
169
+ // Remove the base path from the pathname
170
+ from = basepath != '/' ? from.substring(basepath.length) : from
171
+ // Default to to $ (wildcard)
172
+ const to = `${matchLocation.to ?? '$'}`
173
+ // Parse the from and to
169
174
  const baseSegments = parsePathname(from)
170
- const routeSegments = parsePathname(`${matchLocation.to ?? '*'}`)
175
+ const routeSegments = parsePathname(to)
176
+
177
+ if (!from.startsWith('/')) {
178
+ baseSegments.unshift({
179
+ type: 'pathname',
180
+ value: '/',
181
+ })
182
+ }
183
+
184
+ if (!to.startsWith('/')) {
185
+ routeSegments.unshift({
186
+ type: 'pathname',
187
+ value: '/',
188
+ })
189
+ }
171
190
 
172
191
  const params: Record<string, string> = {}
173
192
 
@@ -180,8 +199,8 @@ export function matchByPath(
180
199
  const baseSegment = baseSegments[i]
181
200
  const routeSegment = routeSegments[i]
182
201
 
183
- const isLastRouteSegment = i === routeSegments.length - 1
184
- const isLastBaseSegment = i === baseSegments.length - 1
202
+ const isLastBaseSegment = i >= baseSegments.length - 1
203
+ const isLastRouteSegment = i >= routeSegments.length - 1
185
204
 
186
205
  if (routeSegment) {
187
206
  if (routeSegment.type === 'wildcard') {
@@ -219,16 +238,17 @@ export function matchByPath(
219
238
  if (baseSegment?.value === '/') {
220
239
  return false
221
240
  }
222
- if (!baseSegment.value.startsWith(':')) {
241
+ if (baseSegment.value.charAt(0) !== '$') {
223
242
  params[routeSegment.value.substring(1)] = baseSegment.value
224
243
  }
225
244
  }
226
245
  }
227
246
 
228
- if (isLastRouteSegment && !isLastBaseSegment) {
247
+ if (!isLastBaseSegment && isLastRouteSegment) {
229
248
  return !!matchLocation.fuzzy
230
249
  }
231
250
  }
251
+
232
252
  return true
233
253
  })()
234
254
 
package/src/qss.ts CHANGED
@@ -30,8 +30,7 @@ function toValue(mix) {
30
30
  var str = decodeURIComponent(mix)
31
31
  if (str === 'false') return false
32
32
  if (str === 'true') return true
33
- if (str.charAt(0) === '0') return str
34
- return +str * 0 === 0 ? +str : str
33
+ return +str * 0 === 0 && +str + '' === str ? +str : str
35
34
  }
36
35
 
37
36
  export function decode(str) {