@sveltejs/kit 1.0.0-next.213 → 1.0.0-next.217

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/kit.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @param {Record<string, string | string[]>} headers
2
+ * @param {Record<string, string | string[] | undefined>} headers
3
3
  * @param {string} key
4
4
  * @returns {string | undefined}
5
5
  * @throws {Error}
@@ -68,21 +68,24 @@ function is_string(s) {
68
68
  return typeof s === 'string' || s instanceof String;
69
69
  }
70
70
 
71
+ const text_types = new Set([
72
+ 'application/xml',
73
+ 'application/json',
74
+ 'application/x-www-form-urlencoded',
75
+ 'multipart/form-data'
76
+ ]);
77
+
71
78
  /**
72
79
  * Decides how the body should be parsed based on its mime type. Should match what's in parse_body
73
80
  *
74
81
  * @param {string | undefined | null} content_type The `content-type` header of a request/response.
75
82
  * @returns {boolean}
76
83
  */
77
- function is_content_type_textual(content_type) {
84
+ function is_text(content_type) {
78
85
  if (!content_type) return true; // defaults to json
79
- const [type] = content_type.split(';'); // get the mime type
80
- return (
81
- type === 'text/plain' ||
82
- type === 'application/json' ||
83
- type === 'application/x-www-form-urlencoded' ||
84
- type === 'multipart/form-data'
85
- );
86
+ const type = content_type.split(';')[0].toLowerCase(); // get the mime type
87
+
88
+ return type.startsWith('text/') || type.endsWith('+xml') || text_types.has(type);
86
89
  }
87
90
 
88
91
  /**
@@ -121,9 +124,7 @@ async function render_endpoint(request, route, match) {
121
124
  headers = lowercase_keys(headers);
122
125
  const type = get_single_valued_header(headers, 'content-type');
123
126
 
124
- const is_type_textual = is_content_type_textual(type);
125
-
126
- if (!is_type_textual && !(body instanceof Uint8Array || is_string(body))) {
127
+ if (!is_text(type) && !(body instanceof Uint8Array || is_string(body))) {
127
128
  return error(
128
129
  `${preface}: body must be an instance of string or Uint8Array if content-type is not a supported textual content-type`
129
130
  );
@@ -1,4 +1,4 @@
1
- import { router as router$1 } from '../internal/singletons.js';
1
+ import { renderer, router as router$1 } from '../internal/singletons.js';
2
2
  import { g as get_base_uri } from '../chunks/utils.js';
3
3
 
4
4
  const router = /** @type {import('../client/router').Router} */ (router$1);
@@ -12,11 +12,21 @@ function guard(name) {
12
12
  };
13
13
  }
14
14
 
15
+ const disableScrollHandling = import.meta.env.SSR
16
+ ? guard('disableScrollHandling')
17
+ : disableScrollHandling_;
15
18
  const goto = import.meta.env.SSR ? guard('goto') : goto_;
16
19
  const invalidate = import.meta.env.SSR ? guard('invalidate') : invalidate_;
17
20
  const prefetch = import.meta.env.SSR ? guard('prefetch') : prefetch_;
18
21
  const prefetchRoutes = import.meta.env.SSR ? guard('prefetchRoutes') : prefetchRoutes_;
19
22
 
23
+ /**
24
+ * @type {import('$app/navigation').goto}
25
+ */
26
+ async function disableScrollHandling_() {
27
+ renderer.disable_scroll_handling();
28
+ }
29
+
20
30
  /**
21
31
  * @type {import('$app/navigation').goto}
22
32
  */
@@ -52,4 +62,4 @@ async function prefetchRoutes_(pathnames) {
52
62
  await Promise.all(promises);
53
63
  }
54
64
 
55
- export { goto, invalidate, prefetch, prefetchRoutes };
65
+ export { disableScrollHandling, goto, invalidate, prefetch, prefetchRoutes };
@@ -1,9 +1,18 @@
1
1
  /** @type {import('./router').Router?} */
2
2
  let router;
3
3
 
4
- /** @param {import('./router').Router?} _ */
5
- function init(_) {
6
- router = _;
4
+ /** @type {import('./renderer').Renderer} */
5
+ let renderer;
6
+
7
+ /**
8
+ * @param {{
9
+ * router: import('./router').Router?;
10
+ * renderer: import('./renderer').Renderer;
11
+ * }} opts
12
+ */
13
+ function init(opts) {
14
+ router = opts.router;
15
+ renderer = opts.renderer;
7
16
  }
8
17
 
9
- export { init, router };
18
+ export { init, renderer, router };
@@ -1,6 +1,7 @@
1
1
  import Root from '../../generated/root.svelte';
2
2
  import { fallback, routes } from '../../generated/manifest.js';
3
3
  import { g as get_base_uri } from '../chunks/utils.js';
4
+ import { tick } from 'svelte';
4
5
  import { writable } from 'svelte/store';
5
6
  import { init } from './singletons.js';
6
7
  import { set_paths } from '../paths.js';
@@ -162,16 +163,17 @@ class Router {
162
163
 
163
164
  if (!this.owns(url)) return;
164
165
 
165
- const noscroll = a.hasAttribute('sveltekit:noscroll');
166
+ // Check if new url only differs by hash
167
+ if (url.href.split('#')[0] === location.href.split('#')[0]) {
168
+ // Call `pushState` to add url to history so going back works.
169
+ // Also make a delay, otherwise the browser default behaviour would not kick in
170
+ setTimeout(() => history.pushState({}, '', url.href));
171
+ return;
172
+ }
166
173
 
167
- const i1 = url_string.indexOf('#');
168
- const i2 = location.href.indexOf('#');
169
- const u1 = i1 >= 0 ? url_string.substring(0, i1) : url_string;
170
- const u2 = i2 >= 0 ? location.href.substring(0, i2) : location.href;
171
174
  history.pushState({}, '', url.href);
172
- if (u1 === u2) {
173
- window.dispatchEvent(new HashChangeEvent('hashchange'));
174
- }
175
+
176
+ const noscroll = a.hasAttribute('sveltekit:noscroll');
175
177
  this._navigate(url, noscroll ? scroll_state() : null, false, [], url.hash);
176
178
  event.preventDefault();
177
179
  });
@@ -466,6 +468,8 @@ class Renderer {
466
468
  this.session_id = 1;
467
469
  this.invalid = new Set();
468
470
  this.invalidating = null;
471
+ this.autoscroll = true;
472
+ this.updating = false;
469
473
 
470
474
  /** @type {import('./types').NavigationState} */
471
475
  this.current = {
@@ -508,6 +512,16 @@ class Renderer {
508
512
  ready = true;
509
513
  }
510
514
 
515
+ disable_scroll_handling() {
516
+ if (import.meta.env.DEV && this.started && !this.updating) {
517
+ throw new Error('Can only disable scroll handling during navigation');
518
+ }
519
+
520
+ if (this.updating || !this.started) {
521
+ this.autoscroll = false;
522
+ }
523
+ }
524
+
511
525
  /**
512
526
  * @param {{
513
527
  * status: number;
@@ -637,6 +651,8 @@ class Renderer {
637
651
  }
638
652
  }
639
653
 
654
+ this.updating = true;
655
+
640
656
  if (this.started) {
641
657
  this.current = navigation_result.state;
642
658
 
@@ -646,7 +662,7 @@ class Renderer {
646
662
  this._init(navigation_result);
647
663
  }
648
664
 
649
- // opts must be passed if we're navigating...
665
+ // opts must be passed if we're navigating
650
666
  if (opts) {
651
667
  const { hash, scroll, keepfocus } = opts;
652
668
 
@@ -655,26 +671,10 @@ class Renderer {
655
671
  document.body.focus();
656
672
  }
657
673
 
658
- const old_page_y_offset = Math.round(pageYOffset);
659
- const old_max_page_y_offset = document.documentElement.scrollHeight - innerHeight;
660
-
661
- await 0;
662
-
663
- const new_page_y_offset = Math.round(pageYOffset);
664
- const new_max_page_y_offset = document.documentElement.scrollHeight - innerHeight;
665
-
666
- // After `await 0`, the `onMount()` function in the component executed.
667
- // Check if no scrolling happened on mount.
668
- const no_scroll_happened =
669
- // In most cases, we can compare whether `pageYOffset` changed between navigation
670
- new_page_y_offset === Math.min(old_page_y_offset, new_max_page_y_offset) ||
671
- // But if the page is scrolled to/near the bottom, the browser would also scroll
672
- // to/near the bottom of the new page on navigation. Since we can't detect when this
673
- // behaviour happens, we naively compare by the y offset from the bottom of the page.
674
- old_max_page_y_offset - old_page_y_offset === new_max_page_y_offset - new_page_y_offset;
674
+ // need to render the DOM before we can scroll to the rendered elements
675
+ await tick();
675
676
 
676
- // If there was no scrolling, we run on our custom scroll handling
677
- if (no_scroll_happened) {
677
+ if (this.autoscroll) {
678
678
  const deep_linked = hash && document.getElementById(hash.slice(1));
679
679
  if (scroll) {
680
680
  scrollTo(scroll.x, scroll.y);
@@ -688,12 +688,14 @@ class Renderer {
688
688
  }
689
689
  }
690
690
  } else {
691
- // ...they will not be supplied if we're simply invalidating
692
- await 0;
691
+ // in this case we're simply invalidating
692
+ await tick();
693
693
  }
694
694
 
695
695
  this.loading.promise = null;
696
696
  this.loading.id = null;
697
+ this.autoscroll = true;
698
+ this.updating = false;
697
699
 
698
700
  if (!this.router) return;
699
701
 
@@ -1202,7 +1204,7 @@ async function start({ paths, target, session, route, spa, trailing_slash, hydra
1202
1204
  })
1203
1205
  : null;
1204
1206
 
1205
- init(router);
1207
+ init({ router, renderer });
1206
1208
  set_paths(paths);
1207
1209
 
1208
1210
  if (hydrate) await renderer.start(hydrate);
@@ -9,13 +9,4 @@ function coalesce_to_error(err) {
9
9
  : new Error(JSON.stringify(err));
10
10
  }
11
11
 
12
- /**
13
- * @param {Error} err
14
- * @param {any} errorCode
15
- * @return {err is Error & {code: any}}
16
- */
17
- function has_error_code(err, errorCode = undefined) {
18
- return 'code' in err && (errorCode === undefined || /** @type {any} */ (err).code === errorCode);
19
- }
20
-
21
- export { coalesce_to_error as c, has_error_code as h };
12
+ export { coalesce_to_error as c };
@@ -12,7 +12,7 @@ import 'querystring';
12
12
  import { URL } from 'url';
13
13
  import require$$10 from 'vm';
14
14
  import vite from 'vite';
15
- import { r as resolve_entry, $, g as get_mime_lookup, a as rimraf, c as copy_assets, p as print_config_conflicts } from '../cli.js';
15
+ import { r as resolve_entry, $, l as load_template, g as get_mime_lookup, a as rimraf, c as copy_assets, p as print_config_conflicts } from '../cli.js';
16
16
  import { c as create_manifest_data, a as create_app, d as deep_merge } from './index2.js';
17
17
  import { S as SVELTE_KIT, a as SVELTE_KIT_ASSETS } from './constants.js';
18
18
  import { respond } from '../ssr.js';
@@ -4407,8 +4407,7 @@ function create_plugin(config, output, cwd, amp) {
4407
4407
  ssr: config.kit.ssr,
4408
4408
  target: config.kit.target,
4409
4409
  template: ({ head, body }) => {
4410
- let rendered = fs__default
4411
- .readFileSync(config.kit.files.template, 'utf8')
4410
+ let rendered = load_template(cwd, config)
4412
4411
  .replace('%svelte.head%', () => head)
4413
4412
  .replace('%svelte.body%', () => body);
4414
4413
 
@@ -1,6 +1,6 @@
1
1
  import fs__default from 'fs';
2
2
  import path__default from 'path';
3
- import { p as print_config_conflicts, c as copy_assets, b as posixify, r as resolve_entry, m as mkdirp, a as rimraf } from '../cli.js';
3
+ import { p as print_config_conflicts, c as copy_assets, b as posixify, r as resolve_entry, l as load_template, m as mkdirp, a as rimraf } from '../cli.js';
4
4
  import { d as deep_merge, a as create_app, c as create_manifest_data } from './index2.js';
5
5
  import { S as SVELTE_KIT } from './constants.js';
6
6
  import { g as generate_manifest } from './index4.js';
@@ -247,21 +247,22 @@ async function build_client({
247
247
 
248
248
  /**
249
249
  * @param {{
250
- * runtime: string,
251
- * hooks: string,
252
- * config: import('types/config').ValidatedConfig,
253
- * has_service_worker: boolean
250
+ * cwd: string;
251
+ * runtime: string;
252
+ * hooks: string;
253
+ * config: import('types/config').ValidatedConfig;
254
+ * has_service_worker: boolean;
254
255
  * }} opts
255
256
  * @returns
256
257
  */
257
- const template = ({ config, hooks, runtime, has_service_worker }) => `
258
+ const template = ({ cwd, config, hooks, runtime, has_service_worker }) => `
258
259
  import { respond } from '${runtime}';
259
260
  import root from './generated/root.svelte';
260
261
  import { set_paths, assets, base } from './runtime/paths.js';
261
262
  import { set_prerendering } from './runtime/env.js';
262
263
  import * as user_hooks from ${s(hooks)};
263
264
 
264
- const template = ({ head, body }) => ${s(fs__default.readFileSync(config.kit.files.template, 'utf-8'))
265
+ const template = ({ head, body }) => ${s(load_template(cwd, config))
265
266
  .replace('%svelte.head%', '" + head + "')
266
267
  .replace('%svelte.body%', '" + body + "')};
267
268
 
@@ -415,6 +416,7 @@ async function build_server(
415
416
  fs__default.writeFileSync(
416
417
  input.app,
417
418
  template({
419
+ cwd,
418
420
  config,
419
421
  hooks: app_relative(hooks_file),
420
422
  runtime,
@@ -1,4 +1,4 @@
1
- import { m as mkdirp, a as rimraf, d as copy, $, l as logger } from '../cli.js';
1
+ import { m as mkdirp, a as rimraf, d as copy, $, e as logger } from '../cli.js';
2
2
  import { S as SVELTE_KIT } from './constants.js';
3
3
  import { readFileSync, writeFileSync } from 'fs';
4
4
  import { resolve, join, dirname } from 'path';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @param {Record<string, string | string[]>} headers
2
+ * @param {Record<string, string | string[] | undefined>} headers
3
3
  * @param {string} key
4
4
  * @returns {string | undefined}
5
5
  * @throws {Error}
package/dist/cli.js CHANGED
@@ -1,12 +1,12 @@
1
- import fs__default, { existsSync } from 'fs';
2
1
  import sade from 'sade';
3
2
  import path__default, { relative } from 'path';
4
3
  import { exec as exec$1 } from 'child_process';
5
4
  import { createConnection, createServer } from 'net';
5
+ import fs__default from 'fs';
6
6
  import * as url from 'url';
7
7
  import { fileURLToPath } from 'url';
8
8
  import { networkInterfaces, release } from 'os';
9
- import { c as coalesce_to_error, h as has_error_code } from './chunks/error.js';
9
+ import { c as coalesce_to_error } from './chunks/error.js';
10
10
 
11
11
  let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;
12
12
  if (typeof process !== 'undefined') {
@@ -740,10 +740,10 @@ function assert_string(input, keypath) {
740
740
 
741
741
  /**
742
742
  * @param {string} cwd
743
- * @param {import('types/config').ValidatedConfig} validated
743
+ * @param {import('types/config').ValidatedConfig} config
744
744
  */
745
- function validate_template(cwd, validated) {
746
- const { template } = validated.kit.files;
745
+ function load_template(cwd, config) {
746
+ const { template } = config.kit.files;
747
747
  const relative = path__default.relative(cwd, template);
748
748
 
749
749
  if (fs__default.existsSync(template)) {
@@ -757,13 +757,19 @@ function validate_template(cwd, validated) {
757
757
  } else {
758
758
  throw new Error(`${relative} does not exist`);
759
759
  }
760
+
761
+ return fs__default.readFileSync(template, 'utf-8');
760
762
  }
761
763
 
762
764
  async function load_config({ cwd = process.cwd() } = {}) {
763
- const config_file_esm = path__default.join(cwd, 'svelte.config.js');
764
- const config_file = fs__default.existsSync(config_file_esm)
765
- ? config_file_esm
766
- : path__default.join(cwd, 'svelte.config.cjs');
765
+ const config_file = path__default.join(cwd, 'svelte.config.js');
766
+
767
+ if (!fs__default.existsSync(config_file)) {
768
+ throw new Error(
769
+ 'You need to create a svelte.config.js file. See https://kit.svelte.dev/docs#configuration'
770
+ );
771
+ }
772
+
767
773
  const config = await import(url.pathToFileURL(config_file).href);
768
774
 
769
775
  const validated = validate_config(config.default);
@@ -775,10 +781,6 @@ async function load_config({ cwd = process.cwd() } = {}) {
775
781
  validated.kit.files.serviceWorker = path__default.resolve(cwd, validated.kit.files.serviceWorker);
776
782
  validated.kit.files.template = path__default.resolve(cwd, validated.kit.files.template);
777
783
 
778
- validate_template(cwd, validated);
779
-
780
- // TODO check all the `files` exist when the config is loaded?
781
-
782
784
  return validated;
783
785
  }
784
786
 
@@ -787,17 +789,9 @@ async function load_config({ cwd = process.cwd() } = {}) {
787
789
  * @returns {import('types/config').ValidatedConfig}
788
790
  */
789
791
  function validate_config(config) {
790
- const type = typeof config;
791
-
792
- if (type === 'undefined') {
793
- throw new Error(
794
- 'Your config is missing default exports. Make sure to include "export default config;"'
795
- );
796
- }
797
-
798
- if (type !== 'object') {
792
+ if (typeof config !== 'object') {
799
793
  throw new Error(
800
- `Unexpected config type "${type}", make sure your default export is an object.`
794
+ 'svelte.config.js must have a configuration object as its default export. See https://kit.svelte.dev/docs#configuration'
801
795
  );
802
796
  }
803
797
 
@@ -819,52 +813,17 @@ function print_config_conflicts(conflicts, pathPrefix = '', scope) {
819
813
  });
820
814
  }
821
815
 
822
- async function get_config() {
823
- // TODO this is temporary, for the benefit of early adopters
824
- if (existsSync('svelte.config.cjs')) {
825
- // prettier-ignore
826
- console.error($.bold().red(
827
- 'svelte.config.cjs should be renamed to svelte.config.js and converted to an ES module. See https://kit.svelte.dev/docs#configuration for an example'
828
- ));
829
- }
816
+ /** @param {unknown} e */
817
+ function handle_error(e) {
818
+ const error = coalesce_to_error(e);
830
819
 
831
- if (existsSync('vite.config.js')) {
832
- // prettier-ignore
833
- console.error($.bold().red(
834
- 'Please remove vite.config.js and put Vite config in svelte.config.js: https://kit.svelte.dev/docs#configuration-vite'
835
- ));
836
- }
837
-
838
- try {
839
- return await load_config();
840
- } catch (err) {
841
- const error = coalesce_to_error(err);
842
- let message = error.message;
843
-
844
- if (
845
- has_error_code(error, 'MODULE_NOT_FOUND') &&
846
- /Cannot find module svelte\.config\./.test(error.message)
847
- ) {
848
- message = 'Missing svelte.config.js';
849
- } else if (error.name === 'SyntaxError') {
850
- message = 'Malformed svelte.config.js';
851
- }
820
+ if (error.name === 'SyntaxError') throw error;
852
821
 
853
- console.error($.bold().red(message));
854
- if (error.stack) {
855
- console.error($.grey(error.stack));
856
- }
857
- process.exit(1);
822
+ console.log($.bold().red(`> ${error.message}`));
823
+ if (error.stack) {
824
+ console.log($.gray(error.stack.split('\n').slice(1).join('\n')));
858
825
  }
859
- }
860
826
 
861
- /** @param {unknown} error */
862
- function handle_error(error) {
863
- const err = coalesce_to_error(error);
864
- console.log($.bold().red(`> ${err.message}`));
865
- if (err.stack) {
866
- console.log($.gray(err.stack));
867
- }
868
827
  process.exit(1);
869
828
  }
870
829
 
@@ -887,7 +846,7 @@ async function launch(port, https) {
887
846
  exec(`${cmd} ${https ? 'https' : 'http'}://localhost:${port}`);
888
847
  }
889
848
 
890
- const prog = sade('svelte-kit').version('1.0.0-next.213');
849
+ const prog = sade('svelte-kit').version('1.0.0-next.217');
891
850
 
892
851
  prog
893
852
  .command('dev')
@@ -897,12 +856,12 @@ prog
897
856
  .option('-H, --https', 'Use self-signed HTTPS certificate')
898
857
  .option('-o, --open', 'Open a browser tab')
899
858
  .action(async ({ port, host, https, open }) => {
900
- process.env.NODE_ENV = process.env.NODE_ENV || 'development';
901
- const config = await get_config();
859
+ try {
860
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
861
+ const config = await load_config();
902
862
 
903
- const { dev } = await import('./chunks/index.js');
863
+ const { dev } = await import('./chunks/index.js');
904
864
 
905
- try {
906
865
  const cwd = process.cwd();
907
866
 
908
867
  const { address_info, server_config } = await dev({
@@ -932,10 +891,10 @@ prog
932
891
  .describe('Create a production build of your app')
933
892
  .option('--verbose', 'Log more stuff', false)
934
893
  .action(async ({ verbose }) => {
935
- process.env.NODE_ENV = process.env.NODE_ENV || 'production';
936
- const config = await get_config();
937
-
938
894
  try {
895
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
896
+ const config = await load_config();
897
+
939
898
  const { build } = await import('./chunks/index3.js');
940
899
  const build_data = await build(config);
941
900
 
@@ -970,14 +929,14 @@ prog
970
929
  .option('-H, --https', 'Use self-signed HTTPS certificate', false)
971
930
  .option('-o, --open', 'Open a browser tab', false)
972
931
  .action(async ({ port, host, https, open }) => {
973
- await check_port(port);
932
+ try {
933
+ await check_port(port);
974
934
 
975
- process.env.NODE_ENV = process.env.NODE_ENV || 'production';
976
- const config = await get_config();
935
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
936
+ const config = await load_config();
977
937
 
978
- const { preview } = await import('./chunks/index6.js');
938
+ const { preview } = await import('./chunks/index6.js');
979
939
 
980
- try {
981
940
  await preview({ port, host, config, https });
982
941
 
983
942
  welcome({ port, host, https, open });
@@ -991,11 +950,11 @@ prog
991
950
  .describe('Create a package')
992
951
  .option('-d, --dir', 'Destination directory', 'package')
993
952
  .action(async () => {
994
- const config = await get_config();
953
+ try {
954
+ const config = await load_config();
995
955
 
996
- const { make_package } = await import('./chunks/index7.js');
956
+ const { make_package } = await import('./chunks/index7.js');
997
957
 
998
- try {
999
958
  await make_package(config);
1000
959
  } catch (error) {
1001
960
  handle_error(error);
@@ -1039,7 +998,7 @@ async function check_port(port) {
1039
998
  function welcome({ port, host, https, open, loose, allow, cwd }) {
1040
999
  if (open) launch(port, https);
1041
1000
 
1042
- console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.213'}\n`));
1001
+ console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.217'}\n`));
1043
1002
 
1044
1003
  const protocol = https ? 'https:' : 'http:';
1045
1004
  const exposed = typeof host !== 'undefined' && host !== 'localhost' && host !== '127.0.0.1';
@@ -1076,4 +1035,4 @@ function welcome({ port, host, https, open, loose, allow, cwd }) {
1076
1035
  console.log('\n');
1077
1036
  }
1078
1037
 
1079
- export { $, rimraf as a, posixify as b, copy_assets as c, copy as d, get_mime_lookup as g, logger as l, mkdirp as m, print_config_conflicts as p, resolve_entry as r, walk as w };
1038
+ export { $, rimraf as a, posixify as b, copy_assets as c, copy as d, logger as e, get_mime_lookup as g, load_template as l, mkdirp as m, print_config_conflicts as p, resolve_entry as r, walk as w };
package/dist/ssr.js CHANGED
@@ -50,21 +50,24 @@ function is_string(s) {
50
50
  return typeof s === 'string' || s instanceof String;
51
51
  }
52
52
 
53
+ const text_types = new Set([
54
+ 'application/xml',
55
+ 'application/json',
56
+ 'application/x-www-form-urlencoded',
57
+ 'multipart/form-data'
58
+ ]);
59
+
53
60
  /**
54
61
  * Decides how the body should be parsed based on its mime type. Should match what's in parse_body
55
62
  *
56
63
  * @param {string | undefined | null} content_type The `content-type` header of a request/response.
57
64
  * @returns {boolean}
58
65
  */
59
- function is_content_type_textual(content_type) {
66
+ function is_text(content_type) {
60
67
  if (!content_type) return true; // defaults to json
61
- const [type] = content_type.split(';'); // get the mime type
62
- return (
63
- type === 'text/plain' ||
64
- type === 'application/json' ||
65
- type === 'application/x-www-form-urlencoded' ||
66
- type === 'multipart/form-data'
67
- );
68
+ const type = content_type.split(';')[0].toLowerCase(); // get the mime type
69
+
70
+ return type.startsWith('text/') || type.endsWith('+xml') || text_types.has(type);
68
71
  }
69
72
 
70
73
  /**
@@ -103,9 +106,7 @@ async function render_endpoint(request, route, match) {
103
106
  headers = lowercase_keys(headers);
104
107
  const type = get_single_valued_header(headers, 'content-type');
105
108
 
106
- const is_type_textual = is_content_type_textual(type);
107
-
108
- if (!is_type_textual && !(body instanceof Uint8Array || is_string(body))) {
109
+ if (!is_text(type) && !(body instanceof Uint8Array || is_string(body))) {
109
110
  return error(
110
111
  `${preface}: body must be an instance of string or Uint8Array if content-type is not a supported textual content-type`
111
112
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.213",
3
+ "version": "1.0.0-next.217",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -15,6 +15,7 @@
15
15
  "vite": "^2.7.2"
16
16
  },
17
17
  "devDependencies": {
18
+ "@playwright/test": "^1.17.1",
18
19
  "@rollup/plugin-replace": "^3.0.0",
19
20
  "@types/amphtml-validator": "^1.0.1",
20
21
  "@types/cookie": "^0.4.1",
@@ -24,6 +25,7 @@
24
25
  "@types/sade": "^1.7.3",
25
26
  "amphtml-validator": "^1.0.35",
26
27
  "cookie": "^0.4.1",
28
+ "cross-env": "^7.0.3",
27
29
  "devalue": "^2.0.1",
28
30
  "eslint": "^8.3.0",
29
31
  "kleur": "^4.1.4",
@@ -37,6 +39,7 @@
37
39
  "sirv": "^1.0.19",
38
40
  "svelte": "^3.44.2",
39
41
  "svelte-check": "^2.2.10",
42
+ "svelte-preprocess": "^4.9.8",
40
43
  "svelte2tsx": "~0.4.10",
41
44
  "tiny-glob": "^0.2.9",
42
45
  "uvu": "^0.5.2"
@@ -85,6 +88,10 @@
85
88
  "test": "npm run test:unit && npm run test:packaging && npm run test:integration",
86
89
  "test:unit": "uvu src \"(spec\\.js|test[\\\\/]index\\.js)\" -i packaging",
87
90
  "test:packaging": "uvu src/packaging \"(spec\\.js|test[\\\\/]index\\.js)\"",
88
- "test:integration": "uvu test test.js"
91
+ "test:integration": "pnpm test:integration:amp && pnpm test:integration:basics && pnpm test:integration:options && pnpm test:integration:options-2",
92
+ "test:integration:amp": "cd test/apps/amp && pnpm test",
93
+ "test:integration:basics": "cd test/apps/basics && pnpm test",
94
+ "test:integration:options": "cd test/apps/options && pnpm test",
95
+ "test:integration:options-2": "cd test/apps/options-2 && pnpm test"
89
96
  }
90
97
  }
@@ -26,6 +26,11 @@ declare module '$app/env' {
26
26
  }
27
27
 
28
28
  declare module '$app/navigation' {
29
+ /**
30
+ * Disable SvelteKit's built-in scroll handling for the current navigation, in case you need to manually control the scroll position.
31
+ * This is generally discouraged, since it breaks user expectations.
32
+ */
33
+ export function disableScrollHandling(): void;
29
34
  /**
30
35
  * Returns a Promise that resolves when SvelteKit navigates (or fails to navigate, in which case the promise rejects) to the specified href.
31
36
  *
@@ -5,7 +5,7 @@ type DefaultBody = JSONString | Uint8Array;
5
5
 
6
6
  export interface EndpointOutput<Body extends DefaultBody = DefaultBody> {
7
7
  status?: number;
8
- headers?: ResponseHeaders;
8
+ headers?: Partial<ResponseHeaders>;
9
9
  body?: Body;
10
10
  }
11
11
 
package/types/hooks.d.ts CHANGED
@@ -15,7 +15,7 @@ export interface ServerRequest<Locals = Record<string, any>, Body = unknown> {
15
15
 
16
16
  export interface ServerResponse {
17
17
  status: number;
18
- headers: ResponseHeaders;
18
+ headers: Partial<ResponseHeaders>;
19
19
  body?: StrictBody;
20
20
  }
21
21