white-label-router 6.2.0 → 6.3.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 +16 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -122,6 +122,8 @@ Only click events that reach `navigationRoot` are considered by that Router. Lin
|
|
|
122
122
|
|
|
123
123
|
`navigationRoot` is deliberately separate from `scope`: `navigationRoot` controls where enhanced-link clicks are observed; `scope` is application data passed to route callbacks.
|
|
124
124
|
|
|
125
|
+
`navigationRoot` does not limit focus. After a navigation, the route's `focus` selector (default `main h1`) is looked up in the whole document, so a heading outside the owned region still receives focus. Use a more specific `focus` selector, or `focus: false`, when the region should keep focus itself.
|
|
126
|
+
|
|
125
127
|
## Define routes
|
|
126
128
|
|
|
127
129
|
A route can be a function:
|
|
@@ -197,6 +199,18 @@ router.routes = {
|
|
|
197
199
|
|
|
198
200
|
Route keys are encoded the same way URL parsing encodes paths, so `'/café'` matches a request for `/caf%C3%A9`. Keys that don't start with `/`, or that contain `?` or `#`, can never match a pathname and are ignored (apart from `defaultRoute`). If two keys normalize to the same path (for example `/x/../same` and `/same`), the key already in normalized form wins, otherwise the alphabetically lowest; insertion order never decides.
|
|
199
201
|
|
|
202
|
+
A trailing `/` is part of the key, not a wildcard. `'/docs'` matches `/docs`, `/docs/`, and `/docs/x`, but `'/docs/'` matches only `/docs/` itself (and paths below its empty last segment, such as `/docs//x`). It doesn't match `/docs` or `/docs/x`. Declare `'/docs'` to cover the section. If both keys exist, `/docs/` selects `'/docs/'` as the longer match. `'/'` follows the same rule: it matches only the root path, so other unmatched paths go to `defaultRoute`.
|
|
203
|
+
|
|
204
|
+
### Large route tables
|
|
205
|
+
|
|
206
|
+
Each match reads the keys of `routes` again so that keys added or removed in place (`router.routes['/x'] = fn`) take effect immediately. That costs time in proportion to the number of keys: about 50 µs per match at 1,000 routes in `npm run benchmark`. For a large table that doesn't change after setup, call `router.indexRoutes()` once the table is ready. Matching then uses the stored index (about 0.15 µs at 1,000 routes) until `routes` is assigned a different object, which drops the index. After adding or removing keys on the same object, call `indexRoutes()` again. Until you do, an added key is not matched, and navigation to a removed key's paths returns `false`. Replacing the value of an existing key needs no re-index.
|
|
207
|
+
|
|
208
|
+
```js
|
|
209
|
+
router.routes = buildRouteTable(); // thousands of keys
|
|
210
|
+
router.indexRoutes();
|
|
211
|
+
router.initialize();
|
|
212
|
+
```
|
|
213
|
+
|
|
200
214
|
A new `Router` starts with a placeholder `defaultRoute` that does nothing, so programmatic navigation to an unmatched URL succeeds until you replace `routes`. That placeholder never intercepts link clicks.
|
|
201
215
|
|
|
202
216
|
## Location contract
|
|
@@ -300,7 +314,7 @@ router.routes = {
|
|
|
300
314
|
};
|
|
301
315
|
```
|
|
302
316
|
|
|
303
|
-
After a route renders, Router sets `document.title` from `title` and focuses the first element matching `focus` (default `main h1`), adding `tabindex="-1"` if the element has no `tabindex`. Set `focus: false` for an in-page refinement that should preserve current focus. The first dispatch from `initialize()` sets the title but does not move focus, because the browser already owns focus on a freshly loaded page; later navigations do. Server runtimes retain `pageTitle` as route state but do not mutate a document or focus target.
|
|
317
|
+
After a route renders, Router sets `document.title` from `title` and focuses the first element in the document matching `focus` (default `main h1`), regardless of `navigationRoot`, adding `tabindex="-1"` if the element has no `tabindex`. Set `focus: false` for an in-page refinement that should preserve current focus. The first dispatch from `initialize()` sets the title but does not move focus, because the browser already owns focus on a freshly loaded page; later navigations do. Server runtimes retain `pageTitle` as route state but do not mutate a document or focus target.
|
|
304
318
|
|
|
305
319
|
## Browser history behavior
|
|
306
320
|
|
|
@@ -320,6 +334,7 @@ When back/forward, or a click on a link to a `#fragment` of the current page, ch
|
|
|
320
334
|
| `navigate(url?, data?, isPopState?)` | Match and run a route; update browser history when appropriate. Invalid/malformed URL candidates and other rejected navigation preserve current route state. | The same Router on success; `false` for rejected navigation. |
|
|
321
335
|
| `addListeners()` | Attach browser and optional mediator listeners once. | The same `Router` instance. |
|
|
322
336
|
| `removeListeners()` | Release listeners owned by this router. | The same `Router` instance. |
|
|
337
|
+
| `indexRoutes()` | Index the current route keys and reuse that index until `routes` is reassigned or this is called again (see [Large route tables](#large-route-tables)). | The same `Router` instance. |
|
|
323
338
|
| `destroy()` | Release routing listeners. Does not call the active route's `destroy()`. | The same `Router` instance after cleanup. |
|
|
324
339
|
| `parseQueryString(query)` | Decode a query string using `URLSearchParams`. | A plain object containing the last value for each query key. |
|
|
325
340
|
| `setLocationData(data?)` | Rebuild the current route location payload. | `undefined`; updates `locationData` in place. |
|
package/dist/index.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ declare class Router {
|
|
|
61
61
|
private boundNavigationRoot;
|
|
62
62
|
private activeDestroy;
|
|
63
63
|
private compiledRoutes;
|
|
64
|
+
private indexedRoutes;
|
|
64
65
|
private navigationToken;
|
|
65
66
|
private initialDispatch;
|
|
66
67
|
private suppressFocus;
|
|
@@ -86,6 +87,17 @@ declare class Router {
|
|
|
86
87
|
private normalizeBrowserUrl;
|
|
87
88
|
/** True if the route has something to run: a function, a `view` function, or a `view.initialize`. */
|
|
88
89
|
private isRunnableRoute;
|
|
90
|
+
/**
|
|
91
|
+
* Index the current route keys and match against that index without re-reading the keys on every navigation.
|
|
92
|
+
* Without it, each match lists the keys of `routes` to notice in-place edits, which costs time in proportion to
|
|
93
|
+
* the number of routes. Use it for large route tables that stop changing after setup. Assigning a different object to
|
|
94
|
+
* `routes` drops the index; after adding or removing keys on the same object, call `indexRoutes()` again. Until then,
|
|
95
|
+
* an added key is not matched, and a removed key still claims its paths, so `navigate()` returns `false` for them
|
|
96
|
+
* as it does for a key set to `undefined`.
|
|
97
|
+
* Replacing the value of an existing key needs no re-index, because the route is looked up when it runs.
|
|
98
|
+
* @returns This router.
|
|
99
|
+
*/
|
|
100
|
+
indexRoutes(): this;
|
|
89
101
|
/** Build (or reuse) the lookup tables for the current route keys. Reused while the own key list is unchanged. */
|
|
90
102
|
private compileRoutes;
|
|
91
103
|
/** Find the route key with the longest matching path prefix, else `'defaultRoute'` if one is set, else `null`. */
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,8 @@ class Router {
|
|
|
38
38
|
boundNavigationRoot = null;
|
|
39
39
|
activeDestroy;
|
|
40
40
|
compiledRoutes;
|
|
41
|
+
// The routes object indexRoutes() indexed. While `routes` is still that object, matching trusts the index as is.
|
|
42
|
+
indexedRoutes;
|
|
41
43
|
// Bumped by each navigation that passes its guard. If it changes while a navigation is calling out to app code,
|
|
42
44
|
// a newer navigation has started, and the older one stops before touching title, focus, or history.
|
|
43
45
|
navigationToken = 0;
|
|
@@ -151,10 +153,30 @@ class Router {
|
|
|
151
153
|
return typeof route === 'function' || typeof route.view === 'function' ||
|
|
152
154
|
Boolean(route.view && typeof route.view.initialize === 'function');
|
|
153
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Index the current route keys and match against that index without re-reading the keys on every navigation.
|
|
158
|
+
* Without it, each match lists the keys of `routes` to notice in-place edits, which costs time in proportion to
|
|
159
|
+
* the number of routes. Use it for large route tables that stop changing after setup. Assigning a different object to
|
|
160
|
+
* `routes` drops the index; after adding or removing keys on the same object, call `indexRoutes()` again. Until then,
|
|
161
|
+
* an added key is not matched, and a removed key still claims its paths, so `navigate()` returns `false` for them
|
|
162
|
+
* as it does for a key set to `undefined`.
|
|
163
|
+
* Replacing the value of an existing key needs no re-index, because the route is looked up when it runs.
|
|
164
|
+
* @returns This router.
|
|
165
|
+
*/
|
|
166
|
+
indexRoutes() {
|
|
167
|
+
this.indexedRoutes = undefined;
|
|
168
|
+
this.compileRoutes();
|
|
169
|
+
this.indexedRoutes = this.routes;
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
154
172
|
/** Build (or reuse) the lookup tables for the current route keys. Reused while the own key list is unchanged. */
|
|
155
173
|
compileRoutes() {
|
|
156
|
-
const keys = Object.keys(this.routes);
|
|
157
174
|
const cached = this.compiledRoutes;
|
|
175
|
+
if (cached && this.indexedRoutes === this.routes) {
|
|
176
|
+
return cached;
|
|
177
|
+
}
|
|
178
|
+
this.indexedRoutes = undefined;
|
|
179
|
+
const keys = Object.keys(this.routes);
|
|
158
180
|
if (cached && cached.keys.length === keys.length && cached.keys.every((key, index) => key === keys[index])) {
|
|
159
181
|
return cached;
|
|
160
182
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/** Extra data passed with a navigation. `url`, if present, is the destination; any other fields are yours. */\ninterface NavigationData {url?: string; [key: string]: unknown}\n/**\n * What a route callback receives about the destination.\n * `url` is the path, query, and hash; `data.url` holds the decoded path segments after the matched route key;\n * `data.query` holds decoded query values; `data.mediator` is the navigation data, if any.\n */\ninterface LocationData {url: string; data: {url: string[]; mediator: NavigationData | undefined; query: Record<string, string>}}\n/** A route callback. It receives `router.scope` and the destination location. */\ntype RouteHandler = (scope: Element | null, location: LocationData) => unknown;\n/** A view with setup and teardown. `destroy` receives the location being navigated to. */\ninterface RouteViewLifecycle {initialize?: RouteHandler; destroy?: RouteHandler}\n/**\n * A route with optional page context and a guard.\n * `secure` must return exactly `true` to allow navigation; `focus: false` leaves focus where it is.\n */\ninterface RouteObject {title?: string; focus?: string | false; secure?: RouteHandler; view?: RouteHandler | RouteViewLifecycle}\ntype Route = RouteHandler | RouteObject;\n/** The teardown captured from the view that actually initialized, so later route-table edits can't change it. */\ninterface ActiveDestroy {receiver: RouteViewLifecycle; callback: RouteHandler}\n/** Any EventTarget-like object; Router only adds and removes a `router:navigate` listener on it. */\ninterface NavigationMediator {\n addEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;\n removeEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;\n}\n/**\n * Route keys prepared for fast matching. `prefixes` maps a normalized path to the route key that owns it;\n * `prefixFor` maps each key to its normalized path. Rebuilt only when the list of own keys changes.\n */\ninterface CompiledRoutes {keys: string[]; prefixes: Map<string, string>; prefixFor: Map<string, string>}\n\n/** The do-nothing `defaultRoute` objects each constructor installs, so link clicks can tell them apart from app routes. */\nconst builtInDefaultRoutes = new WeakSet<object>();\n/** A dummy origin that lets route keys and server URLs go through the standard URL parser. */\nconst routeKeyBase = 'http://white-label.invalid';\n\n/** Encode a route key the way the URL parser encodes paths, so `'/café'` matches `/caf%C3%A9`. */\nfunction normalizeRouteKey(key: string) {\n // A key that doesn't start with '/' or contains '?' or '#' can never equal a pathname, so leave it as is (it won't match).\n if (!key.startsWith('/') || /[?#]/.test(key)) {return key;}\n return new URL(`${routeKeyBase}${key}`).pathname;\n}\n\n/** Strip the `#fragment`, leaving the path and query. */\nfunction withoutHash(url: string) {\n const index = url.indexOf('#');\n return index === -1 ? url : url.slice(0, index);\n}\n\n/**\n * Maps URLs to route callbacks. In a browser it enhances `data-pushstate` links and back/forward with the History API;\n * on a server it dispatches the request URL you pass, with no DOM required.\n */\nclass Router {\n routes: Record<string, Route>;\n url: string;\n route: string | null;\n scope: Element | null;\n previousRoute: string | null;\n pageTitle: string | null;\n boundPushStateClick: (event: MouseEvent) => unknown;\n boundPopState: (event: PopStateEvent) => unknown;\n boundMediatorNavigate: EventListener;\n listenersInitialized: boolean;\n locationData: LocationData = {url: '', data: {url: [], mediator: undefined, query: {}}};\n private currentMediator: NavigationMediator | false = false;\n private boundMediator: NavigationMediator | false = false;\n private currentNavigationRoot: Document | Element | null = null;\n private boundNavigationRoot: Document | Element | null = null;\n private activeDestroy: ActiveDestroy | undefined;\n private compiledRoutes: CompiledRoutes | undefined;\n // Bumped by each navigation that passes its guard. If it changes while a navigation is calling out to app code,\n // a newer navigation has started, and the older one stops before touching title, focus, or history.\n private navigationToken = 0;\n // True only for the first navigate() call made by initialize(), so that dispatch leaves focus alone.\n private initialDispatch = false;\n // Tells applyPageContext() to skip focus for the current call.\n private suppressFocus = false;\n\n /** Create a router with a placeholder `defaultRoute` and no listeners attached yet. */\n constructor() {\n const defaultRoute: RouteObject = {\n view: {\n initialize: () => true,\n destroy: () => true\n }\n };\n builtInDefaultRoutes.add(defaultRoute);\n this.routes = {defaultRoute};\n this.url = '';\n this.route = null;\n this.scope = null;\n this.previousRoute = null;\n this.pageTitle = null;\n this.boundPushStateClick = this.eventPushStateClick.bind(this);\n this.boundPopState = this.eventPopState.bind(this);\n this.boundMediatorNavigate = (event: Event) => {\n const detail = (event as CustomEvent<unknown>).detail;\n if (detail === undefined || detail === null) {\n this.navigate(undefined, {}, false);\n return;\n }\n if (typeof detail !== 'object' || Array.isArray(detail)) {return;}\n const data = detail as NavigationData;\n this.navigate(data.url, data, false);\n };\n this.listenersInitialized = false;\n }\n\n /** Event target that can send `router:navigate` events, or `false` for none. */\n get mediator(): NavigationMediator | false {return this.currentMediator;}\n\n /** Set the mediator. If listeners are active, the `router:navigate` listener moves from the old one to the new one. */\n set mediator(value: NavigationMediator | false) {\n if (value === this.currentMediator) {return;}\n if (this.listenersInitialized && this.boundMediator) {\n this.boundMediator.removeEventListener('router:navigate', this.boundMediatorNavigate);\n this.boundMediator = false;\n }\n this.currentMediator = value;\n if (this.listenersInitialized && value) {\n value.addEventListener('router:navigate', this.boundMediatorNavigate);\n this.boundMediator = value;\n }\n }\n\n /** Element or document whose `data-pushstate` link clicks this router handles; `null` means the whole document. */\n get navigationRoot(): Document | Element | null {return this.currentNavigationRoot;}\n\n /** Set the click root. If listeners are active, the click listener moves to the new root. */\n set navigationRoot(value: Document | Element | null) {\n if (value === this.currentNavigationRoot) {return;}\n if (this.listenersInitialized && this.isBrowserRuntime()) {\n this.boundNavigationRoot?.removeEventListener('click', this.boundPushStateClick as EventListener);\n this.currentNavigationRoot = value;\n const nextRoot = value || document;\n nextRoot.addEventListener('click', this.boundPushStateClick as EventListener);\n this.boundNavigationRoot = nextRoot;\n return;\n }\n this.currentNavigationRoot = value;\n }\n\n /** True when `window` and `document` exist, i.e. browser-only effects should run. */\n private isBrowserRuntime() {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n }\n\n /** Origin used as the base for URL parsing: the page's origin in a browser, a dummy one on a server. */\n private getOrigin() {\n return this.isBrowserRuntime() ? window.location.origin : 'http://white-label.invalid';\n }\n\n /** Current path, query, and hash: from `window.location` in a browser, or the last committed URL (default `/`) on a server. */\n private getCurrentUrl() {\n if (!this.isBrowserRuntime()) {return this.url || '/';}\n return window.location.pathname + window.location.search + (window.location.hash || '');\n }\n\n /** Parse a URL relative to the current page (or the dummy server origin). Returns `null` if it can't be parsed. */\n private parseNavigationUrl(url: string) {\n try {\n const base = this.isBrowserRuntime() ? window.location.href || `${window.location.origin}/` : this.getOrigin();\n return new URL(url || '/', base);\n } catch (_error) {\n return null;\n }\n }\n\n /** In a browser, reduce a URL to its path, query, and hash, or `null` if it is cross-origin or invalid. */\n private normalizeBrowserUrl(url: string) {\n if (!this.isBrowserRuntime()) {return url;}\n const parsedUrl = this.parseNavigationUrl(url);\n if (!parsedUrl || parsedUrl.origin !== window.location.origin) {return null;}\n return `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;\n }\n\n /** True if the route has something to run: a function, a `view` function, or a `view.initialize`. */\n private isRunnableRoute(route: Route): boolean {\n return typeof route === 'function' || typeof route.view === 'function' ||\n Boolean(route.view && typeof route.view.initialize === 'function');\n }\n /** Build (or reuse) the lookup tables for the current route keys. Reused while the own key list is unchanged. */\n private compileRoutes(): CompiledRoutes {\n const keys = Object.keys(this.routes);\n const cached = this.compiledRoutes;\n if (cached && cached.keys.length === keys.length && cached.keys.every((key, index) => key === keys[index])) {\n return cached;\n }\n const prefixes = new Map<string, string>();\n const prefixFor = new Map<string, string>();\n for (const key of keys) {\n if (key === 'defaultRoute') {continue;}\n const prefix = normalizeRouteKey(key);\n prefixFor.set(key, prefix);\n const existing = prefixes.get(prefix);\n // When two keys normalize to the same path, prefer the one already in normalized form, then the alphabetically\n // lowest, so the winner never depends on insertion order.\n if (existing === undefined || (existing !== prefix && (key === prefix || key < existing))) {prefixes.set(prefix, key);}\n }\n this.compiledRoutes = {keys, prefixes, prefixFor};\n return this.compiledRoutes;\n }\n\n /** Find the route key with the longest matching path prefix, else `'defaultRoute'` if one is set, else `null`. */\n private matchRoute(pathname: string): string | null {\n const {prefixes} = this.compileRoutes();\n // Try the full path, then drop one '/segment' at a time; the first hit is the longest match.\n // Cutting only at '/' means '/products' matches '/products/42' but not '/products-old'.\n let candidateRoute = prefixes.get(pathname);\n let index = pathname.lastIndexOf('/');\n while (candidateRoute === undefined && index >= 0) {\n candidateRoute = prefixes.get(pathname.slice(0, index));\n index = index > 0 ? pathname.lastIndexOf('/', index - 1) : -1;\n }\n if (candidateRoute !== undefined) {return candidateRoute;}\n if (Object.prototype.hasOwnProperty.call(this.routes, 'defaultRoute') && this.routes.defaultRoute) {\n return 'defaultRoute';\n }\n return null;\n }\n\n /** Length of the normalized path for a route key, used to slice the matched prefix off `data.url`; 0 for `defaultRoute`. */\n private routePrefixLength(route: string | null) {\n if (!route || route === 'defaultRoute') {return 0;}\n return (this.compileRoutes().prefixFor.get(route) ?? normalizeRouteKey(route)).length;\n }\n\n /** Parse a URL Router committed earlier. A path is prefixed with the origin first, so '//x' stays a path, not a host. */\n private parseStoredUrl(url: string) {\n if (!url.startsWith('/')) {return this.parseNavigationUrl(url);}\n try {\n return new URL(`${this.getOrigin()}${url}`);\n } catch (_error) {\n return null;\n }\n }\n\n /** Build the location object passed to route callbacks. Path segments that fail to decode are kept as-is. */\n private buildLocationData(url: string, route: string | null, mediatorData: NavigationData | undefined, parsedUrl: URL): LocationData {\n return {\n url,\n data: {\n url: parsedUrl.pathname\n .slice(this.routePrefixLength(route))\n .split('/')\n .filter(Boolean)\n .map((fragment) => {\n try {return decodeURIComponent(fragment);} catch (_error) {return fragment;}\n }),\n mediator: mediatorData,\n query: this.parseQueryString(parsedUrl.search)\n }\n };\n }\n\n /**\n * Attach listeners and dispatch the starting URL. Does not add a history entry or move focus.\n * @param url - Request URL on a server. In a browser, omit it to use `window.location`.\n * @returns This router.\n * @throws Whatever a guard or route callback throws.\n */\n initialize(url?: string) {\n this.addListeners();\n // The browser has already placed focus on the page it just loaded, so only later navigations move it.\n this.initialDispatch = true;\n try {\n this.navigate(url ?? this.getCurrentUrl(), {}, true);\n } finally {\n this.initialDispatch = false;\n }\n return this;\n }\n\n /**\n * Attach the click and popstate listeners (browser only) and the mediator listener. Safe to call more than once.\n * @returns This router.\n */\n addListeners() {\n if (this.listenersInitialized) {return this;}\n if (this.isBrowserRuntime()) {\n const navigationRoot = this.currentNavigationRoot || document;\n navigationRoot.addEventListener('click', this.boundPushStateClick as EventListener);\n this.boundNavigationRoot = navigationRoot;\n window.addEventListener('popstate', this.boundPopState);\n }\n if (this.currentMediator) {\n this.currentMediator.addEventListener('router:navigate', this.boundMediatorNavigate);\n this.boundMediator = this.currentMediator;\n }\n this.listenersInitialized = true;\n return this;\n }\n\n /**\n * Remove this router's listeners. Does not call the active route's `destroy()`.\n * @returns This router.\n */\n destroy() {\n this.removeListeners();\n return this;\n }\n\n /**\n * Remove the listeners `addListeners()` attached. Subclasses can override this to release more.\n * @returns This router.\n */\n removeListeners() {\n if (!this.listenersInitialized) {return this;}\n if (this.isBrowserRuntime()) {\n this.boundNavigationRoot?.removeEventListener('click', this.boundPushStateClick as EventListener);\n this.boundNavigationRoot = null;\n window.removeEventListener('popstate', this.boundPopState);\n }\n if (this.boundMediator) {\n this.boundMediator.removeEventListener('router:navigate', this.boundMediatorNavigate);\n this.boundMediator = false;\n }\n this.listenersInitialized = false;\n return this;\n }\n\n /**\n * Click handler for `<a href data-pushstate>` links. Takes over only when Router can handle the link:\n * a plain left click on a same-origin link (no `download`, no other `target`) whose route is app-defined,\n * runnable, and allowed by its guard, and that is not just a `#fragment` of the current page. Anything else is left\n * to the browser.\n * @param e - The click event.\n * @returns This router if it handled the click, otherwise `true`.\n * @throws Whatever a guard or route callback throws.\n */\n eventPushStateClick(e: MouseEvent) {\n if (typeof window === 'undefined') {return true;}\n if (e.defaultPrevented || (e.button !== undefined && e.button !== 0) || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {\n return true;\n }\n const eventTarget = e.target as Element | null;\n const source = eventTarget && (typeof eventTarget.closest === 'function' ? eventTarget : eventTarget.parentElement);\n const anchor = source && typeof source.closest === 'function' ? source.closest('a[href][data-pushstate]') : null;\n if (!anchor) {return true;}\n const target = anchor.getAttribute('target');\n if (anchor.hasAttribute('download') || (target && target.toLowerCase() !== '_self')) {return true;}\n // Read the attribute, because on an SVG <a> the href property is an SVGAnimatedString, not a URL.\n const href = anchor.getAttribute('href') ?? '';\n const baseUrl = typeof document !== 'undefined' && document.baseURI\n ? document.baseURI\n : window.location.href || `${window.location.origin}/`;\n let location: URL;\n try {location = new URL(href, baseUrl);} catch {return true;}\n if (location.origin !== window.location.origin) {return true;}\n // A link to a #fragment of the page already shown is native fragment navigation: let the browser scroll to it.\n // Its popstate then only updates `url`, matching the fragment-only back/forward rule.\n if (location.href.includes('#') && location.pathname === window.location.pathname && location.search === window.location.search) {\n return true;\n }\n const candidateRoute = this.matchRoute(location.pathname);\n const selected = candidateRoute ? this.routes[candidateRoute] : undefined;\n if (!selected || !this.isRunnableRoute(selected) || builtInDefaultRoutes.has(selected)) {return true;}\n // Guards are synchronous, so try the navigation first and cancel the browser's default only if Router took it.\n // A rejected (or throwing) guard therefore falls back to a normal page load. If the route committed and then\n // threw, the token has moved, so the default is still cancelled and the browser doesn't navigate twice.\n const token = this.navigationToken;\n let handled = false;\n try {\n handled = this.navigate(`${location.pathname}${location.search}${location.hash}`, {}, false) !== false;\n } finally {\n if (handled || this.navigationToken !== token) {e.preventDefault();}\n }\n return handled ? this : true;\n }\n\n /**\n * Popstate handler for back/forward. Runs the route for the new URL without adding a history entry.\n * A hash-only change just updates `url` and `locationData.url`.\n * @returns This router.\n */\n eventPopState() {\n if (typeof window === 'undefined') {return this;}\n const currentUrl = this.getCurrentUrl();\n // Moving between #fragments on the same page (footnotes, skip links) keeps the current view and focus.\n if (this.route !== null && withoutHash(currentUrl) === withoutHash(this.url)) {\n this.url = currentUrl;\n this.locationData = {...this.locationData, url: currentUrl};\n return this;\n }\n this.navigate(currentUrl, {}, true);\n return this;\n }\n\n /**\n * Decode a query string into a plain object. For repeated keys the last value wins.\n * @param queryString - Query string, with or without the leading `?`.\n */\n parseQueryString(queryString: string) {\n return Object.fromEntries(new URLSearchParams(queryString));\n }\n\n /**\n * Rebuild `locationData` from the current `url` and `route`. Leaves it unchanged if the URL can't be parsed.\n * @param mediatorData - Value to expose as `locationData.data.mediator`.\n */\n setLocationData(mediatorData?: NavigationData) {\n const parsedUrl = this.parseStoredUrl(this.url || '/');\n if (!parsedUrl) {return;}\n this.locationData = this.buildLocationData(this.url, this.route, mediatorData, parsedUrl);\n }\n\n /**\n * Record the route's title in `pageTitle` and, in a browser, set `document.title` and move focus to the route's\n * `focus` selector (default `main h1`), adding `tabindex=\"-1\"` if needed. `focus: false` skips focus.\n * @param route - The route that just ran.\n * @returns This router.\n */\n applyPageContext(route: Route) {\n if (typeof route === 'function') {\n this.pageTitle = null;\n return this;\n }\n this.pageTitle = typeof route.title === 'string' ? route.title : null;\n if (!this.isBrowserRuntime()) {return this;}\n if (this.pageTitle) {document.title = this.pageTitle;}\n if (route.focus !== false && !this.suppressFocus) {\n const target = document.querySelector<HTMLElement>(route.focus || 'main h1');\n if (target) {\n if (!target.hasAttribute('tabindex')) {target.setAttribute('tabindex', '-1');}\n target.focus();\n }\n }\n return this;\n }\n\n /**\n * Navigate to a URL: match the route, run its guard, commit the new state, call the previous route's `destroy()`,\n * run the new route, apply title and focus, then push a history entry (browser only, unless `isPopState`).\n * If route code starts another navigation part-way through, that one wins and this call stops early.\n * @param url - Destination URL. Omit to re-run the last committed URL (or the current browser URL / `/` at first).\n * @param mediatorData - Value exposed to the route as `location.data.mediator`.\n * @param isPopState - `true` to skip adding a history entry.\n * @returns This router, or `false` if the navigation was rejected (bad or cross-origin URL, no matching route,\n * guard refused, or nothing to run). A rejected navigation changes nothing.\n * @throws Whatever a guard or route callback throws. A throwing guard changes nothing; a throwing route stays committed.\n */\n navigate(url?: string, mediatorData?: NavigationData, isPopState = false) {\n const skipFocus = this.initialDispatch;\n this.initialDispatch = false;\n if (url !== undefined && typeof url !== 'string') {return false;}\n\n const candidateInput = url !== undefined ? url : this.url;\n let parsedUrl: URL | null;\n if (!candidateInput) {\n parsedUrl = this.parseNavigationUrl(this.getCurrentUrl());\n } else {\n parsedUrl = url === undefined ? this.parseStoredUrl(candidateInput) : this.parseNavigationUrl(candidateInput);\n }\n if (!parsedUrl) {return false;}\n if (this.isBrowserRuntime() && parsedUrl.origin !== window.location.origin) {return false;}\n\n // Store only path, query, and hash, even when a server passed an absolute URL.\n const candidateUrl = `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;\n const candidateRoute = this.matchRoute(parsedUrl.pathname);\n if (!candidateRoute) {return false;}\n\n const candidateLocationData = this.buildLocationData(candidateUrl, candidateRoute, mediatorData, parsedUrl);\n const selected = this.routes[candidateRoute];\n if (!selected || (typeof selected !== 'function' && selected.secure && selected.secure(this.scope, candidateLocationData) !== true) ||\n !this.isRunnableRoute(selected)) {\n return false;\n }\n\n const token = ++this.navigationToken;\n this.url = candidateUrl;\n this.route = candidateRoute;\n this.locationData = candidateLocationData;\n // Clear the stored teardown before calling it, so a navigation started inside destroy() can't call it again,\n // and a destroy() that throws is not retried: its error propagates with the destination committed but not run.\n const previous = this.activeDestroy;\n this.activeDestroy = undefined;\n if (previous) {\n previous.callback.call(previous.receiver, this.scope, candidateLocationData);\n if (token !== this.navigationToken) {return this;}\n }\n const selectedView = typeof selected !== 'function' && typeof selected.view === 'object'\n ? selected.view\n : undefined;\n // Store the teardown before initialize() runs, so it still runs later if initialize() throws or navigates away.\n this.activeDestroy = selectedView?.destroy\n ? {receiver: selectedView, callback: selectedView.destroy}\n : undefined;\n if (typeof selected === 'function') {\n selected(this.scope, candidateLocationData);\n } else if (typeof selected.view === 'function') {\n selected.view(this.scope, candidateLocationData);\n } else {\n selectedView!.initialize!(this.scope, candidateLocationData);\n }\n // If initialize() started another navigation, that one has already applied its own title, focus, and history.\n if (token !== this.navigationToken) {return this;}\n this.suppressFocus = skipFocus;\n try {\n this.applyPageContext(selected);\n } finally {\n this.suppressFocus = false;\n }\n if (token !== this.navigationToken) {return this;}\n this.previousRoute = this.route;\n // Re-running the current URL (no `url` given, e.g. a mediator event without a destination) must not add a\n // duplicate history entry for the address already shown.\n if (!isPopState && this.isBrowserRuntime() && !(url === undefined && parsedUrl.href === window.location.href)) {\n window.history.pushState(this.url, this.pageTitle || '', parsedUrl.href);\n }\n return this;\n }\n}\n\n/** Types for route definitions, location data, and navigation data. */\nnamespace Router {\n export type Handler = RouteHandler;\n export type Route = RouteHandler | RouteObject;\n export type Location = LocationData;\n export type Navigation = NavigationData;\n}\nexport = Router;\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/** Extra data passed with a navigation. `url`, if present, is the destination; any other fields are yours. */\ninterface NavigationData {url?: string; [key: string]: unknown}\n/**\n * What a route callback receives about the destination.\n * `url` is the path, query, and hash; `data.url` holds the decoded path segments after the matched route key;\n * `data.query` holds decoded query values; `data.mediator` is the navigation data, if any.\n */\ninterface LocationData {url: string; data: {url: string[]; mediator: NavigationData | undefined; query: Record<string, string>}}\n/** A route callback. It receives `router.scope` and the destination location. */\ntype RouteHandler = (scope: Element | null, location: LocationData) => unknown;\n/** A view with setup and teardown. `destroy` receives the location being navigated to. */\ninterface RouteViewLifecycle {initialize?: RouteHandler; destroy?: RouteHandler}\n/**\n * A route with optional page context and a guard.\n * `secure` must return exactly `true` to allow navigation; `focus: false` leaves focus where it is.\n */\ninterface RouteObject {title?: string; focus?: string | false; secure?: RouteHandler; view?: RouteHandler | RouteViewLifecycle}\ntype Route = RouteHandler | RouteObject;\n/** The teardown captured from the view that actually initialized, so later route-table edits can't change it. */\ninterface ActiveDestroy {receiver: RouteViewLifecycle; callback: RouteHandler}\n/** Any EventTarget-like object; Router only adds and removes a `router:navigate` listener on it. */\ninterface NavigationMediator {\n addEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;\n removeEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;\n}\n/**\n * Route keys prepared for fast matching. `prefixes` maps a normalized path to the route key that owns it;\n * `prefixFor` maps each key to its normalized path. Rebuilt only when the list of own keys changes.\n */\ninterface CompiledRoutes {keys: string[]; prefixes: Map<string, string>; prefixFor: Map<string, string>}\n\n/** The do-nothing `defaultRoute` objects each constructor installs, so link clicks can tell them apart from app routes. */\nconst builtInDefaultRoutes = new WeakSet<object>();\n/** A dummy origin that lets route keys and server URLs go through the standard URL parser. */\nconst routeKeyBase = 'http://white-label.invalid';\n\n/** Encode a route key the way the URL parser encodes paths, so `'/café'` matches `/caf%C3%A9`. */\nfunction normalizeRouteKey(key: string) {\n // A key that doesn't start with '/' or contains '?' or '#' can never equal a pathname, so leave it as is (it won't match).\n if (!key.startsWith('/') || /[?#]/.test(key)) {return key;}\n return new URL(`${routeKeyBase}${key}`).pathname;\n}\n\n/** Strip the `#fragment`, leaving the path and query. */\nfunction withoutHash(url: string) {\n const index = url.indexOf('#');\n return index === -1 ? url : url.slice(0, index);\n}\n\n/**\n * Maps URLs to route callbacks. In a browser it enhances `data-pushstate` links and back/forward with the History API;\n * on a server it dispatches the request URL you pass, with no DOM required.\n */\nclass Router {\n routes: Record<string, Route>;\n url: string;\n route: string | null;\n scope: Element | null;\n previousRoute: string | null;\n pageTitle: string | null;\n boundPushStateClick: (event: MouseEvent) => unknown;\n boundPopState: (event: PopStateEvent) => unknown;\n boundMediatorNavigate: EventListener;\n listenersInitialized: boolean;\n locationData: LocationData = {url: '', data: {url: [], mediator: undefined, query: {}}};\n private currentMediator: NavigationMediator | false = false;\n private boundMediator: NavigationMediator | false = false;\n private currentNavigationRoot: Document | Element | null = null;\n private boundNavigationRoot: Document | Element | null = null;\n private activeDestroy: ActiveDestroy | undefined;\n private compiledRoutes: CompiledRoutes | undefined;\n // The routes object indexRoutes() indexed. While `routes` is still that object, matching trusts the index as is.\n private indexedRoutes: Record<string, Route> | undefined;\n // Bumped by each navigation that passes its guard. If it changes while a navigation is calling out to app code,\n // a newer navigation has started, and the older one stops before touching title, focus, or history.\n private navigationToken = 0;\n // True only for the first navigate() call made by initialize(), so that dispatch leaves focus alone.\n private initialDispatch = false;\n // Tells applyPageContext() to skip focus for the current call.\n private suppressFocus = false;\n\n /** Create a router with a placeholder `defaultRoute` and no listeners attached yet. */\n constructor() {\n const defaultRoute: RouteObject = {\n view: {\n initialize: () => true,\n destroy: () => true\n }\n };\n builtInDefaultRoutes.add(defaultRoute);\n this.routes = {defaultRoute};\n this.url = '';\n this.route = null;\n this.scope = null;\n this.previousRoute = null;\n this.pageTitle = null;\n this.boundPushStateClick = this.eventPushStateClick.bind(this);\n this.boundPopState = this.eventPopState.bind(this);\n this.boundMediatorNavigate = (event: Event) => {\n const detail = (event as CustomEvent<unknown>).detail;\n if (detail === undefined || detail === null) {\n this.navigate(undefined, {}, false);\n return;\n }\n if (typeof detail !== 'object' || Array.isArray(detail)) {return;}\n const data = detail as NavigationData;\n this.navigate(data.url, data, false);\n };\n this.listenersInitialized = false;\n }\n\n /** Event target that can send `router:navigate` events, or `false` for none. */\n get mediator(): NavigationMediator | false {return this.currentMediator;}\n\n /** Set the mediator. If listeners are active, the `router:navigate` listener moves from the old one to the new one. */\n set mediator(value: NavigationMediator | false) {\n if (value === this.currentMediator) {return;}\n if (this.listenersInitialized && this.boundMediator) {\n this.boundMediator.removeEventListener('router:navigate', this.boundMediatorNavigate);\n this.boundMediator = false;\n }\n this.currentMediator = value;\n if (this.listenersInitialized && value) {\n value.addEventListener('router:navigate', this.boundMediatorNavigate);\n this.boundMediator = value;\n }\n }\n\n /** Element or document whose `data-pushstate` link clicks this router handles; `null` means the whole document. */\n get navigationRoot(): Document | Element | null {return this.currentNavigationRoot;}\n\n /** Set the click root. If listeners are active, the click listener moves to the new root. */\n set navigationRoot(value: Document | Element | null) {\n if (value === this.currentNavigationRoot) {return;}\n if (this.listenersInitialized && this.isBrowserRuntime()) {\n this.boundNavigationRoot?.removeEventListener('click', this.boundPushStateClick as EventListener);\n this.currentNavigationRoot = value;\n const nextRoot = value || document;\n nextRoot.addEventListener('click', this.boundPushStateClick as EventListener);\n this.boundNavigationRoot = nextRoot;\n return;\n }\n this.currentNavigationRoot = value;\n }\n\n /** True when `window` and `document` exist, i.e. browser-only effects should run. */\n private isBrowserRuntime() {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n }\n\n /** Origin used as the base for URL parsing: the page's origin in a browser, a dummy one on a server. */\n private getOrigin() {\n return this.isBrowserRuntime() ? window.location.origin : 'http://white-label.invalid';\n }\n\n /** Current path, query, and hash: from `window.location` in a browser, or the last committed URL (default `/`) on a server. */\n private getCurrentUrl() {\n if (!this.isBrowserRuntime()) {return this.url || '/';}\n return window.location.pathname + window.location.search + (window.location.hash || '');\n }\n\n /** Parse a URL relative to the current page (or the dummy server origin). Returns `null` if it can't be parsed. */\n private parseNavigationUrl(url: string) {\n try {\n const base = this.isBrowserRuntime() ? window.location.href || `${window.location.origin}/` : this.getOrigin();\n return new URL(url || '/', base);\n } catch (_error) {\n return null;\n }\n }\n\n /** In a browser, reduce a URL to its path, query, and hash, or `null` if it is cross-origin or invalid. */\n private normalizeBrowserUrl(url: string) {\n if (!this.isBrowserRuntime()) {return url;}\n const parsedUrl = this.parseNavigationUrl(url);\n if (!parsedUrl || parsedUrl.origin !== window.location.origin) {return null;}\n return `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;\n }\n\n /** True if the route has something to run: a function, a `view` function, or a `view.initialize`. */\n private isRunnableRoute(route: Route): boolean {\n return typeof route === 'function' || typeof route.view === 'function' ||\n Boolean(route.view && typeof route.view.initialize === 'function');\n }\n\n /**\n * Index the current route keys and match against that index without re-reading the keys on every navigation.\n * Without it, each match lists the keys of `routes` to notice in-place edits, which costs time in proportion to\n * the number of routes. Use it for large route tables that stop changing after setup. Assigning a different object to\n * `routes` drops the index; after adding or removing keys on the same object, call `indexRoutes()` again. Until then,\n * an added key is not matched, and a removed key still claims its paths, so `navigate()` returns `false` for them\n * as it does for a key set to `undefined`.\n * Replacing the value of an existing key needs no re-index, because the route is looked up when it runs.\n * @returns This router.\n */\n indexRoutes() {\n this.indexedRoutes = undefined;\n this.compileRoutes();\n this.indexedRoutes = this.routes;\n return this;\n }\n\n /** Build (or reuse) the lookup tables for the current route keys. Reused while the own key list is unchanged. */\n private compileRoutes(): CompiledRoutes {\n const cached = this.compiledRoutes;\n if (cached && this.indexedRoutes === this.routes) {return cached;}\n this.indexedRoutes = undefined;\n const keys = Object.keys(this.routes);\n if (cached && cached.keys.length === keys.length && cached.keys.every((key, index) => key === keys[index])) {\n return cached;\n }\n const prefixes = new Map<string, string>();\n const prefixFor = new Map<string, string>();\n for (const key of keys) {\n if (key === 'defaultRoute') {continue;}\n const prefix = normalizeRouteKey(key);\n prefixFor.set(key, prefix);\n const existing = prefixes.get(prefix);\n // When two keys normalize to the same path, prefer the one already in normalized form, then the alphabetically\n // lowest, so the winner never depends on insertion order.\n if (existing === undefined || (existing !== prefix && (key === prefix || key < existing))) {prefixes.set(prefix, key);}\n }\n this.compiledRoutes = {keys, prefixes, prefixFor};\n return this.compiledRoutes;\n }\n\n /** Find the route key with the longest matching path prefix, else `'defaultRoute'` if one is set, else `null`. */\n private matchRoute(pathname: string): string | null {\n const {prefixes} = this.compileRoutes();\n // Try the full path, then drop one '/segment' at a time; the first hit is the longest match.\n // Cutting only at '/' means '/products' matches '/products/42' but not '/products-old'.\n let candidateRoute = prefixes.get(pathname);\n let index = pathname.lastIndexOf('/');\n while (candidateRoute === undefined && index >= 0) {\n candidateRoute = prefixes.get(pathname.slice(0, index));\n index = index > 0 ? pathname.lastIndexOf('/', index - 1) : -1;\n }\n if (candidateRoute !== undefined) {return candidateRoute;}\n if (Object.prototype.hasOwnProperty.call(this.routes, 'defaultRoute') && this.routes.defaultRoute) {\n return 'defaultRoute';\n }\n return null;\n }\n\n /** Length of the normalized path for a route key, used to slice the matched prefix off `data.url`; 0 for `defaultRoute`. */\n private routePrefixLength(route: string | null) {\n if (!route || route === 'defaultRoute') {return 0;}\n return (this.compileRoutes().prefixFor.get(route) ?? normalizeRouteKey(route)).length;\n }\n\n /** Parse a URL Router committed earlier. A path is prefixed with the origin first, so '//x' stays a path, not a host. */\n private parseStoredUrl(url: string) {\n if (!url.startsWith('/')) {return this.parseNavigationUrl(url);}\n try {\n return new URL(`${this.getOrigin()}${url}`);\n } catch (_error) {\n return null;\n }\n }\n\n /** Build the location object passed to route callbacks. Path segments that fail to decode are kept as-is. */\n private buildLocationData(url: string, route: string | null, mediatorData: NavigationData | undefined, parsedUrl: URL): LocationData {\n return {\n url,\n data: {\n url: parsedUrl.pathname\n .slice(this.routePrefixLength(route))\n .split('/')\n .filter(Boolean)\n .map((fragment) => {\n try {return decodeURIComponent(fragment);} catch (_error) {return fragment;}\n }),\n mediator: mediatorData,\n query: this.parseQueryString(parsedUrl.search)\n }\n };\n }\n\n /**\n * Attach listeners and dispatch the starting URL. Does not add a history entry or move focus.\n * @param url - Request URL on a server. In a browser, omit it to use `window.location`.\n * @returns This router.\n * @throws Whatever a guard or route callback throws.\n */\n initialize(url?: string) {\n this.addListeners();\n // The browser has already placed focus on the page it just loaded, so only later navigations move it.\n this.initialDispatch = true;\n try {\n this.navigate(url ?? this.getCurrentUrl(), {}, true);\n } finally {\n this.initialDispatch = false;\n }\n return this;\n }\n\n /**\n * Attach the click and popstate listeners (browser only) and the mediator listener. Safe to call more than once.\n * @returns This router.\n */\n addListeners() {\n if (this.listenersInitialized) {return this;}\n if (this.isBrowserRuntime()) {\n const navigationRoot = this.currentNavigationRoot || document;\n navigationRoot.addEventListener('click', this.boundPushStateClick as EventListener);\n this.boundNavigationRoot = navigationRoot;\n window.addEventListener('popstate', this.boundPopState);\n }\n if (this.currentMediator) {\n this.currentMediator.addEventListener('router:navigate', this.boundMediatorNavigate);\n this.boundMediator = this.currentMediator;\n }\n this.listenersInitialized = true;\n return this;\n }\n\n /**\n * Remove this router's listeners. Does not call the active route's `destroy()`.\n * @returns This router.\n */\n destroy() {\n this.removeListeners();\n return this;\n }\n\n /**\n * Remove the listeners `addListeners()` attached. Subclasses can override this to release more.\n * @returns This router.\n */\n removeListeners() {\n if (!this.listenersInitialized) {return this;}\n if (this.isBrowserRuntime()) {\n this.boundNavigationRoot?.removeEventListener('click', this.boundPushStateClick as EventListener);\n this.boundNavigationRoot = null;\n window.removeEventListener('popstate', this.boundPopState);\n }\n if (this.boundMediator) {\n this.boundMediator.removeEventListener('router:navigate', this.boundMediatorNavigate);\n this.boundMediator = false;\n }\n this.listenersInitialized = false;\n return this;\n }\n\n /**\n * Click handler for `<a href data-pushstate>` links. Takes over only when Router can handle the link:\n * a plain left click on a same-origin link (no `download`, no other `target`) whose route is app-defined,\n * runnable, and allowed by its guard, and that is not just a `#fragment` of the current page. Anything else is left\n * to the browser.\n * @param e - The click event.\n * @returns This router if it handled the click, otherwise `true`.\n * @throws Whatever a guard or route callback throws.\n */\n eventPushStateClick(e: MouseEvent) {\n if (typeof window === 'undefined') {return true;}\n if (e.defaultPrevented || (e.button !== undefined && e.button !== 0) || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {\n return true;\n }\n const eventTarget = e.target as Element | null;\n const source = eventTarget && (typeof eventTarget.closest === 'function' ? eventTarget : eventTarget.parentElement);\n const anchor = source && typeof source.closest === 'function' ? source.closest('a[href][data-pushstate]') : null;\n if (!anchor) {return true;}\n const target = anchor.getAttribute('target');\n if (anchor.hasAttribute('download') || (target && target.toLowerCase() !== '_self')) {return true;}\n // Read the attribute, because on an SVG <a> the href property is an SVGAnimatedString, not a URL.\n const href = anchor.getAttribute('href') ?? '';\n const baseUrl = typeof document !== 'undefined' && document.baseURI\n ? document.baseURI\n : window.location.href || `${window.location.origin}/`;\n let location: URL;\n try {location = new URL(href, baseUrl);} catch {return true;}\n if (location.origin !== window.location.origin) {return true;}\n // A link to a #fragment of the page already shown is native fragment navigation: let the browser scroll to it.\n // Its popstate then only updates `url`, matching the fragment-only back/forward rule.\n if (location.href.includes('#') && location.pathname === window.location.pathname && location.search === window.location.search) {\n return true;\n }\n const candidateRoute = this.matchRoute(location.pathname);\n const selected = candidateRoute ? this.routes[candidateRoute] : undefined;\n if (!selected || !this.isRunnableRoute(selected) || builtInDefaultRoutes.has(selected)) {return true;}\n // Guards are synchronous, so try the navigation first and cancel the browser's default only if Router took it.\n // A rejected (or throwing) guard therefore falls back to a normal page load. If the route committed and then\n // threw, the token has moved, so the default is still cancelled and the browser doesn't navigate twice.\n const token = this.navigationToken;\n let handled = false;\n try {\n handled = this.navigate(`${location.pathname}${location.search}${location.hash}`, {}, false) !== false;\n } finally {\n if (handled || this.navigationToken !== token) {e.preventDefault();}\n }\n return handled ? this : true;\n }\n\n /**\n * Popstate handler for back/forward. Runs the route for the new URL without adding a history entry.\n * A hash-only change just updates `url` and `locationData.url`.\n * @returns This router.\n */\n eventPopState() {\n if (typeof window === 'undefined') {return this;}\n const currentUrl = this.getCurrentUrl();\n // Moving between #fragments on the same page (footnotes, skip links) keeps the current view and focus.\n if (this.route !== null && withoutHash(currentUrl) === withoutHash(this.url)) {\n this.url = currentUrl;\n this.locationData = {...this.locationData, url: currentUrl};\n return this;\n }\n this.navigate(currentUrl, {}, true);\n return this;\n }\n\n /**\n * Decode a query string into a plain object. For repeated keys the last value wins.\n * @param queryString - Query string, with or without the leading `?`.\n */\n parseQueryString(queryString: string) {\n return Object.fromEntries(new URLSearchParams(queryString));\n }\n\n /**\n * Rebuild `locationData` from the current `url` and `route`. Leaves it unchanged if the URL can't be parsed.\n * @param mediatorData - Value to expose as `locationData.data.mediator`.\n */\n setLocationData(mediatorData?: NavigationData) {\n const parsedUrl = this.parseStoredUrl(this.url || '/');\n if (!parsedUrl) {return;}\n this.locationData = this.buildLocationData(this.url, this.route, mediatorData, parsedUrl);\n }\n\n /**\n * Record the route's title in `pageTitle` and, in a browser, set `document.title` and move focus to the route's\n * `focus` selector (default `main h1`), adding `tabindex=\"-1\"` if needed. `focus: false` skips focus.\n * @param route - The route that just ran.\n * @returns This router.\n */\n applyPageContext(route: Route) {\n if (typeof route === 'function') {\n this.pageTitle = null;\n return this;\n }\n this.pageTitle = typeof route.title === 'string' ? route.title : null;\n if (!this.isBrowserRuntime()) {return this;}\n if (this.pageTitle) {document.title = this.pageTitle;}\n if (route.focus !== false && !this.suppressFocus) {\n const target = document.querySelector<HTMLElement>(route.focus || 'main h1');\n if (target) {\n if (!target.hasAttribute('tabindex')) {target.setAttribute('tabindex', '-1');}\n target.focus();\n }\n }\n return this;\n }\n\n /**\n * Navigate to a URL: match the route, run its guard, commit the new state, call the previous route's `destroy()`,\n * run the new route, apply title and focus, then push a history entry (browser only, unless `isPopState`).\n * If route code starts another navigation part-way through, that one wins and this call stops early.\n * @param url - Destination URL. Omit to re-run the last committed URL (or the current browser URL / `/` at first).\n * @param mediatorData - Value exposed to the route as `location.data.mediator`.\n * @param isPopState - `true` to skip adding a history entry.\n * @returns This router, or `false` if the navigation was rejected (bad or cross-origin URL, no matching route,\n * guard refused, or nothing to run). A rejected navigation changes nothing.\n * @throws Whatever a guard or route callback throws. A throwing guard changes nothing; a throwing route stays committed.\n */\n navigate(url?: string, mediatorData?: NavigationData, isPopState = false) {\n const skipFocus = this.initialDispatch;\n this.initialDispatch = false;\n if (url !== undefined && typeof url !== 'string') {return false;}\n\n const candidateInput = url !== undefined ? url : this.url;\n let parsedUrl: URL | null;\n if (!candidateInput) {\n parsedUrl = this.parseNavigationUrl(this.getCurrentUrl());\n } else {\n parsedUrl = url === undefined ? this.parseStoredUrl(candidateInput) : this.parseNavigationUrl(candidateInput);\n }\n if (!parsedUrl) {return false;}\n if (this.isBrowserRuntime() && parsedUrl.origin !== window.location.origin) {return false;}\n\n // Store only path, query, and hash, even when a server passed an absolute URL.\n const candidateUrl = `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;\n const candidateRoute = this.matchRoute(parsedUrl.pathname);\n if (!candidateRoute) {return false;}\n\n const candidateLocationData = this.buildLocationData(candidateUrl, candidateRoute, mediatorData, parsedUrl);\n const selected = this.routes[candidateRoute];\n if (!selected || (typeof selected !== 'function' && selected.secure && selected.secure(this.scope, candidateLocationData) !== true) ||\n !this.isRunnableRoute(selected)) {\n return false;\n }\n\n const token = ++this.navigationToken;\n this.url = candidateUrl;\n this.route = candidateRoute;\n this.locationData = candidateLocationData;\n // Clear the stored teardown before calling it, so a navigation started inside destroy() can't call it again,\n // and a destroy() that throws is not retried: its error propagates with the destination committed but not run.\n const previous = this.activeDestroy;\n this.activeDestroy = undefined;\n if (previous) {\n previous.callback.call(previous.receiver, this.scope, candidateLocationData);\n if (token !== this.navigationToken) {return this;}\n }\n const selectedView = typeof selected !== 'function' && typeof selected.view === 'object'\n ? selected.view\n : undefined;\n // Store the teardown before initialize() runs, so it still runs later if initialize() throws or navigates away.\n this.activeDestroy = selectedView?.destroy\n ? {receiver: selectedView, callback: selectedView.destroy}\n : undefined;\n if (typeof selected === 'function') {\n selected(this.scope, candidateLocationData);\n } else if (typeof selected.view === 'function') {\n selected.view(this.scope, candidateLocationData);\n } else {\n selectedView!.initialize!(this.scope, candidateLocationData);\n }\n // If initialize() started another navigation, that one has already applied its own title, focus, and history.\n if (token !== this.navigationToken) {return this;}\n this.suppressFocus = skipFocus;\n try {\n this.applyPageContext(selected);\n } finally {\n this.suppressFocus = false;\n }\n if (token !== this.navigationToken) {return this;}\n this.previousRoute = this.route;\n // Re-running the current URL (no `url` given, e.g. a mediator event without a destination) must not add a\n // duplicate history entry for the address already shown.\n if (!isPopState && this.isBrowserRuntime() && !(url === undefined && parsedUrl.href === window.location.href)) {\n window.history.pushState(this.url, this.pageTitle || '', parsedUrl.href);\n }\n return this;\n }\n}\n\n/** Types for route definitions, location data, and navigation data. */\nnamespace Router {\n export type Handler = RouteHandler;\n export type Route = RouteHandler | RouteObject;\n export type Location = LocationData;\n export type Navigation = NavigationData;\n}\nexport = Router;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "white-label-router",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "Framework-independent TypeScript router for progressive enhancement in browser, server-rendered, and Node.js applications, with scoped links, guards, and accessible navigation.",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -64,13 +64,13 @@
|
|
|
64
64
|
"lint:fix": "node --run lint -- --fix"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@babel/core": "8.0.
|
|
68
|
-
"@babel/eslint-parser": "8.0.
|
|
69
|
-
"@babel/preset-typescript": "8.0.
|
|
67
|
+
"@babel/core": "8.0.7",
|
|
68
|
+
"@babel/eslint-parser": "8.0.7",
|
|
69
|
+
"@babel/preset-typescript": "8.0.7",
|
|
70
70
|
"@eslint/js": "10.0.1",
|
|
71
|
-
"@types/node": "24.
|
|
71
|
+
"@types/node": "24.19.2",
|
|
72
72
|
"c8": "12.0.0",
|
|
73
|
-
"eslint": "10.
|
|
73
|
+
"eslint": "10.13.0",
|
|
74
74
|
"playwright": "1.64.1",
|
|
75
75
|
"typescript": "7.0.2"
|
|
76
76
|
},
|