@sveltejs/kit 1.0.0-next.261 → 1.0.0-next.265

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.
@@ -1464,10 +1464,6 @@ class Renderer {
1464
1464
  * }} opts
1465
1465
  */
1466
1466
  async function start({ paths, target, session, route, spa, trailing_slash, hydrate }) {
1467
- if (import.meta.env.DEV && !target) {
1468
- throw new Error('Missing target element. See https://kit.svelte.dev/docs#configuration-target');
1469
- }
1470
-
1471
1467
  const renderer = new Renderer({
1472
1468
  Root,
1473
1469
  fallback,
@@ -7,12 +7,12 @@ function to_headers(object) {
7
7
  const value = object[key];
8
8
  if (!value) continue;
9
9
 
10
- if (typeof value === 'string') {
11
- headers.set(key, value);
12
- } else {
10
+ if (Array.isArray(value)) {
13
11
  value.forEach((value) => {
14
- headers.append(key, value);
12
+ headers.append(key, /** @type {string} */ (value));
15
13
  });
14
+ } else {
15
+ headers.set(key, /** @type {string} */ (value));
16
16
  }
17
17
  }
18
18
  }
@@ -38,6 +38,16 @@ function hash(value) {
38
38
  }
39
39
 
40
40
  /** @param {Record<string, any>} obj */
41
+ function lowercase_keys(obj) {
42
+ /** @type {Record<string, any>} */
43
+ const clone = {};
44
+
45
+ for (const key in obj) {
46
+ clone[key.toLowerCase()] = obj[key];
47
+ }
48
+
49
+ return clone;
50
+ }
41
51
 
42
52
  /** @param {Record<string, string>} params */
43
53
  function decode_params(params) {
@@ -475,6 +485,16 @@ function coalesce_to_error(err) {
475
485
 
476
486
  /** @type {Record<string, string>} */
477
487
  const escape_json_in_html_dict = {
488
+ '&': '\\u0026',
489
+ '>': '\\u003e',
490
+ '<': '\\u003c',
491
+ '\u2028': '\\u2028',
492
+ '\u2029': '\\u2029'
493
+ };
494
+
495
+ /** @type {Record<string, string>} */
496
+ const escape_json_value_in_html_dict = {
497
+ '"': '\\"',
478
498
  '<': '\\u003C',
479
499
  '>': '\\u003E',
480
500
  '/': '\\u002F',
@@ -489,53 +509,30 @@ const escape_json_in_html_dict = {
489
509
  '\u2029': '\\u2029'
490
510
  };
491
511
 
492
- /** @type {Record<string, string>} */
493
- const escape_json_string_in_html_dict = {
494
- '"': '\\"',
495
- ...escape_json_in_html_dict
496
- };
497
-
498
512
  /**
499
513
  * Escape a stringified JSON object that's going to be embedded in a `<script>` tag
500
514
  * @param {string} str
501
515
  */
502
516
  function escape_json_in_html(str) {
503
- return escape(str, escape_json_in_html_dict, (code) => `\\u${code.toString(16).toUpperCase()}`);
517
+ // adapted from https://github.com/vercel/next.js/blob/694407450638b037673c6d714bfe4126aeded740/packages/next/server/htmlescape.ts
518
+ // based on https://github.com/zertosh/htmlescape
519
+ // License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE
520
+ return str.replace(/[&><\u2028\u2029]/g, (match) => escape_json_in_html_dict[match]);
504
521
  }
505
522
 
506
523
  /**
507
524
  * Escape a string JSON value to be embedded into a `<script>` tag
508
525
  * @param {string} str
509
526
  */
510
- function escape_json_string_in_html(str) {
527
+ function escape_json_value_in_html(str) {
511
528
  return escape(
512
529
  str,
513
- escape_json_string_in_html_dict,
530
+ escape_json_value_in_html_dict,
514
531
  (code) => `\\u${code.toString(16).toUpperCase()}`
515
532
  );
516
533
  }
517
534
 
518
- /** @type {Record<string, string>} */
519
- const escape_html_attr_dict = {
520
- '<': '&lt;',
521
- '>': '&gt;',
522
- '"': '&quot;'
523
- };
524
-
525
535
  /**
526
- * use for escaping string values to be used html attributes on the page
527
- * e.g.
528
- * <script data-url="here">
529
- *
530
- * @param {string} str
531
- * @returns string escaped string
532
- */
533
- function escape_html_attr(str) {
534
- return '"' + escape(str, escape_html_attr_dict, (code) => `&#${code};`) + '"';
535
- }
536
-
537
- /**
538
- *
539
536
  * @param str {string} string to escape
540
537
  * @param dict {Record<string, string>} dictionary of character replacements
541
538
  * @param unicode_encoder {function(number): string} encoder to use for high unicode characters
@@ -568,6 +565,25 @@ function escape(str, dict, unicode_encoder) {
568
565
  return result;
569
566
  }
570
567
 
568
+ /** @type {Record<string, string>} */
569
+ const escape_html_attr_dict = {
570
+ '<': '&lt;',
571
+ '>': '&gt;',
572
+ '"': '&quot;'
573
+ };
574
+
575
+ /**
576
+ * use for escaping string values to be used html attributes on the page
577
+ * e.g.
578
+ * <script data-url="here">
579
+ *
580
+ * @param {string} str
581
+ * @returns string escaped string
582
+ */
583
+ function escape_html_attr(str) {
584
+ return '"' + escape(str, escape_html_attr_dict, (code) => `&#${code};`) + '"';
585
+ }
586
+
571
587
  const s = JSON.stringify;
572
588
 
573
589
  /** @param {URL} url */
@@ -1730,7 +1746,7 @@ async function load_node({
1730
1746
  fetched.push({
1731
1747
  url: requested,
1732
1748
  body: /** @type {string} */ (opts.body),
1733
- json: `{"status":${response.status},"statusText":${s(response.statusText)},"headers":${s(headers)},"body":"${escape_json_string_in_html(body)}"}`
1749
+ json: `{"status":${response.status},"statusText":${s(response.statusText)},"headers":${s(headers)},"body":"${escape_json_value_in_html(body)}"}`
1734
1750
  });
1735
1751
  }
1736
1752
 
@@ -1870,13 +1886,8 @@ async function load_shadow_data(route, event, prerender) {
1870
1886
 
1871
1887
  if (result.fallthrough) return result;
1872
1888
 
1873
- const { status = 200, headers = {}, body = {} } = result;
1874
-
1875
- validate_shadow_output(headers, body);
1876
-
1877
- if (headers['set-cookie']) {
1878
- /** @type {string[]} */ (data.cookies).push(...headers['set-cookie']);
1879
- }
1889
+ const { status, headers, body } = validate_shadow_output(result);
1890
+ add_cookies(/** @type {string[]} */ (data.cookies), headers);
1880
1891
 
1881
1892
  // Redirects are respected...
1882
1893
  if (status >= 300 && status < 400) {
@@ -1900,13 +1911,8 @@ async function load_shadow_data(route, event, prerender) {
1900
1911
 
1901
1912
  if (result.fallthrough) return result;
1902
1913
 
1903
- const { status = 200, headers = {}, body = {} } = result;
1904
-
1905
- validate_shadow_output(headers, body);
1906
-
1907
- if (headers['set-cookie']) {
1908
- /** @type {string[]} */ (data.cookies).push(...headers['set-cookie']);
1909
- }
1914
+ const { status, headers, body } = validate_shadow_output(result);
1915
+ add_cookies(/** @type {string[]} */ (data.cookies), headers);
1910
1916
 
1911
1917
  if (status >= 400) {
1912
1918
  return {
@@ -1937,19 +1943,42 @@ async function load_shadow_data(route, event, prerender) {
1937
1943
  }
1938
1944
 
1939
1945
  /**
1940
- * @param {Headers | Partial<import('types/helper').ResponseHeaders>} headers
1941
- * @param {import('types/helper').JSONValue} body
1946
+ * @param {string[]} target
1947
+ * @param {Partial<import('types/helper').ResponseHeaders>} headers
1942
1948
  */
1943
- function validate_shadow_output(headers, body) {
1944
- if (headers instanceof Headers && headers.has('set-cookie')) {
1945
- throw new Error(
1946
- 'Shadow endpoint request handler cannot use Headers interface with Set-Cookie headers'
1947
- );
1949
+ function add_cookies(target, headers) {
1950
+ const cookies = headers['set-cookie'];
1951
+ if (cookies) {
1952
+ if (Array.isArray(cookies)) {
1953
+ target.push(...cookies);
1954
+ } else {
1955
+ target.push(/** @type {string} */ (cookies));
1956
+ }
1957
+ }
1958
+ }
1959
+
1960
+ /**
1961
+ * @param {import('types/endpoint').ShadowEndpointOutput} result
1962
+ */
1963
+ function validate_shadow_output(result) {
1964
+ const { status = 200, body = {} } = result;
1965
+ let headers = result.headers || {};
1966
+
1967
+ if (headers instanceof Headers) {
1968
+ if (headers.has('set-cookie')) {
1969
+ throw new Error(
1970
+ 'Shadow endpoint request handler cannot use Headers interface with Set-Cookie headers'
1971
+ );
1972
+ }
1973
+ } else {
1974
+ headers = lowercase_keys(/** @type {Record<string, string>} */ (headers));
1948
1975
  }
1949
1976
 
1950
1977
  if (!is_pojo(body)) {
1951
1978
  throw new Error('Body returned from shadow endpoint request handler must be a plain object');
1952
1979
  }
1980
+
1981
+ return { status, headers, body };
1953
1982
  }
1954
1983
 
1955
1984
  /**
@@ -2282,7 +2311,7 @@ function get_page_config(leaf, options) {
2282
2311
  // TODO remove for 1.0
2283
2312
  if ('ssr' in leaf) {
2284
2313
  throw new Error(
2285
- '`export const ssr` has been removed — use the handle hook instead: https://kit.svelte.dev/docs#hooks-handle'
2314
+ '`export const ssr` has been removed — use the handle hook instead: https://kit.svelte.dev/docs/hooks#handle'
2286
2315
  );
2287
2316
  }
2288
2317
 
@@ -2453,7 +2482,7 @@ async function respond(request, options, state = {}) {
2453
2482
  });
2454
2483
  } else {
2455
2484
  const verb = allowed.length === 0 ? 'enabled' : 'allowed';
2456
- const body = `${parameter}=${method_override} is not ${verb}. See https://kit.svelte.dev/docs#configuration-methodoverride`;
2485
+ const body = `${parameter}=${method_override} is not ${verb}. See https://kit.svelte.dev/docs/configuration#methodoverride`;
2457
2486
 
2458
2487
  return new Response(body, {
2459
2488
  status: 400
@@ -211,7 +211,7 @@ async function create_plugin(config, cwd) {
211
211
  if (/** @type {any} */ (hooks).getContext) {
212
212
  // TODO remove this for 1.0
213
213
  throw new Error(
214
- 'The getContext hook has been removed. See https://kit.svelte.dev/docs#hooks'
214
+ 'The getContext hook has been removed. See https://kit.svelte.dev/docs/hooks'
215
215
  );
216
216
  }
217
217
 
@@ -333,27 +333,7 @@ function crawl(html) {
333
333
 
334
334
  /** @type {Record<string, string>} */
335
335
 
336
- /** @type {Record<string, string>} */
337
- const escape_html_attr_dict = {
338
- '<': '&lt;',
339
- '>': '&gt;',
340
- '"': '&quot;'
341
- };
342
-
343
336
  /**
344
- * use for escaping string values to be used html attributes on the page
345
- * e.g.
346
- * <script data-url="here">
347
- *
348
- * @param {string} str
349
- * @returns string escaped string
350
- */
351
- function escape_html_attr(str) {
352
- return '"' + escape(str, escape_html_attr_dict, (code) => `&#${code};`) + '"';
353
- }
354
-
355
- /**
356
- *
357
337
  * @param str {string} string to escape
358
338
  * @param dict {Record<string, string>} dictionary of character replacements
359
339
  * @param unicode_encoder {function(number): string} encoder to use for high unicode characters
@@ -386,27 +366,46 @@ function escape(str, dict, unicode_encoder) {
386
366
  return result;
387
367
  }
388
368
 
369
+ /** @type {Record<string, string>} */
370
+ const escape_html_attr_dict = {
371
+ '<': '&lt;',
372
+ '>': '&gt;',
373
+ '"': '&quot;'
374
+ };
375
+
376
+ /**
377
+ * use for escaping string values to be used html attributes on the page
378
+ * e.g.
379
+ * <script data-url="here">
380
+ *
381
+ * @param {string} str
382
+ * @returns string escaped string
383
+ */
384
+ function escape_html_attr(str) {
385
+ return '"' + escape(str, escape_html_attr_dict, (code) => `&#${code};`) + '"';
386
+ }
387
+
389
388
  /**
390
389
  * @typedef {import('types/config').PrerenderErrorHandler} PrerenderErrorHandler
391
390
  * @typedef {import('types/config').PrerenderOnErrorValue} OnError
392
391
  * @typedef {import('types/internal').Logger} Logger
393
392
  */
394
393
 
395
- /** @type {(errorDetails: Parameters<PrerenderErrorHandler>[0] ) => string} */
396
- function errorDetailsToString({ status, path, referrer, referenceType }) {
394
+ /** @type {(details: Parameters<PrerenderErrorHandler>[0] ) => string} */
395
+ function format_error({ status, path, referrer, referenceType }) {
397
396
  return `${status} ${path}${referrer ? ` (${referenceType} from ${referrer})` : ''}`;
398
397
  }
399
398
 
400
399
  /** @type {(log: Logger, onError: OnError) => PrerenderErrorHandler} */
401
- function chooseErrorHandler(log, onError) {
400
+ function normalise_error_handler(log, onError) {
402
401
  switch (onError) {
403
402
  case 'continue':
404
- return (errorDetails) => {
405
- log.error(errorDetailsToString(errorDetails));
403
+ return (details) => {
404
+ log.error(format_error(details));
406
405
  };
407
406
  case 'fail':
408
- return (errorDetails) => {
409
- throw new Error(errorDetailsToString(errorDetails));
407
+ return (details) => {
408
+ throw new Error(format_error(details));
410
409
  };
411
410
  default:
412
411
  return onError;
@@ -456,7 +455,7 @@ async function prerender({ cwd, out, log, config, build_data, fallback, all }) {
456
455
 
457
456
  const app = new App(manifest);
458
457
 
459
- const error = chooseErrorHandler(log, config.kit.prerender.onError);
458
+ const error = normalise_error_handler(log, config.kit.prerender.onError);
460
459
 
461
460
  const files = new Set([
462
461
  ...build_data.static,
@@ -493,12 +492,15 @@ async function prerender({ cwd, out, log, config, build_data, fallback, all }) {
493
492
  * @param {boolean} is_html
494
493
  */
495
494
  function output_filename(path, is_html) {
495
+ path = path.slice(config.kit.paths.base.length) || '/';
496
+
496
497
  if (path === '/') {
497
498
  return '/index.html';
498
499
  }
500
+
499
501
  const parts = path.split('/');
500
502
  if (is_html && parts[parts.length - 1] !== 'index.html') {
501
- if (config.kit.prerender.createIndexFiles) {
503
+ if (config.kit.trailingSlash === 'always') {
502
504
  parts.push('index.html');
503
505
  } else {
504
506
  parts[parts.length - 1] += '.html';
@@ -526,114 +528,113 @@ async function prerender({ cwd, out, log, config, build_data, fallback, all }) {
526
528
  * @param {string?} referrer
527
529
  */
528
530
  async function visit(path, decoded_path, referrer) {
531
+ if (!path.startsWith(config.kit.paths.base)) {
532
+ error({ status: 404, path, referrer, referenceType: 'linked' });
533
+ return;
534
+ }
535
+
529
536
  /** @type {Map<string, import('types/internal').PrerenderDependency>} */
530
537
  const dependencies = new Map();
531
538
 
532
- const render_path = config.kit.paths?.base
533
- ? `http://sveltekit-prerender${config.kit.paths.base}${path === '/' ? '' : path}`
534
- : `http://sveltekit-prerender${path}`;
535
-
536
- const rendered = await app.render(new Request(render_path), {
539
+ const rendered = await app.render(new Request(`http://sveltekit-prerender${path}`), {
537
540
  prerender: {
538
541
  all,
539
542
  dependencies
540
543
  }
541
544
  });
542
545
 
543
- if (rendered) {
544
- const response_type = Math.floor(rendered.status / 100);
545
- const type = rendered.headers.get('content-type');
546
- const is_html = response_type === REDIRECT || type === 'text/html';
546
+ const response_type = Math.floor(rendered.status / 100);
547
+ const type = rendered.headers.get('content-type');
548
+ const is_html = response_type === REDIRECT || type === 'text/html';
547
549
 
548
- const file = `${out}${output_filename(decoded_path, is_html)}`;
550
+ const file = `${out}${output_filename(decoded_path, is_html)}`;
549
551
 
550
- if (response_type === REDIRECT) {
551
- const location = rendered.headers.get('location');
552
+ if (response_type === REDIRECT) {
553
+ const location = rendered.headers.get('location');
552
554
 
553
- if (location) {
554
- mkdirp(dirname(file));
555
+ if (location) {
556
+ mkdirp(dirname(file));
555
557
 
556
- log.warn(`${rendered.status} ${decoded_path} -> ${location}`);
558
+ log.warn(`${rendered.status} ${decoded_path} -> ${location}`);
557
559
 
558
- writeFileSync(
559
- file,
560
- `<meta http-equiv="refresh" content=${escape_html_attr(`0;url=${location}`)}>`
561
- );
560
+ writeFileSync(
561
+ file,
562
+ `<meta http-equiv="refresh" content=${escape_html_attr(`0;url=${location}`)}>`
563
+ );
562
564
 
563
- const resolved = resolve(path, location);
564
- if (is_root_relative(resolved)) {
565
- enqueue(resolved, path);
566
- }
567
- } else {
568
- log.warn(`location header missing on redirect received from ${decoded_path}`);
565
+ const resolved = resolve(path, location);
566
+ if (is_root_relative(resolved)) {
567
+ enqueue(resolved, path);
569
568
  }
570
-
571
- return;
569
+ } else {
570
+ log.warn(`location header missing on redirect received from ${decoded_path}`);
572
571
  }
573
572
 
574
- const text = await rendered.text();
573
+ return;
574
+ }
575
575
 
576
- if (rendered.status === 200) {
577
- mkdirp(dirname(file));
576
+ const text = await rendered.text();
578
577
 
579
- log.info(`${rendered.status} ${decoded_path}`);
580
- writeFileSync(file, text);
581
- paths.push(normalize(decoded_path));
582
- } else if (response_type !== OK) {
583
- error({ status: rendered.status, path, referrer, referenceType: 'linked' });
584
- }
578
+ if (rendered.status === 200) {
579
+ mkdirp(dirname(file));
585
580
 
586
- for (const [dependency_path, result] of dependencies) {
587
- const { status, headers } = result.response;
581
+ log.info(`${rendered.status} ${decoded_path}`);
582
+ writeFileSync(file, text);
583
+ paths.push(normalize(decoded_path));
584
+ } else if (response_type !== OK) {
585
+ error({ status: rendered.status, path, referrer, referenceType: 'linked' });
586
+ }
588
587
 
589
- const response_type = Math.floor(status / 100);
588
+ for (const [dependency_path, result] of dependencies) {
589
+ const { status, headers } = result.response;
590
590
 
591
- const is_html = headers.get('content-type') === 'text/html';
591
+ const response_type = Math.floor(status / 100);
592
592
 
593
- const file = `${out}${output_filename(dependency_path, is_html)}`;
594
- mkdirp(dirname(file));
593
+ const is_html = headers.get('content-type') === 'text/html';
595
594
 
596
- writeFileSync(
597
- file,
598
- result.body === null ? new Uint8Array(await result.response.arrayBuffer()) : result.body
599
- );
600
- paths.push(dependency_path);
601
-
602
- if (response_type === OK) {
603
- log.info(`${status} ${dependency_path}`);
604
- } else {
605
- error({
606
- status,
607
- path: dependency_path,
608
- referrer: path,
609
- referenceType: 'fetched'
610
- });
611
- }
595
+ const file = `${out}${output_filename(dependency_path, is_html)}`;
596
+ mkdirp(dirname(file));
597
+
598
+ writeFileSync(
599
+ file,
600
+ result.body === null ? new Uint8Array(await result.response.arrayBuffer()) : result.body
601
+ );
602
+ paths.push(dependency_path);
603
+
604
+ if (response_type === OK) {
605
+ log.info(`${status} ${dependency_path}`);
606
+ } else {
607
+ error({
608
+ status,
609
+ path: dependency_path,
610
+ referrer: path,
611
+ referenceType: 'fetched'
612
+ });
612
613
  }
614
+ }
613
615
 
614
- if (is_html && config.kit.prerender.crawl) {
615
- for (const href of crawl(text)) {
616
- if (href.startsWith('data:') || href.startsWith('#')) continue;
616
+ if (is_html && config.kit.prerender.crawl) {
617
+ for (const href of crawl(text)) {
618
+ if (href.startsWith('data:') || href.startsWith('#')) continue;
617
619
 
618
- const resolved = resolve(path, href);
619
- if (!is_root_relative(resolved)) continue;
620
+ const resolved = resolve(path, href);
621
+ if (!is_root_relative(resolved)) continue;
620
622
 
621
- const parsed = new URL(resolved, 'http://localhost');
623
+ const parsed = new URL(resolved, 'http://localhost');
622
624
 
623
- let pathname = decodeURI(parsed.pathname);
625
+ let pathname = decodeURI(parsed.pathname);
624
626
 
625
- if (config.kit.paths.base) {
626
- if (!pathname.startsWith(config.kit.paths.base)) continue;
627
- pathname = pathname.slice(config.kit.paths.base.length) || '/';
628
- }
627
+ if (config.kit.paths.base) {
628
+ if (!pathname.startsWith(config.kit.paths.base)) continue;
629
+ pathname = pathname.slice(config.kit.paths.base.length) || '/';
630
+ }
629
631
 
630
- const file = pathname.slice(1);
631
- if (files.has(file)) continue;
632
+ const file = pathname.slice(1);
633
+ if (files.has(file)) continue;
632
634
 
633
- if (parsed.search) ;
635
+ if (parsed.search) ;
634
636
 
635
- enqueue(pathname, path);
636
- }
637
+ enqueue(pathname, path);
637
638
  }
638
639
  }
639
640
  }
@@ -642,10 +643,10 @@ async function prerender({ cwd, out, log, config, build_data, fallback, all }) {
642
643
  for (const entry of config.kit.prerender.entries) {
643
644
  if (entry === '*') {
644
645
  for (const entry of build_data.entries) {
645
- enqueue(entry, null);
646
+ enqueue(config.kit.paths.base + entry, null);
646
647
  }
647
648
  } else {
648
- enqueue(entry, null);
649
+ enqueue(config.kit.paths.base + entry, null);
649
650
  }
650
651
  }
651
652
 
@@ -701,6 +702,7 @@ function create_builder({ cwd, config, build_data, log }) {
701
702
  copy,
702
703
 
703
704
  appDir: config.kit.appDir,
705
+ trailingSlash: config.kit.trailingSlash,
704
706
 
705
707
  createEntries(fn) {
706
708
  generated_manifest = true;
@@ -15296,14 +15296,16 @@ async function make_package(config, cwd = process.cwd()) {
15296
15296
  const svelte_ext = config.extensions.find((ext) => file.endsWith(ext)); // unlike `ext`, could be e.g. `.svelte.md`
15297
15297
 
15298
15298
  if (!config.kit.package.files(normalized)) {
15299
- const dts_file = (svelte_ext ? file : file.slice(0, -ext.length)) + '.d.ts';
15300
- const dts_path = path.join(package_dir, dts_file);
15301
- if (fs.existsSync(dts_path)) {
15302
- fs.unlinkSync(dts_path);
15303
-
15304
- const dir = path.dirname(dts_path);
15305
- if (fs.readdirSync(dir).length === 0) {
15306
- fs.rmdirSync(dir);
15299
+ const base = svelte_ext ? file : file.slice(0, -ext.length);
15300
+ for (const e of ['.d.ts', '.d.mts', '.d.cts']) {
15301
+ const dts_path = path.join(package_dir, base + e);
15302
+ if (fs.existsSync(dts_path)) {
15303
+ fs.unlinkSync(dts_path);
15304
+
15305
+ const dir = path.dirname(dts_path);
15306
+ if (fs.readdirSync(dir).length === 0) {
15307
+ fs.rmdirSync(dir);
15308
+ }
15307
15309
  }
15308
15310
  }
15309
15311
  continue;
@@ -15573,7 +15575,7 @@ async function try_load_svelte2tsx() {
15573
15575
  return await import('svelte2tsx');
15574
15576
  } catch (e) {
15575
15577
  throw new Error(
15576
- 'You need svelte2tsx and typescript if you want to generate type definitions. Install it through your package manager, or disable generation which is highly discouraged. See https://kit.svelte.dev/docs#packaging'
15578
+ 'You need svelte2tsx and typescript if you want to generate type definitions. Install it through your package manager, or disable generation which is highly discouraged. See https://kit.svelte.dev/docs/packaging'
15577
15579
  );
15578
15580
  }
15579
15581
  }
package/dist/cli.js CHANGED
@@ -466,7 +466,7 @@ const options = object(
466
466
  message += ', rather than the name of an adapter';
467
467
  }
468
468
 
469
- throw new Error(`${message}. See https://kit.svelte.dev/docs#adapters`);
469
+ throw new Error(`${message}. See https://kit.svelte.dev/docs/adapters`);
470
470
  }
471
471
 
472
472
  return input;
@@ -480,7 +480,7 @@ const options = object(
480
480
  if (input) {
481
481
  if (input.startsWith('/') || input.endsWith('/')) {
482
482
  throw new Error(
483
- "config.kit.appDir cannot start or end with '/'. See https://kit.svelte.dev/docs#configuration"
483
+ "config.kit.appDir cannot start or end with '/'. See https://kit.svelte.dev/docs/configuration"
484
484
  );
485
485
  }
486
486
  } else {
@@ -589,7 +589,7 @@ const options = object(
589
589
 
590
590
  if (input !== '' && (input.endsWith('/') || !input.startsWith('/'))) {
591
591
  throw new Error(
592
- `${keypath} option must be a root-relative path that starts but doesn't end with '/'. See https://kit.svelte.dev/docs#configuration-paths`
592
+ `${keypath} option must be a root-relative path that starts but doesn't end with '/'. See https://kit.svelte.dev/docs/configuration#paths`
593
593
  );
594
594
  }
595
595
 
@@ -601,13 +601,13 @@ const options = object(
601
601
  if (input) {
602
602
  if (!/^[a-z]+:\/\//.test(input)) {
603
603
  throw new Error(
604
- `${keypath} option must be an absolute path, if specified. See https://kit.svelte.dev/docs#configuration-paths`
604
+ `${keypath} option must be an absolute path, if specified. See https://kit.svelte.dev/docs/configuration#paths`
605
605
  );
606
606
  }
607
607
 
608
608
  if (input.endsWith('/')) {
609
609
  throw new Error(
610
- `${keypath} option must not end with '/'. See https://kit.svelte.dev/docs#configuration-paths`
610
+ `${keypath} option must not end with '/'. See https://kit.svelte.dev/docs/configuration#paths`
611
611
  );
612
612
  }
613
613
  }
@@ -619,7 +619,9 @@ const options = object(
619
619
  prerender: object({
620
620
  concurrency: number(1),
621
621
  crawl: boolean(true),
622
- createIndexFiles: boolean(true),
622
+ createIndexFiles: error(
623
+ (keypath) => `${keypath} has been removed — it is now controlled by the trailingSlash option. See https://kit.svelte.dev/docs/configuration#trailingslash`
624
+ ),
623
625
  enabled: boolean(true),
624
626
  entries: validate(['*'], (input, keypath) => {
625
627
  if (!Array.isArray(input) || !input.every((page) => typeof page === 'string')) {
@@ -681,7 +683,7 @@ const options = object(
681
683
  // TODO remove this for 1.0
682
684
  ssr: error(
683
685
  (keypath) =>
684
- `${keypath} has been removed — use the handle hook instead: https://kit.svelte.dev/docs#hooks-handle'`
686
+ `${keypath} has been removed — use the handle hook instead: https://kit.svelte.dev/docs/hooks#handle'`
685
687
  ),
686
688
 
687
689
  // TODO remove this for 1.0
@@ -904,7 +906,7 @@ async function load_config({ cwd = process.cwd() } = {}) {
904
906
 
905
907
  if (!fs__default.existsSync(config_file)) {
906
908
  throw new Error(
907
- 'You need to create a svelte.config.js file. See https://kit.svelte.dev/docs#configuration'
909
+ 'You need to create a svelte.config.js file. See https://kit.svelte.dev/docs/configuration'
908
910
  );
909
911
  }
910
912
 
@@ -929,7 +931,7 @@ async function load_config({ cwd = process.cwd() } = {}) {
929
931
  function validate_config(config) {
930
932
  if (typeof config !== 'object') {
931
933
  throw new Error(
932
- 'svelte.config.js must have a configuration object as its default export. See https://kit.svelte.dev/docs#configuration'
934
+ 'svelte.config.js must have a configuration object as its default export. See https://kit.svelte.dev/docs/configuration'
933
935
  );
934
936
  }
935
937
 
@@ -995,7 +997,7 @@ async function launch(port, https) {
995
997
  exec(`${cmd} ${https ? 'https' : 'http'}://localhost:${port}`);
996
998
  }
997
999
 
998
- const prog = sade('svelte-kit').version('1.0.0-next.261');
1000
+ const prog = sade('svelte-kit').version('1.0.0-next.265');
999
1001
 
1000
1002
  prog
1001
1003
  .command('dev')
@@ -1066,7 +1068,7 @@ prog
1066
1068
 
1067
1069
  // prettier-ignore
1068
1070
  console.log(
1069
- `See ${$.bold().cyan('https://kit.svelte.dev/docs#adapters')} to learn how to configure your app to run on the platform of your choosing`
1071
+ `See ${$.bold().cyan('https://kit.svelte.dev/docs/adapters')} to learn how to configure your app to run on the platform of your choosing`
1070
1072
  );
1071
1073
  } catch (error) {
1072
1074
  handle_error(error);
@@ -1153,7 +1155,7 @@ async function check_port(port) {
1153
1155
  function welcome({ port, host, https, open, loose, allow, cwd }) {
1154
1156
  if (open) launch(port, https);
1155
1157
 
1156
- console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.261'}\n`));
1158
+ console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.265'}\n`));
1157
1159
 
1158
1160
  const protocol = https ? 'https:' : 'http:';
1159
1161
  const exposed = typeof host !== 'undefined' && host !== 'localhost' && host !== '127.0.0.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.261",
3
+ "version": "1.0.0-next.265",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -12,7 +12,7 @@
12
12
  "dependencies": {
13
13
  "@sveltejs/vite-plugin-svelte": "^1.0.0-next.32",
14
14
  "sade": "^1.7.4",
15
- "vite": "^2.7.2"
15
+ "vite": "^2.8.0"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@playwright/test": "^1.17.1",
@@ -84,8 +84,9 @@
84
84
  "check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore",
85
85
  "test": "npm run test:unit && npm run test:packaging && npm run test:prerendering && npm run test:integration",
86
86
  "test:unit": "uvu src \"(spec\\.js|test[\\\\/]index\\.js)\" -i packaging",
87
- "test:prerendering": "pnpm test:prerendering:basics",
87
+ "test:prerendering": "pnpm test:prerendering:basics && pnpm test:prerendering:options",
88
88
  "test:prerendering:basics": "cd test/prerendering/basics && pnpm test",
89
+ "test:prerendering:options": "cd test/prerendering/options && pnpm test",
89
90
  "test:packaging": "uvu src/packaging \"(spec\\.js|test[\\\\/]index\\.js)\"",
90
91
  "test:integration": "pnpm test:integration:amp && pnpm test:integration:basics && pnpm test:integration:options && pnpm test:integration:options-2",
91
92
  "test:integration:amp": "cd test/apps/amp && pnpm test",
package/types/config.d.ts CHANGED
@@ -41,6 +41,7 @@ export interface Builder {
41
41
  mkdirp(dir: string): void;
42
42
 
43
43
  appDir: string;
44
+ trailingSlash: 'always' | 'never' | 'ignore';
44
45
 
45
46
  /**
46
47
  * Create entry points that map to individual functions
@@ -153,7 +154,6 @@ export interface Config {
153
154
  prerender?: {
154
155
  concurrency?: number;
155
156
  crawl?: boolean;
156
- createIndexFiles?: boolean;
157
157
  enabled?: boolean;
158
158
  entries?: string[];
159
159
  onError?: PrerenderOnErrorValue;
package/types/helper.d.ts CHANGED
@@ -4,7 +4,7 @@ export type JSONObject = { [key: string]: JSONValue };
4
4
  export type JSONValue = string | number | boolean | null | ToJSON | JSONValue[] | JSONObject;
5
5
 
6
6
  /** `string[]` is only for set-cookie, everything else must be type of `string` */
7
- export type ResponseHeaders = Record<string, string | string[]>;
7
+ export type ResponseHeaders = Record<string, string | number | string[]>;
8
8
 
9
9
  // <-- Utility Types -->
10
10
  type Only<T, U> = { [P in keyof T]: T[P] } & { [P in Exclude<keyof U, keyof T>]?: never };