@sveltejs/kit 1.0.0-next.222 → 1.0.0-next.227

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/dist/ssr.js CHANGED
@@ -536,7 +536,8 @@ async function render_response({
536
536
  }) {
537
537
  const css = new Set(options.manifest._.entry.css);
538
538
  const js = new Set(options.manifest._.entry.js);
539
- const styles = new Set();
539
+ /** @type {Map<string, string>} */
540
+ const styles = new Map();
540
541
 
541
542
  /** @type {Array<{ url: string, body: string, json: string }>} */
542
543
  const serialized_data = [];
@@ -554,7 +555,7 @@ async function render_response({
554
555
  branch.forEach(({ node, loaded, fetched, uses_credentials }) => {
555
556
  if (node.css) node.css.forEach((url) => css.add(url));
556
557
  if (node.js) node.js.forEach((url) => js.add(url));
557
- if (node.styles) node.styles.forEach((content) => styles.add(content));
558
+ if (node.styles) Object.entries(node.styles).forEach(([k, v]) => styles.set(k, v));
558
559
 
559
560
  // TODO probably better if `fetched` wasn't populated unless `hydrate`
560
561
  if (fetched && page_config.hydrate) serialized_data.push(...fetched);
@@ -615,94 +616,80 @@ async function render_response({
615
616
  rendered = { head: '', html: '', css: { code: '', map: null } };
616
617
  }
617
618
 
618
- const include_js = page_config.router || page_config.hydrate;
619
- if (!include_js) js.clear();
620
-
621
- // TODO strip the AMP stuff out of the build if not relevant
622
- const links = options.amp
623
- ? styles.size > 0 || rendered.css.code.length > 0
624
- ? `<style amp-custom>${Array.from(styles).concat(rendered.css.code).join('\n')}</style>`
625
- : ''
626
- : [
627
- // From https://web.dev/priority-hints/:
628
- // Generally, preloads will load in the order the parser gets to them for anything above "Medium" priority
629
- // Thus, we should list CSS first
630
- ...Array.from(css).map((dep) => `<link rel="stylesheet" href="${options.prefix}${dep}">`),
631
- ...Array.from(js).map((dep) => `<link rel="modulepreload" href="${options.prefix}${dep}">`)
632
- ].join('\n\t\t');
633
-
634
- /** @type {string} */
635
- let init = '';
619
+ let { head, html: body } = rendered;
620
+
621
+ const inlined_style = Array.from(styles.values()).join('\n');
636
622
 
637
623
  if (options.amp) {
638
- init = `
624
+ head += `
639
625
  <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style>
640
626
  <noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
641
- <script async src="https://cdn.ampproject.org/v0.js"></script>`;
642
- init += options.service_worker
643
- ? '<script async custom-element="amp-install-serviceworker" src="https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js"></script>'
644
- : '';
645
- } else if (include_js) {
646
- // prettier-ignore
647
- init = `<script type="module">
648
- import { start } from ${s(options.prefix + options.manifest._.entry.file)};
649
- start({
650
- target: ${options.target ? `document.querySelector(${s(options.target)})` : 'document.body'},
651
- paths: ${s(options.paths)},
652
- session: ${try_serialize($session, (error) => {
653
- throw new Error(`Failed to serialize session data: ${error.message}`);
654
- })},
655
- route: ${!!page_config.router},
656
- spa: ${!ssr},
657
- trailing_slash: ${s(options.trailing_slash)},
658
- hydrate: ${ssr && page_config.hydrate ? `{
659
- status: ${status},
660
- error: ${serialize_error(error)},
661
- nodes: [
662
- ${(branch || [])
663
- .map(({ node }) => `import(${s(options.prefix + node.entry)})`)
664
- .join(',\n\t\t\t\t\t\t')}
665
- ],
666
- url: new URL(${s(url.href)}),
667
- params: ${devalue(params)}
668
- }` : 'null'}
669
- });
670
- </script>`;
671
- }
672
-
673
- if (options.service_worker && !options.amp) {
674
- init += `<script>
675
- if ('serviceWorker' in navigator) {
676
- navigator.serviceWorker.register('${options.service_worker}');
677
- }
678
- </script>`;
679
- }
627
+ <script async src="https://cdn.ampproject.org/v0.js"></script>
680
628
 
681
- const head = [
682
- rendered.head,
683
- styles.size && !options.amp
684
- ? `<style data-svelte>${Array.from(styles).join('\n')}</style>`
685
- : '',
686
- links,
687
- init
688
- ].join('\n\n\t\t');
629
+ <style amp-custom>${inlined_style}\n${rendered.css.code}</style>`;
689
630
 
690
- let body = rendered.html;
691
- if (options.amp) {
692
631
  if (options.service_worker) {
632
+ head +=
633
+ '<script async custom-element="amp-install-serviceworker" src="https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js"></script>';
634
+
693
635
  body += `<amp-install-serviceworker src="${options.service_worker}" layout="nodisplay"></amp-install-serviceworker>`;
694
636
  }
695
637
  } else {
696
- body += serialized_data
697
- .map(({ url, body, json }) => {
698
- let attributes = `type="application/json" data-type="svelte-data" data-url=${escape_html_attr(
699
- url
700
- )}`;
701
- if (body) attributes += ` data-body="${hash(body)}"`;
702
-
703
- return `<script ${attributes}>${json}</script>`;
704
- })
705
- .join('\n\n\t');
638
+ if (inlined_style) {
639
+ head += `\n\t<style${options.dev ? ' data-svelte' : ''}>${inlined_style}</style>`;
640
+ }
641
+ // prettier-ignore
642
+ head += Array.from(css)
643
+ .map((dep) => `\n\t<link${styles.has(dep) ? ' disabled' : ''} rel="stylesheet" href="${options.prefix + dep}">`)
644
+ .join('');
645
+
646
+ if (page_config.router || page_config.hydrate) {
647
+ head += Array.from(js)
648
+ .map((dep) => `\n\t<link rel="modulepreload" href="${options.prefix + dep}">`)
649
+ .join('');
650
+ // prettier-ignore
651
+ head += `
652
+ <script type="module">
653
+ import { start } from ${s(options.prefix + options.manifest._.entry.file)};
654
+ start({
655
+ target: ${options.target ? `document.querySelector(${s(options.target)})` : 'document.body'},
656
+ paths: ${s(options.paths)},
657
+ session: ${try_serialize($session, (error) => {
658
+ throw new Error(`Failed to serialize session data: ${error.message}`);
659
+ })},
660
+ route: ${!!page_config.router},
661
+ spa: ${!ssr},
662
+ trailing_slash: ${s(options.trailing_slash)},
663
+ hydrate: ${ssr && page_config.hydrate ? `{
664
+ status: ${status},
665
+ error: ${serialize_error(error)},
666
+ nodes: [
667
+ ${(branch || [])
668
+ .map(({ node }) => `import(${s(options.prefix + node.entry)})`)
669
+ .join(',\n\t\t\t\t\t\t')}
670
+ ],
671
+ url: new URL(${s(url.href)}),
672
+ params: ${devalue(params)}
673
+ }` : 'null'}
674
+ });
675
+ </script>${options.service_worker ? `
676
+ <script>
677
+ if ('serviceWorker' in navigator) {
678
+ navigator.serviceWorker.register('${options.service_worker}');
679
+ }
680
+ </script>` : ''}`;
681
+
682
+ body += serialized_data
683
+ .map(({ url, body, json }) => {
684
+ let attributes = `type="application/json" data-type="svelte-data" data-url=${escape_html_attr(
685
+ url
686
+ )}`;
687
+ if (body) attributes += ` data-body="${hash(body)}"`;
688
+
689
+ return `<script ${attributes}>${json}</script>`;
690
+ })
691
+ .join('\n\n\t');
692
+ }
706
693
  }
707
694
 
708
695
  /** @type {import('types/helper').ResponseHeaders} */
@@ -1571,8 +1558,9 @@ function read_only_form_data() {
1571
1558
  * @param {string} value
1572
1559
  */
1573
1560
  append(key, value) {
1574
- if (map.has(key)) {
1575
- (map.get(key) || []).push(value);
1561
+ const existing_values = map.get(key);
1562
+ if (existing_values) {
1563
+ existing_values.push(value);
1576
1564
  } else {
1577
1565
  map.set(key, [value]);
1578
1566
  }
@@ -1594,12 +1582,15 @@ class ReadOnlyFormData {
1594
1582
  /** @param {string} key */
1595
1583
  get(key) {
1596
1584
  const value = this.#map.get(key);
1597
- return value && value[0];
1585
+ if (!value) {
1586
+ return null;
1587
+ }
1588
+ return value[0];
1598
1589
  }
1599
1590
 
1600
1591
  /** @param {string} key */
1601
1592
  getAll(key) {
1602
- return this.#map.get(key);
1593
+ return this.#map.get(key) || [];
1603
1594
  }
1604
1595
 
1605
1596
  /** @param {string} key */
@@ -1779,6 +1770,28 @@ async function respond(incoming, options, state = {}) {
1779
1770
  locals: {}
1780
1771
  };
1781
1772
 
1773
+ const { parameter, allowed } = options.method_override;
1774
+ const method_override = incoming.url.searchParams.get(parameter)?.toUpperCase();
1775
+
1776
+ if (method_override) {
1777
+ if (request.method.toUpperCase() === 'POST') {
1778
+ if (allowed.includes(method_override)) {
1779
+ request.method = method_override;
1780
+ } else {
1781
+ const verb = allowed.length === 0 ? 'enabled' : 'allowed';
1782
+ const body = `${parameter}=${method_override} is not ${verb}. See https://kit.svelte.dev/docs#configuration-methodoverride`;
1783
+
1784
+ return {
1785
+ status: 400,
1786
+ headers: {},
1787
+ body
1788
+ };
1789
+ }
1790
+ } else {
1791
+ throw new Error(`${parameter}=${method_override} is only allowed with POST requests`);
1792
+ }
1793
+ }
1794
+
1782
1795
  // TODO remove this for 1.0
1783
1796
  /**
1784
1797
  * @param {string} property
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.222",
3
+ "version": "1.0.0-next.227",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -35,7 +35,7 @@
35
35
  "node-fetch": "^3.1.0",
36
36
  "port-authority": "^1.1.2",
37
37
  "rollup": "^2.60.2",
38
- "selfsigned": "^1.10.11",
38
+ "selfsigned": "^2.0.0",
39
39
  "sirv": "^2.0.0",
40
40
  "svelte": "^3.44.2",
41
41
  "svelte-check": "^2.2.10",
@@ -72,6 +72,19 @@ declare module '$app/navigation' {
72
72
  * Returns a Promise that resolves when the routes have been prefetched.
73
73
  */
74
74
  export function prefetchRoutes(routes?: string[]): Promise<any>;
75
+
76
+ /**
77
+ * A navigation interceptor that triggers before we navigate to a new route.
78
+ * This is helpful if we want to conditionally prevent a navigation from completing or lookup the upcoming url.
79
+ */
80
+ export function beforeNavigate(
81
+ fn: ({ from, to, cancel }: { from: URL; to: URL | null; cancel: () => void }) => void
82
+ ): any;
83
+
84
+ /**
85
+ * A lifecycle function that runs when the page mounts, and also whenever SvelteKit navigates to a new URL but stays on this component.
86
+ */
87
+ export function afterNavigate(fn: ({ from, to }: { from: URL | null; to: URL }) => void): any;
75
88
  }
76
89
 
77
90
  declare module '$app/paths' {
package/types/config.d.ts CHANGED
@@ -131,6 +131,11 @@ export interface Config {
131
131
  };
132
132
  host?: string;
133
133
  hydrate?: boolean;
134
+ inlineStyleThreshold?: number;
135
+ methodOverride?: {
136
+ parameter?: string;
137
+ allowed?: string[];
138
+ };
134
139
  package?: {
135
140
  dir?: string;
136
141
  emitTypes?: boolean;
package/types/helper.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  interface ReadOnlyFormData {
2
- get(key: string): string;
2
+ get(key: string): string | null;
3
3
  getAll(key: string): string[];
4
4
  has(key: string): boolean;
5
5
  entries(): Generator<[string, string], void>;
@@ -119,7 +119,7 @@ export interface SSRNode {
119
119
  /** external JS files */
120
120
  js: string[];
121
121
  /** inlined styles */
122
- styles: string[];
122
+ styles?: Record<string, string>;
123
123
  }
124
124
 
125
125
  export interface SSRRenderOptions {
@@ -131,6 +131,7 @@ export interface SSRRenderOptions {
131
131
  hooks: Hooks;
132
132
  hydrate: boolean;
133
133
  manifest: SSRManifest;
134
+ method_override: MethodOverride;
134
135
  paths: {
135
136
  base: string;
136
137
  assets: string;
@@ -230,3 +231,7 @@ export type NormalizedLoadOutput = Either<
230
231
  >;
231
232
 
232
233
  export type TrailingSlash = 'never' | 'always' | 'ignore';
234
+ export interface MethodOverride {
235
+ parameter: string;
236
+ allowed: string[];
237
+ }