@reidelsaltres/pureper 0.1.89 → 0.1.91

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.
@@ -20,5 +20,10 @@ export declare abstract class Router {
20
20
  static tryFindRoute(url: URL): Route;
21
21
  static registerRoute<T extends UniHtml>(path: string, route: string, pageFactory: (search?: URLSearchParams) => T, inheritedRoute?: Route): Promise<Route>;
22
22
  private static createPage;
23
+ private static normalizeIncomingUrl;
24
+ private static normalizeRoutePath;
25
+ private static extractRelativePath;
26
+ private static resolveRouteHref;
27
+ private static buildHostedUrl;
23
28
  }
24
29
  //# sourceMappingURL=Router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../../src/foundation/worker/Router.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,6BAA6B,CAAC;AAElD,MAAM,WAAW,KAAK,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IAEb,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,eAAe,KAAK,CAAC,CAAC;CAC9C;AACD,oBAAY,UAAU;IACpB,OAAO,IAAA;IACP,MAAM,IAAA;IACN,IAAI,IAAA;CACL;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,EAAO,CAAC;AAClC,eAAO,MAAM,QAAQ,EAAE,MAAM,EAAO,CAAC;AAErC,8BAAsB,MAAM;WACZ,kBAAkB,CAAC,GAAG,EAAE,GAAG;WAO3B,iBAAiB,IAAI,GAAG,GAAG,IAAI;WAS/B,mBAAmB;WASnB,aAAa,CAAC,KAAK,EAAE,MAAM;WAM3B,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,GAAE,OAAc;WAc9C,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,KAAK;WASvB,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,eAAe,KAAK,CAAC,EAC5H,cAAc,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAezC,OAAO,CAAC,MAAM,CAAC,UAAU;CAG1B"}
1
+ {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../../src/foundation/worker/Router.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,6BAA6B,CAAC;AAKlD,MAAM,WAAW,KAAK,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IAEb,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,eAAe,KAAK,CAAC,CAAC;CAC9C;AACD,oBAAY,UAAU;IACpB,OAAO,IAAA;IACP,MAAM,IAAA;IACN,IAAI,IAAA;CACL;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,EAAO,CAAC;AAClC,eAAO,MAAM,QAAQ,EAAE,MAAM,EAAO,CAAC;AAErC,8BAAsB,MAAM;WACZ,kBAAkB,CAAC,GAAG,EAAE,GAAG;WAO3B,iBAAiB,IAAI,GAAG,GAAG,IAAI;WAS/B,mBAAmB;WAQnB,aAAa,CAAC,KAAK,EAAE,MAAM;WAO3B,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,GAAE,OAAc;WAmB9C,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,KAAK;WASvB,aAAa,CAAC,CAAC,SAAS,OAAO,EACjD,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,eAAe,KAAK,CAAC,EAC5C,cAAc,CAAC,EAAE,KAAK,GACrB,OAAO,CAAC,KAAK,CAAC;IAejB,OAAO,CAAC,MAAM,CAAC,UAAU;IAIzB,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAQnC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAWjC,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAkBlC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAa/B,OAAO,CAAC,MAAM,CAAC,cAAc;CAY9B"}
@@ -1,4 +1,6 @@
1
1
  import { HOSTING, HOSTING_ORIGIN } from "../../index.js";
2
+ const HOSTING_BASE = HOSTING.endsWith("/") ? HOSTING.slice(0, -1) : HOSTING;
3
+ const ABSOLUTE_URL_PATTERN = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
2
4
  export var AccessType;
3
5
  (function (AccessType) {
4
6
  AccessType[AccessType["OFFLINE"] = 0] = "OFFLINE";
@@ -35,75 +37,160 @@ export class Router {
35
37
  }
36
38
  }
37
39
  static legacyRouteTo(route) {
38
- let url = new URL(route, HOSTING_ORIGIN);
39
- if (window.location.pathname !== route) {
40
- window.location.replace(url.href);
40
+ const target = Router.resolveRouteHref(route);
41
+ if (window.location.href !== target.href) {
42
+ window.location.replace(target.href);
41
43
  }
42
44
  }
43
45
  static tryRouteTo(url, pushState = true) {
44
- const urlH = new URL(url.href, HOSTING_ORIGIN);
45
46
  try {
46
- const found = this.tryFindRoute(urlH);
47
- const page = this.createPage(found, url.searchParams);
48
- page.load(document.getElementById('page'));
47
+ const normalizedUrl = Router.normalizeIncomingUrl(url);
48
+ const found = Router.tryFindRoute(normalizedUrl);
49
+ const page = Router.createPage(found, normalizedUrl.searchParams);
50
+ page.load(document.getElementById("page"));
51
+ const hostedUrl = Router.buildHostedUrl(normalizedUrl);
49
52
  if (pushState && typeof window !== "undefined" && window.location) {
50
- window.history.pushState(page, '', urlH.href);
53
+ window.history.pushState(page, "", hostedUrl.href);
51
54
  }
55
+ window.dispatchEvent(new CustomEvent("spa:navigated", { detail: { url: hostedUrl } }));
52
56
  }
53
57
  catch (error) {
54
- console.error("[Router]: Unable to route to ", urlH.href, error);
58
+ console.error("[Router]: Unable to route to ", url.href, error);
55
59
  }
56
60
  }
57
61
  static tryFindRoute(url) {
58
- const tt = HOSTING.substring(0, HOSTING.length - 1) + url.pathname;
59
- const found = ROUTES.find(r => r.route === tt);
62
+ const relativePath = Router.normalizeRoutePath(Router.extractRelativePath(url.pathname));
63
+ const found = ROUTES.find((r) => r.route === relativePath);
60
64
  if (!found) {
61
65
  throw new Error(`[Router]: Route not found: ${url.pathname}`);
62
66
  }
63
67
  return found;
64
68
  }
65
69
  static async registerRoute(path, route, pageFactory, inheritedRoute) {
66
- let prepRoute = route;
67
- let fullRoute = inheritedRoute ? inheritedRoute.route + prepRoute : prepRoute;
68
- const tt = HOSTING.substring(0, HOSTING.length - 1) + fullRoute;
69
- let routeObj = { route: tt, path, pageFactory };
70
+ const normalizedRouteSegment = Router.normalizeRoutePath(route);
71
+ const compositeRoute = inheritedRoute
72
+ ? Router.normalizeRoutePath(`${inheritedRoute.route}${normalizedRouteSegment}`)
73
+ : normalizedRouteSegment;
74
+ const routeObj = { route: compositeRoute, path, pageFactory };
70
75
  ROUTES.push(routeObj);
71
- console.log(`[Router]: Registered route: ${tt} -> ${path}`);
76
+ const hostedPreview = Router.buildHostedUrl(new URL(compositeRoute, window.location.origin));
77
+ console.log(`[Router]: Registered route: ${hostedPreview.pathname} -> ${path}`);
72
78
  return Promise.resolve(routeObj);
73
79
  }
74
80
  static createPage(route, search) {
75
81
  return route.pageFactory(search);
76
82
  }
83
+ static normalizeIncomingUrl(url) {
84
+ if (url.origin && url.origin !== window.location.origin) {
85
+ return url;
86
+ }
87
+ return new URL(url.href, window.location.origin);
88
+ }
89
+ static normalizeRoutePath(route) {
90
+ if (!route || route === "/") {
91
+ return "/";
92
+ }
93
+ const withSlash = route.startsWith("/") ? route : `/${route}`;
94
+ const collapsed = withSlash.replace(/\/{2,}/g, "/");
95
+ const withoutTrailing = collapsed.length > 1 && collapsed.endsWith("/") ? collapsed.slice(0, -1) : collapsed;
96
+ return withoutTrailing === "" ? "/" : withoutTrailing;
97
+ }
98
+ static extractRelativePath(pathname) {
99
+ if (!pathname) {
100
+ return "/";
101
+ }
102
+ const ensuredPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
103
+ if (HOSTING_BASE && ensuredPath.startsWith(HOSTING_BASE)) {
104
+ const trimmed = ensuredPath.slice(HOSTING_BASE.length);
105
+ if (!trimmed || trimmed === "") {
106
+ return "/";
107
+ }
108
+ return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
109
+ }
110
+ return ensuredPath;
111
+ }
112
+ static resolveRouteHref(route) {
113
+ if (!route || route === "/") {
114
+ return new URL("./", HOSTING_ORIGIN);
115
+ }
116
+ if (ABSOLUTE_URL_PATTERN.test(route)) {
117
+ return new URL(route);
118
+ }
119
+ const normalized = route.startsWith("/") ? `.${route}` : route;
120
+ return new URL(normalized, HOSTING_ORIGIN);
121
+ }
122
+ static buildHostedUrl(url) {
123
+ if (url.origin && url.origin !== window.location.origin) {
124
+ return url;
125
+ }
126
+ const relativePath = Router.normalizeRoutePath(Router.extractRelativePath(url.pathname));
127
+ const routeSegment = relativePath === "/" ? "./" : `.${relativePath}`;
128
+ const hosted = new URL(routeSegment, HOSTING_ORIGIN);
129
+ hosted.search = url.search;
130
+ hosted.hash = url.hash;
131
+ return hosted;
132
+ }
77
133
  }
78
- //For SPA navigation
79
- document.addEventListener('click', e => {
80
- const target = e.target;
81
- if (target) {
82
- const link = target.closest('a[data-link]') ?? target.closest('re-button[data-link]');
83
- if (link) {
84
- e.preventDefault();
85
- const url = new URL(link.getAttribute('href'), HOSTING_ORIGIN);
86
- Router.tryRouteTo(url);
134
+ const resolveLocalNavigationUrl = (rawHref) => {
135
+ if (!rawHref) {
136
+ return null;
137
+ }
138
+ const trimmed = rawHref.trim();
139
+ if (trimmed === "" || trimmed.toLowerCase().startsWith("javascript:")) {
140
+ return null;
141
+ }
142
+ try {
143
+ const candidate = ABSOLUTE_URL_PATTERN.test(trimmed)
144
+ ? new URL(trimmed)
145
+ : new URL(trimmed, window.location.href);
146
+ if (candidate.origin !== window.location.origin) {
147
+ return null;
87
148
  }
149
+ return candidate;
150
+ }
151
+ catch {
152
+ return null;
88
153
  }
154
+ };
155
+ // For SPA navigation
156
+ document.addEventListener("click", (e) => {
157
+ const target = e.target;
158
+ if (!target) {
159
+ return;
160
+ }
161
+ const link = target.closest("a[data-link]") ?? target.closest("re-button[data-link]");
162
+ if (!link) {
163
+ return;
164
+ }
165
+ const resolved = resolveLocalNavigationUrl(link.getAttribute("href"));
166
+ if (!resolved) {
167
+ return;
168
+ }
169
+ e.preventDefault();
170
+ Router.tryRouteTo(resolved);
89
171
  });
90
- //For back/forward navigation
91
- window.addEventListener('popstate', e => {
172
+ // For back/forward navigation
173
+ window.addEventListener("popstate", () => {
92
174
  try {
93
- const url = new URL(window.location.href, HOSTING_ORIGIN);
175
+ const url = new URL(window.location.href);
94
176
  Router.tryRouteTo(url, false);
95
177
  }
96
178
  catch (error) {
97
- console.error('[Router] (popstate): failed to route to current location', error);
179
+ console.error("[Router] (popstate): failed to route to current location", error);
98
180
  }
99
181
  });
100
- window.addEventListener('DOMContentLoaded', () => {
101
- const checkRoutes = () => {
102
- const routes = ROUTES;
103
- if (routes) {
104
- console.log('[Init] [Router]: available routes =', routes.map(r => r.route).join(', '));
105
- }
106
- };
107
- checkRoutes();
182
+ window.addEventListener("DOMContentLoaded", () => {
183
+ const routes = ROUTES;
184
+ if (routes.length > 0) {
185
+ const hostedRoutes = routes.map((r) => describeHostedPath(r.route));
186
+ console.log("[Init] [Router]: available routes =", hostedRoutes.join(", "));
187
+ }
108
188
  });
189
+ const describeHostedPath = (route) => {
190
+ if (!route || route === "/") {
191
+ return new URL("./", HOSTING_ORIGIN).pathname;
192
+ }
193
+ const segment = route.startsWith("/") ? `.${route}` : route;
194
+ return new URL(segment, HOSTING_ORIGIN).pathname;
195
+ };
109
196
  //# sourceMappingURL=Router.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Router.js","sourceRoot":"","sources":["../../../src/foundation/worker/Router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Router.js","sourceRoot":"","sources":["../../../src/foundation/worker/Router.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAE1D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAG,MAAM,EAAC,MAAM,kCAAkC,CAAC;AAEvE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAEhF,cAAc,uBAAuB,CAAC;AAGtC,eAAO,MAAM,OAAO,EAAE,MAEjB,CAAC;AAEN,eAAO,MAAM,cAAc,EAAE,MAAyC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAE1D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAG,MAAM,EAAC,MAAM,kCAAkC,CAAC;AAEvE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAEhF,cAAc,uBAAuB,CAAC;AA+BtC,eAAO,MAAM,OAAO,EAAE,MAA6B,CAAC;AAEpD,eAAO,MAAM,cAAc,EAAE,MAA8C,CAAC"}
package/out/index.js CHANGED
@@ -9,9 +9,29 @@ export { default as Fetcher } from './foundation/Fetcher.js';
9
9
  export { Router } from './foundation/worker/Router.js';
10
10
  export { default as ServiceWorker } from './foundation/worker/ServiceWorker.js';
11
11
  export * from './foundation/Theme.js';
12
- // derive the part of href after the origin (e.g. "/path?query#hash")
13
- export const HOSTING = window.location.href.startsWith(window.location.origin)
14
- ? window.location.href.substring(window.location.origin.length)
15
- : "";
16
- export const HOSTING_ORIGIN = window.location.origin + HOSTING;
12
+ const computeHostingPath = () => {
13
+ if (typeof window === "undefined" || typeof window.location === "undefined") {
14
+ return "/";
15
+ }
16
+ const pathname = window.location.pathname || "/";
17
+ if (pathname === "") {
18
+ return "/";
19
+ }
20
+ if (pathname.endsWith("/")) {
21
+ return pathname;
22
+ }
23
+ const lastSlash = pathname.lastIndexOf("/");
24
+ if (lastSlash <= 0) {
25
+ // either no slash at all or only the leading slash
26
+ return pathname.includes(".") ? "/" : `${pathname}/`;
27
+ }
28
+ const lastSegment = pathname.slice(lastSlash + 1);
29
+ if (lastSegment && !lastSegment.includes(".")) {
30
+ // we are on a nested route without trailing slash — treat it as a directory
31
+ return `${pathname}/`;
32
+ }
33
+ return pathname.slice(0, lastSlash + 1);
34
+ };
35
+ export const HOSTING = computeHostingPath();
36
+ export const HOSTING_ORIGIN = `${window.location.origin}${HOSTING}`;
17
37
  //# sourceMappingURL=index.js.map
package/out/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAE1D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAG,MAAM,EAAC,MAAM,kCAAkC,CAAC;AAEvE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAEhF,cAAc,uBAAuB,CAAC;AAEtC,qEAAqE;AACrE,MAAM,CAAC,MAAM,OAAO,GAAW,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IACrF,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IAC/D,CAAC,CAAC,EAAE,CAAC;AAEN,MAAM,CAAC,MAAM,cAAc,GAAW,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAE1D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAG,MAAM,EAAC,MAAM,kCAAkC,CAAC;AAEvE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAEhF,cAAc,uBAAuB,CAAC;AAEtC,MAAM,kBAAkB,GAAG,GAAW,EAAE;IACvC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC7E,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC;IACjD,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QACrB,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACpB,mDAAmD;QACnD,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC;IACtD,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IAClD,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,4EAA4E;QAC5E,OAAO,GAAG,QAAQ,GAAG,CAAC;IACvB,CAAC;IAED,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAW,kBAAkB,EAAE,CAAC;AAEpD,MAAM,CAAC,MAAM,cAAc,GAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,OAAO,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reidelsaltres/pureper",
3
- "version": "0.1.89",
3
+ "version": "0.1.91",
4
4
  "description": "Minimal library extracted from the Pureper SPA foundation — utilities and base classes for components/pages.",
5
5
  "type": "module",
6
6
  "main": "out/src/index.js",
@@ -1,6 +1,9 @@
1
1
  import { HOSTING, HOSTING_ORIGIN } from "../../index.js";
2
2
  import UniHtml from "../component_api/UniHtml.js";
3
3
 
4
+ const HOSTING_BASE = HOSTING.endsWith("/") ? HOSTING.slice(0, -1) : HOSTING;
5
+ const ABSOLUTE_URL_PATTERN = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
6
+
4
7
  export interface Route<T extends UniHtml = UniHtml> {
5
8
  route: string;
6
9
  path: string;
@@ -41,48 +44,57 @@ export abstract class Router {
41
44
  }
42
45
  }
43
46
 
44
-
45
47
  public static legacyRouteTo(route: string) {
46
- let url = new URL(route, HOSTING_ORIGIN);
47
- if (window.location.pathname !== route) {
48
- window.location.replace(url.href);
48
+ const target = Router.resolveRouteHref(route);
49
+ if (window.location.href !== target.href) {
50
+ window.location.replace(target.href);
49
51
  }
50
52
  }
53
+
51
54
  public static tryRouteTo(url: URL, pushState: boolean = true) {
52
- const urlH = new URL(url.href, HOSTING_ORIGIN);
53
55
  try {
54
- const found: Route = this.tryFindRoute(urlH);
55
- const page: UniHtml = this.createPage(found, url.searchParams);
56
+ const normalizedUrl = Router.normalizeIncomingUrl(url);
57
+ const found: Route = Router.tryFindRoute(normalizedUrl);
58
+ const page: UniHtml = Router.createPage(found, normalizedUrl.searchParams);
59
+
60
+ page.load(document.getElementById("page")!);
56
61
 
57
- page.load(document.getElementById('page')!);
62
+ const hostedUrl = Router.buildHostedUrl(normalizedUrl);
58
63
  if (pushState && typeof window !== "undefined" && window.location) {
59
- window.history.pushState(page, '', urlH.href);
64
+ window.history.pushState(page, "", hostedUrl.href);
60
65
  }
66
+
67
+ window.dispatchEvent(new CustomEvent("spa:navigated", { detail: { url: hostedUrl } }));
61
68
  } catch (error) {
62
- console.error("[Router]: Unable to route to ", urlH.href, error);
69
+ console.error("[Router]: Unable to route to ", url.href, error);
63
70
  }
64
71
  }
72
+
65
73
  public static tryFindRoute(url: URL): Route {
66
- const tt = HOSTING.substring(0, HOSTING.length - 1) + url.pathname;
67
- const found = ROUTES.find(r => r.route === tt);
74
+ const relativePath = Router.normalizeRoutePath(Router.extractRelativePath(url.pathname));
75
+ const found = ROUTES.find((r) => r.route === relativePath);
68
76
  if (!found) {
69
77
  throw new Error(`[Router]: Route not found: ${url.pathname}`);
70
78
  }
71
79
  return found;
72
80
  }
73
81
 
74
- public static async registerRoute<T extends UniHtml>(path: string, route: string, pageFactory: (search?: URLSearchParams) => T,
75
- inheritedRoute?: Route): Promise<Route> {
76
-
77
- let prepRoute = route
78
- let fullRoute = inheritedRoute ? inheritedRoute.route + prepRoute : prepRoute;
82
+ public static async registerRoute<T extends UniHtml>(
83
+ path: string,
84
+ route: string,
85
+ pageFactory: (search?: URLSearchParams) => T,
86
+ inheritedRoute?: Route
87
+ ): Promise<Route> {
88
+ const normalizedRouteSegment = Router.normalizeRoutePath(route);
89
+ const compositeRoute = inheritedRoute
90
+ ? Router.normalizeRoutePath(`${inheritedRoute.route}${normalizedRouteSegment}`)
91
+ : normalizedRouteSegment;
79
92
 
80
- const tt = HOSTING.substring(0, HOSTING.length - 1) + fullRoute;
81
-
82
- let routeObj: Route = { route: tt, path, pageFactory };
93
+ const routeObj: Route = { route: compositeRoute, path, pageFactory };
83
94
 
84
95
  ROUTES.push(routeObj);
85
- console.log(`[Router]: Registered route: ${tt} -> ${path}`);
96
+ const hostedPreview = Router.buildHostedUrl(new URL(compositeRoute, window.location.origin));
97
+ console.log(`[Router]: Registered route: ${hostedPreview.pathname} -> ${path}`);
86
98
 
87
99
  return Promise.resolve(routeObj);
88
100
  }
@@ -90,38 +102,140 @@ export abstract class Router {
90
102
  private static createPage(route: Route, search?: URLSearchParams): UniHtml {
91
103
  return route.pageFactory(search);
92
104
  }
105
+
106
+ private static normalizeIncomingUrl(url: URL): URL {
107
+ if (url.origin && url.origin !== window.location.origin) {
108
+ return url;
109
+ }
110
+
111
+ return new URL(url.href, window.location.origin);
112
+ }
113
+
114
+ private static normalizeRoutePath(route: string): string {
115
+ if (!route || route === "/") {
116
+ return "/";
117
+ }
118
+
119
+ const withSlash = route.startsWith("/") ? route : `/${route}`;
120
+ const collapsed = withSlash.replace(/\/{2,}/g, "/");
121
+ const withoutTrailing = collapsed.length > 1 && collapsed.endsWith("/") ? collapsed.slice(0, -1) : collapsed;
122
+ return withoutTrailing === "" ? "/" : withoutTrailing;
123
+ }
124
+
125
+ private static extractRelativePath(pathname: string): string {
126
+ if (!pathname) {
127
+ return "/";
128
+ }
129
+
130
+ const ensuredPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
131
+
132
+ if (HOSTING_BASE && ensuredPath.startsWith(HOSTING_BASE)) {
133
+ const trimmed = ensuredPath.slice(HOSTING_BASE.length);
134
+ if (!trimmed || trimmed === "") {
135
+ return "/";
136
+ }
137
+ return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
138
+ }
139
+
140
+ return ensuredPath;
141
+ }
142
+
143
+ private static resolveRouteHref(route: string): URL {
144
+ if (!route || route === "/") {
145
+ return new URL("./", HOSTING_ORIGIN);
146
+ }
147
+
148
+ if (ABSOLUTE_URL_PATTERN.test(route)) {
149
+ return new URL(route);
150
+ }
151
+
152
+ const normalized = route.startsWith("/") ? `.${route}` : route;
153
+ return new URL(normalized, HOSTING_ORIGIN);
154
+ }
155
+
156
+ private static buildHostedUrl(url: URL): URL {
157
+ if (url.origin && url.origin !== window.location.origin) {
158
+ return url;
159
+ }
160
+
161
+ const relativePath = Router.normalizeRoutePath(Router.extractRelativePath(url.pathname));
162
+ const routeSegment = relativePath === "/" ? "./" : `.${relativePath}`;
163
+ const hosted = new URL(routeSegment, HOSTING_ORIGIN);
164
+ hosted.search = url.search;
165
+ hosted.hash = url.hash;
166
+ return hosted;
167
+ }
93
168
  }
94
169
 
95
- //For SPA navigation
96
- document.addEventListener('click', e => {
97
- const target = e.target as Element | null;
98
- if (target) {
99
- const link = target.closest('a[data-link]') ?? target.closest('re-button[data-link]');
100
- if (link) {
101
- e.preventDefault();
102
- const url : URL = new URL(link.getAttribute('href')!, HOSTING_ORIGIN);
103
- Router.tryRouteTo(url);
170
+ const resolveLocalNavigationUrl = (rawHref: string | null): URL | null => {
171
+ if (!rawHref) {
172
+ return null;
173
+ }
174
+
175
+ const trimmed = rawHref.trim();
176
+ if (trimmed === "" || trimmed.toLowerCase().startsWith("javascript:")) {
177
+ return null;
178
+ }
179
+
180
+ try {
181
+ const candidate = ABSOLUTE_URL_PATTERN.test(trimmed)
182
+ ? new URL(trimmed)
183
+ : new URL(trimmed, window.location.href);
184
+
185
+ if (candidate.origin !== window.location.origin) {
186
+ return null;
104
187
  }
188
+
189
+ return candidate;
190
+ } catch {
191
+ return null;
192
+ }
193
+ };
194
+
195
+ // For SPA navigation
196
+ document.addEventListener("click", (e) => {
197
+ const target = e.target as Element | null;
198
+ if (!target) {
199
+ return;
200
+ }
201
+
202
+ const link = target.closest("a[data-link]") ?? target.closest("re-button[data-link]");
203
+ if (!link) {
204
+ return;
205
+ }
206
+
207
+ const resolved = resolveLocalNavigationUrl(link.getAttribute("href"));
208
+ if (!resolved) {
209
+ return;
105
210
  }
211
+
212
+ e.preventDefault();
213
+ Router.tryRouteTo(resolved);
106
214
  });
107
215
 
108
- //For back/forward navigation
109
- window.addEventListener('popstate', e => {
216
+ // For back/forward navigation
217
+ window.addEventListener("popstate", () => {
110
218
  try {
111
- const url = new URL(window.location.href, HOSTING_ORIGIN);
219
+ const url = new URL(window.location.href);
112
220
  Router.tryRouteTo(url, false);
113
221
  } catch (error) {
114
- console.error('[Router] (popstate): failed to route to current location', error);
222
+ console.error("[Router] (popstate): failed to route to current location", error);
115
223
  }
116
224
  });
117
225
 
118
- window.addEventListener('DOMContentLoaded', () => {
119
- const checkRoutes = () => {
120
- const routes = ROUTES;
121
- if (routes) {
122
- console.log('[Init] [Router]: available routes =', routes.map(r => r.route).join(', '));
123
- }
124
- };
226
+ window.addEventListener("DOMContentLoaded", () => {
227
+ const routes = ROUTES;
228
+ if (routes.length > 0) {
229
+ const hostedRoutes = routes.map((r) => describeHostedPath(r.route));
230
+ console.log("[Init] [Router]: available routes =", hostedRoutes.join(", "));
231
+ }
232
+ });
233
+
234
+ const describeHostedPath = (route: string): string => {
235
+ if (!route || route === "/") {
236
+ return new URL("./", HOSTING_ORIGIN).pathname;
237
+ }
125
238
 
126
- checkRoutes();
127
- });
239
+ const segment = route.startsWith("/") ? `.${route}` : route;
240
+ return new URL(segment, HOSTING_ORIGIN).pathname;
241
+ };
package/src/index.ts CHANGED
@@ -19,9 +19,35 @@ export { default as ServiceWorker } from './foundation/worker/ServiceWorker.js';
19
19
 
20
20
  export * from './foundation/Theme.js';
21
21
 
22
- // derive the part of href after the origin (e.g. "/path?query#hash")
23
- export const HOSTING: string = window.location.href.startsWith(window.location.origin)
24
- ? window.location.href.substring(window.location.origin.length)
25
- : "";
26
-
27
- export const HOSTING_ORIGIN: string = window.location.origin + HOSTING;
22
+ const computeHostingPath = (): string => {
23
+ if (typeof window === "undefined" || typeof window.location === "undefined") {
24
+ return "/";
25
+ }
26
+
27
+ const pathname = window.location.pathname || "/";
28
+ if (pathname === "") {
29
+ return "/";
30
+ }
31
+
32
+ if (pathname.endsWith("/")) {
33
+ return pathname;
34
+ }
35
+
36
+ const lastSlash = pathname.lastIndexOf("/");
37
+ if (lastSlash <= 0) {
38
+ // either no slash at all or only the leading slash
39
+ return pathname.includes(".") ? "/" : `${pathname}/`;
40
+ }
41
+
42
+ const lastSegment = pathname.slice(lastSlash + 1);
43
+ if (lastSegment && !lastSegment.includes(".")) {
44
+ // we are on a nested route without trailing slash — treat it as a directory
45
+ return `${pathname}/`;
46
+ }
47
+
48
+ return pathname.slice(0, lastSlash + 1);
49
+ };
50
+
51
+ export const HOSTING: string = computeHostingPath();
52
+
53
+ export const HOSTING_ORIGIN: string = `${window.location.origin}${HOSTING}`;