white-label-router 6.1.1 → 6.1.2

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 CHANGED
@@ -145,13 +145,13 @@ router.routes = {
145
145
  };
146
146
  ```
147
147
 
148
- `secure()` must return exactly `true` to allow navigation. Client guards are interface behavior, not server authorization. Router validates the destination guard and runnable view behavior before tearing down the current route. On a successful route change, the previous route's `destroy()` runs before the next route's `initialize()`.
148
+ `secure()` must return exactly `true` to allow navigation. Client guards are interface behavior, not server authorization. Router validates the destination guard and runnable view behavior before tearing down the current route. On a successful route change, the previous route's `destroy()` runs before the next route's `initialize()`. Router snapshots the destroy callback that belongs to the lifecycle that actually initialized, so later replacement or mutation of the route table does not retarget teardown. The destroy callback receives the incoming location as `nextLocation`. If browser title/focus work throws after a route has initialized, that initialized lifecycle remains owned and is still torn down before a later successful route starts.
149
149
 
150
150
  ## Matching
151
151
 
152
152
  Routes match complete path boundaries. `/products` matches `/products` and `/products/42`, but not `/products-old`.
153
153
 
154
- When multiple route prefixes match, Router selects the **longest matching route**, so specific routes win without depending on object insertion order. Only own route-table properties participate in matching:
154
+ When multiple route prefixes match, Router selects the **longest matching route**, so specific routes win without depending on object insertion order. Only own route-table properties participate in matching. If nothing matches and no own `defaultRoute` is configured, navigation is rejected; in browser click interception the real link remains native.
155
155
 
156
156
  ```js
157
157
  router.routes = {
@@ -190,7 +190,7 @@ const result = router.navigate('/products/42', {
190
190
 
191
191
  In browsers, successful navigation updates history unless the call represents `popstate`. On servers it dispatches without History API effects.
192
192
 
193
- Rejected navigation is atomic from Router's perspective: malformed or wrong-type URL candidates, cross-origin browser URLs, failed guards, and routes without runnable view behavior return `false` without destroying the current route, pushing browser history, or replacing the last successful URL, selected route, or location payload.
193
+ Rejected navigation is atomic from Router's perspective: malformed or wrong-type URL candidates, cross-origin browser URLs, URLs with no matching route/default route, failed guards, and routes without runnable view behavior return `false` without destroying the current route, pushing browser history, or replacing the last successful URL, selected route, or location payload.
194
194
 
195
195
  Calling `navigate()` without a URL dispatches the current browser URL. In a non-browser runtime the safe default is `/`; server applications should normally supply a fully qualified request URL explicitly.
196
196
 
package/dist/index.d.ts CHANGED
@@ -13,15 +13,16 @@ interface LocationData {
13
13
  };
14
14
  }
15
15
  type RouteHandler = (scope: Element | null, location: LocationData) => unknown;
16
+ interface RouteViewLifecycle {
17
+ initialize?: RouteHandler;
18
+ destroy?: RouteHandler;
19
+ }
16
20
  /** An object route can own a function or a view lifecycle. */
17
21
  interface RouteObject {
18
22
  title?: string;
19
23
  focus?: string | false;
20
24
  secure?: RouteHandler;
21
- view?: RouteHandler | {
22
- initialize?: RouteHandler;
23
- destroy?: RouteHandler;
24
- };
25
+ view?: RouteHandler | RouteViewLifecycle;
25
26
  }
26
27
  type Route = RouteHandler | RouteObject;
27
28
  /** Minimal standards-based event target contract required by the router. */
@@ -46,6 +47,7 @@ declare class Router {
46
47
  private boundMediator;
47
48
  private currentNavigationRoot;
48
49
  private boundNavigationRoot;
50
+ private activeDestroy;
49
51
  /** Create an instance with its own state and listener references. */
50
52
  constructor();
51
53
  get mediator(): NavigationMediator | false;
@@ -66,6 +68,8 @@ declare class Router {
66
68
  private normalizeBrowserUrl;
67
69
  /** Return whether a selected route has runnable view behavior. */
68
70
  private isRunnableRoute;
71
+ /** Return the longest matching own route-table prefix, falling back to defaultRoute when configured. */
72
+ private matchRoute;
69
73
  /** Build decoded path, query, and mediator data for a navigation candidate. */
70
74
  private buildLocationData;
71
75
  /**
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ class Router {
16
16
  boundMediator = false;
17
17
  currentNavigationRoot = null;
18
18
  boundNavigationRoot = null;
19
+ activeDestroy;
19
20
  /** Create an instance with its own state and listener references. */
20
21
  constructor() {
21
22
  this.routes = {
@@ -120,6 +121,22 @@ class Router {
120
121
  return typeof route === 'function' || typeof route.view === 'function' ||
121
122
  Boolean(route.view && typeof route.view.initialize === 'function');
122
123
  }
124
+ /** Return the longest matching own route-table prefix, falling back to defaultRoute when configured. */
125
+ matchRoute(pathname) {
126
+ let candidateRoute = null;
127
+ for (const route of Object.keys(this.routes)) {
128
+ if (route === 'defaultRoute' || (pathname !== route && !pathname.startsWith(`${route}/`))) {
129
+ continue;
130
+ }
131
+ if (!candidateRoute || route.length > candidateRoute.length) {
132
+ candidateRoute = route;
133
+ }
134
+ }
135
+ if (!candidateRoute && Object.prototype.hasOwnProperty.call(this.routes, 'defaultRoute') && this.routes.defaultRoute) {
136
+ return 'defaultRoute';
137
+ }
138
+ return candidateRoute;
139
+ }
123
140
  /** Build decoded path, query, and mediator data for a navigation candidate. */
124
141
  buildLocationData(url, route, mediatorData, parsedUrl) {
125
142
  const matchedRoute = route && route !== 'defaultRoute' ? route : '';
@@ -214,10 +231,21 @@ class Router {
214
231
  const baseUrl = typeof document !== 'undefined' && document.baseURI
215
232
  ? document.baseURI
216
233
  : window.location.href || `${window.location.origin}/`;
217
- const location = new URL(href, baseUrl);
234
+ let location;
235
+ try {
236
+ location = new URL(href, baseUrl);
237
+ }
238
+ catch {
239
+ return true;
240
+ }
218
241
  if (location.origin !== window.location.origin) {
219
242
  return true;
220
243
  }
244
+ const candidateRoute = this.matchRoute(location.pathname);
245
+ const selected = candidateRoute ? this.routes[candidateRoute] : undefined;
246
+ if (!selected || !this.isRunnableRoute(selected)) {
247
+ return true;
248
+ }
221
249
  e.preventDefault();
222
250
  this.navigate(`${location.pathname}${location.search}${location.hash}`, {}, false);
223
251
  return this;
@@ -290,31 +318,24 @@ class Router {
290
318
  const candidateUrl = this.isBrowserRuntime()
291
319
  ? `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`
292
320
  : candidateInput;
293
- let candidateRoute = null;
294
- for (const route of Object.keys(this.routes)) {
295
- if (route === 'defaultRoute' || (parsedUrl.pathname !== route && !parsedUrl.pathname.startsWith(`${route}/`))) {
296
- continue;
297
- }
298
- if (!candidateRoute || route.length > candidateRoute.length) {
299
- candidateRoute = route;
300
- }
301
- }
302
- if (!candidateRoute && Object.prototype.hasOwnProperty.call(this.routes, 'defaultRoute') && this.routes.defaultRoute) {
303
- candidateRoute = 'defaultRoute';
321
+ const candidateRoute = this.matchRoute(parsedUrl.pathname);
322
+ if (!candidateRoute) {
323
+ return false;
304
324
  }
305
325
  const candidateLocationData = this.buildLocationData(candidateUrl, candidateRoute, mediatorData, parsedUrl);
306
- const selected = candidateRoute ? this.routes[candidateRoute] : undefined;
307
- if (selected && ((typeof selected !== 'function' && selected.secure && selected.secure(this.scope, candidateLocationData) !== true) ||
308
- !this.isRunnableRoute(selected))) {
326
+ const selected = this.routes[candidateRoute];
327
+ if (!selected || (typeof selected !== 'function' && selected.secure && selected.secure(this.scope, candidateLocationData) !== true) ||
328
+ !this.isRunnableRoute(selected)) {
309
329
  return false;
310
330
  }
311
331
  this.url = candidateUrl;
312
332
  this.route = candidateRoute;
313
333
  this.locationData = candidateLocationData;
314
334
  if (selected) {
315
- const previous = this.previousRoute ? this.routes[this.previousRoute] : undefined;
316
- if (previous && typeof previous !== 'function' && typeof previous.view === 'object' && previous.view.destroy) {
317
- previous.view.destroy(this.scope, this.locationData);
335
+ if (this.activeDestroy) {
336
+ const { receiver, callback } = this.activeDestroy;
337
+ callback.call(receiver, this.scope, this.locationData);
338
+ this.activeDestroy = undefined;
318
339
  }
319
340
  if (typeof selected === 'function') {
320
341
  selected(this.scope, this.locationData);
@@ -325,6 +346,12 @@ class Router {
325
346
  else {
326
347
  selected.view.initialize(this.scope, this.locationData);
327
348
  }
349
+ const selectedView = typeof selected !== 'function' && typeof selected.view === 'object'
350
+ ? selected.view
351
+ : undefined;
352
+ this.activeDestroy = selectedView?.destroy
353
+ ? { receiver: selectedView, callback: selectedView.destroy }
354
+ : undefined;
328
355
  this.applyPageContext(selected);
329
356
  this.previousRoute = this.route;
330
357
  }
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":["/** Navigation payload, including caller-defined metadata. */\ninterface NavigationData {url?: string; [key: string]: unknown}\n/** URL-derived values supplied to route handlers. */\ninterface LocationData {url: string; data: {url: string[]; mediator: NavigationData | undefined; query: Record<string, string>}}\ntype RouteHandler = (scope: Element | null, location: LocationData) => unknown;\n/** An object route can own a function or a view lifecycle. */\ninterface RouteObject {title?: string; focus?: string | false; secure?: RouteHandler; view?: RouteHandler | {initialize?: RouteHandler; destroy?: RouteHandler}}\ntype Route = RouteHandler | RouteObject;\n/** Minimal standards-based event target contract required by the router. */\ninterface NavigationMediator {\n addEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;\n removeEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;\n}\n/** History API router that also dispatches request URLs in non-browser runtimes. */\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\n /** Create an instance with its own state and listener references. */\n constructor() {\n this.routes = {\n defaultRoute: {\n view: {\n initialize: () => true,\n destroy: () => true\n }\n }\n };\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 get mediator(): NavigationMediator | false {return this.currentMediator;}\n\n /** Move an active router:navigate subscription when the mediator changes. */\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 get navigationRoot(): Document | Element | null {return this.currentNavigationRoot;}\n\n /** Scope progressive link interception and move an active click listener when the root changes. */\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 browser navigation APIs are available. */\n private isBrowserRuntime() {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n }\n\n /** Stable base URL for WHATWG URL parsing in browser and server runtimes. */\n private getOrigin() {\n return this.isBrowserRuntime() ? window.location.origin : 'http://white-label.invalid';\n }\n\n /** Read the authoritative browser URL, or retain the supplied server URL. */\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 navigation candidate without changing Router state. */\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 /** Normalize browser navigation to a same-origin path, query, and hash. */\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 /** Return whether a selected route has runnable view behavior. */\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 /** Build decoded path, query, and mediator data for a navigation candidate. */\n private buildLocationData(url: string, route: string | null, mediatorData: NavigationData | undefined, parsedUrl: URL): LocationData {\n const matchedRoute = route && route !== 'defaultRoute' ? route : '';\n return {\n url,\n data: {\n url: parsedUrl.pathname\n .slice(matchedRoute.length)\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 * Start this instance and return it for lifecycle chaining.\n * In a browser the URL is optional and defaults to window.location. On a server pass the request URL.\n */\n initialize(url?: string) {\n this.addListeners();\n this.navigate(url ?? this.getCurrentUrl(), {}, true);\n return this;\n }\n\n /** Register browser and optional mediator handlers once. */\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 /** Release owned state and listeners so the instance can leave the application lifecycle. */\n destroy() {\n this.removeListeners();\n return this;\n }\n\n /** Release listeners owned by this instance; subclasses may extend the lifecycle hook. */\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 /** Intercept eligible same-origin push-state links while preserving normal browser actions. */\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 const href = (anchor as HTMLAnchorElement).href || anchor.getAttribute('href') || '';\n const baseUrl = typeof document !== 'undefined' && document.baseURI\n ? document.baseURI\n : window.location.href || `${window.location.origin}/`;\n const location = new URL(href, baseUrl);\n if (location.origin !== window.location.origin) {return true;}\n e.preventDefault();\n this.navigate(`${location.pathname}${location.search}${location.hash}`, {}, false);\n return this;\n }\n\n /** Restore browser history state without adding a new history entry. */\n eventPopState() {\n if (typeof window === 'undefined') {return this;}\n this.navigate(this.getCurrentUrl(), {}, true);\n return this;\n }\n\n /** Decode URL query parameters, keeping the last value for duplicate keys. */\n parseQueryString(queryString: string) {\n return Object.fromEntries(new URLSearchParams(queryString));\n }\n\n /** Build decoded path, query, and mediator data for the selected route. */\n setLocationData(mediatorData?: NavigationData) {\n const url = this.url || '/';\n let parsedUrl: URL;\n try {\n const value = this.isBrowserRuntime() ? `${window.location.origin}${url}` : url;\n parsedUrl = new URL(value, this.getOrigin());\n } catch (_error) {\n return;\n }\n this.locationData = this.buildLocationData(this.url, this.route, mediatorData, parsedUrl);\n }\n\n /** Update page context after a route renders. DOM effects are browser-only. */\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) {\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 /** Select a route, enforce its guard, transition view lifecycles, and update browser history when available. */\n navigate(url?: string, mediatorData?: NavigationData, isPopState = false) {\n if (url !== undefined && typeof url !== 'string') {return false;}\n\n let candidateInput = url !== undefined ? url : this.url;\n if (!candidateInput) {candidateInput = this.getCurrentUrl();}\n const parsedUrl = this.parseNavigationUrl(candidateInput);\n if (!parsedUrl) {return false;}\n if (this.isBrowserRuntime() && parsedUrl.origin !== window.location.origin) {return false;}\n\n const candidateUrl = this.isBrowserRuntime()\n ? `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`\n : candidateInput;\n let candidateRoute: string | null = null;\n for (const route of Object.keys(this.routes)) {\n if (route === 'defaultRoute' || (parsedUrl.pathname !== route && !parsedUrl.pathname.startsWith(`${route}/`))) {continue;}\n if (!candidateRoute || route.length > candidateRoute.length) {candidateRoute = route;}\n }\n if (!candidateRoute && Object.prototype.hasOwnProperty.call(this.routes, 'defaultRoute') && this.routes.defaultRoute) {\n candidateRoute = 'defaultRoute';\n }\n\n const candidateLocationData = this.buildLocationData(candidateUrl, candidateRoute, mediatorData, parsedUrl);\n const selected = candidateRoute ? this.routes[candidateRoute] : undefined;\n if (selected && ((typeof selected !== 'function' && selected.secure && selected.secure(this.scope, candidateLocationData) !== true) ||\n !this.isRunnableRoute(selected))) {\n return false;\n }\n\n this.url = candidateUrl;\n this.route = candidateRoute;\n this.locationData = candidateLocationData;\n if (selected) {\n const previous = this.previousRoute ? this.routes[this.previousRoute] : undefined;\n if (previous && typeof previous !== 'function' && typeof previous.view === 'object' && previous.view.destroy) {\n previous.view.destroy(this.scope, this.locationData);\n }\n if (typeof selected === 'function') {\n selected(this.scope, this.locationData);\n } else if (typeof selected.view === 'function') {\n selected.view(this.scope, this.locationData);\n } else {\n selected.view!.initialize!(this.scope, this.locationData);\n }\n this.applyPageContext(selected);\n this.previousRoute = this.route;\n }\n if (!isPopState && this.isBrowserRuntime()) {\n window.history.pushState(this.url, this.pageTitle || '', parsedUrl.href);\n }\n return this;\n }\n}\n\n/** Public route configuration and navigation payload types. */\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":["/** Navigation payload, including caller-defined metadata. */\ninterface NavigationData {url?: string; [key: string]: unknown}\n/** URL-derived values supplied to route handlers. */\ninterface LocationData {url: string; data: {url: string[]; mediator: NavigationData | undefined; query: Record<string, string>}}\ntype RouteHandler = (scope: Element | null, location: LocationData) => unknown;\ninterface RouteViewLifecycle {initialize?: RouteHandler; destroy?: RouteHandler}\n/** An object route can own a function or a view lifecycle. */\ninterface RouteObject {title?: string; focus?: string | false; secure?: RouteHandler; view?: RouteHandler | RouteViewLifecycle}\ntype Route = RouteHandler | RouteObject;\ninterface ActiveDestroy {receiver: RouteViewLifecycle; callback: RouteHandler}\n/** Minimal standards-based event target contract required by the router. */\ninterface NavigationMediator {\n addEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;\n removeEventListener(type: string, callback: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;\n}\n/** History API router that also dispatches request URLs in non-browser runtimes. */\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\n /** Create an instance with its own state and listener references. */\n constructor() {\n this.routes = {\n defaultRoute: {\n view: {\n initialize: () => true,\n destroy: () => true\n }\n }\n };\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 get mediator(): NavigationMediator | false {return this.currentMediator;}\n\n /** Move an active router:navigate subscription when the mediator changes. */\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 get navigationRoot(): Document | Element | null {return this.currentNavigationRoot;}\n\n /** Scope progressive link interception and move an active click listener when the root changes. */\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 browser navigation APIs are available. */\n private isBrowserRuntime() {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n }\n\n /** Stable base URL for WHATWG URL parsing in browser and server runtimes. */\n private getOrigin() {\n return this.isBrowserRuntime() ? window.location.origin : 'http://white-label.invalid';\n }\n\n /** Read the authoritative browser URL, or retain the supplied server URL. */\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 navigation candidate without changing Router state. */\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 /** Normalize browser navigation to a same-origin path, query, and hash. */\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 /** Return whether a selected route has runnable view behavior. */\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 /** Return the longest matching own route-table prefix, falling back to defaultRoute when configured. */\n private matchRoute(pathname: string): string | null {\n let candidateRoute: string | null = null;\n for (const route of Object.keys(this.routes)) {\n if (route === 'defaultRoute' || (pathname !== route && !pathname.startsWith(`${route}/`))) {continue;}\n if (!candidateRoute || route.length > candidateRoute.length) {candidateRoute = route;}\n }\n if (!candidateRoute && Object.prototype.hasOwnProperty.call(this.routes, 'defaultRoute') && this.routes.defaultRoute) {\n return 'defaultRoute';\n }\n return candidateRoute;\n }\n\n\n /** Build decoded path, query, and mediator data for a navigation candidate. */\n private buildLocationData(url: string, route: string | null, mediatorData: NavigationData | undefined, parsedUrl: URL): LocationData {\n const matchedRoute = route && route !== 'defaultRoute' ? route : '';\n return {\n url,\n data: {\n url: parsedUrl.pathname\n .slice(matchedRoute.length)\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 * Start this instance and return it for lifecycle chaining.\n * In a browser the URL is optional and defaults to window.location. On a server pass the request URL.\n */\n initialize(url?: string) {\n this.addListeners();\n this.navigate(url ?? this.getCurrentUrl(), {}, true);\n return this;\n }\n\n /** Register browser and optional mediator handlers once. */\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 /** Release owned state and listeners so the instance can leave the application lifecycle. */\n destroy() {\n this.removeListeners();\n return this;\n }\n\n /** Release listeners owned by this instance; subclasses may extend the lifecycle hook. */\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 /** Intercept eligible same-origin push-state links while preserving normal browser actions. */\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 const href = (anchor as HTMLAnchorElement).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 const candidateRoute = this.matchRoute(location.pathname);\n const selected = candidateRoute ? this.routes[candidateRoute] : undefined;\n if (!selected || !this.isRunnableRoute(selected)) {return true;}\n e.preventDefault();\n this.navigate(`${location.pathname}${location.search}${location.hash}`, {}, false);\n return this;\n }\n\n /** Restore browser history state without adding a new history entry. */\n eventPopState() {\n if (typeof window === 'undefined') {return this;}\n this.navigate(this.getCurrentUrl(), {}, true);\n return this;\n }\n\n /** Decode URL query parameters, keeping the last value for duplicate keys. */\n parseQueryString(queryString: string) {\n return Object.fromEntries(new URLSearchParams(queryString));\n }\n\n /** Build decoded path, query, and mediator data for the selected route. */\n setLocationData(mediatorData?: NavigationData) {\n const url = this.url || '/';\n let parsedUrl: URL;\n try {\n const value = this.isBrowserRuntime() ? `${window.location.origin}${url}` : url;\n parsedUrl = new URL(value, this.getOrigin());\n } catch (_error) {\n return;\n }\n this.locationData = this.buildLocationData(this.url, this.route, mediatorData, parsedUrl);\n }\n\n /** Update page context after a route renders. DOM effects are browser-only. */\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) {\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 /** Select a route, enforce its guard, transition view lifecycles, and update browser history when available. */\n navigate(url?: string, mediatorData?: NavigationData, isPopState = false) {\n if (url !== undefined && typeof url !== 'string') {return false;}\n\n let candidateInput = url !== undefined ? url : this.url;\n if (!candidateInput) {candidateInput = this.getCurrentUrl();}\n const parsedUrl = this.parseNavigationUrl(candidateInput);\n if (!parsedUrl) {return false;}\n if (this.isBrowserRuntime() && parsedUrl.origin !== window.location.origin) {return false;}\n\n const candidateUrl = this.isBrowserRuntime()\n ? `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`\n : candidateInput;\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 this.url = candidateUrl;\n this.route = candidateRoute;\n this.locationData = candidateLocationData;\n if (selected) {\n if (this.activeDestroy) {\n const {receiver, callback} = this.activeDestroy;\n callback.call(receiver, this.scope, this.locationData);\n this.activeDestroy = undefined;\n }\n if (typeof selected === 'function') {\n selected(this.scope, this.locationData);\n } else if (typeof selected.view === 'function') {\n selected.view(this.scope, this.locationData);\n } else {\n selected.view!.initialize!(this.scope, this.locationData);\n }\n const selectedView = typeof selected !== 'function' && typeof selected.view === 'object'\n ? selected.view\n : undefined;\n this.activeDestroy = selectedView?.destroy\n ? {receiver: selectedView, callback: selectedView.destroy}\n : undefined;\n this.applyPageContext(selected);\n this.previousRoute = this.route;\n }\n if (!isPopState && this.isBrowserRuntime()) {\n window.history.pushState(this.url, this.pageTitle || '', parsedUrl.href);\n }\n return this;\n }\n}\n\n/** Public route configuration and navigation payload types. */\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.1.1",
3
+ "version": "6.1.2",
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",