netjes 0.0.2 → 0.0.3

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.
Files changed (148) hide show
  1. package/README.md +11 -11
  2. package/cli/agents.mjs +25 -2
  3. package/cli/commands.mjs +56 -6
  4. package/cli/help.mjs +7 -2
  5. package/cli/info.mjs +7 -2
  6. package/cli/scaffold.mjs +31 -4
  7. package/dist/actions.d.ts +7 -2
  8. package/dist/actions.d.ts.map +1 -1
  9. package/dist/actions.js +9 -3
  10. package/dist/actions.js.map +1 -1
  11. package/dist/client-entry.d.ts +1 -0
  12. package/dist/client-entry.d.ts.map +1 -1
  13. package/dist/client-entry.js +19 -2
  14. package/dist/client-entry.js.map +1 -1
  15. package/dist/deferred.d.ts +11 -0
  16. package/dist/deferred.d.ts.map +1 -1
  17. package/dist/deferred.js +15 -1
  18. package/dist/deferred.js.map +1 -1
  19. package/dist/document.d.ts.map +1 -1
  20. package/dist/document.js +10 -1
  21. package/dist/document.js.map +1 -1
  22. package/dist/errors.d.ts +7 -0
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +11 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/form.d.ts +5 -5
  27. package/dist/form.d.ts.map +1 -1
  28. package/dist/form.js +5 -2
  29. package/dist/form.js.map +1 -1
  30. package/dist/href.d.ts +24 -3
  31. package/dist/href.d.ts.map +1 -1
  32. package/dist/href.js +117 -7
  33. package/dist/href.js.map +1 -1
  34. package/dist/image.d.ts +3 -3
  35. package/dist/image.d.ts.map +1 -1
  36. package/dist/image.js.map +1 -1
  37. package/dist/index.d.ts +2 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/link.d.ts +15 -7
  42. package/dist/link.d.ts.map +1 -1
  43. package/dist/link.js +38 -7
  44. package/dist/link.js.map +1 -1
  45. package/dist/metadata.d.ts +8 -2
  46. package/dist/metadata.d.ts.map +1 -1
  47. package/dist/metadata.js +14 -5
  48. package/dist/metadata.js.map +1 -1
  49. package/dist/modules.d.ts +15 -1
  50. package/dist/modules.d.ts.map +1 -1
  51. package/dist/modules.js.map +1 -1
  52. package/dist/navigation-focus.d.ts +38 -0
  53. package/dist/navigation-focus.d.ts.map +1 -0
  54. package/dist/navigation-focus.js +71 -0
  55. package/dist/navigation-focus.js.map +1 -0
  56. package/dist/query.d.ts +5 -2
  57. package/dist/query.d.ts.map +1 -1
  58. package/dist/query.js +11 -8
  59. package/dist/query.js.map +1 -1
  60. package/dist/render-document.d.ts +60 -0
  61. package/dist/render-document.d.ts.map +1 -0
  62. package/dist/render-document.js +330 -0
  63. package/dist/render-document.js.map +1 -0
  64. package/dist/route-announcer.d.ts +18 -0
  65. package/dist/route-announcer.d.ts.map +1 -0
  66. package/dist/route-announcer.js +58 -0
  67. package/dist/route-announcer.js.map +1 -0
  68. package/dist/route-tree.d.ts +6 -2
  69. package/dist/route-tree.d.ts.map +1 -1
  70. package/dist/route-tree.js +17 -7
  71. package/dist/route-tree.js.map +1 -1
  72. package/dist/router.d.ts +28 -5
  73. package/dist/router.d.ts.map +1 -1
  74. package/dist/router.js +71 -26
  75. package/dist/router.js.map +1 -1
  76. package/dist/script.d.ts +28 -5
  77. package/dist/script.d.ts.map +1 -1
  78. package/dist/script.js +192 -21
  79. package/dist/script.js.map +1 -1
  80. package/dist/server-render.d.ts.map +1 -1
  81. package/dist/server-render.js +4 -1
  82. package/dist/server-render.js.map +1 -1
  83. package/dist/testing-vitest.d.ts +8 -0
  84. package/dist/testing-vitest.d.ts.map +1 -0
  85. package/dist/testing-vitest.js +26 -0
  86. package/dist/testing-vitest.js.map +1 -0
  87. package/dist/testing.d.ts +11 -1
  88. package/dist/testing.d.ts.map +1 -1
  89. package/dist/testing.js +17 -3
  90. package/dist/testing.js.map +1 -1
  91. package/dist/zod-jitless.d.ts +2 -0
  92. package/dist/zod-jitless.d.ts.map +1 -0
  93. package/dist/zod-jitless.js +4 -0
  94. package/dist/zod-jitless.js.map +1 -0
  95. package/package.json +1 -1
  96. package/sidecar/server.mjs +73 -6
  97. package/skills/netjes/SKILL.md +13 -6
  98. package/skills/netjes/references/caching-and-streaming.md +37 -4
  99. package/skills/netjes/references/data-and-actions.md +9 -5
  100. package/skills/netjes/references/deployment.md +7 -3
  101. package/skills/netjes/references/routing.md +18 -6
  102. package/skills/netjes/references/testing.md +23 -7
  103. package/src/actions.tsx +9 -3
  104. package/src/client-entry.tsx +20 -2
  105. package/src/deferred.ts +14 -1
  106. package/src/document.tsx +22 -3
  107. package/src/errors.ts +12 -0
  108. package/src/form.tsx +10 -7
  109. package/src/href.ts +123 -8
  110. package/src/image.tsx +3 -3
  111. package/src/index.ts +2 -1
  112. package/src/link.tsx +47 -13
  113. package/src/metadata.tsx +19 -6
  114. package/src/modules.ts +15 -2
  115. package/src/navigation-focus.ts +75 -0
  116. package/src/query.tsx +14 -8
  117. package/src/render-document.tsx +386 -0
  118. package/src/route-announcer.tsx +69 -0
  119. package/src/route-tree.tsx +17 -6
  120. package/src/router.tsx +116 -31
  121. package/src/script.tsx +214 -23
  122. package/src/server-render.tsx +4 -1
  123. package/src/testing-vitest.ts +37 -0
  124. package/src/testing.tsx +31 -5
  125. package/src/virtual.d.ts +2 -0
  126. package/src/zod-jitless.ts +15 -0
  127. package/template/.dockerignore +3 -0
  128. package/template/Dockerfile +11 -1
  129. package/template/README.md +11 -7
  130. package/template/_AGENTS.md +36 -8
  131. package/template/__NAME__.csproj +2 -0
  132. package/template/app/document.test.ts +29 -0
  133. package/template/app/error.tsx +3 -2
  134. package/template/app/layout.tsx +10 -1
  135. package/template/docker-compose.override.yml +4 -3
  136. package/template/docker-compose.prod.yml +2 -1
  137. package/template/e2e/home.spec.ts +32 -0
  138. package/template/generated/netjes.ts +43 -14
  139. package/template/package.json +4 -1
  140. package/template/playwright.config.ts +36 -0
  141. package/template/tests/__NAME__.Tests/AppFactory.cs +31 -0
  142. package/template/tests/__NAME__.Tests/HomePageTests.cs +55 -0
  143. package/template/tests/__NAME__.Tests/__NAME__.Tests.csproj +30 -0
  144. package/template/tsconfig.app.json +20 -0
  145. package/template/tsconfig.json +2 -17
  146. package/template/tsconfig.node.json +8 -0
  147. package/vite/plugin.d.ts +9 -1
  148. package/vite/plugin.mjs +17 -5
@@ -0,0 +1,330 @@
1
+ // renderDocument and inlineScriptHashes, which netjes/testing exports: a page's whole document, rendered from its
2
+ // props as the Node sidecar renders it for a crawler, and the hashes of the inline scripts in it. The server builds
3
+ // the payload the sidecar renders; documentPayload builds one here from the pages map and the test's options, by the
4
+ // server's rules for the route and the segments (RouteTable and PageRenderer in src/Netjes). The two are checked
5
+ // against the same cases, test/fixtures/segments/cases.json, so a change to either rule fails a suite until both agree.
6
+ import { htmlSafeJson } from './deferred.js';
7
+ /** The files renderDocument renders besides pages, with the kind and the status the server gives them. */
8
+ const BOUNDARIES = new Map([
9
+ ['not-found', { kind: 'notFound', status: 404 }],
10
+ ['forbidden', { kind: 'forbidden', status: 403 }],
11
+ ['unauthorized', { kind: 'unauthorized', status: 401 }],
12
+ ['error', { kind: 'error', status: 500 }],
13
+ ['global-error', { kind: 'error', status: 500 }],
14
+ ]);
15
+ /** The files that make a folder a segment of the pages below it; the payload names the first four. */
16
+ const SEGMENT_FILES = ['layout', 'template', 'loading', 'error', 'not-found', 'forbidden', 'unauthorized'];
17
+ const PAGE_EXTENSION = /\.(?:tsx|jsx)$/i;
18
+ const isGroup = (folder) => folder.length > 2 && folder.startsWith('(') && folder.endsWith(')');
19
+ const isSlot = (folder) => folder.length > 1 && folder.startsWith('@');
20
+ const isPrivate = (folder) => folder.startsWith('_');
21
+ /** UTF-16 code unit order, as the server's ordinal order. */
22
+ const ordinal = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
23
+ /** "a", "a and b", "a, b and c". */
24
+ function list(items) {
25
+ return items.length < 2 ? (items[0] ?? '') : `${items.slice(0, -1).join(', ')} and ${items.at(-1) ?? ''}`;
26
+ }
27
+ /** A file in the app directory: the folders below the directory and the file's name without its extension; null for any other file. */
28
+ function parse(file, appDir) {
29
+ if (!file.startsWith(`${appDir}/`) || !PAGE_EXTENSION.test(file))
30
+ return null;
31
+ const folders = file.slice(appDir.length + 1).split('/');
32
+ const name = (folders.pop() ?? '').replace(PAGE_EXTENSION, '');
33
+ return { folders, name };
34
+ }
35
+ /** The convention files the server routes: none in private folders, and the slots that pages and defaults make. */
36
+ function appFiles(files, appDir) {
37
+ const folders = new Map();
38
+ const slots = new Map();
39
+ for (const file of [...files].sort(ordinal)) {
40
+ const parsed = parse(file, appDir);
41
+ if (!parsed || parsed.folders.some(isPrivate))
42
+ continue;
43
+ const slot = parsed.folders.findIndex(isSlot);
44
+ if (slot >= 0) {
45
+ const parent = parsed.folders.slice(0, slot).join('/');
46
+ if ((parsed.name === 'page' || parsed.name === 'default') && !slots.has(parent)) {
47
+ slots.set(parent, [appDir, ...parsed.folders.slice(0, slot + 1)].join('/'));
48
+ }
49
+ continue;
50
+ }
51
+ const folder = parsed.folders.join('/');
52
+ let conventions = folders.get(folder);
53
+ if (!conventions)
54
+ folders.set(folder, (conventions = new Map()));
55
+ if (!conventions.has(parsed.name))
56
+ conventions.set(parsed.name, file);
57
+ }
58
+ return { folders, slots };
59
+ }
60
+ /**
61
+ * How many URL segments a layout's folders cover for these route values, as the server counts them: one per folder,
62
+ * none for a route group, and a catch-all as many as its value has.
63
+ */
64
+ function urlDepth(folders, params) {
65
+ let depth = 0;
66
+ for (const folder of folders.filter((name) => !isGroup(name))) {
67
+ if (!folder.startsWith('[...') && !folder.startsWith('[[...')) {
68
+ depth++;
69
+ continue;
70
+ }
71
+ const value = params[folder.replace(/^[[\]]+|[[\]]+$/g, '').slice(3)];
72
+ depth += (Array.isArray(value) ? value.join('/') : (value ?? '')).split('/').filter(Boolean).length;
73
+ }
74
+ return depth;
75
+ }
76
+ function slotError(page, where, slot) {
77
+ return new Error(`netjes: renderDocument cannot render ${page}, which ${where} the parallel route slot ${slot}: the server chooses what a slot renders.`);
78
+ }
79
+ /**
80
+ * The folders above `folders` and the folder itself that are segments, outermost first, as the server sends them:
81
+ * each folder with a segment file, its layout's props from `layouts` and, for a layout, the URL depth it covers.
82
+ */
83
+ function segmentsFor(page, app, folders, appDir, options) {
84
+ const segments = [];
85
+ for (let end = 0; end <= folders.length; end++) {
86
+ const path = folders.slice(0, end);
87
+ const folder = path.join('/');
88
+ const slot = app.slots.get(folder);
89
+ if (slot)
90
+ throw slotError(page, 'renders under', slot);
91
+ const conventions = app.folders.get(folder);
92
+ if (!conventions || !SEGMENT_FILES.some((name) => conventions.has(name)))
93
+ continue;
94
+ const segment = { id: folder ? `${appDir}/${folder}` : appDir };
95
+ for (const name of ['layout', 'template', 'loading', 'error']) {
96
+ const file = conventions.get(name);
97
+ if (file)
98
+ segment[name] = file;
99
+ }
100
+ if (segment.layout) {
101
+ if (options.layouts && Object.hasOwn(options.layouts, segment.layout))
102
+ segment.props = options.layouts[segment.layout];
103
+ segment.depth = urlDepth(path, options.params ?? {});
104
+ }
105
+ segments.push(segment);
106
+ }
107
+ return segments;
108
+ }
109
+ /** Every file renderDocument could render from these: the pages and the boundary files, in ordinal order. */
110
+ function renderable(files, appDir) {
111
+ return files
112
+ .filter((file) => {
113
+ const parsed = parse(file, appDir);
114
+ if (!parsed || parsed.folders.some((folder) => isPrivate(folder) || isSlot(folder)))
115
+ return false;
116
+ return parsed.name === 'page' || (BOUNDARIES.has(parsed.name) && (parsed.name !== 'global-error' || parsed.folders.length === 0));
117
+ })
118
+ .sort(ordinal);
119
+ }
120
+ /**
121
+ * The payload the server sends with the document of `page`, a file of the pages map named without its leading slash,
122
+ * for the values in `options`: the route, kind, status and segments by the server's rules, and a build with no
123
+ * stylesheets or scripts. Throws for a file it cannot render: one not in `files`, a layout, or a page in a private
124
+ * folder or under a parallel route slot.
125
+ */
126
+ export function documentPayload(page, options, files, appDir) {
127
+ const paths = files.map((file) => file.replace(/^\//, ''));
128
+ if (!paths.includes(page)) {
129
+ const hint = page.startsWith('/') && paths.includes(page.slice(1))
130
+ ? `; name the file without the leading slash: ${page.slice(1)}.`
131
+ : `. The files it can render are ${list(renderable(paths, appDir))}.`;
132
+ throw new Error(`netjes: renderDocument has no ${page} in the pages map${hint}`);
133
+ }
134
+ const parsed = parse(page, appDir);
135
+ if (!parsed)
136
+ throw new Error(`netjes: renderDocument cannot render ${page}, which is not in the app's directory, ${appDir}.`);
137
+ if (parsed.folders.some(isPrivate))
138
+ throw new Error(`netjes: renderDocument cannot render ${page}: a private folder is not routed.`);
139
+ const slot = parsed.folders.findIndex(isSlot);
140
+ if (slot >= 0)
141
+ throw slotError(page, 'is in', [appDir, ...parsed.folders.slice(0, slot + 1)].join('/'));
142
+ const boundary = BOUNDARIES.get(parsed.name);
143
+ if ((parsed.name !== 'page' && !boundary) || (parsed.name === 'global-error' && parsed.folders.length > 0)) {
144
+ throw new Error(`netjes: renderDocument renders a page or a not-found, error, forbidden, unauthorized or global-error file, not ${page}.`);
145
+ }
146
+ // The global error page renders without any layout, the others inside the segments down to their own folder.
147
+ const segments = parsed.name === 'global-error' ? [] : segmentsFor(page, appFiles(paths, appDir), parsed.folders, appDir, options);
148
+ for (const file of Object.keys(options.layouts ?? {})) {
149
+ if (!segments.some((segment) => segment.layout === file)) {
150
+ const layouts = segments.flatMap((segment) => (segment.layout ? [segment.layout] : []));
151
+ throw new Error(`netjes: renderDocument has props for ${file}, which is not a layout of ${page}. ` +
152
+ (layouts.length > 0 ? `Its layouts are ${list(layouts)}.` : 'It has no layouts.'));
153
+ }
154
+ }
155
+ // An error boundary renders in place of the pages below its folder, so it is not wrapped in itself.
156
+ for (const segment of segments)
157
+ if (segment.error === page)
158
+ delete segment.error;
159
+ return {
160
+ kind: 'page',
161
+ route: parsed.name === 'page' ? `/${parsed.folders.filter((folder) => !isGroup(folder)).join('/')}` : null,
162
+ page,
163
+ ...(boundary ? { pageKind: boundary.kind } : {}),
164
+ segments,
165
+ props: options.props ?? {},
166
+ params: options.params ?? {},
167
+ shared: options.shared ?? null,
168
+ status: options.status ?? boundary?.status ?? 200,
169
+ url: options.url ?? '/',
170
+ version: 'test',
171
+ document: {
172
+ lang: options.lang ?? 'en',
173
+ assets: { stylesheets: [], modulePreloads: [], scripts: [] },
174
+ errorPage: null,
175
+ ...(options.publicConfig ? { publicConfig: options.publicConfig } : {}),
176
+ ...(options.nonce ? { nonce: options.nonce } : {}),
177
+ },
178
+ };
179
+ }
180
+ function isThenable(value) {
181
+ if ((typeof value !== 'object' && typeof value !== 'function') || value === null)
182
+ return false;
183
+ return typeof value.then === 'function';
184
+ }
185
+ function isPlainObject(value) {
186
+ if (typeof value !== 'object' || value === null)
187
+ return false;
188
+ const prototype = Object.getPrototypeOf(value);
189
+ return prototype === Object.prototype || prototype === null;
190
+ }
191
+ /** A JSON value with each Promise in it, at any depth, replaced by a `Page.Defer` placeholder; `values` keeps the Promises by id. */
192
+ function withPlaceholders(value, values) {
193
+ if (isThenable(value)) {
194
+ const id = `d${values.size}`;
195
+ values.set(id, value);
196
+ // Read once the document renders; until then a rejection is not an unhandled one.
197
+ Promise.resolve(value).catch(() => { });
198
+ return { $netjes: 'deferred', id };
199
+ }
200
+ if (Array.isArray(value))
201
+ return value.map((item) => withPlaceholders(item, values));
202
+ return isPlainObject(value) ? placeholdersIn(value, values) : value;
203
+ }
204
+ function placeholdersIn(props, values) {
205
+ // Keys are defined, not assigned, so a "__proto__" key stays a key.
206
+ return Object.fromEntries(Object.entries(props).map(([key, item]) => [key, withPlaceholders(item, values)]));
207
+ }
208
+ async function text(stream) {
209
+ const decoder = new TextDecoder();
210
+ let html = '';
211
+ for await (const chunk of stream) {
212
+ html += chunk instanceof Uint8Array ? decoder.decode(chunk, { stream: true }) : decoder.decode() + String(chunk);
213
+ }
214
+ return html + decoder.decode();
215
+ }
216
+ /**
217
+ * Renders a page's whole document, from `<!DOCTYPE html>` to `</html>`, as the Node sidecar renders it for a crawler:
218
+ * the page from `page`, a file of the pages map such as `app/blog/[slug]/page.tsx`, inside the layouts the server
219
+ * would wrap it in, with the head, Netjes's inline scripts and the payload. It waits for every Suspense boundary, and
220
+ * a Promise in the props or in a layout's props is a `Page.Defer` value: rendered in place once it resolves, left as its
221
+ * Suspense fallback when it rejects. The build's stylesheets and scripts, development styles and an antiforgery token
222
+ * are left out, and no C# runs: the props come from `options`. Runs in Vitest's node environment, with the `netjes()`
223
+ * plugin, which provides the pages map, the app's folder and the query shell, also when `modules` is given.
224
+ */
225
+ export async function renderDocument(page, options = {}) {
226
+ const { modules, signal, props, layouts, ...rest } = options;
227
+ // Before the first await, so that a Promise that has failed already gets its handler before Node looks for one.
228
+ const values = new Map();
229
+ const sent = {
230
+ ...rest,
231
+ props: placeholdersIn(props ?? {}, values),
232
+ ...(layouts
233
+ ? { layouts: Object.fromEntries(Object.entries(layouts).map(([file, layoutProps]) => [file, placeholdersIn(layoutProps, values)])) }
234
+ : {}),
235
+ };
236
+ // A form's server action, the query client and the router's first URL take their browser path where these exist.
237
+ if (typeof window !== 'undefined' || typeof document !== 'undefined') {
238
+ throw new Error('netjes: renderDocument renders a page as the Node sidecar does, without a DOM. ' +
239
+ "Put '// @vitest-environment node' at the top of the test file.");
240
+ }
241
+ signal?.throwIfAborted();
242
+ const app = await import('virtual:netjes/pages');
243
+ const pages = modules ?? app.pages;
244
+ const payload = documentPayload(page, sent, Object.keys(pages), app.appDir);
245
+ // Loaded here, so that component tests, which import netjes/testing too, never load react-dom/server.
246
+ const { createServerRenderer } = await import('./server-render.js');
247
+ const stream = await createServerRenderer(pages).renderToStream(htmlSafeJson(payload), {
248
+ waitForAll: true,
249
+ deferred: (id) => values.get(id) ?? new Promise(() => { }),
250
+ ...(signal ? { signal } : {}),
251
+ });
252
+ return text(stream);
253
+ }
254
+ /** JavaScript MIME type essences: a script element whose type is one of them, in any case, runs as a classic script. */
255
+ const JAVASCRIPT_TYPES = new Set([
256
+ 'application/ecmascript',
257
+ 'application/javascript',
258
+ 'application/x-ecmascript',
259
+ 'application/x-javascript',
260
+ 'text/ecmascript',
261
+ 'text/javascript',
262
+ 'text/javascript1.0',
263
+ 'text/javascript1.1',
264
+ 'text/javascript1.2',
265
+ 'text/javascript1.3',
266
+ 'text/javascript1.4',
267
+ 'text/javascript1.5',
268
+ 'text/jscript',
269
+ 'text/livescript',
270
+ 'text/x-ecmascript',
271
+ 'text/x-javascript',
272
+ ]);
273
+ /** The other script types whose inline text a browser checks against a policy's script sources. */
274
+ const OTHER_SCRIPT_TYPES = new Set(['module', 'importmap', 'speculationrules']);
275
+ /** A script element: its start tag's attributes (quoted values can hold a `>`) and its text, up to `</script`. */
276
+ const SCRIPT = /<script(?=[\s/>])((?:"[^"]*"|'[^']*'|[^'">])*)>([\s\S]*?)<\/script(?=[\s/>])[^>]*>/gi;
277
+ const ATTRIBUTE = /([^\s"'>/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
278
+ const asciiLowerCase = (text) => text.replace(/[A-Z]/g, (letter) => letter.toLowerCase());
279
+ function attributesOf(source) {
280
+ const attributes = new Map();
281
+ for (const [, name = '', double, single, bare] of source.matchAll(ATTRIBUTE)) {
282
+ const key = asciiLowerCase(name);
283
+ // As in HTML, the first of two attributes with one name counts.
284
+ if (!attributes.has(key))
285
+ attributes.set(key, double ?? single ?? bare ?? '');
286
+ }
287
+ return attributes;
288
+ }
289
+ /** Whether a browser runs an inline script element with these attributes, by HTML's rules for its type. */
290
+ function runs(attributes) {
291
+ const type = attributes.get('type');
292
+ const language = attributes.get('language');
293
+ const typeString = type === '' || (type === undefined && !language)
294
+ ? 'text/javascript'
295
+ : type === undefined
296
+ ? `text/${language ?? ''}`
297
+ : type.replace(/^[\t\n\f\r ]+|[\t\n\f\r ]+$/g, '');
298
+ const kind = asciiLowerCase(typeString);
299
+ if (JAVASCRIPT_TYPES.has(kind))
300
+ return !attributes.has('nomodule');
301
+ return OTHER_SCRIPT_TYPES.has(kind);
302
+ }
303
+ async function hashSource(script) {
304
+ const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(script)));
305
+ let bytes = '';
306
+ for (const byte of digest)
307
+ bytes += String.fromCharCode(byte);
308
+ return `'sha256-${btoa(bytes)}'`;
309
+ }
310
+ /**
311
+ * The hash-sources, `'sha256-…'` in their quotes, of the inline scripts in `html` that a browser runs and checks
312
+ * against a Content-Security-Policy's script sources: each script element without `src` whose type a browser runs
313
+ * (none, a JavaScript type, `module`, `importmap` or `speculationrules`), with text. Each hash is listed once, in the
314
+ * order of the first script with it. Data blocks such as the page payload (`application/json`) are left out.
315
+ */
316
+ export async function inlineScriptHashes(html) {
317
+ const scripts = [];
318
+ for (const [, tag = '', body = ''] of html.matchAll(SCRIPT)) {
319
+ const attributes = attributesOf(tag);
320
+ if (attributes.has('src') || !runs(attributes))
321
+ continue;
322
+ // The HTML parser turns each CR LF, and each CR on its own, into LF before the script sees its text.
323
+ const script = body.replace(/\r\n?/g, '\n');
324
+ // A browser checks an empty script against no policy, since it does not run it.
325
+ if (script !== '')
326
+ scripts.push(script);
327
+ }
328
+ return [...new Set(await Promise.all(scripts.map(hashSource)))];
329
+ }
330
+ //# sourceMappingURL=render-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-document.js","sourceRoot":"","sources":["../src/render-document.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ type RouteAnnouncerProps = {
2
+ /** The page's path and query: a navigation that changes neither (a refresh, a fragment link) names no page. */
3
+ location: string;
4
+ /** The path without the base path, the name of a page with neither a title nor an `h1`. */
5
+ path: string;
6
+ };
7
+ /**
8
+ * A polite live region that names the page after a client navigation, as a screen reader names the page a document
9
+ * load opens. It renders in the browser only, after hydration, so the server's HTML has none. It has no role, which
10
+ * would make it one more `status` or `alert` for an app's tests to find. Its effect runs after the app's, as a later
11
+ * sibling of the pages, so it reads the title and headings the new page has set. The first run records the name of
12
+ * the page the document loaded with; a later one, for another path or query, puts the new page's name in the region
13
+ * when it differs from the name of the page before. An intercepted page keeps the title of the page under it, so it
14
+ * is not named.
15
+ */
16
+ export declare function RouteAnnouncer({ location, path }: RouteAnnouncerProps): import("react").JSX.Element | null;
17
+ export {};
18
+ //# sourceMappingURL=route-announcer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-announcer.d.ts","sourceRoot":"","sources":["../src/route-announcer.tsx"],"names":[],"mappings":"AAqCA,KAAK,mBAAmB,GAAG;IACzB,+GAA+G;IAC/G,QAAQ,EAAE,MAAM,CAAC;IACjB,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,mBAAmB,sCAerE"}
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState, useSyncExternalStore } from 'react';
3
+ /**
4
+ * Out of sight and still read by screen readers. React sets these styles through the CSSOM on an element it creates
5
+ * in the browser, which a Content-Security-Policy without `'unsafe-inline'` in `style-src` allows.
6
+ */
7
+ const VISUALLY_HIDDEN = {
8
+ position: 'absolute',
9
+ width: 1,
10
+ height: 1,
11
+ margin: -1,
12
+ padding: 0,
13
+ border: 0,
14
+ overflow: 'hidden',
15
+ clip: 'rect(0 0 0 0)',
16
+ clipPath: 'inset(50%)',
17
+ whiteSpace: 'nowrap',
18
+ };
19
+ const subscribe = () => () => { };
20
+ const inBrowser = () => true;
21
+ const onServer = () => false;
22
+ /** A segment as a person reads it, `café` rather than `caf%C3%A9`; one that does not decode stays as it is. */
23
+ function decodeSegment(segment) {
24
+ try {
25
+ return decodeURIComponent(segment);
26
+ }
27
+ catch {
28
+ return segment;
29
+ }
30
+ }
31
+ /** How a screen reader can name the page on screen: its title, else its first `h1`, else its path, decoded. */
32
+ function pageName(path) {
33
+ return document.title.trim() || document.querySelector('h1')?.textContent?.trim() || path.split('/').map(decodeSegment).join('/');
34
+ }
35
+ /**
36
+ * A polite live region that names the page after a client navigation, as a screen reader names the page a document
37
+ * load opens. It renders in the browser only, after hydration, so the server's HTML has none. It has no role, which
38
+ * would make it one more `status` or `alert` for an app's tests to find. Its effect runs after the app's, as a later
39
+ * sibling of the pages, so it reads the title and headings the new page has set. The first run records the name of
40
+ * the page the document loaded with; a later one, for another path or query, puts the new page's name in the region
41
+ * when it differs from the name of the page before. An intercepted page keeps the title of the page under it, so it
42
+ * is not named.
43
+ */
44
+ export function RouteAnnouncer({ location, path }) {
45
+ const rendered = useSyncExternalStore(subscribe, inBrowser, onServer);
46
+ const [message, setMessage] = useState('');
47
+ const named = useRef(null);
48
+ useEffect(() => {
49
+ const name = pageName(path);
50
+ if (named.current !== null && name !== named.current)
51
+ setMessage(name);
52
+ named.current = name;
53
+ }, [location, path]);
54
+ if (!rendered)
55
+ return null;
56
+ return (_jsx("div", { "aria-live": "polite", "aria-atomic": "true", "data-netjes-route-announcer": "", style: VISUALLY_HIDDEN, children: message }));
57
+ }
58
+ //# sourceMappingURL=route-announcer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-announcer.js","sourceRoot":"","sources":["../src/route-announcer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAsB,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE9F;;;GAGG;AACH,MAAM,eAAe,GAAkB;IACrC,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC,CAAC;IACV,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,eAAe;IACrB,QAAQ,EAAE,YAAY;IACtB,UAAU,EAAE,QAAQ;CACrB,CAAC;AAEF,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;AACjC,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;AAC7B,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC;AAE7B,+GAA+G;AAC/G,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,+GAA+G;AAC/G,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpI,CAAC;AASD;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAuB;IACpE,MAAM,QAAQ,GAAG,oBAAoB,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACtE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAC1C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,CAAC,OAAO;YAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACvE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IACvB,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;IACrB,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,CACL,2BAAe,QAAQ,iBAAa,MAAM,iCAA6B,EAAE,EAAC,KAAK,EAAE,eAAe,YAC7F,OAAO,GACJ,CACP,CAAC;AACJ,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { Component, type ReactElement, type ReactNode } from 'react';
2
2
  import { type Metadata } from './metadata.tsx';
3
- import type { RouteModules } from './modules.ts';
3
+ import type { ErrorPageProps, RouteModules } from './modules.ts';
4
4
  import type { PageKind, Params, SegmentRef } from './payload.ts';
5
5
  export type { ErrorPageProps } from './modules.ts';
6
6
  type RouteTreeProps = {
@@ -15,6 +15,8 @@ type RouteTreeProps = {
15
15
  pageKey: string;
16
16
  /** What `reset` does on an error page the server chose: load the page again. */
17
17
  retry?: () => void;
18
+ /** The error an error page (`pageKind` error) gets in place of the one the server's props describe: one caught here. */
19
+ error?: ErrorPageProps['error'];
18
20
  /** Metadata from the C# loader. */
19
21
  metadata?: Metadata | undefined;
20
22
  };
@@ -42,12 +44,14 @@ export declare class ErrorBoundary extends Component<BoundaryProps, {
42
44
  private readonly reset;
43
45
  render(): ReactNode;
44
46
  }
47
+ /** What a boundary caught, as the Error `error.tsx` gets: an Error as it is, a string as its message, else a stand-in. */
48
+ export declare function asError(error: unknown): ErrorPageProps['error'];
45
49
  /**
46
50
  * The page wrapped in its segments, outermost first. Per segment, as in the Next.js App Router:
47
51
  * layout > template > error boundary > Suspense (loading) > the next segment or the page. Layouts keep their state
48
52
  * while the page underneath changes; templates remount.
49
53
  */
50
- export declare function RouteTree({ modules, segments, props, params, status, pageKind, pageKey, retry, metadata }: RouteTreeProps): ReactElement;
54
+ export declare function RouteTree({ modules, segments, props, params, status, pageKind, pageKey, retry, metadata, error }: RouteTreeProps): ReactElement;
51
55
  /** Shown for 404s and errors when the app has no not-found or error page of its own. */
52
56
  export declare function BuiltInPage({ status, props }: {
53
57
  status: number;
@@ -1 +1 @@
1
- {"version":3,"file":"route-tree.d.ts","sourceRoot":"","sources":["../src/route-tree.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAA2B,MAAM,OAAO,CAAC;AAC9F,OAAO,EAAE,KAAK,QAAQ,EAAiC,MAAM,gBAAgB,CAAC;AAC9E,OAAO,KAAK,EAAiC,YAAY,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEjE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,YAAY,CAAC;IACtB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC,+GAA+G;IAC/G,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CACjC,CAAC;AAEF,2GAA2G;AAC3G,eAAO,MAAM,kBAAkB,iCAAmB,CAAC;AAUnD,KAAK,aAAa,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,CAAC;AAE5H,0GAA0G;AAC1G,qBAAa,aAAc,SAAQ,SAAS,CAAC,aAAa,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;IACrF,KAAK;QAAK,KAAK,EAAU,OAAO;QAAE,MAAM;MAAU;IAE3D,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO;;;MAE7C;IAEQ,kBAAkB,CAAC,QAAQ,EAAE,aAAa,QAElD;IAED,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuD;IAEpE,MAAM,cAEd;CACF;AAcD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,OAAO,EAAE,QAAa,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,cAAc,GAAG,YAAY,CAoC7I;AAWD,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,+BAkBhG"}
1
+ {"version":3,"file":"route-tree.d.ts","sourceRoot":"","sources":["../src/route-tree.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAA2B,MAAM,OAAO,CAAC;AAE9F,OAAO,EAAE,KAAK,QAAQ,EAAiC,MAAM,gBAAgB,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAiB,YAAY,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEjE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,YAAY,CAAC;IACtB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC,+GAA+G;IAC/G,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,wHAAwH;IACxH,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IAChC,mCAAmC;IACnC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CACjC,CAAC;AAEF,2GAA2G;AAC3G,eAAO,MAAM,kBAAkB,iCAAmB,CAAC;AAUnD,KAAK,aAAa,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,CAAC;AAE5H,0GAA0G;AAC1G,qBAAa,aAAc,SAAQ,SAAS,CAAC,aAAa,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;IACrF,KAAK;QAAK,KAAK,EAAU,OAAO;QAAE,MAAM;MAAU;IAE3D,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO;;;MAE7C;IAEQ,kBAAkB,CAAC,QAAQ,EAAE,aAAa,QAElD;IAED,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuD;IAEpE,MAAM,cAEd;CACF;AAED,0HAA0H;AAC1H,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAG/D;AAgBD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,OAAO,EAAE,QAAa,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,cAAc,GAAG,YAAY,CAoCpJ;AAWD,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,+BAkBhG"}
@@ -1,5 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Component, Suspense, createContext } from 'react';
3
+ import { withheldError } from './errors.js';
3
4
  import { MetadataTags, resolveMetadata } from './metadata.js';
4
5
  /** How many URL segments the layout rendering here covers: what useSelectedLayoutSegment(s) count from. */
5
6
  export const LayoutDepthContext = createContext(0);
@@ -25,16 +26,25 @@ export class ErrorBoundary extends Component {
25
26
  return this.state.failed ? this.props.fallback(this.state.error, this.reset) : this.props.children;
26
27
  }
27
28
  }
28
- function asError(error) {
29
- return error instanceof Error ? error : new Error(typeof error === 'string' ? error : 'Something went wrong');
29
+ /** What a boundary caught, as the Error `error.tsx` gets: an Error as it is, a string as its message, else a stand-in. */
30
+ export function asError(error) {
31
+ if (error instanceof Error)
32
+ return error;
33
+ return typeof error === 'string' ? new Error(error) : withheldError();
30
34
  }
31
- /** The error the server reported (props of the error page it rendered), as an Error for `error.tsx`. */
35
+ /**
36
+ * The error the server reported (props of the error page it rendered), as an Error for `error.tsx`: marked withheld
37
+ * when the server says its message stands in for the exception's, and with the server's stack or none, never the
38
+ * stack of the code here that built it.
39
+ */
32
40
  function serverError(props) {
33
41
  const error = new Error(typeof props.message === 'string' ? props.message : 'Something went wrong');
34
42
  if (typeof props.status === 'number')
35
43
  error.status = props.status;
36
- if (typeof props.stack === 'string')
37
- error.stack = props.stack;
44
+ if (props.withheld === true)
45
+ error.withheld = true;
46
+ // Defined rather than assigned, as an own property: Firefox keeps the stack in an accessor on Error.prototype.
47
+ Object.defineProperty(error, 'stack', { value: typeof props.stack === 'string' ? props.stack : undefined, writable: true, configurable: true });
38
48
  return error;
39
49
  }
40
50
  /**
@@ -42,9 +52,9 @@ function serverError(props) {
42
52
  * layout > template > error boundary > Suspense (loading) > the next segment or the page. Layouts keep their state
43
53
  * while the page underneath changes; templates remount.
44
54
  */
45
- export function RouteTree({ modules, segments = [], props, params, status, pageKind, pageKey, retry, metadata }) {
55
+ export function RouteTree({ modules, segments = [], props, params, status, pageKind, pageKey, retry, metadata, error }) {
46
56
  const Page = modules.page;
47
- const pageProps = pageKind === 'error' ? { ...props, error: serverError(props), reset: retry ?? (() => { }) } : props;
57
+ const pageProps = pageKind === 'error' ? { ...props, error: error ?? serverError(props), reset: retry ?? (() => { }) } : props;
48
58
  let element = Page ? _jsx(Page, { ...pageProps }, pageKey) : _jsx(BuiltInPage, { status: status, props: props }, pageKey);
49
59
  for (let i = modules.segments.length - 1; i >= 0; i--) {
50
60
  const { Layout, Template, Loading, Error: SegmentError, slots } = modules.segments[i];
@@ -1 +1 @@
1
- {"version":3,"file":"route-tree.js","sourceRoot":"","sources":["../src/route-tree.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route-tree.js","sourceRoot":"","sources":["../src/route-tree.tsx"],"names":[],"mappings":"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"}
package/dist/router.d.ts CHANGED
@@ -19,15 +19,23 @@ export type NavigationState = {
19
19
  };
20
20
  /** The client router that `useRouter()` returns. */
21
21
  export type Router = {
22
+ /**
23
+ * Navigates, adding a history entry. The promise resolves once the router has handed the page to React, which can be
24
+ * before React shows it, or once the navigation has ended another way.
25
+ */
22
26
  push(href: Href, options?: {
23
27
  scroll?: boolean;
24
28
  }): Promise<void>;
29
+ /** Navigates, replacing the history entry. The promise resolves as `push`'s does. */
25
30
  replace(href: Href, options?: {
26
31
  scroll?: boolean;
27
32
  }): Promise<void>;
28
- /** Fetches the page payload and modules ahead of a navigation. Links do this on hover and focus. */
33
+ /** Fetches the page payload and modules ahead of a navigation. Links do this on hover, focus and touch. */
29
34
  prefetch(href: Href): void;
30
- /** Re-runs the current page's loader and re-renders with the new props. */
35
+ /**
36
+ * Runs every loader of the page on screen again, layout loaders included, and renders the page with the new props, in
37
+ * the same history entry and without scrolling. The promise resolves as `push`'s does.
38
+ */
31
39
  refresh(): Promise<void>;
32
40
  back(): void;
33
41
  forward(): void;
@@ -35,8 +43,22 @@ export type Router = {
35
43
  export type SubmitBody = EncodedForm;
36
44
  /** Called with every server action response, e.g. by the query shell to apply query updates. */
37
45
  export type ActionListener = (response: ActionResponse) => void;
38
- export type InternalRouter = Router & {
39
- submit(action: URL, body: SubmitBody): Promise<void>;
46
+ /**
47
+ * What `<Link>` and `<Form>` also pass: what had the focus before the app's own `onClick` or `onSubmit` ran. Those run
48
+ * as the navigation starts, so where they move the focus, such as back to the button of a menu that closes, is where
49
+ * the navigation put it.
50
+ */
51
+ type FocusAtStart = {
52
+ focusedAtStart?: Element | null;
53
+ };
54
+ export type InternalRouter = Omit<Router, 'push' | 'replace'> & {
55
+ push(href: Href, options?: {
56
+ scroll?: boolean;
57
+ } & FocusAtStart): Promise<void>;
58
+ replace(href: Href, options?: {
59
+ scroll?: boolean;
60
+ } & FocusAtStart): Promise<void>;
61
+ submit(action: URL, body: SubmitBody, options?: FocusAtStart): Promise<void>;
40
62
  onActionResponse(listener: ActionListener): () => void;
41
63
  /**
42
64
  * Called as soon as a server action call or form post says it set or deleted a cookie (signed someone in or out),
@@ -82,7 +104,7 @@ export declare function useInternalRouter(): InternalRouter;
82
104
  export declare function useRouter(): Router;
83
105
  /** The path without the base path, as the app's routes see it (like Next.js's `usePathname` with `basePath`). */
84
106
  export declare function usePathname(): string;
85
- /** An href for a plain `<a>` or attribute, under the base path: what `<Link>` does for its own. */
107
+ /** An href for a plain `<a>`, another attribute or a `fetch`, under the base path: what `<Link>` does for its own. */
86
108
  export declare function useHref(href: string): string;
87
109
  /** `UsePathBase`'s base path for this page, or '' when the app is mounted at the root. */
88
110
  export declare function useBasePath(): string;
@@ -115,4 +137,5 @@ export declare function useSelectedLayoutSegment(): string | null;
115
137
  export declare function usePagePayload(): PagePayload;
116
138
  /** The router's state: `loading` during a navigation, `submitting` during a form post, else `idle` (with `error` after a post that produced no page). */
117
139
  export declare function useNavigation(): NavigationState;
140
+ export {};
118
141
  //# sourceMappingURL=router.d.ts.map