@sveltejs/kit 1.0.0-next.272 → 1.0.0-next.276
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/assets/client/start.js +72 -48
- package/assets/server/index.js +4 -5
- package/dist/cli.js +2 -2
- package/package.json +1 -1
package/assets/client/start.js
CHANGED
|
@@ -22,6 +22,21 @@ function normalize_path(path, trailing_slash) {
|
|
|
22
22
|
return path;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
// We track the scroll position associated with each history entry in sessionStorage,
|
|
26
|
+
// rather than on history.state itself, because when navigation is driven by
|
|
27
|
+
// popstate it's too late to update the scroll position associated with the
|
|
28
|
+
// state we're navigating from
|
|
29
|
+
const SCROLL_KEY = 'sveltekit:scroll';
|
|
30
|
+
|
|
31
|
+
/** @typedef {{ x: number, y: number }} ScrollPosition */
|
|
32
|
+
/** @type {Record<number, ScrollPosition>} */
|
|
33
|
+
let scroll_positions = {};
|
|
34
|
+
try {
|
|
35
|
+
scroll_positions = JSON.parse(sessionStorage[SCROLL_KEY]);
|
|
36
|
+
} catch {
|
|
37
|
+
// do nothing
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
function scroll_state() {
|
|
26
41
|
return {
|
|
27
42
|
x: pageXOffset,
|
|
@@ -83,6 +98,11 @@ class Router {
|
|
|
83
98
|
history.replaceState({ ...history.state, 'sveltekit:index': 0 }, '', location.href);
|
|
84
99
|
}
|
|
85
100
|
|
|
101
|
+
// if we reload the page, or Cmd-Shift-T back to it,
|
|
102
|
+
// recover scroll position
|
|
103
|
+
const scroll = scroll_positions[this.current_history_index];
|
|
104
|
+
if (scroll) scrollTo(scroll.x, scroll.y);
|
|
105
|
+
|
|
86
106
|
this.hash_navigating = false;
|
|
87
107
|
|
|
88
108
|
this.callbacks = {
|
|
@@ -95,9 +115,7 @@ class Router {
|
|
|
95
115
|
}
|
|
96
116
|
|
|
97
117
|
init_listeners() {
|
|
98
|
-
|
|
99
|
-
history.scrollRestoration = 'manual';
|
|
100
|
-
}
|
|
118
|
+
history.scrollRestoration = 'manual';
|
|
101
119
|
|
|
102
120
|
// Adopted from Nuxt.js
|
|
103
121
|
// Reset scrollRestoration to auto when leaving page, allowing page reload
|
|
@@ -122,28 +140,16 @@ class Router {
|
|
|
122
140
|
}
|
|
123
141
|
});
|
|
124
142
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// There's no API to capture the scroll location right before the user
|
|
131
|
-
// hits the back/forward button, so we listen for scroll events
|
|
143
|
+
addEventListener('visibilitychange', () => {
|
|
144
|
+
if (document.visibilityState === 'hidden') {
|
|
145
|
+
this.#update_scroll_positions();
|
|
132
146
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// This will persist even if we navigate away from the site and come back
|
|
140
|
-
const new_state = {
|
|
141
|
-
...(history.state || {}),
|
|
142
|
-
'sveltekit:scroll': scroll_state()
|
|
143
|
-
};
|
|
144
|
-
history.replaceState(new_state, document.title, window.location.href);
|
|
145
|
-
// iOS scroll event intervals happen between 30-150ms, sometimes around 200ms
|
|
146
|
-
}, 200);
|
|
147
|
+
try {
|
|
148
|
+
sessionStorage[SCROLL_KEY] = JSON.stringify(scroll_positions);
|
|
149
|
+
} catch {
|
|
150
|
+
// do nothing
|
|
151
|
+
}
|
|
152
|
+
}
|
|
147
153
|
});
|
|
148
154
|
|
|
149
155
|
/** @param {Event} event */
|
|
@@ -212,8 +218,12 @@ class Router {
|
|
|
212
218
|
// Removing the hash does a full page navigation in the browser, so make sure a hash is present
|
|
213
219
|
const [base, hash] = url.href.split('#');
|
|
214
220
|
if (hash !== undefined && base === location.href.split('#')[0]) {
|
|
221
|
+
// set this flag to distinguish between navigations triggered by
|
|
222
|
+
// clicking a hash link and those triggered by popstate
|
|
215
223
|
this.hash_navigating = true;
|
|
216
224
|
|
|
225
|
+
this.#update_scroll_positions();
|
|
226
|
+
|
|
217
227
|
const info = this.parse(url);
|
|
218
228
|
if (info) {
|
|
219
229
|
return this.renderer.update(info, [], false);
|
|
@@ -243,7 +253,7 @@ class Router {
|
|
|
243
253
|
|
|
244
254
|
this._navigate({
|
|
245
255
|
url: new URL(location.href),
|
|
246
|
-
scroll: event.state['sveltekit:
|
|
256
|
+
scroll: scroll_positions[event.state['sveltekit:index']],
|
|
247
257
|
keepfocus: false,
|
|
248
258
|
chain: [],
|
|
249
259
|
details: null,
|
|
@@ -259,6 +269,8 @@ class Router {
|
|
|
259
269
|
});
|
|
260
270
|
|
|
261
271
|
addEventListener('hashchange', () => {
|
|
272
|
+
// if the hashchange happened as a result of clicking on a link,
|
|
273
|
+
// we need to update history, otherwise we have to leave it alone
|
|
262
274
|
if (this.hash_navigating) {
|
|
263
275
|
this.hash_navigating = false;
|
|
264
276
|
history.replaceState(
|
|
@@ -270,6 +282,10 @@ class Router {
|
|
|
270
282
|
});
|
|
271
283
|
}
|
|
272
284
|
|
|
285
|
+
#update_scroll_positions() {
|
|
286
|
+
scroll_positions[this.current_history_index] = scroll_state();
|
|
287
|
+
}
|
|
288
|
+
|
|
273
289
|
/**
|
|
274
290
|
* Returns true if `url` has the same origin and basepath as the app
|
|
275
291
|
* @param {URL} url
|
|
@@ -417,6 +433,8 @@ class Router {
|
|
|
417
433
|
});
|
|
418
434
|
}
|
|
419
435
|
|
|
436
|
+
this.#update_scroll_positions();
|
|
437
|
+
|
|
420
438
|
accepted();
|
|
421
439
|
|
|
422
440
|
if (!this.navigating) {
|
|
@@ -732,11 +750,12 @@ class Renderer {
|
|
|
732
750
|
* status: number;
|
|
733
751
|
* error: Error;
|
|
734
752
|
* nodes: Array<Promise<CSRComponent>>;
|
|
735
|
-
* url: URL;
|
|
736
753
|
* params: Record<string, string>;
|
|
737
754
|
* }} selected
|
|
738
755
|
*/
|
|
739
|
-
async start({ status, error, nodes,
|
|
756
|
+
async start({ status, error, nodes, params }) {
|
|
757
|
+
const url = new URL(location.href);
|
|
758
|
+
|
|
740
759
|
/** @type {Array<import('./types').BranchNode | undefined>} */
|
|
741
760
|
const branch = [];
|
|
742
761
|
|
|
@@ -748,9 +767,6 @@ class Renderer {
|
|
|
748
767
|
|
|
749
768
|
let error_args;
|
|
750
769
|
|
|
751
|
-
// url.hash is empty when coming from the server
|
|
752
|
-
url.hash = window.location.hash;
|
|
753
|
-
|
|
754
770
|
try {
|
|
755
771
|
for (let i = 0; i < nodes.length; i += 1) {
|
|
756
772
|
const is_leaf = i === nodes.length - 1;
|
|
@@ -776,6 +792,7 @@ class Renderer {
|
|
|
776
792
|
|
|
777
793
|
if (props) {
|
|
778
794
|
node.uses.dependencies.add(url.href);
|
|
795
|
+
node.uses.url = true;
|
|
779
796
|
}
|
|
780
797
|
|
|
781
798
|
branch.push(node);
|
|
@@ -1289,7 +1306,9 @@ class Renderer {
|
|
|
1289
1306
|
/** @type {Record<string, any>} */
|
|
1290
1307
|
let props = {};
|
|
1291
1308
|
|
|
1292
|
-
|
|
1309
|
+
const is_shadow_page = has_shadow && i === a.length - 1;
|
|
1310
|
+
|
|
1311
|
+
if (is_shadow_page) {
|
|
1293
1312
|
const res = await fetch(
|
|
1294
1313
|
`${url.pathname}${url.pathname.endsWith('/') ? '' : '/'}__data.json${url.search}`,
|
|
1295
1314
|
{
|
|
@@ -1327,25 +1346,31 @@ class Renderer {
|
|
|
1327
1346
|
});
|
|
1328
1347
|
}
|
|
1329
1348
|
|
|
1330
|
-
if (node
|
|
1331
|
-
if (
|
|
1332
|
-
|
|
1333
|
-
}
|
|
1334
|
-
if (node.loaded.error) {
|
|
1335
|
-
status = node.loaded.status;
|
|
1336
|
-
error = node.loaded.error;
|
|
1349
|
+
if (node) {
|
|
1350
|
+
if (is_shadow_page) {
|
|
1351
|
+
node.uses.url = true;
|
|
1337
1352
|
}
|
|
1338
1353
|
|
|
1339
|
-
if (node.loaded
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1354
|
+
if (node.loaded) {
|
|
1355
|
+
if (node.loaded.fallthrough) {
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
if (node.loaded.error) {
|
|
1359
|
+
status = node.loaded.status;
|
|
1360
|
+
error = node.loaded.error;
|
|
1361
|
+
}
|
|
1346
1362
|
|
|
1347
|
-
|
|
1348
|
-
|
|
1363
|
+
if (node.loaded.redirect) {
|
|
1364
|
+
return {
|
|
1365
|
+
redirect: node.loaded.redirect,
|
|
1366
|
+
props: {},
|
|
1367
|
+
state: this.current
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
if (node.loaded.stuff) {
|
|
1372
|
+
stuff_changed = true;
|
|
1373
|
+
}
|
|
1349
1374
|
}
|
|
1350
1375
|
}
|
|
1351
1376
|
} else {
|
|
@@ -1479,7 +1504,6 @@ class Renderer {
|
|
|
1479
1504
|
* status: number;
|
|
1480
1505
|
* error: Error;
|
|
1481
1506
|
* nodes: Array<Promise<import('types/internal').CSRComponent>>;
|
|
1482
|
-
* url: URL;
|
|
1483
1507
|
* params: Record<string, string>;
|
|
1484
1508
|
* };
|
|
1485
1509
|
* }} opts
|
package/assets/server/index.js
CHANGED
|
@@ -80,7 +80,7 @@ function is_pojo(body) {
|
|
|
80
80
|
|
|
81
81
|
// body could be a node Readable, but we don't want to import
|
|
82
82
|
// node built-ins, so we use duck typing
|
|
83
|
-
if (body._readableState && body.
|
|
83
|
+
if (body._readableState && typeof body.pipe === 'function') return false;
|
|
84
84
|
|
|
85
85
|
// similarly, it could be a web ReadableStream
|
|
86
86
|
if (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) return false;
|
|
@@ -1209,7 +1209,6 @@ async function render_response({
|
|
|
1209
1209
|
.map(({ node }) => `import(${s(options.prefix + node.entry)})`)
|
|
1210
1210
|
.join(',\n\t\t\t\t\t\t')}
|
|
1211
1211
|
],
|
|
1212
|
-
url: new URL(${s(url.href)}),
|
|
1213
1212
|
params: ${devalue(params)}
|
|
1214
1213
|
}` : 'null'}
|
|
1215
1214
|
});
|
|
@@ -1881,7 +1880,7 @@ async function load_shadow_data(route, event, options, prerender) {
|
|
|
1881
1880
|
const mod = await route.shadow();
|
|
1882
1881
|
|
|
1883
1882
|
if (prerender && (mod.post || mod.put || mod.del || mod.patch)) {
|
|
1884
|
-
throw new Error('Cannot prerender pages that have
|
|
1883
|
+
throw new Error('Cannot prerender pages that have endpoints with mutative methods');
|
|
1885
1884
|
}
|
|
1886
1885
|
|
|
1887
1886
|
const method = normalize_request_method(event);
|
|
@@ -1988,7 +1987,7 @@ function validate_shadow_output(result) {
|
|
|
1988
1987
|
if (headers instanceof Headers) {
|
|
1989
1988
|
if (headers.has('set-cookie')) {
|
|
1990
1989
|
throw new Error(
|
|
1991
|
-
'
|
|
1990
|
+
'Endpoint request handler cannot use Headers interface with Set-Cookie headers'
|
|
1992
1991
|
);
|
|
1993
1992
|
}
|
|
1994
1993
|
} else {
|
|
@@ -1996,7 +1995,7 @@ function validate_shadow_output(result) {
|
|
|
1996
1995
|
}
|
|
1997
1996
|
|
|
1998
1997
|
if (!is_pojo(body)) {
|
|
1999
|
-
throw new Error('Body returned from
|
|
1998
|
+
throw new Error('Body returned from endpoint request handler must be a plain object');
|
|
2000
1999
|
}
|
|
2001
2000
|
|
|
2002
2001
|
return { status, headers, body };
|
package/dist/cli.js
CHANGED
|
@@ -998,7 +998,7 @@ async function launch(port, https) {
|
|
|
998
998
|
exec(`${cmd} ${https ? 'https' : 'http'}://localhost:${port}`);
|
|
999
999
|
}
|
|
1000
1000
|
|
|
1001
|
-
const prog = sade('svelte-kit').version('1.0.0-next.
|
|
1001
|
+
const prog = sade('svelte-kit').version('1.0.0-next.276');
|
|
1002
1002
|
|
|
1003
1003
|
prog
|
|
1004
1004
|
.command('dev')
|
|
@@ -1156,7 +1156,7 @@ async function check_port(port) {
|
|
|
1156
1156
|
function welcome({ port, host, https, open, loose, allow, cwd }) {
|
|
1157
1157
|
if (open) launch(port, https);
|
|
1158
1158
|
|
|
1159
|
-
console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.
|
|
1159
|
+
console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.276'}\n`));
|
|
1160
1160
|
|
|
1161
1161
|
const protocol = https ? 'https:' : 'http:';
|
|
1162
1162
|
const exposed = typeof host !== 'undefined' && host !== 'localhost' && host !== '127.0.0.1';
|