@native-router/core 1.1.0 → 1.2.0
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/README.md +7 -3
- package/dist/index.cjs +92 -27
- package/dist/index.mjs +92 -28
- package/dist/types/router.d.ts +22 -2
- package/dist/types/types.d.ts +36 -2
- package/package.json +7 -16
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[](https://www.npmjs.com/package/@native-router/core)
|
|
2
|
-
[](https://github.com/native-router/core/actions)
|
|
3
|
+
[](https://codecov.io/gh/native-router/core)
|
|
4
4
|
[](https://packagephobia.now.sh/result?p=@native-router/core)
|
|
5
5
|
|
|
6
6
|
# Native Router React
|
|
@@ -18,6 +18,10 @@ English | [简体中文](./README-zh_CN.md)
|
|
|
18
18
|
- Most unused features can be tree-shaking
|
|
19
19
|
- SSR support
|
|
20
20
|
|
|
21
|
+
## Matching semantics
|
|
22
|
+
|
|
23
|
+
Routes are matched in declaration order and the first match wins — there is no sorting by specificity. Trailing slashes are significant (`/users/` does not match `/users`). Matching is case-sensitive.
|
|
24
|
+
|
|
21
25
|
## Install
|
|
22
26
|
|
|
23
27
|
```bash
|
|
@@ -76,4 +80,4 @@ See [demos](/demos/) for a complete example.
|
|
|
76
80
|
|
|
77
81
|
## Documentation
|
|
78
82
|
|
|
79
|
-
[API](https://
|
|
83
|
+
[API](https://native-router.github.io/core/modules.html)
|
package/dist/index.cjs
CHANGED
|
@@ -13,6 +13,8 @@ class NotFoundError extends NativeRouterError {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
const DEFAULT_MAX_STACK_DEPTH = 100;
|
|
17
|
+
|
|
16
18
|
/**
|
|
17
19
|
* Create a router instance.
|
|
18
20
|
* @group Methods
|
|
@@ -26,12 +28,15 @@ class NotFoundError extends NativeRouterError {
|
|
|
26
28
|
function create(routes, history, resolveView, options) {
|
|
27
29
|
const [currentGuard, cancelAll] = util.createCurrentGuard();
|
|
28
30
|
const {
|
|
29
|
-
index
|
|
30
|
-
locationStack
|
|
31
|
+
index
|
|
31
32
|
} = getHistoryState({
|
|
32
33
|
history: history
|
|
33
34
|
});
|
|
34
|
-
|
|
35
|
+
// Restore the session stack from the bounded window serialized in the
|
|
36
|
+
// current entry state; entries before the window become placeholders.
|
|
37
|
+
// Legacy index-only state(1.x) degrades to a single-entry stack.
|
|
38
|
+
const locationStack = restoreLocationStack(history);
|
|
39
|
+
const viewStack = new Array(Math.max(index + 1, locationStack.length)).fill(null);
|
|
35
40
|
if (options?.currentView) {
|
|
36
41
|
viewStack[index] = options.currentView;
|
|
37
42
|
}
|
|
@@ -45,7 +50,8 @@ function create(routes, history, resolveView, options) {
|
|
|
45
50
|
cancelAll,
|
|
46
51
|
errorHandler: util.reject,
|
|
47
52
|
...options,
|
|
48
|
-
baseUrl: options?.baseUrl || ''
|
|
53
|
+
baseUrl: options?.baseUrl || '',
|
|
54
|
+
maxStackDepth: options?.maxStackDepth || DEFAULT_MAX_STACK_DEPTH
|
|
49
55
|
};
|
|
50
56
|
}
|
|
51
57
|
function setOptions(router, options) {
|
|
@@ -60,14 +66,43 @@ function getLocation({
|
|
|
60
66
|
state: state.state
|
|
61
67
|
};
|
|
62
68
|
}
|
|
63
|
-
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Restore the in-memory location stack from the bounded window in the
|
|
72
|
+
* current history entry state. Slots before the window become
|
|
73
|
+
* placeholders(`undefined`) so {@link initHistoryStack} can skip them
|
|
74
|
+
* and a POP onto them still falls back to a lazy refresh.
|
|
75
|
+
*/
|
|
76
|
+
function restoreLocationStack(history) {
|
|
77
|
+
const state = history.location.state || {};
|
|
64
78
|
const {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
79
|
+
locationStack,
|
|
80
|
+
base
|
|
81
|
+
} = state;
|
|
82
|
+
return locationStack?.length ? [...new Array(base || 0), ...locationStack] : [getLocation({
|
|
83
|
+
history
|
|
84
|
+
})];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Serialize the tail window of the in-memory stack, bounded by
|
|
89
|
+
* `maxStackDepth`, together with the absolute index of its first entry.
|
|
90
|
+
*/
|
|
91
|
+
function serializeStack(router) {
|
|
92
|
+
const {
|
|
93
|
+
locationStack,
|
|
94
|
+
maxStackDepth
|
|
95
|
+
} = router;
|
|
96
|
+
const windowed = locationStack.slice(-maxStackDepth);
|
|
97
|
+
return {
|
|
98
|
+
base: locationStack.length - windowed.length,
|
|
99
|
+
locationStack: windowed
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function getHistoryState(router) {
|
|
103
|
+
const state = router.history.location.state || {};
|
|
68
104
|
return {
|
|
69
|
-
index: state.index || 0
|
|
70
|
-
locationStack: state.locationStack || [getLocation(router)]
|
|
105
|
+
index: state.index || 0
|
|
71
106
|
};
|
|
72
107
|
}
|
|
73
108
|
function getCurrentView(router) {
|
|
@@ -189,8 +224,8 @@ function commit(router, resolvePromise, location) {
|
|
|
189
224
|
router.viewStack = [...router.viewStack.slice(0, nextIndex), resolvedView];
|
|
190
225
|
history.push(location, {
|
|
191
226
|
index: nextIndex,
|
|
192
|
-
|
|
193
|
-
|
|
227
|
+
state: location.state,
|
|
228
|
+
...serializeStack(router)
|
|
194
229
|
});
|
|
195
230
|
});
|
|
196
231
|
}
|
|
@@ -215,8 +250,8 @@ function commitReplace(router, resolvePromise, location) {
|
|
|
215
250
|
router.viewStack[index] = resolvedView;
|
|
216
251
|
history.replace(location, {
|
|
217
252
|
index,
|
|
218
|
-
|
|
219
|
-
|
|
253
|
+
state: location.state,
|
|
254
|
+
...serializeStack(router)
|
|
220
255
|
});
|
|
221
256
|
});
|
|
222
257
|
}
|
|
@@ -324,16 +359,21 @@ function cancel({
|
|
|
324
359
|
cancelAll();
|
|
325
360
|
onLoadingChange();
|
|
326
361
|
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Restore/warm up the view stack by re-resolving every reachable entry
|
|
365
|
+
* of the in-memory location stack. Call it after a refresh: in-window
|
|
366
|
+
* back/forward then switch views without new resolves.
|
|
367
|
+
*
|
|
368
|
+
* 恢复/预热内存栈中的可达条目(窗口内有 location 的槽位),刷新后调用
|
|
369
|
+
* 可让窗口内前进/后退零请求。
|
|
370
|
+
* @group Methods
|
|
371
|
+
* @category Router
|
|
372
|
+
* @param router router instance
|
|
373
|
+
*/
|
|
327
374
|
function initHistoryStack(router) {
|
|
328
|
-
|
|
329
|
-
history: history$1
|
|
330
|
-
} = router;
|
|
331
|
-
const {
|
|
332
|
-
locationStack
|
|
333
|
-
} = getHistoryState(router);
|
|
334
|
-
return Promise.all(locationStack.map(l => resolve(router, l))).then(views => {
|
|
375
|
+
return Promise.all(router.locationStack.map(location => location ? resolve(router, location) : Promise.resolve(null))).then(views => {
|
|
335
376
|
router.viewStack = views;
|
|
336
|
-
history$1.replace(history.createPath(history$1.location), history$1.location.state);
|
|
337
377
|
});
|
|
338
378
|
}
|
|
339
379
|
|
|
@@ -358,11 +398,18 @@ function listen(router, onViewChange) {
|
|
|
358
398
|
const index = state?.index || 0;
|
|
359
399
|
const view = router.viewStack[index];
|
|
360
400
|
onViewChange(view);
|
|
361
|
-
if (!view)
|
|
362
|
-
|
|
401
|
+
if (!view) {
|
|
402
|
+
// Lazy fallback for placeholder slots and legacy-shaped state:
|
|
403
|
+
// re-resolving the landed entry also re-serializes the window
|
|
404
|
+
// into it via the replace commit.
|
|
405
|
+
refresh(router);
|
|
406
|
+
} else if (action === 'POP') {
|
|
407
|
+
// Sync the current window into the landed entry so a later
|
|
408
|
+
// refresh("refresh → back → refresh again") still restores it.
|
|
363
409
|
history$1.replace(history.createPath(history$1.location), {
|
|
364
410
|
...state,
|
|
365
|
-
|
|
411
|
+
index,
|
|
412
|
+
...serializeStack(router)
|
|
366
413
|
});
|
|
367
414
|
}
|
|
368
415
|
});
|
|
@@ -374,7 +421,24 @@ function listen(router, onViewChange) {
|
|
|
374
421
|
}
|
|
375
422
|
|
|
376
423
|
/**
|
|
377
|
-
*
|
|
424
|
+
* Merge params of all matched levels. Params of deeper levels override
|
|
425
|
+
* the same keys of shallower ones.
|
|
426
|
+
* @group Methods
|
|
427
|
+
* @category Router
|
|
428
|
+
* @param matched matched route levels, see {@link match}
|
|
429
|
+
* @returns the merged params object
|
|
430
|
+
*/
|
|
431
|
+
function mergeMatchedParams(matched) {
|
|
432
|
+
return matched.reduce((params, {
|
|
433
|
+
params: levelParams
|
|
434
|
+
}) => ({
|
|
435
|
+
...params,
|
|
436
|
+
...levelParams
|
|
437
|
+
}), {});
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Get current route params from router. Merges params of all matched levels.
|
|
378
442
|
* @group Methods
|
|
379
443
|
* @category Router
|
|
380
444
|
* @param router router instance
|
|
@@ -386,7 +450,7 @@ function getParams(router) {
|
|
|
386
450
|
} = getHistoryState(router);
|
|
387
451
|
const matched = router.viewStack[index];
|
|
388
452
|
if (!matched || !matched.length) return {};
|
|
389
|
-
return matched
|
|
453
|
+
return mergeMatchedParams(matched);
|
|
390
454
|
}
|
|
391
455
|
|
|
392
456
|
exports.NativeRouterError = NativeRouterError;
|
|
@@ -405,6 +469,7 @@ exports.go = go;
|
|
|
405
469
|
exports.initHistoryStack = initHistoryStack;
|
|
406
470
|
exports.listen = listen;
|
|
407
471
|
exports.match = match;
|
|
472
|
+
exports.mergeMatchedParams = mergeMatchedParams;
|
|
408
473
|
exports.navigate = navigate;
|
|
409
474
|
exports.refresh = refresh;
|
|
410
475
|
exports.resolve = resolve;
|
package/dist/index.mjs
CHANGED
|
@@ -11,6 +11,8 @@ class NotFoundError extends NativeRouterError {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
const DEFAULT_MAX_STACK_DEPTH = 100;
|
|
15
|
+
|
|
14
16
|
/**
|
|
15
17
|
* Create a router instance.
|
|
16
18
|
* @group Methods
|
|
@@ -24,12 +26,15 @@ class NotFoundError extends NativeRouterError {
|
|
|
24
26
|
function create(routes, history, resolveView, options) {
|
|
25
27
|
const [currentGuard, cancelAll] = createCurrentGuard();
|
|
26
28
|
const {
|
|
27
|
-
index
|
|
28
|
-
locationStack
|
|
29
|
+
index
|
|
29
30
|
} = getHistoryState({
|
|
30
31
|
history: history
|
|
31
32
|
});
|
|
32
|
-
|
|
33
|
+
// Restore the session stack from the bounded window serialized in the
|
|
34
|
+
// current entry state; entries before the window become placeholders.
|
|
35
|
+
// Legacy index-only state(1.x) degrades to a single-entry stack.
|
|
36
|
+
const locationStack = restoreLocationStack(history);
|
|
37
|
+
const viewStack = new Array(Math.max(index + 1, locationStack.length)).fill(null);
|
|
33
38
|
if (options?.currentView) {
|
|
34
39
|
viewStack[index] = options.currentView;
|
|
35
40
|
}
|
|
@@ -43,7 +48,8 @@ function create(routes, history, resolveView, options) {
|
|
|
43
48
|
cancelAll,
|
|
44
49
|
errorHandler: reject,
|
|
45
50
|
...options,
|
|
46
|
-
baseUrl: options?.baseUrl || ''
|
|
51
|
+
baseUrl: options?.baseUrl || '',
|
|
52
|
+
maxStackDepth: options?.maxStackDepth || DEFAULT_MAX_STACK_DEPTH
|
|
47
53
|
};
|
|
48
54
|
}
|
|
49
55
|
function setOptions(router, options) {
|
|
@@ -58,14 +64,43 @@ function getLocation({
|
|
|
58
64
|
state: state.state
|
|
59
65
|
};
|
|
60
66
|
}
|
|
61
|
-
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Restore the in-memory location stack from the bounded window in the
|
|
70
|
+
* current history entry state. Slots before the window become
|
|
71
|
+
* placeholders(`undefined`) so {@link initHistoryStack} can skip them
|
|
72
|
+
* and a POP onto them still falls back to a lazy refresh.
|
|
73
|
+
*/
|
|
74
|
+
function restoreLocationStack(history) {
|
|
75
|
+
const state = history.location.state || {};
|
|
62
76
|
const {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
locationStack,
|
|
78
|
+
base
|
|
79
|
+
} = state;
|
|
80
|
+
return locationStack?.length ? [...new Array(base || 0), ...locationStack] : [getLocation({
|
|
81
|
+
history
|
|
82
|
+
})];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Serialize the tail window of the in-memory stack, bounded by
|
|
87
|
+
* `maxStackDepth`, together with the absolute index of its first entry.
|
|
88
|
+
*/
|
|
89
|
+
function serializeStack(router) {
|
|
90
|
+
const {
|
|
91
|
+
locationStack,
|
|
92
|
+
maxStackDepth
|
|
93
|
+
} = router;
|
|
94
|
+
const windowed = locationStack.slice(-maxStackDepth);
|
|
95
|
+
return {
|
|
96
|
+
base: locationStack.length - windowed.length,
|
|
97
|
+
locationStack: windowed
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function getHistoryState(router) {
|
|
101
|
+
const state = router.history.location.state || {};
|
|
66
102
|
return {
|
|
67
|
-
index: state.index || 0
|
|
68
|
-
locationStack: state.locationStack || [getLocation(router)]
|
|
103
|
+
index: state.index || 0
|
|
69
104
|
};
|
|
70
105
|
}
|
|
71
106
|
function getCurrentView(router) {
|
|
@@ -187,8 +222,8 @@ function commit(router, resolvePromise, location) {
|
|
|
187
222
|
router.viewStack = [...router.viewStack.slice(0, nextIndex), resolvedView];
|
|
188
223
|
history.push(location, {
|
|
189
224
|
index: nextIndex,
|
|
190
|
-
|
|
191
|
-
|
|
225
|
+
state: location.state,
|
|
226
|
+
...serializeStack(router)
|
|
192
227
|
});
|
|
193
228
|
});
|
|
194
229
|
}
|
|
@@ -213,8 +248,8 @@ function commitReplace(router, resolvePromise, location) {
|
|
|
213
248
|
router.viewStack[index] = resolvedView;
|
|
214
249
|
history.replace(location, {
|
|
215
250
|
index,
|
|
216
|
-
|
|
217
|
-
|
|
251
|
+
state: location.state,
|
|
252
|
+
...serializeStack(router)
|
|
218
253
|
});
|
|
219
254
|
});
|
|
220
255
|
}
|
|
@@ -322,16 +357,21 @@ function cancel({
|
|
|
322
357
|
cancelAll();
|
|
323
358
|
onLoadingChange();
|
|
324
359
|
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Restore/warm up the view stack by re-resolving every reachable entry
|
|
363
|
+
* of the in-memory location stack. Call it after a refresh: in-window
|
|
364
|
+
* back/forward then switch views without new resolves.
|
|
365
|
+
*
|
|
366
|
+
* 恢复/预热内存栈中的可达条目(窗口内有 location 的槽位),刷新后调用
|
|
367
|
+
* 可让窗口内前进/后退零请求。
|
|
368
|
+
* @group Methods
|
|
369
|
+
* @category Router
|
|
370
|
+
* @param router router instance
|
|
371
|
+
*/
|
|
325
372
|
function initHistoryStack(router) {
|
|
326
|
-
|
|
327
|
-
history
|
|
328
|
-
} = router;
|
|
329
|
-
const {
|
|
330
|
-
locationStack
|
|
331
|
-
} = getHistoryState(router);
|
|
332
|
-
return Promise.all(locationStack.map(l => resolve(router, l))).then(views => {
|
|
373
|
+
return Promise.all(router.locationStack.map(location => location ? resolve(router, location) : Promise.resolve(null))).then(views => {
|
|
333
374
|
router.viewStack = views;
|
|
334
|
-
history.replace(createPath(history.location), history.location.state);
|
|
335
375
|
});
|
|
336
376
|
}
|
|
337
377
|
|
|
@@ -356,11 +396,18 @@ function listen(router, onViewChange) {
|
|
|
356
396
|
const index = state?.index || 0;
|
|
357
397
|
const view = router.viewStack[index];
|
|
358
398
|
onViewChange(view);
|
|
359
|
-
if (!view)
|
|
360
|
-
|
|
399
|
+
if (!view) {
|
|
400
|
+
// Lazy fallback for placeholder slots and legacy-shaped state:
|
|
401
|
+
// re-resolving the landed entry also re-serializes the window
|
|
402
|
+
// into it via the replace commit.
|
|
403
|
+
refresh(router);
|
|
404
|
+
} else if (action === 'POP') {
|
|
405
|
+
// Sync the current window into the landed entry so a later
|
|
406
|
+
// refresh("refresh → back → refresh again") still restores it.
|
|
361
407
|
history.replace(createPath(history.location), {
|
|
362
408
|
...state,
|
|
363
|
-
|
|
409
|
+
index,
|
|
410
|
+
...serializeStack(router)
|
|
364
411
|
});
|
|
365
412
|
}
|
|
366
413
|
});
|
|
@@ -372,7 +419,24 @@ function listen(router, onViewChange) {
|
|
|
372
419
|
}
|
|
373
420
|
|
|
374
421
|
/**
|
|
375
|
-
*
|
|
422
|
+
* Merge params of all matched levels. Params of deeper levels override
|
|
423
|
+
* the same keys of shallower ones.
|
|
424
|
+
* @group Methods
|
|
425
|
+
* @category Router
|
|
426
|
+
* @param matched matched route levels, see {@link match}
|
|
427
|
+
* @returns the merged params object
|
|
428
|
+
*/
|
|
429
|
+
function mergeMatchedParams(matched) {
|
|
430
|
+
return matched.reduce((params, {
|
|
431
|
+
params: levelParams
|
|
432
|
+
}) => ({
|
|
433
|
+
...params,
|
|
434
|
+
...levelParams
|
|
435
|
+
}), {});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Get current route params from router. Merges params of all matched levels.
|
|
376
440
|
* @group Methods
|
|
377
441
|
* @category Router
|
|
378
442
|
* @param router router instance
|
|
@@ -384,7 +448,7 @@ function getParams(router) {
|
|
|
384
448
|
} = getHistoryState(router);
|
|
385
449
|
const matched = router.viewStack[index];
|
|
386
450
|
if (!matched || !matched.length) return {};
|
|
387
|
-
return matched
|
|
451
|
+
return mergeMatchedParams(matched);
|
|
388
452
|
}
|
|
389
453
|
|
|
390
|
-
export { NativeRouterError, NotFoundError, back, cancel, commit, commitReplace, create, createHref, forward, getCurrentView, getLocation, getParams, go, initHistoryStack, listen, match, navigate, refresh, resolve, resolveTo, setOptions, toLocation };
|
|
454
|
+
export { NativeRouterError, NotFoundError, back, cancel, commit, commitReplace, create, createHref, forward, getCurrentView, getLocation, getParams, go, initHistoryStack, listen, match, mergeMatchedParams, navigate, refresh, resolve, resolveTo, setOptions, toLocation };
|
package/dist/types/router.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare function setOptions<R extends BaseRoute = BaseRoute, V = any>(rou
|
|
|
23
23
|
currentGuard<T>(promise: Promise<T>): Promise<T>;
|
|
24
24
|
cancelAll(): void;
|
|
25
25
|
resolving?: Location;
|
|
26
|
-
} & Required<Pick<Options<V>, "baseUrl">> & Omit<Options<V>, "baseUrl"> & Omit<Options<V>, "currentView">;
|
|
26
|
+
} & Required<Pick<Options<V>, "baseUrl" | "maxStackDepth">> & Omit<Options<V>, "baseUrl" | "maxStackDepth"> & Omit<Options<V>, "currentView">;
|
|
27
27
|
export declare function getLocation({ history }: Pick<RouterInstance<any>, 'history'>): {
|
|
28
28
|
state: any;
|
|
29
29
|
key: import("history").Key;
|
|
@@ -142,6 +142,17 @@ export declare function createHref<R extends BaseRoute = BaseRoute, V = any>({ b
|
|
|
142
142
|
* @param router router instance
|
|
143
143
|
*/
|
|
144
144
|
export declare function cancel<R extends BaseRoute = BaseRoute, V = any>({ cancelAll, onLoadingChange }: RouterInstance<R, V>): void;
|
|
145
|
+
/**
|
|
146
|
+
* Restore/warm up the view stack by re-resolving every reachable entry
|
|
147
|
+
* of the in-memory location stack. Call it after a refresh: in-window
|
|
148
|
+
* back/forward then switch views without new resolves.
|
|
149
|
+
*
|
|
150
|
+
* 恢复/预热内存栈中的可达条目(窗口内有 location 的槽位),刷新后调用
|
|
151
|
+
* 可让窗口内前进/后退零请求。
|
|
152
|
+
* @group Methods
|
|
153
|
+
* @category Router
|
|
154
|
+
* @param router router instance
|
|
155
|
+
*/
|
|
145
156
|
export declare function initHistoryStack<R extends BaseRoute = BaseRoute, V = any>(router: RouterInstance<R, V>): Promise<void>;
|
|
146
157
|
/**
|
|
147
158
|
* Listen the history change.
|
|
@@ -153,7 +164,16 @@ export declare function initHistoryStack<R extends BaseRoute = BaseRoute, V = an
|
|
|
153
164
|
*/
|
|
154
165
|
export declare function listen<R extends BaseRoute = BaseRoute, V = any>(router: RouterInstance<R, V>, onViewChange: (v: V) => void): () => void;
|
|
155
166
|
/**
|
|
156
|
-
*
|
|
167
|
+
* Merge params of all matched levels. Params of deeper levels override
|
|
168
|
+
* the same keys of shallower ones.
|
|
169
|
+
* @group Methods
|
|
170
|
+
* @category Router
|
|
171
|
+
* @param matched matched route levels, see {@link match}
|
|
172
|
+
* @returns the merged params object
|
|
173
|
+
*/
|
|
174
|
+
export declare function mergeMatchedParams<R extends BaseRoute = BaseRoute>(matched: Matched<R>[]): Record<string, string>;
|
|
175
|
+
/**
|
|
176
|
+
* Get current route params from router. Merges params of all matched levels.
|
|
157
177
|
* @group Methods
|
|
158
178
|
* @category Router
|
|
159
179
|
* @param router router instance
|
package/dist/types/types.d.ts
CHANGED
|
@@ -4,9 +4,21 @@ export type Location<T = any> = HPath & {
|
|
|
4
4
|
state?: T;
|
|
5
5
|
};
|
|
6
6
|
export type HistoryState = {
|
|
7
|
-
locationStack: Location[];
|
|
8
7
|
index: number;
|
|
9
8
|
state?: any;
|
|
9
|
+
/**
|
|
10
|
+
* Bounded window(tail entries) of the session location stack,
|
|
11
|
+
* serialized into the history entry so {@link create} can restore it
|
|
12
|
+
* after a refresh. Its length never exceeds `maxStackDepth`.
|
|
13
|
+
* 有界窗口:会话 locationStack 的尾部条目,刷新后据此恢复内存栈。
|
|
14
|
+
*/
|
|
15
|
+
locationStack?: Location[];
|
|
16
|
+
/**
|
|
17
|
+
* Absolute stack index of `locationStack[0]`; omitted(or 0) means the
|
|
18
|
+
* window starts at the session root.
|
|
19
|
+
* locationStack[0] 对应的绝对 index,省略时为 0。
|
|
20
|
+
*/
|
|
21
|
+
base?: number;
|
|
10
22
|
};
|
|
11
23
|
export type WrappedLocation = Location<HistoryState>;
|
|
12
24
|
export type Awaitable<T> = T | Promise<T>;
|
|
@@ -27,6 +39,22 @@ export type Options<V> = {
|
|
|
27
39
|
currentView?: V;
|
|
28
40
|
errorHandler?(e: Error): V | Promise<V>;
|
|
29
41
|
onLoadingChange?(status?: 'pending' | 'resolved' | 'rejected'): void;
|
|
42
|
+
/**
|
|
43
|
+
* Max number of locations serialized into the history state window,
|
|
44
|
+
* see {@link HistoryState.locationStack}.
|
|
45
|
+
*
|
|
46
|
+
* Defaults to 100, at or above the per-tab history caps of mainstream
|
|
47
|
+
* browsers(Chromium/Gecko ~50, WebKit ~100). The window boundary can
|
|
48
|
+
* therefore only appear after the browser itself has already evicted
|
|
49
|
+
* entries: anything outside the window is unreachable to the user, so
|
|
50
|
+
* a bounded window is observationally equivalent to full serialization.
|
|
51
|
+
*
|
|
52
|
+
* 序列化进 history state 的栈窗口上限,默认 100,不低于主流浏览器
|
|
53
|
+
* 单标签历史上限(Chromium/Gecko 约 50、WebKit 约 100)。窗口边界只会在
|
|
54
|
+
* 浏览器自身裁剪历史之后才可能出现,用户不可达窗口外条目,行为与
|
|
55
|
+
* 全量序列化无可观察差异。
|
|
56
|
+
*/
|
|
57
|
+
maxStackDepth?: number;
|
|
30
58
|
};
|
|
31
59
|
export type RequiredOf<T, K extends keyof T> = Required<Pick<T, K>> & Omit<T, K>;
|
|
32
60
|
export type RouterInstance<R extends BaseRoute, V = any> = {
|
|
@@ -36,9 +64,15 @@ export type RouterInstance<R extends BaseRoute, V = any> = {
|
|
|
36
64
|
location: WrappedLocation;
|
|
37
65
|
};
|
|
38
66
|
viewStack: V[];
|
|
67
|
+
/**
|
|
68
|
+
* In-memory location stack of the current session. On creation it is
|
|
69
|
+
* restored from the bounded window serialized in the history state,
|
|
70
|
+
* so in-window back/forward survive a refresh.
|
|
71
|
+
* 会话内存栈;create 时从 history state 的有界窗口恢复。
|
|
72
|
+
*/
|
|
39
73
|
locationStack: Location[];
|
|
40
74
|
resolveView: ResolveView<R, V>;
|
|
41
75
|
currentGuard<T>(promise: Promise<T>): Promise<T>;
|
|
42
76
|
cancelAll(): void;
|
|
43
77
|
resolving?: Location;
|
|
44
|
-
} & RequiredOf<Options<V>, 'baseUrl'>;
|
|
78
|
+
} & RequiredOf<Options<V>, 'baseUrl' | 'maxStackDepth'>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@native-router/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": {
|
|
6
6
|
"types": "./dist/types/index.d.ts",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"dist"
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
|
-
"start": "
|
|
30
|
+
"start": "vitest",
|
|
31
31
|
"build": "rm -rf dist && rollup -c && tsc -p tsconfig.production.json && tsc-alias -p tsconfig.production.json",
|
|
32
32
|
"commit": "lint-staged && git-cz -n",
|
|
33
|
-
"coverage": "
|
|
33
|
+
"coverage": "vitest run --coverage",
|
|
34
34
|
"lint": "eslint --fix src test *.js --ext .js,.jsx,.ts,.tsx",
|
|
35
35
|
"doc:gen": "typedoc",
|
|
36
36
|
"deploy": "npm run doc:gen && gh-pages -d dist",
|
|
37
|
-
"test": "
|
|
37
|
+
"test": "vitest run"
|
|
38
38
|
},
|
|
39
39
|
"repository": {
|
|
40
40
|
"type": "git",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"homepage": "https://github.com/native-router/core",
|
|
50
50
|
"engines": {
|
|
51
|
-
"node": ">=
|
|
51
|
+
"node": ">=18"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"history": "^5.3.0",
|
|
@@ -58,22 +58,17 @@
|
|
|
58
58
|
"@babel/core": "^7.22.9",
|
|
59
59
|
"@babel/preset-env": "^7.22.9",
|
|
60
60
|
"@babel/preset-typescript": "^7.22.5",
|
|
61
|
-
"@babel/register": "^7.22.5",
|
|
62
|
-
"@linaria/babel-preset": "^4.5.4",
|
|
63
|
-
"@linaria/core": "^4.5.4",
|
|
64
61
|
"@rollup/plugin-babel": "^6.0.3",
|
|
65
62
|
"@rollup/plugin-commonjs": "^25.0.4",
|
|
66
63
|
"@rollup/plugin-node-resolve": "^15.1.0",
|
|
67
64
|
"@rollup/plugin-replace": "^5.0.2",
|
|
68
|
-
"@types/mocha": "^10.0.1",
|
|
69
65
|
"@types/node": "^20.4.5",
|
|
70
66
|
"@types/sinon": "^10.0.15",
|
|
71
67
|
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
|
72
68
|
"@typescript-eslint/parser": "^6.2.0",
|
|
73
|
-
"
|
|
69
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
74
70
|
"commitizen": "^4.3.0",
|
|
75
71
|
"core-js": "^3.31.1",
|
|
76
|
-
"coveralls": "^3.1.1",
|
|
77
72
|
"cross-env": "^7.0.3",
|
|
78
73
|
"eslint": "^8.50.0",
|
|
79
74
|
"eslint-config-airbnb": "^19.0.4",
|
|
@@ -83,17 +78,12 @@
|
|
|
83
78
|
"eslint-plugin-compat": "^4.1.4",
|
|
84
79
|
"eslint-plugin-import": "^2.27.5",
|
|
85
80
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
86
|
-
"eslint-plugin-mocha": "^10.1.0",
|
|
87
81
|
"eslint-plugin-prettier": "^5.0.0",
|
|
88
82
|
"eslint-plugin-react": "^7.33.0",
|
|
89
83
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
90
84
|
"gh-pages": "^5.0.0",
|
|
91
|
-
"global-jsdom": "^9.0.1",
|
|
92
85
|
"husky": "^8.0.3",
|
|
93
|
-
"jsdom": "^22.1.0",
|
|
94
86
|
"lint-staged": "^13.2.3",
|
|
95
|
-
"mocha": "^10.2.0",
|
|
96
|
-
"nyc": "^15.1.0",
|
|
97
87
|
"prettier": "^3.0.0",
|
|
98
88
|
"rollup": "^3.28.0",
|
|
99
89
|
"should": "^13.2.3",
|
|
@@ -105,6 +95,7 @@
|
|
|
105
95
|
"typedoc-plugin-mark-react-functional-components": "^0.2.2",
|
|
106
96
|
"typedoc-plugin-missing-exports": "^2.0.0",
|
|
107
97
|
"typescript": "^5.9.3",
|
|
98
|
+
"vitest": "^4.0.18",
|
|
108
99
|
"semantic-release": "^25.0.3"
|
|
109
100
|
}
|
|
110
101
|
}
|