@sveltejs/kit 2.51.0 → 2.52.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "2.51.0",
3
+ "version": "2.52.0",
4
4
  "description": "SvelteKit is the fastest way to build Svelte apps",
5
5
  "keywords": [
6
6
  "framework",
@@ -65,21 +65,8 @@ async function analyse({
65
65
  internal.set_manifest(manifest);
66
66
  internal.set_read_implementation((file) => createReadableStream(`${server_root}/server/${file}`));
67
67
 
68
- /** @type {Map<string, { page_options: Record<string, any> | null, children: string[] }>} */
69
- const static_exports = new Map();
70
-
71
68
  // first, build server nodes without the client manifest so we can analyse it
72
- await build_server_nodes(
73
- out,
74
- config,
75
- manifest_data,
76
- server_manifest,
77
- null,
78
- null,
79
- null,
80
- output_config,
81
- static_exports
82
- );
69
+ build_server_nodes(out, config, manifest_data, server_manifest, null, null, null, output_config);
83
70
 
84
71
  /** @type {import('types').ServerMetadata} */
85
72
  const metadata = {
@@ -188,7 +175,7 @@ async function analyse({
188
175
  metadata.remotes.set(remote.hash, exports);
189
176
  }
190
177
 
191
- return { metadata, static_exports };
178
+ return { metadata };
192
179
  }
193
180
 
194
181
  /**
@@ -8,6 +8,10 @@ import { posixify, resolve_entry } from '../../../utils/filesystem.js';
8
8
  import { parse_route_id } from '../../../utils/routing.js';
9
9
  import { sort_routes } from './sort.js';
10
10
  import { isSvelte5Plus } from '../utils.js';
11
+ import {
12
+ create_node_analyser,
13
+ get_page_options
14
+ } from '../../../exports/vite/static_analysis/index.js';
11
15
 
12
16
  /**
13
17
  * Generates the manifest data used for the client-side manifest and types generation.
@@ -342,7 +346,8 @@ function create_routes_and_nodes(cwd, config, fallback) {
342
346
  }
343
347
 
344
348
  route.endpoint = {
345
- file: project_relative
349
+ file: project_relative,
350
+ page_options: null // will be filled later
346
351
  };
347
352
  }
348
353
  }
@@ -415,6 +420,8 @@ function create_routes_and_nodes(cwd, config, fallback) {
415
420
 
416
421
  const indexes = new Map(nodes.map((node, i) => [node, i]));
417
422
 
423
+ const node_analyser = create_node_analyser();
424
+
418
425
  for (const route of routes) {
419
426
  if (!route.leaf) continue;
420
427
 
@@ -459,6 +466,16 @@ function create_routes_and_nodes(cwd, config, fallback) {
459
466
  }
460
467
  }
461
468
 
469
+ for (const node of nodes) {
470
+ node.page_options = node_analyser.get_page_options(node);
471
+ }
472
+
473
+ for (const route of routes) {
474
+ if (route.endpoint) {
475
+ route.endpoint.page_options = get_page_options(route.endpoint.file);
476
+ }
477
+ }
478
+
462
479
  return {
463
480
  nodes,
464
481
  routes: sort_routes(routes)
@@ -7,6 +7,10 @@ import { write_types, write_all_types } from './write_types/index.js';
7
7
  import { write_ambient } from './write_ambient.js';
8
8
  import { write_non_ambient } from './write_non_ambient.js';
9
9
  import { write_server } from './write_server.js';
10
+ import {
11
+ create_node_analyser,
12
+ get_page_options
13
+ } from '../../exports/vite/static_analysis/index.js';
10
14
 
11
15
  /**
12
16
  * Initialize SvelteKit's generated files that only depend on the config and mode.
@@ -45,7 +49,20 @@ export function create(config) {
45
49
  * @param {string} file
46
50
  */
47
51
  export function update(config, manifest_data, file) {
52
+ const node_analyser = create_node_analyser();
53
+
54
+ for (const node of manifest_data.nodes) {
55
+ node.page_options = node_analyser.get_page_options(node);
56
+ }
57
+
58
+ for (const route of manifest_data.routes) {
59
+ if (route.endpoint) {
60
+ route.endpoint.page_options = get_page_options(route.endpoint.file);
61
+ }
62
+ }
63
+
48
64
  write_types(config, manifest_data, file);
65
+ write_non_ambient(config.kit, manifest_data);
49
66
  }
50
67
 
51
68
  /**
@@ -13,6 +13,40 @@ const remove_group_segments = (/** @type {string} */ id) => {
13
13
  return '/' + get_route_segments(id).join('/');
14
14
  };
15
15
 
16
+ /**
17
+ * Get pathnames to add based on trailingSlash settings
18
+ * @param {string} pathname
19
+ * @param {import('types').RouteData} route
20
+ * @returns {string[]}
21
+ */
22
+ function get_pathnames_for_trailing_slash(pathname, route) {
23
+ if (pathname === '/') {
24
+ return [pathname];
25
+ }
26
+
27
+ /** @type {({ trailingSlash?: import('types').TrailingSlash } | null)[]} */
28
+ const routes = [];
29
+
30
+ if (route.leaf) routes.push(route.leaf.page_options ?? null);
31
+ if (route.endpoint) routes.push(route.endpoint.page_options);
32
+
33
+ /** @type {Set<string>} */
34
+ const pathnames = new Set();
35
+
36
+ for (const page_options of routes) {
37
+ if (page_options === null || page_options.trailingSlash === 'ignore') {
38
+ pathnames.add(pathname);
39
+ pathnames.add(pathname + '/');
40
+ } else if (page_options.trailingSlash === 'always') {
41
+ pathnames.add(pathname + '/');
42
+ } else {
43
+ pathnames.add(pathname);
44
+ }
45
+ }
46
+
47
+ return Array.from(pathnames);
48
+ }
49
+
16
50
  // `declare module "svelte/elements"` needs to happen in a non-ambient module, and dts-buddy generates one big ambient module,
17
51
  // so we can't add it there - therefore generate the typings ourselves here.
18
52
  // We're not using the `declare namespace svelteHTML` variant because that one doesn't augment the HTMLAttributes interface
@@ -67,19 +101,14 @@ function generate_app_types(manifest_data) {
67
101
 
68
102
  const pathname = remove_group_segments(route.id);
69
103
  const replaced_pathname = replace_required_params(replace_optional_params(pathname));
70
- pathnames.add(`\`${replaced_pathname}\` & {}`);
71
104
 
72
- if (pathname !== '/') {
73
- // Support trailing slash
74
- pathnames.add(`\`${replaced_pathname + '/'}\` & {}`);
105
+ for (const p of get_pathnames_for_trailing_slash(replaced_pathname, route)) {
106
+ pathnames.add(`\`${p}\` & {}`);
75
107
  }
76
108
  } else {
77
109
  const pathname = remove_group_segments(route.id);
78
- pathnames.add(s(pathname));
79
-
80
- if (pathname !== '/') {
81
- // Support trailing slash
82
- pathnames.add(s(pathname + '/'));
110
+ for (const p of get_pathnames_for_trailing_slash(pathname, route)) {
111
+ pathnames.add(s(p));
83
112
  }
84
113
  }
85
114
 
@@ -3,38 +3,9 @@ import { mkdirp } from '../../../utils/filesystem.js';
3
3
  import { filter_fonts, find_deps, resolve_symlinks } from './utils.js';
4
4
  import { s } from '../../../utils/misc.js';
5
5
  import { normalizePath } from 'vite';
6
- import { basename, join } from 'node:path';
7
- import { create_node_analyser } from '../static_analysis/index.js';
6
+ import { basename } from 'node:path';
8
7
  import { fix_css_urls } from '../../../utils/css.js';
9
8
 
10
- /**
11
- * Regenerate server nodes after acquiring client manifest
12
- * @overload
13
- * @param {string} out
14
- * @param {import('types').ValidatedKitConfig} kit
15
- * @param {import('types').ManifestData} manifest_data
16
- * @param {import('vite').Manifest} server_manifest
17
- * @param {import('vite').Manifest} client_manifest
18
- * @param {string} assets_path
19
- * @param {import('vite').Rollup.RollupOutput['output']} client_chunks
20
- * @param {import('types').RecursiveRequired<import('types').ValidatedConfig['kit']['output']>} output_config
21
- * @param {Map<string, { page_options: Record<string, any> | null, children: string[] }>} static_exports
22
- * @returns {Promise<void>}
23
- */
24
- /**
25
- * Build server nodes without client manifest for analysis phase
26
- * @overload
27
- * @param {string} out
28
- * @param {import('types').ValidatedKitConfig} kit
29
- * @param {import('types').ManifestData} manifest_data
30
- * @param {import('vite').Manifest} server_manifest
31
- * @param {null} client_manifest
32
- * @param {null} assets_path
33
- * @param {null} client_chunks
34
- * @param {import('types').RecursiveRequired<import('types').ValidatedConfig['kit']['output']>} output_config
35
- * @param {Map<string, { page_options: Record<string, any> | null, children: string[] }>} static_exports
36
- * @returns {Promise<void>}
37
- */
38
9
  /**
39
10
  * @param {string} out
40
11
  * @param {import('types').ValidatedKitConfig} kit
@@ -44,9 +15,8 @@ import { fix_css_urls } from '../../../utils/css.js';
44
15
  * @param {string | null} assets_path
45
16
  * @param {import('vite').Rollup.RollupOutput['output'] | null} client_chunks
46
17
  * @param {import('types').RecursiveRequired<import('types').ValidatedConfig['kit']['output']>} output_config
47
- * @param {Map<string, { page_options: Record<string, any> | null, children: string[] }>} static_exports
48
18
  */
49
- export async function build_server_nodes(
19
+ export function build_server_nodes(
50
20
  out,
51
21
  kit,
52
22
  manifest_data,
@@ -54,8 +24,7 @@ export async function build_server_nodes(
54
24
  client_manifest,
55
25
  assets_path,
56
26
  client_chunks,
57
- output_config,
58
- static_exports
27
+ output_config
59
28
  ) {
60
29
  mkdirp(`${out}/server/nodes`);
61
30
  mkdirp(`${out}/server/stylesheets`);
@@ -116,16 +85,6 @@ export async function build_server_nodes(
116
85
  }
117
86
  }
118
87
 
119
- const { get_page_options } = create_node_analyser({
120
- resolve: (server_node) => {
121
- // Windows needs the file:// protocol for absolute path dynamic imports
122
- return import(
123
- `file://${join(out, 'server', resolve_symlinks(server_manifest, server_node).chunk.file)}`
124
- );
125
- },
126
- static_exports
127
- });
128
-
129
88
  for (let i = 0; i < manifest_data.nodes.length; i++) {
130
89
  const node = manifest_data.nodes[i];
131
90
 
@@ -159,9 +118,8 @@ export async function build_server_nodes(
159
118
  }
160
119
 
161
120
  if (node.universal) {
162
- const page_options = await get_page_options(node);
163
- if (!!page_options && page_options.ssr === false) {
164
- exports.push(`export const universal = ${s(page_options, null, 2)};`);
121
+ if (!!node.page_options && node.page_options.ssr === false) {
122
+ exports.push(`export const universal = ${s(node.page_options, null, 2)};`);
165
123
  } else {
166
124
  imports.push(
167
125
  `import * as universal from '../${resolve_symlinks(server_manifest, node.universal).chunk.file}';`
@@ -19,7 +19,6 @@ import { not_found } from '../utils.js';
19
19
  import { SCHEME } from '../../../utils/url.js';
20
20
  import { check_feature } from '../../../utils/features.js';
21
21
  import { escape_html } from '../../../utils/escape.js';
22
- import { create_node_analyser } from '../static_analysis/index.js';
23
22
 
24
23
  const cwd = process.cwd();
25
24
  // vite-specifc queries that we should skip handling for css urls
@@ -103,9 +102,6 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
103
102
  return { module, module_node, url };
104
103
  }
105
104
 
106
- /** @type {(file: string) => void} */
107
- let invalidate_page_options;
108
-
109
105
  function update_manifest() {
110
106
  try {
111
107
  ({ manifest_data } = sync.create(svelte_config));
@@ -129,14 +125,6 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
129
125
  return;
130
126
  }
131
127
 
132
- const node_analyser = create_node_analyser({
133
- resolve: async (server_node) => {
134
- const { module } = await resolve(server_node);
135
- return module;
136
- }
137
- });
138
- invalidate_page_options = node_analyser.invalidate_page_options;
139
-
140
128
  manifest = {
141
129
  appDir: svelte_config.kit.appDir,
142
130
  appPath: svelte_config.kit.appDir,
@@ -215,9 +203,8 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
215
203
  }
216
204
 
217
205
  if (node.universal) {
218
- const page_options = await node_analyser.get_page_options(node);
219
- if (page_options?.ssr === false) {
220
- result.universal = page_options;
206
+ if (node.page_options?.ssr === false) {
207
+ result.universal = node.page_options;
221
208
  } else {
222
209
  // TODO: explain why the file was loaded on the server if we fail to load it
223
210
  const { module, module_node } = await resolve(node.universal);
@@ -370,12 +357,8 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
370
357
  watch('unlink', () => debounce(update_manifest));
371
358
  watch('change', (file) => {
372
359
  // Don't run for a single file if the whole manifest is about to get updated
373
- if (timeout || restarting) return;
374
-
375
- if (/\+(page|layout).*$/.test(file)) {
376
- invalidate_page_options(path.relative(cwd, file));
377
- }
378
-
360
+ // Unless it's a file where the trailing slash page option might have changed
361
+ if (timeout || restarting || !/\+(page|layout|server).*$/.test(file)) return;
379
362
  sync.update(svelte_config, manifest_data, file);
380
363
  });
381
364
 
@@ -1063,7 +1063,7 @@ async function kit({ svelte_config }) {
1063
1063
 
1064
1064
  log.info('Analysing routes');
1065
1065
 
1066
- const { metadata, static_exports } = await analyse({
1066
+ const { metadata } = await analyse({
1067
1067
  hash: kit.router.type === 'hash',
1068
1068
  manifest_path,
1069
1069
  manifest_data,
@@ -1263,7 +1263,7 @@ async function kit({ svelte_config }) {
1263
1263
  );
1264
1264
 
1265
1265
  // regenerate nodes with the client manifest...
1266
- await build_server_nodes(
1266
+ build_server_nodes(
1267
1267
  out,
1268
1268
  kit,
1269
1269
  manifest_data,
@@ -1271,8 +1271,7 @@ async function kit({ svelte_config }) {
1271
1271
  client_manifest,
1272
1272
  assets_path,
1273
1273
  client_chunks,
1274
- svelte_config.kit.output,
1275
- static_exports
1274
+ svelte_config.kit.output
1276
1275
  );
1277
1276
 
1278
1277
  // ...and prerender
@@ -2,9 +2,21 @@ import { tsPlugin } from '@sveltejs/acorn-typescript';
2
2
  import { Parser } from 'acorn';
3
3
  import { read } from '../../../utils/filesystem.js';
4
4
 
5
- const inheritable_page_options = new Set(['ssr', 'prerender', 'csr', 'trailingSlash', 'config']);
6
-
7
- const valid_page_options = new Set([...inheritable_page_options, 'entries', 'load']);
5
+ const valid_page_options_array = /** @type {const} */ ([
6
+ 'ssr',
7
+ 'prerender',
8
+ 'csr',
9
+ 'trailingSlash',
10
+ 'config',
11
+ 'entries',
12
+ 'load'
13
+ ]);
14
+
15
+ /** @type {Set<string>} */
16
+ const valid_page_options = new Set(valid_page_options_array);
17
+
18
+ /** @typedef {typeof valid_page_options_array[number]} ValidPageOption */
19
+ /** @typedef {Partial<Record<ValidPageOption, any>>} PageOptions */
8
20
 
9
21
  const skip_parsing_regex = new RegExp(
10
22
  `${Array.from(valid_page_options).join('|')}|(?:export[\\s\\n]+\\*[\\s\\n]+from)`
@@ -18,11 +30,11 @@ const parser = Parser.extend(tsPlugin());
18
30
  * Returns `null` if any export is too difficult to analyse.
19
31
  * @param {string} filename The name of the file to report when an error occurs
20
32
  * @param {string} input
21
- * @returns {Record<string, any> | null}
33
+ * @returns {PageOptions | null}
22
34
  */
23
35
  export function statically_analyse_page_options(filename, input) {
24
- // if there's a chance there are no page exports or export all declaration,
25
- // then we can skip the AST parsing which is expensive
36
+ // if there's a chance there are no page exports or an unparseable
37
+ // export all declaration, then we can skip the AST parsing which is expensive
26
38
  if (!skip_parsing_regex.test(input)) {
27
39
  return {};
28
40
  }
@@ -194,33 +206,56 @@ export function statically_analyse_page_options(filename, input) {
194
206
  * @param {import('acorn').Identifier | import('acorn').Literal} node
195
207
  * @returns {string}
196
208
  */
197
- export function get_name(node) {
209
+ function get_name(node) {
198
210
  return node.type === 'Identifier' ? node.name : /** @type {string} */ (node.value);
199
211
  }
200
212
 
201
213
  /**
202
- * @param {{
203
- * resolve: (file: string) => Promise<Record<string, any>>;
204
- * static_exports?: Map<string, { page_options: Record<string, any> | null, children: string[] }>;
205
- * }} opts
214
+ * Reads and statically analyses a file for page options
215
+ * @param {string} filepath
216
+ * @returns {PageOptions | null} Returns the page options for the file or `null` if unanalysable
206
217
  */
207
- export function create_node_analyser({ resolve, static_exports = new Map() }) {
218
+ export function get_page_options(filepath) {
219
+ try {
220
+ const input = read(filepath);
221
+ const page_options = statically_analyse_page_options(filepath, input);
222
+ if (page_options === null) {
223
+ return null;
224
+ }
225
+
226
+ return page_options;
227
+ } catch {
228
+ return null;
229
+ }
230
+ }
231
+
232
+ export function create_node_analyser() {
233
+ const static_exports = new Map();
234
+
235
+ /**
236
+ * @param {string | undefined} key
237
+ * @param {PageOptions | null} page_options
238
+ */
239
+ const cache = (key, page_options) => {
240
+ if (key) static_exports.set(key, { page_options, children: [] });
241
+ };
242
+
208
243
  /**
209
244
  * Computes the final page options (may include load function as `load: null`; special case) for a node (if possible). Otherwise, returns `null`.
210
245
  * @param {import('types').PageNode} node
211
- * @returns {Promise<Record<string, any> | null>}
246
+ * @returns {PageOptions | null}
212
247
  */
213
- const get_page_options = async (node) => {
248
+ const crawl = (node) => {
214
249
  const key = node.universal || node.server;
215
250
  if (key && static_exports.has(key)) {
216
251
  return { ...static_exports.get(key)?.page_options };
217
252
  }
218
253
 
219
- /** @type {Record<string, any>} */
254
+ /** @type {PageOptions} */
220
255
  let page_options = {};
221
256
 
222
257
  if (node.parent) {
223
- const parent_options = await get_page_options(node.parent);
258
+ const parent_options = crawl(node.parent);
224
259
 
225
260
  const parent_key = node.parent.universal || node.parent.server;
226
261
  if (key && parent_key) {
@@ -230,9 +265,7 @@ export function create_node_analyser({ resolve, static_exports = new Map() }) {
230
265
  if (parent_options === null) {
231
266
  // if the parent cannot be analysed, we can't know what page options
232
267
  // the child node inherits, so we also mark it as unanalysable
233
- if (key) {
234
- static_exports.set(key, { page_options: null, children: [] });
235
- }
268
+ cache(key, null);
236
269
  return null;
237
270
  }
238
271
 
@@ -240,43 +273,29 @@ export function create_node_analyser({ resolve, static_exports = new Map() }) {
240
273
  }
241
274
 
242
275
  if (node.server) {
243
- const module = await resolve(node.server);
244
- for (const page_option in inheritable_page_options) {
245
- if (page_option in module) {
246
- page_options[page_option] = module[page_option];
247
- }
276
+ const server_page_options = get_page_options(node.server);
277
+ if (server_page_options === null) {
278
+ cache(key, null);
279
+ return null;
248
280
  }
281
+ page_options = { ...page_options, ...server_page_options };
249
282
  }
250
283
 
251
284
  if (node.universal) {
252
- const input = read(node.universal);
253
- const universal_page_options = statically_analyse_page_options(node.universal, input);
254
-
285
+ const universal_page_options = get_page_options(node.universal);
255
286
  if (universal_page_options === null) {
256
- static_exports.set(node.universal, { page_options: null, children: [] });
287
+ cache(key, null);
257
288
  return null;
258
289
  }
259
-
260
290
  page_options = { ...page_options, ...universal_page_options };
261
291
  }
262
292
 
263
- if (key) {
264
- static_exports.set(key, { page_options, children: [] });
265
- }
293
+ cache(key, page_options);
266
294
 
267
295
  return page_options;
268
296
  };
269
297
 
270
- /**
271
- * @param {string} file
272
- */
273
- const invalidate_page_options = (file) => {
274
- static_exports.get(file)?.children.forEach((child) => static_exports.delete(child));
275
- static_exports.delete(file);
276
- };
277
-
278
298
  return {
279
- get_page_options,
280
- invalidate_page_options
299
+ get_page_options: crawl
281
300
  };
282
301
  }
@@ -2,6 +2,7 @@
2
2
  /** @import { ResolveArgs } from './types.js' */
3
3
  import { base, assets, hash_routing } from './internal/client.js';
4
4
  import { resolve_route } from '../../../utils/routing.js';
5
+ import { get_navigation_intent } from '../../client/client.js';
5
6
 
6
7
  /**
7
8
  * Resolve the URL of an asset in your `static` directory, by prefixing it with [`config.kit.paths.assets`](https://svelte.dev/docs/kit/configuration#paths) if configured, or otherwise by prefixing it with the base path.
@@ -58,4 +59,41 @@ export function resolve(...args) {
58
59
  );
59
60
  }
60
61
 
62
+ /**
63
+ * Match a path or URL to a route ID and extracts any parameters.
64
+ *
65
+ * @example
66
+ * ```js
67
+ * import { match } from '$app/paths';
68
+ *
69
+ * const route = await match('/blog/hello-world');
70
+ *
71
+ * if (route?.id === '/blog/[slug]') {
72
+ * const slug = route.params.slug;
73
+ * const response = await fetch(`/api/posts/${slug}`);
74
+ * const post = await response.json();
75
+ * }
76
+ * ```
77
+ * @since 2.52.0
78
+ *
79
+ * @param {Pathname | URL | (string & {})} url
80
+ * @returns {Promise<{ id: RouteId, params: Record<string, string> } | null>}
81
+ */
82
+ export async function match(url) {
83
+ if (typeof url === 'string') {
84
+ url = new URL(url, location.href);
85
+ }
86
+
87
+ const intent = await get_navigation_intent(url, false);
88
+
89
+ if (intent) {
90
+ return {
91
+ id: /** @type {RouteId} */ (intent.route.id),
92
+ params: intent.params
93
+ };
94
+ }
95
+
96
+ return null;
97
+ }
98
+
61
99
  export { base, assets, resolve as resolveRoute };
@@ -1,7 +1,7 @@
1
1
  import { RouteId, Pathname, ResolvedPathname } from '$app/types';
2
2
  import { ResolveArgs } from './types.js';
3
3
 
4
- export { resolve, asset } from './client.js';
4
+ export { resolve, asset, match } from './client.js';
5
5
 
6
6
  /**
7
7
  * A string that matches [`config.kit.paths.base`](https://svelte.dev/docs/kit/configuration#paths).
@@ -1,6 +1,9 @@
1
1
  import { base, assets, relative, initial_base } from './internal/server.js';
2
- import { resolve_route } from '../../../utils/routing.js';
2
+ import { resolve_route, find_route } from '../../../utils/routing.js';
3
+ import { decode_pathname } from '../../../utils/url.js';
3
4
  import { try_get_request_store } from '@sveltejs/kit/internal/server';
5
+ import { manifest } from '__sveltekit/server';
6
+ import { get_hooks } from '__SERVER__/internal.js';
4
7
 
5
8
  /** @type {import('./client.js').asset} */
6
9
  export function asset(file) {
@@ -27,4 +30,42 @@ export function resolve(id, params) {
27
30
  return base + resolved;
28
31
  }
29
32
 
33
+ /** @type {import('./client.js').match} */
34
+ export async function match(url) {
35
+ const store = try_get_request_store();
36
+
37
+ if (typeof url === 'string') {
38
+ const origin = store?.event.url.origin ?? 'http://internal';
39
+ url = new URL(url, origin);
40
+ }
41
+
42
+ const { reroute } = await get_hooks();
43
+
44
+ let resolved_path = url.pathname;
45
+
46
+ try {
47
+ resolved_path = decode_pathname(
48
+ (await reroute?.({ url: new URL(url), fetch: store?.event.fetch ?? fetch })) ?? url.pathname
49
+ );
50
+ } catch {
51
+ return null;
52
+ }
53
+
54
+ if (base && resolved_path.startsWith(base)) {
55
+ resolved_path = resolved_path.slice(base.length) || '/';
56
+ }
57
+
58
+ const matchers = await manifest._.matchers();
59
+ const result = find_route(resolved_path, manifest._.routes, matchers);
60
+
61
+ if (result) {
62
+ return {
63
+ id: /** @type {import('$app/types').RouteId} */ (result.route.id),
64
+ params: result.params
65
+ };
66
+ }
67
+
68
+ return null;
69
+ }
70
+
30
71
  export { base, assets, resolve as resolveRoute };
@@ -1401,7 +1401,7 @@ async function get_rerouted_url(url) {
1401
1401
  * @param {boolean} invalidating
1402
1402
  * @returns {Promise<import('./types.js').NavigationIntent | undefined>}
1403
1403
  */
1404
- async function get_navigation_intent(url, invalidating) {
1404
+ export async function get_navigation_intent(url, invalidating) {
1405
1405
  if (!url) return;
1406
1406
  if (is_external_url(url, base, app.hash)) return;
1407
1407
 
@@ -1761,26 +1761,18 @@ async function navigate({
1761
1761
  await svelte.tick();
1762
1762
 
1763
1763
  // we reset scroll before dealing with focus, to avoid a flash of unscrolled content
1764
- let scroll = popped ? popped.scroll : noscroll ? scroll_state() : null;
1764
+ /** @type {Element | null | ''} */
1765
+ let deep_linked = null;
1765
1766
 
1766
1767
  if (autoscroll) {
1767
- const deep_linked = url.hash && document.getElementById(get_id(url));
1768
+ const scroll = popped ? popped.scroll : noscroll ? scroll_state() : null;
1768
1769
  if (scroll) {
1769
1770
  scrollTo(scroll.x, scroll.y);
1770
- } else if (deep_linked) {
1771
+ } else if ((deep_linked = url.hash && document.getElementById(get_id(url)))) {
1771
1772
  // Here we use `scrollIntoView` on the element instead of `scrollTo`
1772
1773
  // because it natively supports the `scroll-margin` and `scroll-behavior`
1773
1774
  // CSS properties.
1774
1775
  deep_linked.scrollIntoView();
1775
-
1776
- // Get target position at this point because with smooth scrolling the scroll position
1777
- // retrieved from current x/y above might be wrong (since we might not have arrived at the destination yet)
1778
- const { top, left } = deep_linked.getBoundingClientRect();
1779
-
1780
- scroll = {
1781
- x: pageXOffset + left,
1782
- y: pageYOffset + top
1783
- };
1784
1776
  } else {
1785
1777
  scrollTo(0, 0);
1786
1778
  }
@@ -1794,7 +1786,10 @@ async function navigate({
1794
1786
  document.activeElement !== document.body;
1795
1787
 
1796
1788
  if (!keepfocus && !changed_focus) {
1797
- reset_focus(url, scroll);
1789
+ // We don't need to manually restore the scroll position if we're navigating
1790
+ // to a fragment identifier. It is automatically done for us when we set the
1791
+ // sequential navigation starting point with `location.replace`
1792
+ reset_focus(url, !deep_linked);
1798
1793
  }
1799
1794
 
1800
1795
  autoscroll = true;
@@ -2999,9 +2994,9 @@ let resetting_focus = false;
2999
2994
 
3000
2995
  /**
3001
2996
  * @param {URL} url
3002
- * @param {{ x: number, y: number } | null} scroll
2997
+ * @param {boolean} [scroll]
3003
2998
  */
3004
- function reset_focus(url, scroll = null) {
2999
+ function reset_focus(url, scroll = true) {
3005
3000
  const autofocus = document.querySelector('[autofocus]');
3006
3001
  if (autofocus) {
3007
3002
  // @ts-ignore
@@ -3013,7 +3008,7 @@ function reset_focus(url, scroll = null) {
3013
3008
  // starting point to the fragment identifier.
3014
3009
  const id = get_id(url);
3015
3010
  if (id && document.getElementById(id)) {
3016
- const { x, y } = scroll ?? scroll_state();
3011
+ const { x, y } = scroll_state();
3017
3012
 
3018
3013
  // `element.focus()` doesn't work on Safari and Firefox Ubuntu so we need
3019
3014
  // to use this hack with `location.replace()` instead.
@@ -3028,9 +3023,9 @@ function reset_focus(url, scroll = null) {
3028
3023
  // This is also needed to restore the original hash if we're using hash routing
3029
3024
  history.replaceState(history_state, '', url);
3030
3025
 
3031
- // Scroll management has already happened earlier so we need to restore
3026
+ // If scroll management has already happened earlier, we need to restore
3032
3027
  // the scroll position after setting the sequential focus navigation starting point
3033
- scrollTo(x, y);
3028
+ if (scroll) scrollTo(x, y);
3034
3029
  resetting_focus = false;
3035
3030
  });
3036
3031
  } else {
@@ -1,8 +1,7 @@
1
1
  import { base, assets, relative } from '$app/paths/internal/server';
2
2
  import { text } from '@sveltejs/kit';
3
3
  import { s } from '../../../utils/misc.js';
4
- import { exec } from '../../../utils/routing.js';
5
- import { decode_params } from '../../../utils/url.js';
4
+ import { find_route } from '../../../utils/routing.js';
6
5
  import { get_relative_path } from '../../utils.js';
7
6
 
8
7
  /**
@@ -69,26 +68,11 @@ export async function resolve_route(resolved_path, url, manifest) {
69
68
  return text('Server-side route resolution disabled', { status: 400 });
70
69
  }
71
70
 
72
- /** @type {import('types').SSRClientRoute | null} */
73
- let route = null;
74
- /** @type {Record<string, string>} */
75
- let params = {};
76
-
77
71
  const matchers = await manifest._.matchers();
72
+ const result = find_route(resolved_path, manifest._.client.routes, matchers);
78
73
 
79
- for (const candidate of manifest._.client.routes) {
80
- const match = candidate.pattern.exec(resolved_path);
81
- if (!match) continue;
82
-
83
- const matched = exec(match, candidate.params, matchers);
84
- if (matched) {
85
- route = candidate;
86
- params = decode_params(matched);
87
- break;
88
- }
89
- }
90
-
91
- return create_server_routing_response(route, params, url, manifest).response;
74
+ return create_server_routing_response(result?.route ?? null, result?.params ?? {}, url, manifest)
75
+ .response;
92
76
  }
93
77
 
94
78
  /**
@@ -15,8 +15,8 @@ import {
15
15
  method_not_allowed,
16
16
  redirect_response
17
17
  } from './utils.js';
18
- import { decode_pathname, decode_params, disable_search, normalize_path } from '../../utils/url.js';
19
- import { exec } from '../../utils/routing.js';
18
+ import { decode_pathname, disable_search, normalize_path } from '../../utils/url.js';
19
+ import { find_route } from '../../utils/routing.js';
20
20
  import { redirect_json_response, render_data } from './data/index.js';
21
21
  import { add_cookies_to_headers, get_cookies } from './cookie.js';
22
22
  import { create_fetch } from './fetch.js';
@@ -309,18 +309,12 @@ export async function internal_respond(request, options, manifest, state) {
309
309
  if (!state.prerendering?.fallback) {
310
310
  // TODO this could theoretically break — should probably be inside a try-catch
311
311
  const matchers = await manifest._.matchers();
312
+ const result = find_route(resolved_path, manifest._.routes, matchers);
312
313
 
313
- for (const candidate of manifest._.routes) {
314
- const match = candidate.pattern.exec(resolved_path);
315
- if (!match) continue;
316
-
317
- const matched = exec(match, candidate.params, matchers);
318
- if (matched) {
319
- route = candidate;
320
- event.route = { id: route.id };
321
- event.params = decode_params(matched);
322
- break;
323
- }
314
+ if (result) {
315
+ route = result.route;
316
+ event.route = { id: route.id };
317
+ event.params = result.params;
324
318
  }
325
319
  }
326
320
 
@@ -32,6 +32,7 @@ import {
32
32
  TrailingSlash
33
33
  } from './private.js';
34
34
  import { Span } from '@opentelemetry/api';
35
+ import type { PageOptions } from '../exports/vite/static_analysis/index.js';
35
36
 
36
37
  export interface ServerModule {
37
38
  Server: typeof InternalServer;
@@ -214,6 +215,8 @@ export interface PageNode {
214
215
  parent?: PageNode;
215
216
  /** Filled with the pages that reference this layout (if this is a layout). */
216
217
  child_pages?: PageNode[];
218
+ /** The final page options for a node if it was statically analysable */
219
+ page_options?: PageOptions | null;
217
220
  }
218
221
 
219
222
  export interface PrerenderDependency {
@@ -278,6 +281,8 @@ export interface RouteData {
278
281
 
279
282
  endpoint: {
280
283
  file: string;
284
+ /** The final page options for the endpoint if it was statically analysable */
285
+ page_options: PageOptions | null;
281
286
  } | null;
282
287
  }
283
288
 
@@ -240,6 +240,7 @@ export interface RouteSegment {
240
240
  rest: boolean;
241
241
  }
242
242
 
243
+ /** @default 'never' */
243
244
  export type TrailingSlash = 'never' | 'always' | 'ignore';
244
245
 
245
246
  export type IsAny<T> = 0 extends 1 & T ? true : false;
@@ -1,4 +1,5 @@
1
1
  import { BROWSER } from 'esm-env';
2
+ import { decode_params } from './url.js';
2
3
 
3
4
  const param_pattern = /^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;
4
5
 
@@ -280,3 +281,27 @@ export function resolve_route(id, params) {
280
281
  export function has_server_load(node) {
281
282
  return node.server?.load !== undefined || node.server?.trailingSlash !== undefined;
282
283
  }
284
+
285
+ /**
286
+ * Find the first route that matches the given path
287
+ * @template {{pattern: RegExp, params: import('types').RouteParam[]}} Route
288
+ * @param {string} path - The decoded pathname to match
289
+ * @param {Route[]} routes
290
+ * @param {Record<string, import('@sveltejs/kit').ParamMatcher>} matchers
291
+ * @returns {{ route: Route, params: Record<string, string> } | null}
292
+ */
293
+ export function find_route(path, routes, matchers) {
294
+ for (const route of routes) {
295
+ const match = route.pattern.exec(path);
296
+ if (!match) continue;
297
+
298
+ const matched = exec(match, route.params, matchers);
299
+ if (matched) {
300
+ return {
301
+ route,
302
+ params: decode_params(matched)
303
+ };
304
+ }
305
+ }
306
+ return null;
307
+ }
package/src/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // generated during release, do not modify
2
2
 
3
3
  /** @type {string} */
4
- export const VERSION = '2.51.0';
4
+ export const VERSION = '2.52.0';
package/types/index.d.ts CHANGED
@@ -2395,6 +2395,7 @@ declare module '@sveltejs/kit' {
2395
2395
  rest: boolean;
2396
2396
  }
2397
2397
 
2398
+ /** @default 'never' */
2398
2399
  type TrailingSlash = 'never' | 'always' | 'ignore';
2399
2400
 
2400
2401
  type IsAny<T> = 0 extends 1 & T ? true : false;
@@ -2472,6 +2473,8 @@ declare module '@sveltejs/kit' {
2472
2473
  parent?: PageNode;
2473
2474
  /** Filled with the pages that reference this layout (if this is a layout). */
2474
2475
  child_pages?: PageNode[];
2476
+ /** The final page options for a node if it was statically analysable */
2477
+ page_options?: PageOptions | null;
2475
2478
  }
2476
2479
 
2477
2480
  type RecursiveRequired<T> = {
@@ -2516,6 +2519,8 @@ declare module '@sveltejs/kit' {
2516
2519
 
2517
2520
  endpoint: {
2518
2521
  file: string;
2522
+ /** The final page options for the endpoint if it was statically analysable */
2523
+ page_options: PageOptions | null;
2519
2524
  } | null;
2520
2525
  }
2521
2526
 
@@ -2765,6 +2770,9 @@ declare module '@sveltejs/kit' {
2765
2770
  };
2766
2771
  export type LessThan<TNumber extends number, TArray extends any[] = []> = TNumber extends TArray["length"] ? TArray[number] : LessThan<TNumber, [...TArray, TArray["length"]]>;
2767
2772
  export type NumericRange<TStart extends number, TEnd extends number> = Exclude<TEnd | LessThan<TEnd>, LessThan<TStart>>;
2773
+ type ValidPageOption = (typeof valid_page_options_array)[number];
2774
+ type PageOptions = Partial<Record<ValidPageOption, any>>;
2775
+ const valid_page_options_array: readonly ["ssr", "prerender", "csr", "trailingSlash", "config", "entries", "load"];
2768
2776
  export const VERSION: string;
2769
2777
  class HttpError_1 {
2770
2778
 
@@ -3172,6 +3180,28 @@ declare module '$app/paths' {
3172
3180
  *
3173
3181
  * */
3174
3182
  export function resolve<T extends RouteId | Pathname>(...args: ResolveArgs<T>): ResolvedPathname;
3183
+ /**
3184
+ * Match a path or URL to a route ID and extracts any parameters.
3185
+ *
3186
+ * @example
3187
+ * ```js
3188
+ * import { match } from '$app/paths';
3189
+ *
3190
+ * const route = await match('/blog/hello-world');
3191
+ *
3192
+ * if (route?.id === '/blog/[slug]') {
3193
+ * const slug = route.params.slug;
3194
+ * const response = await fetch(`/api/posts/${slug}`);
3195
+ * const post = await response.json();
3196
+ * }
3197
+ * ```
3198
+ * @since 2.52.0
3199
+ *
3200
+ * */
3201
+ export function match(url: Pathname | URL | (string & {})): Promise<{
3202
+ id: RouteId;
3203
+ params: Record<string, string>;
3204
+ } | null>;
3175
3205
 
3176
3206
  export {};
3177
3207
  }
@@ -133,6 +133,9 @@
133
133
  "invalid",
134
134
  "isValidationError",
135
135
  "normalizeUrl",
136
+ "ValidPageOption",
137
+ "PageOptions",
138
+ "valid_page_options_array",
136
139
  "VERSION",
137
140
  "sequence",
138
141
  "getRequest",
@@ -165,6 +168,7 @@
165
168
  "ResolveArgs",
166
169
  "asset",
167
170
  "resolve",
171
+ "match",
168
172
  "read",
169
173
  "getRequestEvent",
170
174
  "RemotePrerenderInputsGenerator",
@@ -179,6 +183,7 @@
179
183
  "../src/types/private.d.ts",
180
184
  "../src/types/internal.d.ts",
181
185
  "../src/exports/index.js",
186
+ "../src/exports/vite/static_analysis/index.js",
182
187
  "../src/version.js",
183
188
  "../src/exports/hooks/sequence.js",
184
189
  "../src/exports/node/index.js",
@@ -215,8 +220,9 @@
215
220
  null,
216
221
  null,
217
222
  null,
223
+ null,
218
224
  null
219
225
  ],
220
- "mappings": "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",
226
+ "mappings": "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",
221
227
  "ignoreList": []
222
228
  }