@thi.ng/router 4.0.6 → 4.0.8
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/CHANGELOG.md +7 -1
- package/README.md +3 -3
- package/api.d.ts +2 -2
- package/html.d.ts +1 -1
- package/package.json +6 -6
- package/router.d.ts +5 -5
- package/trie.d.ts +3 -2
- package/basic.d.ts +0 -46
- package/basic.js +0 -233
- package/history.d.ts +0 -31
- package/history.js +0 -91
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-04-
|
|
3
|
+
- **Last updated**: 2024-04-20T14:42:45Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,12 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
### [4.0.8](https://github.com/thi-ng/umbrella/tree/@thi.ng/router@4.0.8) (2024-04-20)
|
|
13
|
+
|
|
14
|
+
#### ♻️ Refactoring
|
|
15
|
+
|
|
16
|
+
- update type usage ([835dfb0](https://github.com/thi-ng/umbrella/commit/835dfb0))
|
|
17
|
+
|
|
12
18
|
### [4.0.1](https://github.com/thi-ng/umbrella/tree/@thi.ng/router@4.0.1) (2024-03-13)
|
|
13
19
|
|
|
14
20
|
#### ♻️ Refactoring
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://mastodon.thi.ng/@toxi)
|
|
8
8
|
|
|
9
9
|
> [!NOTE]
|
|
10
|
-
> This is one of
|
|
10
|
+
> This is one of 192 standalone projects, maintained as part
|
|
11
11
|
> of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
|
|
12
12
|
> and anti-framework.
|
|
13
13
|
>
|
|
@@ -66,10 +66,10 @@ import * as rou from "@thi.ng/router";
|
|
|
66
66
|
Browser ESM import:
|
|
67
67
|
|
|
68
68
|
```html
|
|
69
|
-
<script type="module" src="https://
|
|
69
|
+
<script type="module" src="https://esm.run/@thi.ng/router"></script>
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
[
|
|
72
|
+
[JSDelivr documentation](https://www.jsdelivr.com/)
|
|
73
73
|
|
|
74
74
|
Package sizes (brotli'd, pre-treeshake): ESM: 1.94 KB
|
|
75
75
|
|
package/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EVENT_ALL, Fn, IObjectOf } from "@thi.ng/api";
|
|
1
|
+
import type { EVENT_ALL, Fn, IObjectOf, Maybe } from "@thi.ng/api";
|
|
2
2
|
/**
|
|
3
3
|
* A validation function for to-be authenticated routes.
|
|
4
4
|
*
|
|
@@ -13,7 +13,7 @@ import type { EVENT_ALL, Fn, IObjectOf } from "@thi.ng/api";
|
|
|
13
13
|
* The optional `ctx` is an arbitrary user provided context value given to
|
|
14
14
|
* {@link Router.route} (e.g. the original request object).
|
|
15
15
|
*/
|
|
16
|
-
export type RouteAuthenticator<T = any> = (match: RouteMatch, route: AugmentedRoute, ctx?: T) => RouteMatch
|
|
16
|
+
export type RouteAuthenticator<T = any> = (match: RouteMatch, route: AugmentedRoute, ctx?: T) => Maybe<RouteMatch>;
|
|
17
17
|
/**
|
|
18
18
|
* Route validator subspecs are optional and used to coerce and/or validate
|
|
19
19
|
* individual route parameters.
|
package/html.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare class HTMLRouter<T = any> extends Router<T> {
|
|
|
22
22
|
* @param ctx -
|
|
23
23
|
* @param pushState -
|
|
24
24
|
*/
|
|
25
|
-
route(src: string, ctx?: T, pushState?: boolean): import("./api.js").RouteMatch
|
|
25
|
+
route(src: string, ctx?: T, pushState?: boolean): import("@thi.ng/api").Maybe<import("./api.js").RouteMatch>;
|
|
26
26
|
routeTo(route: string, ctx?: T): void;
|
|
27
27
|
protected handlePopChange(): Fn<PopStateEvent, void>;
|
|
28
28
|
protected handleHashChange(): EventListener;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/router",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.8",
|
|
4
4
|
"description": "Generic trie-based router with support for wildcards, route param validation/coercion, auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@thi.ng/api": "^8.
|
|
40
|
-
"@thi.ng/checks": "^3.6.
|
|
41
|
-
"@thi.ng/equiv": "^2.1.
|
|
42
|
-
"@thi.ng/errors": "^2.5.
|
|
39
|
+
"@thi.ng/api": "^8.11.0",
|
|
40
|
+
"@thi.ng/checks": "^3.6.2",
|
|
41
|
+
"@thi.ng/equiv": "^2.1.56",
|
|
42
|
+
"@thi.ng/errors": "^2.5.5",
|
|
43
43
|
"tslib": "^2.6.2"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
@@ -98,5 +98,5 @@
|
|
|
98
98
|
],
|
|
99
99
|
"year": 2014
|
|
100
100
|
},
|
|
101
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "8339d05ecc857e529c7325a9839c0063b89e728d\n"
|
|
102
102
|
}
|
package/router.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { Event, INotify, IObjectOf, Listener, SomeRequired } from "@thi.ng/api";
|
|
1
|
+
import type { Event, INotify, IObjectOf, Listener, Maybe, SomeRequired } from "@thi.ng/api";
|
|
2
2
|
import { type AugmentedRoute, type Route, type RouteMatch, type RouteParamValidator, type RouterEventType, type RouterOpts } from "./api.js";
|
|
3
3
|
import { Trie } from "./trie.js";
|
|
4
4
|
export declare class Router<T = any> implements INotify<RouterEventType> {
|
|
5
5
|
opts: RouterOpts<T>;
|
|
6
|
-
current: RouteMatch
|
|
6
|
+
current: Maybe<RouteMatch>;
|
|
7
7
|
protected index: Record<string, AugmentedRoute>;
|
|
8
8
|
protected routes: Trie<AugmentedRoute>;
|
|
9
9
|
constructor(config: RouterOpts<T>);
|
|
@@ -25,7 +25,7 @@ export declare class Router<T = any> implements INotify<RouterEventType> {
|
|
|
25
25
|
* @param src - route path to match
|
|
26
26
|
* @param ctx - arbitrary user context
|
|
27
27
|
*/
|
|
28
|
-
route(src: string, ctx?: T): RouteMatch
|
|
28
|
+
route(src: string, ctx?: T): Maybe<RouteMatch>;
|
|
29
29
|
/**
|
|
30
30
|
* Returns a formatted version of given {@link RouteMatch}, incl. any
|
|
31
31
|
* params, or alternatively a registered route ID (and optional route
|
|
@@ -37,9 +37,9 @@ export declare class Router<T = any> implements INotify<RouterEventType> {
|
|
|
37
37
|
*/
|
|
38
38
|
format(id: string, params?: any, rest?: string[]): string;
|
|
39
39
|
format(match: SomeRequired<RouteMatch, "id">): string;
|
|
40
|
-
routeForID(id: string): AugmentedRoute
|
|
40
|
+
routeForID(id: string): Maybe<AugmentedRoute>;
|
|
41
41
|
protected augmentRoute(route: Route): AugmentedRoute;
|
|
42
|
-
protected matchRoutes(src: string, ctx?: T): RouteMatch
|
|
42
|
+
protected matchRoutes(src: string, ctx?: T): Maybe<RouteMatch>;
|
|
43
43
|
protected validateRouteParams(params: any, validators: IObjectOf<Partial<RouteParamValidator>>): boolean;
|
|
44
44
|
protected handleRouteFailure(): boolean;
|
|
45
45
|
}
|
package/trie.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Maybe } from "@thi.ng/api";
|
|
1
2
|
/**
|
|
2
3
|
* Trie data structure for storing & matching route patterns with wildcards.
|
|
3
4
|
*
|
|
@@ -47,8 +48,8 @@
|
|
|
47
48
|
export declare class Trie<T> {
|
|
48
49
|
n: Record<string, Trie<T>>;
|
|
49
50
|
v?: T;
|
|
50
|
-
constructor(key?: string[], v?: T
|
|
51
|
+
constructor(key?: string[], v?: Maybe<T>, i?: number);
|
|
51
52
|
set(key: string[], v: T, i?: number): void;
|
|
52
|
-
get(key: string[], i?: number): T
|
|
53
|
+
get(key: string[], i?: number): Maybe<T>;
|
|
53
54
|
}
|
|
54
55
|
//# sourceMappingURL=trie.d.ts.map
|
package/basic.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { Event, INotify, IObjectOf, Listener, SomeRequired } from "@thi.ng/api";
|
|
2
|
-
import { type AugmentedRoute, type Route, type RouteMatch, type RouteParamValidator, type RouterEventType, type RouterOpts } from "./api.js";
|
|
3
|
-
import { Trie } from "./trie.js";
|
|
4
|
-
export declare class BasicRouter<T = any> implements INotify<RouterEventType> {
|
|
5
|
-
opts: RouterOpts<T>;
|
|
6
|
-
current: RouteMatch | undefined;
|
|
7
|
-
protected index: Record<string, AugmentedRoute>;
|
|
8
|
-
protected routes: Trie<AugmentedRoute>;
|
|
9
|
-
constructor(config: RouterOpts<T>);
|
|
10
|
-
addListener(id: RouterEventType, fn: Listener<RouterEventType>, scope?: any): boolean;
|
|
11
|
-
removeListener(id: RouterEventType, fn: Listener<RouterEventType>, scope?: any): boolean;
|
|
12
|
-
notify(event: Event<RouterEventType>): boolean;
|
|
13
|
-
start(): void;
|
|
14
|
-
addRoutes(routes: Route[]): void;
|
|
15
|
-
/**
|
|
16
|
-
* Main router function. Attempts to match given input string against all
|
|
17
|
-
* configured routes. Before returning, triggers {@link EVENT_ROUTE_CHANGED}
|
|
18
|
-
* with return value as well. If none of the routes matches, emits
|
|
19
|
-
* {@link EVENT_ROUTE_FAILED} and then falls back to configured default
|
|
20
|
-
* route.
|
|
21
|
-
*
|
|
22
|
-
* @remarks
|
|
23
|
-
* See {@link RouteAuthenticator} for details about `ctx` handling.
|
|
24
|
-
*
|
|
25
|
-
* @param src - route path to match
|
|
26
|
-
* @param ctx - arbitrary user context
|
|
27
|
-
*/
|
|
28
|
-
route(src: string, ctx?: T): RouteMatch | undefined;
|
|
29
|
-
/**
|
|
30
|
-
* Returns a formatted version of given {@link RouteMatch}, incl. any
|
|
31
|
-
* params, or alternatively a registered route ID (and optional route
|
|
32
|
-
* params). Throws an error if an invalid route `id` is provided.
|
|
33
|
-
*
|
|
34
|
-
* @param id -
|
|
35
|
-
* @param params -
|
|
36
|
-
* @param rest -
|
|
37
|
-
*/
|
|
38
|
-
format(id: string, params?: any, rest?: string[]): string;
|
|
39
|
-
format(match: SomeRequired<RouteMatch, "id">): string;
|
|
40
|
-
routeForID(id: string): AugmentedRoute | undefined;
|
|
41
|
-
protected augmentRoute(route: Route): AugmentedRoute;
|
|
42
|
-
protected matchRoutes(src: string, ctx?: T): RouteMatch | undefined;
|
|
43
|
-
protected validateRouteParams(params: any, validators: IObjectOf<Partial<RouteParamValidator>>): boolean;
|
|
44
|
-
protected handleRouteFailure(): boolean;
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=basic.d.ts.map
|
package/basic.js
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
-
if (decorator = decorators[i])
|
|
7
|
-
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
-
if (kind && result)
|
|
9
|
-
__defProp(target, key, result);
|
|
10
|
-
return result;
|
|
11
|
-
};
|
|
12
|
-
import { INotifyMixin } from "@thi.ng/api/mixins/inotify";
|
|
13
|
-
import { isString } from "@thi.ng/checks/is-string";
|
|
14
|
-
import { equiv } from "@thi.ng/equiv";
|
|
15
|
-
import { assert } from "@thi.ng/errors/assert";
|
|
16
|
-
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
|
|
17
|
-
import { illegalArity } from "@thi.ng/errors/illegal-arity";
|
|
18
|
-
import { illegalState } from "@thi.ng/errors/illegal-state";
|
|
19
|
-
import {
|
|
20
|
-
EVENT_ROUTE_CHANGED,
|
|
21
|
-
EVENT_ROUTE_FAILED
|
|
22
|
-
} from "./api.js";
|
|
23
|
-
import { Trie } from "./trie.js";
|
|
24
|
-
let BasicRouter = class {
|
|
25
|
-
opts;
|
|
26
|
-
current;
|
|
27
|
-
index = {};
|
|
28
|
-
routes = new Trie();
|
|
29
|
-
constructor(config) {
|
|
30
|
-
this.opts = {
|
|
31
|
-
authenticator: (match) => match,
|
|
32
|
-
prefix: "/",
|
|
33
|
-
separator: "/",
|
|
34
|
-
trim: true,
|
|
35
|
-
...config
|
|
36
|
-
};
|
|
37
|
-
this.addRoutes(this.opts.routes);
|
|
38
|
-
assert(
|
|
39
|
-
this.routeForID(this.opts.default) !== void 0,
|
|
40
|
-
`missing config for default route: '${this.opts.default}'`
|
|
41
|
-
);
|
|
42
|
-
if (config.initial) {
|
|
43
|
-
const route = this.routeForID(config.initial);
|
|
44
|
-
assert(
|
|
45
|
-
route !== void 0,
|
|
46
|
-
`missing config for initial route: ${this.opts.initial}`
|
|
47
|
-
);
|
|
48
|
-
assert(!route.params, "initial route MUST not be parametric");
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// @ts-ignore: arguments
|
|
52
|
-
// prettier-ignore
|
|
53
|
-
addListener(id, fn, scope) {
|
|
54
|
-
}
|
|
55
|
-
// @ts-ignore: arguments
|
|
56
|
-
// prettier-ignore
|
|
57
|
-
removeListener(id, fn, scope) {
|
|
58
|
-
}
|
|
59
|
-
// @ts-ignore: arguments
|
|
60
|
-
notify(event) {
|
|
61
|
-
}
|
|
62
|
-
start() {
|
|
63
|
-
if (this.opts.initial) {
|
|
64
|
-
const route = this.routeForID(this.opts.initial);
|
|
65
|
-
this.current = { id: route.id, params: {} };
|
|
66
|
-
this.notify({ id: EVENT_ROUTE_CHANGED, value: this.current });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
addRoutes(routes) {
|
|
70
|
-
for (let r of routes) {
|
|
71
|
-
try {
|
|
72
|
-
const route = this.augmentRoute(r);
|
|
73
|
-
this.routes.set(route.match, route);
|
|
74
|
-
this.index[route.id] = route;
|
|
75
|
-
} catch (e) {
|
|
76
|
-
illegalArgs(
|
|
77
|
-
`error in route "${r.id}": ${e.origMessage}`
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Main router function. Attempts to match given input string against all
|
|
84
|
-
* configured routes. Before returning, triggers {@link EVENT_ROUTE_CHANGED}
|
|
85
|
-
* with return value as well. If none of the routes matches, emits
|
|
86
|
-
* {@link EVENT_ROUTE_FAILED} and then falls back to configured default
|
|
87
|
-
* route.
|
|
88
|
-
*
|
|
89
|
-
* @remarks
|
|
90
|
-
* See {@link RouteAuthenticator} for details about `ctx` handling.
|
|
91
|
-
*
|
|
92
|
-
* @param src - route path to match
|
|
93
|
-
* @param ctx - arbitrary user context
|
|
94
|
-
*/
|
|
95
|
-
route(src, ctx) {
|
|
96
|
-
if (this.opts.trim && src.charAt(src.length - 1) === this.opts.separator) {
|
|
97
|
-
src = src.substring(0, src.length - 1);
|
|
98
|
-
}
|
|
99
|
-
src = src.substring(this.opts.prefix.length);
|
|
100
|
-
let match = this.matchRoutes(src, ctx);
|
|
101
|
-
if (!match) {
|
|
102
|
-
this.notify({ id: EVENT_ROUTE_FAILED, value: src });
|
|
103
|
-
if (!this.handleRouteFailure()) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
const route = this.routeForID(this.opts.default);
|
|
107
|
-
match = { id: route.id, redirect: true };
|
|
108
|
-
}
|
|
109
|
-
if (!equiv(match, this.current)) {
|
|
110
|
-
this.current = match;
|
|
111
|
-
this.notify({ id: EVENT_ROUTE_CHANGED, value: match });
|
|
112
|
-
}
|
|
113
|
-
return match;
|
|
114
|
-
}
|
|
115
|
-
format(...args) {
|
|
116
|
-
let [id, params, rest] = args;
|
|
117
|
-
let match;
|
|
118
|
-
switch (args.length) {
|
|
119
|
-
case 3:
|
|
120
|
-
match = { id, params, rest };
|
|
121
|
-
break;
|
|
122
|
-
case 2:
|
|
123
|
-
match = { id, params };
|
|
124
|
-
break;
|
|
125
|
-
case 1:
|
|
126
|
-
match = isString(id) ? { id } : id;
|
|
127
|
-
break;
|
|
128
|
-
default:
|
|
129
|
-
illegalArity(args.length);
|
|
130
|
-
}
|
|
131
|
-
const route = this.routeForID(match.id);
|
|
132
|
-
if (route) {
|
|
133
|
-
const params2 = match.params;
|
|
134
|
-
let parts = route.match.map((x) => {
|
|
135
|
-
if (isRouteParam(x)) {
|
|
136
|
-
const id2 = x.substring(1);
|
|
137
|
-
const p = params2?.[id2];
|
|
138
|
-
if (p == null) {
|
|
139
|
-
illegalArgs(`missing value for param '${id2}'`);
|
|
140
|
-
}
|
|
141
|
-
return p;
|
|
142
|
-
}
|
|
143
|
-
return x;
|
|
144
|
-
});
|
|
145
|
-
if (route.rest >= 0)
|
|
146
|
-
parts = parts.slice(0, route.rest).concat(match.rest || []);
|
|
147
|
-
return this.opts.prefix + parts.join(this.opts.separator);
|
|
148
|
-
} else {
|
|
149
|
-
illegalArgs(`invalid route ID: ${match.id}`);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
routeForID(id) {
|
|
153
|
-
return this.index[id];
|
|
154
|
-
}
|
|
155
|
-
augmentRoute(route) {
|
|
156
|
-
const match = isString(route.match) ? route.match.split(this.opts.separator).filter((x) => !!x) : route.match;
|
|
157
|
-
const existing = this.routes.get(match);
|
|
158
|
-
if (existing) {
|
|
159
|
-
illegalArgs(
|
|
160
|
-
`duplicate route: ${match} (id: ${route.id}, conflicts with: ${existing.id})`
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
let hasParams = false;
|
|
164
|
-
const params = match.reduce((acc, x, i) => {
|
|
165
|
-
if (isRouteParam(x)) {
|
|
166
|
-
hasParams = true;
|
|
167
|
-
acc[i] = x.substring(1);
|
|
168
|
-
}
|
|
169
|
-
return acc;
|
|
170
|
-
}, {});
|
|
171
|
-
return {
|
|
172
|
-
...route,
|
|
173
|
-
match,
|
|
174
|
-
params: hasParams ? params : void 0,
|
|
175
|
-
rest: match.indexOf("+")
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
matchRoutes(src, ctx) {
|
|
179
|
-
const curr = src.split(this.opts.separator);
|
|
180
|
-
const route = this.routes.get(curr);
|
|
181
|
-
if (!route)
|
|
182
|
-
return;
|
|
183
|
-
let params;
|
|
184
|
-
if (route.params) {
|
|
185
|
-
params = Object.entries(route.params).reduce(
|
|
186
|
-
(acc, [i, k]) => (acc[k] = curr[+i], acc),
|
|
187
|
-
{}
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
if (route.validate && !this.validateRouteParams(params, route.validate)) {
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
const rest = route.rest >= 0 ? curr.slice(route.rest) : void 0;
|
|
194
|
-
let match = {
|
|
195
|
-
id: route.id,
|
|
196
|
-
params,
|
|
197
|
-
rest
|
|
198
|
-
};
|
|
199
|
-
if (route.auth) {
|
|
200
|
-
match = this.opts.authenticator(match, route, ctx);
|
|
201
|
-
if (match && !this.index[match.id]) {
|
|
202
|
-
illegalState(
|
|
203
|
-
"auth handler returned invalid route ID: " + match.id
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return match;
|
|
208
|
-
}
|
|
209
|
-
validateRouteParams(params, validators) {
|
|
210
|
-
for (let id in validators) {
|
|
211
|
-
if (params[id] !== void 0) {
|
|
212
|
-
const val = validators[id];
|
|
213
|
-
if (val.coerce) {
|
|
214
|
-
params[id] = val.coerce(params[id]);
|
|
215
|
-
}
|
|
216
|
-
if (val.check && !val.check(params[id])) {
|
|
217
|
-
return false;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return true;
|
|
222
|
-
}
|
|
223
|
-
handleRouteFailure() {
|
|
224
|
-
return true;
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
BasicRouter = __decorateClass([
|
|
228
|
-
INotifyMixin
|
|
229
|
-
], BasicRouter);
|
|
230
|
-
const isRouteParam = (x) => x[0] === "?";
|
|
231
|
-
export {
|
|
232
|
-
BasicRouter
|
|
233
|
-
};
|
package/history.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Fn } from "@thi.ng/api";
|
|
2
|
-
import type { HTMLRouterConfig } from "./api.js";
|
|
3
|
-
import { BasicRouter } from "./basic.js";
|
|
4
|
-
export declare class HTMLRouter<T = any> extends BasicRouter<T> {
|
|
5
|
-
protected currentPath: string;
|
|
6
|
-
protected popHandler: Fn<PopStateEvent, void>;
|
|
7
|
-
protected hashHandler: EventListener;
|
|
8
|
-
protected useFragment: boolean;
|
|
9
|
-
protected ignoreHashChange: boolean;
|
|
10
|
-
constructor(config: HTMLRouterConfig);
|
|
11
|
-
start(): void;
|
|
12
|
-
release(): void;
|
|
13
|
-
/**
|
|
14
|
-
* Like {@link BasicRouter.route}, but takes additional arg to control if
|
|
15
|
-
* this routing operation should manipulate the browser's `history`.
|
|
16
|
-
*
|
|
17
|
-
* @remarks
|
|
18
|
-
* If called from userland, this normally is true (also default). However,
|
|
19
|
-
* we want to avoid this if called from this router's own event handlers.
|
|
20
|
-
*
|
|
21
|
-
* @param src -
|
|
22
|
-
* @param ctx -
|
|
23
|
-
* @param pushState -
|
|
24
|
-
*/
|
|
25
|
-
route(src: string, ctx?: T, pushState?: boolean): import("./api.js").RouteMatch | undefined;
|
|
26
|
-
routeTo(route: string, ctx?: T): void;
|
|
27
|
-
protected handlePopChange(): Fn<PopStateEvent, void>;
|
|
28
|
-
protected handleHashChange(): EventListener;
|
|
29
|
-
protected handleRouteFailure(): boolean;
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=history.d.ts.map
|
package/history.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { equiv } from "@thi.ng/equiv";
|
|
2
|
-
import { BasicRouter } from "./basic.js";
|
|
3
|
-
class HTMLRouter extends BasicRouter {
|
|
4
|
-
currentPath;
|
|
5
|
-
popHandler;
|
|
6
|
-
hashHandler;
|
|
7
|
-
useFragment;
|
|
8
|
-
ignoreHashChange;
|
|
9
|
-
constructor(config) {
|
|
10
|
-
super({ prefix: config.useFragment ? "#/" : "/", ...config });
|
|
11
|
-
this.useFragment = config.useFragment !== false;
|
|
12
|
-
this.ignoreHashChange = false;
|
|
13
|
-
}
|
|
14
|
-
start() {
|
|
15
|
-
window.addEventListener("popstate", this.handlePopChange());
|
|
16
|
-
if (this.useFragment) {
|
|
17
|
-
window.addEventListener("hashchange", this.handleHashChange());
|
|
18
|
-
}
|
|
19
|
-
if (this.opts.initial) {
|
|
20
|
-
const route = this.routeForID(this.opts.initial);
|
|
21
|
-
this.route(this.format({ id: route.id }));
|
|
22
|
-
} else {
|
|
23
|
-
this.route(this.useFragment ? location.hash : location.pathname);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
release() {
|
|
27
|
-
window.removeEventListener("popstate", this.popHandler);
|
|
28
|
-
if (this.useFragment) {
|
|
29
|
-
window.removeEventListener("hashchange", this.hashHandler);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Like {@link BasicRouter.route}, but takes additional arg to control if
|
|
34
|
-
* this routing operation should manipulate the browser's `history`.
|
|
35
|
-
*
|
|
36
|
-
* @remarks
|
|
37
|
-
* If called from userland, this normally is true (also default). However,
|
|
38
|
-
* we want to avoid this if called from this router's own event handlers.
|
|
39
|
-
*
|
|
40
|
-
* @param src -
|
|
41
|
-
* @param ctx -
|
|
42
|
-
* @param pushState -
|
|
43
|
-
*/
|
|
44
|
-
route(src, ctx, pushState = true) {
|
|
45
|
-
const old = this.current;
|
|
46
|
-
const route = super.route(src, ctx);
|
|
47
|
-
if (route && !equiv(route, old)) {
|
|
48
|
-
this.currentPath = this.format(route);
|
|
49
|
-
if (pushState) {
|
|
50
|
-
history.pushState(this.currentPath, "", this.currentPath);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return route;
|
|
54
|
-
}
|
|
55
|
-
routeTo(route, ctx) {
|
|
56
|
-
if (this.useFragment) {
|
|
57
|
-
location.hash = route;
|
|
58
|
-
}
|
|
59
|
-
this.route(route, ctx);
|
|
60
|
-
}
|
|
61
|
-
handlePopChange() {
|
|
62
|
-
return this.popHandler = this.popHandler || ((e) => {
|
|
63
|
-
this.route(
|
|
64
|
-
e.state || (this.useFragment ? location.hash : location.pathname),
|
|
65
|
-
void 0,
|
|
66
|
-
false
|
|
67
|
-
);
|
|
68
|
-
}).bind(this);
|
|
69
|
-
}
|
|
70
|
-
handleHashChange() {
|
|
71
|
-
return this.hashHandler = this.hashHandler || ((e) => {
|
|
72
|
-
if (!this.ignoreHashChange) {
|
|
73
|
-
const hash = e.newURL.substring(e.newURL.indexOf("#"));
|
|
74
|
-
if (hash !== this.currentPath) {
|
|
75
|
-
this.route(hash, void 0, false);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}).bind(this);
|
|
79
|
-
}
|
|
80
|
-
handleRouteFailure() {
|
|
81
|
-
this.ignoreHashChange = true;
|
|
82
|
-
location.hash = this.format({
|
|
83
|
-
id: this.routeForID(this.opts.default).id
|
|
84
|
-
});
|
|
85
|
-
this.ignoreHashChange = false;
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
export {
|
|
90
|
-
HTMLRouter
|
|
91
|
-
};
|