crelte 0.4.8 → 0.5.0-alpha.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.
Files changed (110) hide show
  1. package/dist/Crelte.d.ts +7 -6
  2. package/dist/Crelte.d.ts.map +1 -1
  3. package/dist/Crelte.js +5 -13
  4. package/dist/CrelteRequest.d.ts +9 -0
  5. package/dist/CrelteRequest.d.ts.map +1 -1
  6. package/dist/CrelteRequest.js +16 -2
  7. package/dist/blocks/Blocks.svelte +2 -2
  8. package/dist/blocks/Blocks.svelte.d.ts +3 -19
  9. package/dist/blocks/Blocks.svelte.d.ts.map +1 -1
  10. package/dist/cookies/ClientCookies.d.ts +0 -1
  11. package/dist/cookies/ClientCookies.d.ts.map +1 -1
  12. package/dist/cookies/ClientCookies.js +0 -1
  13. package/dist/cookies/ServerCookies.d.ts +1 -2
  14. package/dist/cookies/ServerCookies.d.ts.map +1 -1
  15. package/dist/cookies/ServerCookies.js +2 -6
  16. package/dist/cookies/index.d.ts +0 -2
  17. package/dist/cookies/index.d.ts.map +1 -1
  18. package/dist/graphql/GraphQl.d.ts +2 -2
  19. package/dist/graphql/GraphQl.d.ts.map +1 -1
  20. package/dist/index.d.ts +9 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +14 -6
  23. package/dist/init/InternalApp.d.ts +30 -0
  24. package/dist/init/InternalApp.d.ts.map +1 -0
  25. package/dist/init/InternalApp.js +71 -0
  26. package/dist/init/client.d.ts +0 -5
  27. package/dist/init/client.d.ts.map +1 -1
  28. package/dist/init/client.js +88 -75
  29. package/dist/init/crelte-vite-plugin.d.ts +5 -0
  30. package/dist/init/server.d.ts +0 -5
  31. package/dist/init/server.d.ts.map +1 -1
  32. package/dist/init/server.js +49 -20
  33. package/dist/init/shared.d.ts +7 -18
  34. package/dist/init/shared.d.ts.map +1 -1
  35. package/dist/init/shared.js +97 -154
  36. package/dist/init/svelteComponents.d.ts +3 -0
  37. package/dist/init/svelteComponents.d.ts.map +1 -0
  38. package/dist/init/svelteComponents.js +7 -0
  39. package/dist/loadData/Globals.d.ts +40 -33
  40. package/dist/loadData/Globals.d.ts.map +1 -1
  41. package/dist/loadData/Globals.js +99 -88
  42. package/dist/loadData/index.d.ts +3 -2
  43. package/dist/loadData/index.d.ts.map +1 -1
  44. package/dist/loadData/index.js +2 -0
  45. package/dist/plugins/Events.d.ts +11 -13
  46. package/dist/plugins/Events.d.ts.map +1 -1
  47. package/dist/plugins/Events.js +10 -3
  48. package/dist/routing/BaseRoute.d.ts +255 -0
  49. package/dist/routing/BaseRoute.d.ts.map +1 -0
  50. package/dist/routing/BaseRoute.js +349 -0
  51. package/dist/routing/BaseRouter.d.ts +210 -0
  52. package/dist/routing/BaseRouter.d.ts.map +1 -0
  53. package/dist/routing/BaseRouter.js +444 -0
  54. package/dist/routing/ClientRouter.d.ts +32 -0
  55. package/dist/routing/ClientRouter.d.ts.map +1 -0
  56. package/dist/routing/ClientRouter.js +259 -0
  57. package/dist/routing/LoadRunner.d.ts +39 -0
  58. package/dist/routing/LoadRunner.d.ts.map +1 -0
  59. package/dist/routing/{PageLoader.js → LoadRunner.js} +32 -20
  60. package/dist/routing/Request.d.ts +35 -3
  61. package/dist/routing/Request.d.ts.map +1 -1
  62. package/dist/routing/Request.js +64 -5
  63. package/dist/routing/Route.d.ts +24 -223
  64. package/dist/routing/Route.d.ts.map +1 -1
  65. package/dist/routing/Route.js +26 -315
  66. package/dist/routing/Router.d.ts +49 -73
  67. package/dist/routing/Router.d.ts.map +1 -1
  68. package/dist/routing/Router.js +85 -251
  69. package/dist/routing/ServerRouter.d.ts +23 -0
  70. package/dist/routing/ServerRouter.d.ts.map +1 -0
  71. package/dist/routing/ServerRouter.js +57 -0
  72. package/dist/routing/utils.d.ts +5 -0
  73. package/dist/routing/utils.d.ts.map +1 -1
  74. package/dist/routing/utils.js +39 -0
  75. package/dist/utils.d.ts +1 -0
  76. package/dist/utils.d.ts.map +1 -1
  77. package/dist/utils.js +3 -0
  78. package/package.json +7 -6
  79. package/src/Crelte.ts +12 -18
  80. package/src/CrelteRequest.ts +21 -2
  81. package/src/cookies/ClientCookies.ts +0 -2
  82. package/src/cookies/ServerCookies.ts +2 -7
  83. package/src/cookies/index.ts +0 -3
  84. package/src/graphql/GraphQl.ts +2 -1
  85. package/src/index.ts +17 -9
  86. package/src/init/InternalApp.ts +134 -0
  87. package/src/init/client.ts +104 -93
  88. package/src/init/crelte-vite-plugin.d.ts +5 -0
  89. package/src/init/server.ts +67 -35
  90. package/src/init/shared.ts +107 -227
  91. package/src/init/svelteComponents.ts +12 -0
  92. package/src/loadData/Globals.ts +121 -102
  93. package/src/loadData/index.ts +3 -2
  94. package/src/plugins/Events.ts +40 -42
  95. package/src/routing/BaseRoute.ts +422 -0
  96. package/src/routing/BaseRouter.ts +528 -0
  97. package/src/routing/ClientRouter.ts +329 -0
  98. package/src/routing/{PageLoader.ts → LoadRunner.ts} +43 -30
  99. package/src/routing/Request.ts +97 -12
  100. package/src/routing/Route.ts +56 -376
  101. package/src/routing/Router.ts +100 -359
  102. package/src/routing/ServerRouter.ts +78 -0
  103. package/src/routing/utils.ts +53 -0
  104. package/src/utils.ts +4 -0
  105. package/dist/routing/InnerRouter.d.ts +0 -113
  106. package/dist/routing/InnerRouter.d.ts.map +0 -1
  107. package/dist/routing/InnerRouter.js +0 -417
  108. package/dist/routing/PageLoader.d.ts +0 -36
  109. package/dist/routing/PageLoader.d.ts.map +0 -1
  110. package/src/routing/InnerRouter.ts +0 -498
@@ -1,3 +1,56 @@
1
1
  export function trimSlashEnd(str: string) {
2
2
  return str.endsWith('/') ? str.substring(0, str.length - 1) : str;
3
3
  }
4
+
5
+ /**
6
+ * `parseAcceptLang('fr-CH, en;q=0.7, fr;q=0.8')` will return `[['fr-CH', 1], ['fr', 0.8], ['en', 0.7]]`
7
+ */
8
+ function parseAcceptLang(acceptLang: string): [string, number][] {
9
+ return acceptLang
10
+ .split(',')
11
+ .map(d => {
12
+ // eslint-disable-next-line prefer-const
13
+ let [lang, pq] = d.split(';');
14
+ lang = lang.trim();
15
+ if (!lang) return null;
16
+
17
+ let quality = 1;
18
+ if (pq?.startsWith('q=')) {
19
+ const q = parseFloat(pq.substring(2));
20
+ if (!isNaN(q)) quality = q;
21
+ }
22
+
23
+ return [lang, quality] as [string, number];
24
+ })
25
+ .filter(d => !!d)
26
+ .sort((a, b) => b[1] - a[1]);
27
+ }
28
+
29
+ /**
30
+ * if no match was found null is returned
31
+ * `matchAcceptLang('fr-CH, en;q=0.7, fr;q=0.8', ['en-GB'])` will return `en-GB`
32
+ */
33
+ export function matchAcceptLang(
34
+ acceptLang: string,
35
+ langs: string[],
36
+ ): string | null {
37
+ const qualities = new Map(
38
+ parseAcceptLang(acceptLang).map(([l, q]) => [l.toLowerCase(), q]),
39
+ );
40
+
41
+ return langs.reduce<{ lang: string | null; q: number }>(
42
+ (best, lang) => {
43
+ const lowerLang = lang.toLowerCase();
44
+ // this might splitting to much
45
+ const [p1, p2] = lowerLang.split('-');
46
+
47
+ const q1 = qualities.get(lowerLang) ?? 0;
48
+ const q2 = p2 ? (qualities.get(p1) ?? 0) : 0;
49
+
50
+ const q = Math.max(q1, q2);
51
+
52
+ return best.q < q ? { lang, q } : best;
53
+ },
54
+ { lang: null, q: 0 },
55
+ ).lang;
56
+ }
package/src/utils.ts CHANGED
@@ -9,5 +9,9 @@ export function objClone(obj: any): any {
9
9
  return JSON.parse(JSON.stringify(obj));
10
10
  }
11
11
 
12
+ export function isPromise<T>(p: Promise<T> | T): p is Promise<T> {
13
+ return typeof (p as any)?.then === 'function';
14
+ }
15
+
12
16
  // this allows us to fix cyclic dependencies
13
17
  export const circles: Record<string, any> = {};
@@ -1,113 +0,0 @@
1
- import Site, { SiteFromGraphQl } from './Site.js';
2
- import History from './History.js';
3
- import Request, { RequestOptions } from './Request.js';
4
- import Route from './Route.js';
5
- export type InnerRouterOpts = {
6
- preloadOnMouseOver: boolean;
7
- };
8
- /**
9
- * Manages event listeners or functions.
10
- */
11
- export default class InnerRouter {
12
- sites: Site[];
13
- /**
14
- * The current route
15
- *
16
- * ## Null
17
- * It might be null on the first targetToRequest, open, and routeFromUrl call
18
- */
19
- route: Route | null;
20
- history: History;
21
- preloadOnMouseOver: boolean;
22
- /**
23
- * @param changeHistory returns a function you need to call when you are ready to
24
- update the window history (note do not call this after another onRoute call was made)
25
- */
26
- onRoute: (route: Request, changeHistory: () => void) => void;
27
- onPreload: (route: Request) => void;
28
- private scrollDebounceTimeout;
29
- /**
30
- * Creates a new Router
31
- *
32
- * @param sites - sites needs to be from craft-graphql-sites plugin
33
- * @param opts - Options for the router
34
- */
35
- constructor(sites: SiteFromGraphQl[], opts: InnerRouterOpts);
36
- /**
37
- * Initializes the router when running on the client.
38
- */
39
- initClient(): void;
40
- /**
41
- * Initializes the router when running on the server.
42
- */
43
- initServer(): void;
44
- /**
45
- * Get a site and if possible use the accept lang header.
46
- *
47
- * @param acceptLang Accept Language header.
48
- */
49
- siteByAcceptLang(acceptLang?: string | null): Site;
50
- /**
51
- * Get the default site
52
- */
53
- defaultSite(): Site;
54
- /**
55
- * Tries to get a site by it's id
56
- */
57
- siteById(id: number): Site | null;
58
- /**
59
- * Resolve a url or Route and convert it to a Request
60
- *
61
- * @param target
62
- * @param opts, any option present will override the value in target
63
- * @return Returns null if the url does not match our host (the protocol get's ignored)
64
- */
65
- targetToRequest(target: string | URL | Route | Request, opts?: RequestOptions): Request;
66
- /**
67
- * Resolve a url and convert it to a Route
68
- *
69
- * @param url
70
- * @return Returns null if the url does not match our host (the protocol get's ignored)
71
- */
72
- routeFromUrl(fullUrl: URL): Route;
73
- listen(): void;
74
- /**
75
- * Open a new route
76
- *
77
- * @param route a route object or an url or uri, never input the same route object again
78
- * @param pushState if true pushed the state to the window.history
79
- *
80
- * ## Important
81
- * Make sure a req always has the correct origin,
82
- * `push` and `replace` will cause this function to throw an error
83
- */
84
- open(req: Request): void;
85
- /**
86
- * This pushes a new route to the history
87
- *
88
- * @param req, never input the same route object again
89
- *
90
- * ## Important
91
- * Make sure the route has the correct origin
92
- */
93
- push(req: Request): void;
94
- /**
95
- * This replaces the current route
96
- *
97
- * @param req, never input the same route object again
98
- *
99
- * ## Important
100
- * Make sure the route has the correct origin
101
- */
102
- replace(req: Request): void;
103
- /**
104
- * Preload a url
105
- *
106
- * This will only work if the origin of the url matches the current site
107
- *
108
- * @param url
109
- */
110
- preload(target: string | URL | Route | Request): void;
111
- domReady(req: Request): void;
112
- }
113
- //# sourceMappingURL=InnerRouter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"InnerRouter.d.ts","sourceRoot":"","sources":["../../src/routing/InnerRouter.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,EAAE,EAAE,eAAe,EAAe,MAAM,WAAW,CAAC;AAC/D,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,OAAO,EAAE,EAAa,cAAc,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,MAAM,MAAM,eAAe,GAAG;IAC7B,kBAAkB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAW;IAC/B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;;;OAKG;IACH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC7D,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAEpC,OAAO,CAAC,qBAAqB,CAAa;IAE1C;;;;;OAKG;gBACS,KAAK,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,eAAe;IAkB3D;;OAEG;IACH,UAAU;IAgBV;;OAEG;IACH,UAAU;IAEV;;;;OAIG;IACH,gBAAgB,CAAC,UAAU,GAAE,MAAM,GAAG,IAAW,GAAG,IAAI;IAsCxD;;OAEG;IACH,WAAW,IAAI,IAAI;IAInB;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKjC;;;;;;OAMG;IACH,eAAe,CACd,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,KAAK,GAAG,OAAO,EACtC,IAAI,GAAE,cAAmB,GACvB,OAAO;IA0BV;;;;;OAKG;IACH,YAAY,CAAC,OAAO,EAAE,GAAG,GAAG,KAAK;IAcjC,MAAM;IAiGN;;;;;;;;;OASG;IACH,IAAI,CAAC,GAAG,EAAE,OAAO;IA6CjB;;;;;;;OAOG;IACH,IAAI,CAAC,GAAG,EAAE,OAAO;IAuBjB;;;;;;;OAOG;IACH,OAAO,CAAC,GAAG,EAAE,OAAO;IAuBpB;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,KAAK,GAAG,OAAO;IAW9C,QAAQ,CAAC,GAAG,EAAE,OAAO;CAsErB"}
@@ -1,417 +0,0 @@
1
- import Site, { siteFromUrl } from './Site.js';
2
- import { ClientHistory, ServerHistory } from './History.js';
3
- import Request, { isRequest } from './Request.js';
4
- import Route from './Route.js';
5
- /**
6
- * Manages event listeners or functions.
7
- */
8
- export default class InnerRouter {
9
- sites;
10
- /**
11
- * The current route
12
- *
13
- * ## Null
14
- * It might be null on the first targetToRequest, open, and routeFromUrl call
15
- */
16
- route;
17
- history;
18
- preloadOnMouseOver;
19
- /**
20
- * @param changeHistory returns a function you need to call when you are ready to
21
- update the window history (note do not call this after another onRoute call was made)
22
- */
23
- onRoute;
24
- onPreload;
25
- scrollDebounceTimeout;
26
- /**
27
- * Creates a new Router
28
- *
29
- * @param sites - sites needs to be from craft-graphql-sites plugin
30
- * @param opts - Options for the router
31
- */
32
- constructor(sites, opts) {
33
- this.sites = sites.map(s => new Site(s));
34
- this.route = null;
35
- // @ts-ignore
36
- this.history = import.meta.env.SSR
37
- ? new ServerHistory()
38
- : new ClientHistory();
39
- this.preloadOnMouseOver = opts.preloadOnMouseOver;
40
- // this.preloadListeners = new Listeners();
41
- this.onRoute = () => { };
42
- this.onPreload = () => { };
43
- this.scrollDebounceTimeout = null;
44
- }
45
- /**
46
- * Initializes the router when running on the client.
47
- */
48
- initClient() {
49
- this.listen();
50
- // let's first try to load from the state
51
- const req = this.targetToRequest(window.location.href);
52
- req._fillFromState(window.history.state);
53
- req.origin = 'init';
54
- window.history.scrollRestoration = 'manual';
55
- // we set it now instead of waiting for the onRoute call
56
- // because the window.history is already set
57
- this.route = req.toRoute();
58
- this.onRoute(req, () => { });
59
- }
60
- /**
61
- * Initializes the router when running on the server.
62
- */
63
- initServer() { }
64
- /**
65
- * Get a site and if possible use the accept lang header.
66
- *
67
- * @param acceptLang Accept Language header.
68
- */
69
- siteByAcceptLang(acceptLang = null) {
70
- if (!acceptLang)
71
- return this.defaultSite();
72
- const directives = acceptLang
73
- .split(',')
74
- .map(d => d.trim())
75
- .filter(d => !!d);
76
- // let's expect that weights are correctly ordered
77
- const languages = directives
78
- .map(d => {
79
- const lang = d.split(';');
80
- return lang[0].trim();
81
- })
82
- .filter(d => !!d);
83
- // find a site which matches the language
84
- // first try to match the full language
85
- for (const lang of languages) {
86
- const site = this.sites.find(s => s.language === lang);
87
- if (site)
88
- return site;
89
- }
90
- // if we don't find any language which matches
91
- // try to match languages without the -
92
- for (let lang of languages) {
93
- lang = lang.split('-')[0];
94
- const site = this.sites.find(s => {
95
- const sLang = s.language.split('-')[0];
96
- return sLang === lang;
97
- });
98
- if (site)
99
- return site;
100
- }
101
- // we did not find a match then just return the first site
102
- return this.defaultSite();
103
- }
104
- /**
105
- * Get the default site
106
- */
107
- defaultSite() {
108
- return this.sites.find(s => s.primary) ?? this.sites[0];
109
- }
110
- /**
111
- * Tries to get a site by it's id
112
- */
113
- siteById(id) {
114
- return this.sites.find(s => s.id === id) ?? null;
115
- }
116
- // keep this doc in sync with Router.targetToRequest
117
- /**
118
- * Resolve a url or Route and convert it to a Request
119
- *
120
- * @param target
121
- * @param opts, any option present will override the value in target
122
- * @return Returns null if the url does not match our host (the protocol get's ignored)
123
- */
124
- targetToRequest(target, opts = {}) {
125
- if (typeof target === 'string') {
126
- if (target.startsWith('/')) {
127
- // todo should we use the language matching or throw if the route does not
128
- // exists
129
- const site = this.route?.site ?? this.defaultSite();
130
- target = new URL(site.uri + target, site.url);
131
- }
132
- else if (!target) {
133
- throw new Error('the url is not allowed to be empty');
134
- }
135
- else {
136
- target = new URL(target);
137
- }
138
- }
139
- if (target instanceof URL) {
140
- target = this.routeFromUrl(target);
141
- }
142
- if (!isRequest(target)) {
143
- return Request.fromRoute(target, opts);
144
- }
145
- target._updateOpts(opts);
146
- return target;
147
- }
148
- /**
149
- * Resolve a url and convert it to a Route
150
- *
151
- * @param url
152
- * @return Returns null if the url does not match our host (the protocol get's ignored)
153
- */
154
- routeFromUrl(fullUrl) {
155
- // strip stuff we dont need from url
156
- const route = new Route(fullUrl, null);
157
- const url = route.url;
158
- const site = siteFromUrl(url, this.sites);
159
- // todo should we throw if we can't find a site
160
- // or use the site which matches the language
161
- route.site = site ?? this.defaultSite();
162
- return route;
163
- }
164
- listen() {
165
- window.addEventListener('click', async (e) => {
166
- // @ts-ignore
167
- const link = e.target.closest('a');
168
- const openInNewTab = e.metaKey || e.ctrlKey || e.shiftKey;
169
- const saveLink = e.altKey;
170
- if (!link || !link.href || openInNewTab || saveLink)
171
- return;
172
- if (link.target.toLowerCase() === '_blank')
173
- return;
174
- if (!link.href.startsWith('http'))
175
- return;
176
- e.preventDefault();
177
- const req = this.targetToRequest(link.href, { origin: 'click' });
178
- const routeEq = this.route && this.route.eqUrl(req) && this.route.eqSearch(req);
179
- // this means the route is the same maybe with a different hash
180
- // so it is not necessary to load the data again
181
- if (routeEq) {
182
- req.disableLoadData = true;
183
- }
184
- this.open(req);
185
- });
186
- if (this.preloadOnMouseOver) {
187
- let currentMouseOver = null;
188
- window.addEventListener('mouseover', e => {
189
- // @ts-ignore
190
- const link = e.target.closest('a');
191
- if (currentMouseOver && link === currentMouseOver)
192
- return;
193
- if (link && link.target.toLowerCase() === '_blank')
194
- return;
195
- if (link &&
196
- !link.hasAttribute('data-no-preload') &&
197
- link.href) {
198
- this.preload(link.href);
199
- }
200
- currentMouseOver = link;
201
- });
202
- }
203
- // store the scrollY position every 200ms
204
- // we can't do this at the time of the open call since the pop event
205
- // has already changed to a new history state so we can't update our
206
- // current/previous state
207
- // eslint-disable-next-line no-constant-condition
208
- if (true) {
209
- window.addEventListener('scroll', () => {
210
- const current = this.route;
211
- if (!current)
212
- return;
213
- // store the scroll position
214
- current.scrollY = window.scrollY;
215
- if (this.scrollDebounceTimeout)
216
- return;
217
- // this might cause `Attempt to use history.replaceState() more than
218
- // 100 times per 30 seconds` in safari
219
- // since we wait a moment we should almost ever be fine
220
- this.scrollDebounceTimeout = setTimeout(() => {
221
- if (!this.route || !current.eq(this.route))
222
- return;
223
- // use the latest state
224
- this.history.replaceState(this.route._toState());
225
- if (current.inLivePreview()) {
226
- sessionStorage.setItem('live-preview-scroll',
227
- // use the latest scrollY
228
- this.route.scrollY + '');
229
- }
230
- this.scrollDebounceTimeout = null;
231
- }, 280);
232
- });
233
- }
234
- window.addEventListener('popstate', async (e) => {
235
- if (!e.state?.route)
236
- return;
237
- const req = this.targetToRequest(window.location.href);
238
- req._fillFromState(e.state);
239
- req.origin = 'pop';
240
- // we set it now instead of waiting for the onRoute call
241
- // because the window.history was already modified
242
- this.route = req.toRoute();
243
- this.onRoute(req, () => { });
244
- });
245
- }
246
- /**
247
- * Open a new route
248
- *
249
- * @param route a route object or an url or uri, never input the same route object again
250
- * @param pushState if true pushed the state to the window.history
251
- *
252
- * ## Important
253
- * Make sure a req always has the correct origin,
254
- * `push` and `replace` will cause this function to throw an error
255
- */
256
- open(req) {
257
- if (['push', 'replace'].includes(req.origin)) {
258
- throw new Error('Do not use open with push or replace');
259
- }
260
- const current = this.route;
261
- // store scrollY
262
- if (current) {
263
- // if the scrollY would still be updated we clear the timeout
264
- // since we should have the latest scrollY
265
- if (this.scrollDebounceTimeout) {
266
- clearTimeout(this.scrollDebounceTimeout);
267
- this.scrollDebounceTimeout = null;
268
- }
269
- // store the scroll position
270
- const scrollY = this.history.scrollY();
271
- if (typeof scrollY === 'number') {
272
- current.scrollY = scrollY;
273
- this.history.replaceState(current._toState());
274
- }
275
- }
276
- // if the domain of the current site is different than the domain of the
277
- // new site we need to do a window.location.href call
278
- if ((current && current.url.origin !== req.url.origin) ||
279
- // @ts-ignore
280
- import.meta.env.SSR) {
281
- this.history.open(req);
282
- return;
283
- }
284
- req.index = (current?.index ?? 0) + 1;
285
- this.onRoute(req, () => {
286
- const url = req.url;
287
- this.history.pushState(req._toState(), url.pathname + url.search + url.hash);
288
- this.route = req.toRoute();
289
- });
290
- }
291
- /**
292
- * This pushes a new route to the history
293
- *
294
- * @param req, never input the same route object again
295
- *
296
- * ## Important
297
- * Make sure the route has the correct origin
298
- */
299
- push(req) {
300
- const url = req.url;
301
- // todo a push should also store the previous scrollY
302
- let nReq = req;
303
- if (req.scrollY === null) {
304
- // if there is no scrollY stored we store the current scrollY
305
- // since a push does not cause a scroll top
306
- // todo: probably should refactor something probably
307
- // should not be here
308
- nReq = req.clone();
309
- nReq.scrollY = this.history.scrollY();
310
- }
311
- this.onRoute(req, () => {
312
- this.history.pushState(req._toState(), url.pathname + url.search + url.hash);
313
- this.route = req.toRoute();
314
- });
315
- }
316
- /**
317
- * This replaces the current route
318
- *
319
- * @param req, never input the same route object again
320
- *
321
- * ## Important
322
- * Make sure the route has the correct origin
323
- */
324
- replace(req) {
325
- const url = req.url;
326
- let nReq = req;
327
- if (req.scrollY === null) {
328
- // if there is no scrollY stored we store the current scrollY
329
- // since a replace does not cause a scrollTo and we wan't
330
- // history back to work as intended
331
- // todo: probably should refactor something probably
332
- // should not be here
333
- nReq = req.clone();
334
- nReq.scrollY = this.history.scrollY();
335
- }
336
- this.onRoute(req, () => {
337
- this.history.replaceState(req._toState(), url.pathname + url.search + url.hash);
338
- this.route = req.toRoute();
339
- });
340
- }
341
- /**
342
- * Preload a url
343
- *
344
- * This will only work if the origin of the url matches the current site
345
- *
346
- * @param url
347
- */
348
- preload(target) {
349
- const req = this.targetToRequest(target);
350
- const current = this.route;
351
- // if the origin matches, the route will be able to be load
352
- // so let's preload it
353
- if (current && current.url.origin === req.url.origin) {
354
- this.onPreload(req);
355
- }
356
- }
357
- domReady(req) {
358
- if (req.disableScroll)
359
- return;
360
- // scroll to target
361
- let scrollTo = null;
362
- // if the route is a live preview init and we have a scrollY stored
363
- // scroll to that
364
- if (req.inLivePreview()) {
365
- const scrollY = sessionStorage.getItem('live-preview-scroll');
366
- if (scrollY) {
367
- scrollTo = {
368
- top: parseInt(scrollY),
369
- behavior: 'instant',
370
- };
371
- }
372
- // if we have a hash and the route was not visited
373
- }
374
- else if (req.hash &&
375
- ((req.origin === 'init' && typeof req.scrollY !== 'number') ||
376
- req.origin === 'click')) {
377
- const el = document.getElementById(req.hash.substring(1));
378
- if (el) {
379
- scrollTo = {
380
- intoView: el,
381
- behavior: 'smooth',
382
- };
383
- }
384
- }
385
- // restore scroll position
386
- if (!scrollTo &&
387
- req.origin !== 'click' &&
388
- typeof req.scrollY === 'number') {
389
- scrollTo = {
390
- top: req.scrollY,
391
- behavior: 'instant',
392
- };
393
- }
394
- // make sure push and replace don't cause a scroll if it is not intended
395
- if (!scrollTo && (req.origin === 'push' || req.origin === 'replace'))
396
- return;
397
- // scroll to the top if nothing else matches
398
- if (!scrollTo) {
399
- scrollTo = {
400
- top: 0,
401
- behavior: 'instant',
402
- };
403
- }
404
- if ('top' in scrollTo) {
405
- window.scrollTo({
406
- top: scrollTo.top,
407
- behavior: scrollTo.behavior,
408
- });
409
- }
410
- else {
411
- scrollTo.intoView.scrollIntoView({
412
- behavior: scrollTo.behavior,
413
- block: 'start',
414
- });
415
- }
416
- }
417
- }
@@ -1,36 +0,0 @@
1
- import Request from './Request.js';
2
- export type PageLoaderOptions = {
3
- debugTiming: boolean;
4
- };
5
- export type LoadResponse = {
6
- success: boolean;
7
- data: any;
8
- };
9
- export type LoadFn = (req: Request, opts: LoadOptions) => Promise<any> | any;
10
- export type LoadOptions = {
11
- setProgress: (num: number) => void;
12
- };
13
- /**
14
- * The PageLoader which is responsible for loading page Data
15
- */
16
- export default class PageLoader<More> {
17
- private debugTiming;
18
- private preloadedUrls;
19
- private loadingVersion;
20
- onLoaded: (resp: LoadResponse, req: Request, more: More) => void;
21
- onProgress: (loading: boolean, progress?: number) => void;
22
- loadFn: LoadFn;
23
- /**
24
- * Creates a new PageLoader
25
- *
26
- * @param {Object} options `{debugTiming}`
27
- */
28
- constructor(options: PageLoaderOptions);
29
- /**
30
- * Discard the current page load if one is happening
31
- */
32
- discard(): void;
33
- load(req: Request, more: More): Promise<void>;
34
- preload(req: Request): Promise<void>;
35
- }
36
- //# sourceMappingURL=PageLoader.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PageLoader.d.ts","sourceRoot":"","sources":["../../src/routing/PageLoader.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,MAAM,MAAM,iBAAiB,GAAG;IAC/B,WAAW,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AAE7E,MAAM,MAAM,WAAW,GAAG;IACzB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU,CAAC,IAAI;IACnC,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,aAAa,CAAc;IAEnC,OAAO,CAAC,cAAc,CAAS;IAE/B,QAAQ,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACjE,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,MAAM,EAAE,MAAM,CAAC;IAEf;;;;OAIG;gBACS,OAAO,EAAE,iBAAiB;IAWtC;;OAEG;IACH,OAAO;IAKD,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI;IAiC7B,OAAO,CAAC,GAAG,EAAE,OAAO;CAc1B"}