@react-router/dev 7.13.1 → 7.13.2-pre.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/CHANGELOG.md +56 -15
- package/dist/cli/index.js +26 -8
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -1
- package/dist/routes.js +1 -1
- package/dist/vite/cloudflare.js +26 -8
- package/dist/vite.js +49 -16
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# `@react-router/dev`
|
|
2
2
|
|
|
3
|
+
## 7.13.2-pre.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix `react-router dev` crash when Unix socket files exist in the project root ([#14854](https://github.com/remix-run/react-router/pull/14854))
|
|
8
|
+
- Escape redirect locations in prerendered redirect HTML ([#14880](https://github.com/remix-run/react-router/pull/14880))
|
|
9
|
+
- Add `future.unstable_passThroughRequests` flag ([#14775](https://github.com/remix-run/react-router/pull/14775))
|
|
10
|
+
|
|
11
|
+
By default, React Router normalizes the `request.url` passed to your `loader`, `action`, and `middleware` functions by removing React Router's internal implementation details (`.data` suffixes, `index` + `_routes` query params).
|
|
12
|
+
|
|
13
|
+
Enabling this flag removes that normalization and passes the raw HTTP `request` instance to your handlers. This provides a few benefits:
|
|
14
|
+
- Reduces server-side overhead by eliminating multiple `new Request()` calls on the critical path
|
|
15
|
+
- Allows you to distinguish document from data requests in your handlers base don the presence of a `.data` suffix (useful for observability purposes)
|
|
16
|
+
|
|
17
|
+
If you were previously relying on the normalization of `request.url`, you can switch to use the new sibling `unstable_url` parameter which contains a `URL` instance representing the normalized location:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
// ❌ Before: you could assume there was no `.data` suffix in `request.url`
|
|
21
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
22
|
+
let url = new URL(request.url);
|
|
23
|
+
if (url.pathname === "/path") {
|
|
24
|
+
// This check will fail with the flag enabled because the `.data` suffix will
|
|
25
|
+
// exist on data requests
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ✅ After: use `unstable_url` for normalized routing logic and `request.url`
|
|
30
|
+
// for raw routing logic
|
|
31
|
+
export async function loader({ request, unstable_url }: Route.LoaderArgs) {
|
|
32
|
+
if (unstable_url.pathname === "/path") {
|
|
33
|
+
// This will always have the `.data` suffix stripped
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// And now you can distinguish between document versus data requests
|
|
37
|
+
let isDataRequest = new URL(request.url).pathname.endsWith(".data");
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- Add a new `unstable_url: URL` parameter to route handler methods (`loader`, `action`, `middleware`, etc.) representing the normalized URL the application is navigating to or fetching, with React Router implementation details removed (`.data`suffix, `index`/`_routes` query params) ([#14775](https://github.com/remix-run/react-router/pull/14775))
|
|
42
|
+
|
|
43
|
+
This is being added alongside the new `future.unstable_passthroughRequests` future flag so that users still have a way to access the normalized URL when that flag is enabled and non-normalized `request`'s are being passed to your handlers. When adopting this flag, you will only need to start leveraging this new parameter if you are relying on the normalization of `request.url` in your application code.
|
|
44
|
+
|
|
45
|
+
If you don't have the flag enabled, then `unstable_url` will match `request.url`.
|
|
46
|
+
|
|
47
|
+
- Updated dependencies:
|
|
48
|
+
- `react-router@7.13.2-pre.0`
|
|
49
|
+
- `@react-router/node@7.13.2-pre.0`
|
|
50
|
+
- `@react-router/serve@7.13.2-pre.0`
|
|
51
|
+
|
|
3
52
|
## 7.13.1
|
|
4
53
|
|
|
5
54
|
### Patch Changes
|
|
@@ -37,25 +86,25 @@
|
|
|
37
86
|
|
|
38
87
|
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname\`** |
|
|
39
88
|
| ------------ | ----------------- | ------------------------ |
|
|
40
|
-
| **Document** | `/a/b/c` | `/a/b/c` ✅
|
|
41
|
-
| **Data** | `/a/b/c.data` | `/a/b/c` ✅
|
|
89
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
90
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
42
91
|
|
|
43
92
|
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname\`** |
|
|
44
93
|
| ------------- | ----------------- | ------------------------ |
|
|
45
|
-
| **Document** | `/a/b/c/` | `/a/b/c/` ✅
|
|
94
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
46
95
|
| **Data** | `/a/b/c.data` | `/a/b/c` ⚠️ |
|
|
47
96
|
|
|
48
97
|
With this flag enabled, these pathnames will be made consistent though a new `_.data` format for client-side `.data` requests:
|
|
49
98
|
|
|
50
99
|
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname\`** |
|
|
51
100
|
| ------------ | ----------------- | ------------------------ |
|
|
52
|
-
| **Document** | `/a/b/c` | `/a/b/c` ✅
|
|
53
|
-
| **Data** | `/a/b/c.data` | `/a/b/c` ✅
|
|
101
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
102
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
54
103
|
|
|
55
104
|
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname\`** |
|
|
56
105
|
| ------------- | ------------------ | ------------------------ |
|
|
57
|
-
| **Document** | `/a/b/c/` | `/a/b/c/` ✅
|
|
58
|
-
| **Data** | `/a/b/c/_.data` ⬅️ | `/a/b/c/` ✅
|
|
106
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
107
|
+
| **Data** | `/a/b/c/_.data` ⬅️ | `/a/b/c/` ✅ |
|
|
59
108
|
|
|
60
109
|
This a bug fix but we are putting it behind an opt-in flag because it has the potential to be a "breaking bug fix" if you are relying on the URL format for any other application or caching logic.
|
|
61
110
|
|
|
@@ -313,7 +362,6 @@
|
|
|
313
362
|
- Stabilize middleware and context APIs. ([#14215](https://github.com/remix-run/react-router/pull/14215))
|
|
314
363
|
|
|
315
364
|
We have removed the `unstable_` prefix from the following APIs and they are now considered stable and ready for production use:
|
|
316
|
-
|
|
317
365
|
- [`RouterContextProvider`](https://reactrouter.com/api/utils/RouterContextProvider)
|
|
318
366
|
- [`createContext`](https://reactrouter.com/api/utils/createContext)
|
|
319
367
|
- `createBrowserRouter` [`getContext`](https://reactrouter.com/api/data-routers/createBrowserRouter#optsgetcontext) option
|
|
@@ -1056,7 +1104,6 @@
|
|
|
1056
1104
|
```
|
|
1057
1105
|
|
|
1058
1106
|
This initial implementation targets type inference for:
|
|
1059
|
-
|
|
1060
1107
|
- `Params` : Path parameters from your routing config in `routes.ts` including file-based routing
|
|
1061
1108
|
- `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module
|
|
1062
1109
|
- `ActionData` : Action data from `action` and/or `clientAction` within your route module
|
|
@@ -1071,7 +1118,6 @@
|
|
|
1071
1118
|
```
|
|
1072
1119
|
|
|
1073
1120
|
Check out our docs for more:
|
|
1074
|
-
|
|
1075
1121
|
- [_Explanations > Type Safety_](https://reactrouter.com/dev/guides/explanation/type-safety)
|
|
1076
1122
|
- [_How-To > Setting up type safety_](https://reactrouter.com/dev/guides/how-to/setting-up-type-safety)
|
|
1077
1123
|
|
|
@@ -1271,7 +1317,6 @@
|
|
|
1271
1317
|
- Vite: Provide `Unstable_ServerBundlesFunction` and `Unstable_VitePluginConfig` types ([#8654](https://github.com/remix-run/remix/pull/8654))
|
|
1272
1318
|
|
|
1273
1319
|
- Vite: add `--sourcemapClient` and `--sourcemapServer` flags to `remix vite:build` ([#8613](https://github.com/remix-run/remix/pull/8613))
|
|
1274
|
-
|
|
1275
1320
|
- `--sourcemapClient`
|
|
1276
1321
|
|
|
1277
1322
|
- `--sourcemapClient=inline`
|
|
@@ -1608,7 +1653,6 @@
|
|
|
1608
1653
|
- Add support for `clientLoader`/`clientAction`/`HydrateFallback` route exports ([RFC](https://github.com/remix-run/remix/discussions/7634)) ([#8173](https://github.com/remix-run/remix/pull/8173))
|
|
1609
1654
|
|
|
1610
1655
|
Remix now supports loaders/actions that run on the client (in addition to, or instead of the loader/action that runs on the server). While we still recommend server loaders/actions for the majority of your data needs in a Remix app - these provide some levers you can pull for more advanced use-cases such as:
|
|
1611
|
-
|
|
1612
1656
|
- Leveraging a data source local to the browser (i.e., `localStorage`)
|
|
1613
1657
|
- Managing a client-side cache of server data (like `IndexedDB`)
|
|
1614
1658
|
- Bypassing the Remix server in a BFF setup and hitting your API directly from the browser
|
|
@@ -2012,7 +2056,6 @@
|
|
|
2012
2056
|
- Output esbuild metafiles for bundle analysis ([#6772](https://github.com/remix-run/remix/pull/6772))
|
|
2013
2057
|
|
|
2014
2058
|
Written to server build directory (`build/` by default):
|
|
2015
|
-
|
|
2016
2059
|
- `metafile.css.json`
|
|
2017
2060
|
- `metafile.js.json` (browser JS)
|
|
2018
2061
|
- `metafile.server.json` (server JS)
|
|
@@ -2110,7 +2153,6 @@
|
|
|
2110
2153
|
- built-in tls support ([#6483](https://github.com/remix-run/remix/pull/6483))
|
|
2111
2154
|
|
|
2112
2155
|
New options:
|
|
2113
|
-
|
|
2114
2156
|
- `--tls-key` / `tlsKey`: TLS key
|
|
2115
2157
|
- `--tls-cert` / `tlsCert`: TLS Certificate
|
|
2116
2158
|
|
|
@@ -2381,7 +2423,6 @@
|
|
|
2381
2423
|
```
|
|
2382
2424
|
|
|
2383
2425
|
The dev server will:
|
|
2384
|
-
|
|
2385
2426
|
- force `NODE_ENV=development` and warn you if it was previously set to something else
|
|
2386
2427
|
- rebuild your app whenever your Remix app code changes
|
|
2387
2428
|
- restart your app server whenever rebuilds succeed
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @react-router/dev v7.13.
|
|
3
|
+
* @react-router/dev v7.13.2-pre.0
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) Remix Software Inc.
|
|
6
6
|
*
|
|
@@ -505,6 +505,7 @@ async function resolveConfig({
|
|
|
505
505
|
}
|
|
506
506
|
let future = {
|
|
507
507
|
unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
|
|
508
|
+
unstable_passThroughRequests: userAndPresetConfigs.future?.unstable_passThroughRequests ?? false,
|
|
508
509
|
unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
|
|
509
510
|
unstable_trailingSlashAwareDataRequests: userAndPresetConfigs.future?.unstable_trailingSlashAwareDataRequests ?? false,
|
|
510
511
|
unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
|
|
@@ -586,13 +587,11 @@ async function createConfigLoader({
|
|
|
586
587
|
if (!fsWatcher) {
|
|
587
588
|
fsWatcher = import_chokidar.default.watch([root, appDirectory], {
|
|
588
589
|
ignoreInitial: true,
|
|
589
|
-
ignored: (path10) => {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
dirname5 !== root;
|
|
595
|
-
}
|
|
590
|
+
ignored: (path10) => isIgnoredByWatcher(path10, { root, appDirectory })
|
|
591
|
+
});
|
|
592
|
+
fsWatcher.on("error", (error) => {
|
|
593
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
594
|
+
console.warn(import_picocolors.default.yellow(`File watcher error: ${message}`));
|
|
596
595
|
});
|
|
597
596
|
fsWatcher.on("all", async (...args) => {
|
|
598
597
|
let [event, rawFilepath] = args;
|
|
@@ -733,6 +732,25 @@ function isEntryFileDependency(moduleGraph, entryFilepath, filepath, visited = /
|
|
|
733
732
|
}
|
|
734
733
|
return false;
|
|
735
734
|
}
|
|
735
|
+
function isIgnoredByWatcher(path10, { root, appDirectory }) {
|
|
736
|
+
let dirname5 = import_pathe3.default.dirname(path10);
|
|
737
|
+
let ignoredByPath = !dirname5.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
|
|
738
|
+
// that are at the root level, not nested in subdirectories
|
|
739
|
+
path10 !== root && // Watch the root directory itself
|
|
740
|
+
dirname5 !== root;
|
|
741
|
+
if (ignoredByPath) {
|
|
742
|
+
return true;
|
|
743
|
+
}
|
|
744
|
+
try {
|
|
745
|
+
let stat = import_node_fs.default.statSync(path10, { throwIfNoEntry: false });
|
|
746
|
+
if (stat && !stat.isFile() && !stat.isDirectory()) {
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
} catch {
|
|
750
|
+
return true;
|
|
751
|
+
}
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
736
754
|
var import_node_fs, import_node_child_process, import_pathe3, import_chokidar, import_picocolors, import_pick2, import_omit, import_cloneDeep, import_isEqual, excludedConfigPresetKeys, mergeReactRouterConfig, deepFreeze, entryExts;
|
|
737
755
|
var init_config = __esm({
|
|
738
756
|
"config/config.ts"() {
|
package/dist/config.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ type ServerBundlesBuildManifest = BaseBuildManifest & {
|
|
|
38
38
|
type ServerModuleFormat = "esm" | "cjs";
|
|
39
39
|
interface FutureConfig {
|
|
40
40
|
unstable_optimizeDeps: boolean;
|
|
41
|
+
unstable_passThroughRequests: boolean;
|
|
41
42
|
unstable_subResourceIntegrity: boolean;
|
|
42
43
|
unstable_trailingSlashAwareDataRequests: boolean;
|
|
43
44
|
/**
|
package/dist/config.js
CHANGED
package/dist/routes.js
CHANGED
package/dist/vite/cloudflare.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v7.13.
|
|
2
|
+
* @react-router/dev v7.13.2-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -531,6 +531,7 @@ async function resolveConfig({
|
|
|
531
531
|
}
|
|
532
532
|
let future = {
|
|
533
533
|
unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
|
|
534
|
+
unstable_passThroughRequests: userAndPresetConfigs.future?.unstable_passThroughRequests ?? false,
|
|
534
535
|
unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
|
|
535
536
|
unstable_trailingSlashAwareDataRequests: userAndPresetConfigs.future?.unstable_trailingSlashAwareDataRequests ?? false,
|
|
536
537
|
unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
|
|
@@ -612,13 +613,11 @@ async function createConfigLoader({
|
|
|
612
613
|
if (!fsWatcher) {
|
|
613
614
|
fsWatcher = import_chokidar.default.watch([root, appDirectory], {
|
|
614
615
|
ignoreInitial: true,
|
|
615
|
-
ignored: (path3) => {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
dirname !== root;
|
|
621
|
-
}
|
|
616
|
+
ignored: (path3) => isIgnoredByWatcher(path3, { root, appDirectory })
|
|
617
|
+
});
|
|
618
|
+
fsWatcher.on("error", (error) => {
|
|
619
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
620
|
+
console.warn(import_picocolors.default.yellow(`File watcher error: ${message}`));
|
|
622
621
|
});
|
|
623
622
|
fsWatcher.on("all", async (...args) => {
|
|
624
623
|
let [event, rawFilepath] = args;
|
|
@@ -760,6 +759,25 @@ function isEntryFileDependency(moduleGraph, entryFilepath, filepath, visited = /
|
|
|
760
759
|
}
|
|
761
760
|
return false;
|
|
762
761
|
}
|
|
762
|
+
function isIgnoredByWatcher(path3, { root, appDirectory }) {
|
|
763
|
+
let dirname = import_pathe3.default.dirname(path3);
|
|
764
|
+
let ignoredByPath = !dirname.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
|
|
765
|
+
// that are at the root level, not nested in subdirectories
|
|
766
|
+
path3 !== root && // Watch the root directory itself
|
|
767
|
+
dirname !== root;
|
|
768
|
+
if (ignoredByPath) {
|
|
769
|
+
return true;
|
|
770
|
+
}
|
|
771
|
+
try {
|
|
772
|
+
let stat = import_node_fs.default.statSync(path3, { throwIfNoEntry: false });
|
|
773
|
+
if (stat && !stat.isFile() && !stat.isDirectory()) {
|
|
774
|
+
return true;
|
|
775
|
+
}
|
|
776
|
+
} catch {
|
|
777
|
+
return true;
|
|
778
|
+
}
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
763
781
|
|
|
764
782
|
// vite/cloudflare-dev-proxy.ts
|
|
765
783
|
var serverBuildId = "virtual:react-router/server-build";
|
package/dist/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v7.13.
|
|
2
|
+
* @react-router/dev v7.13.2-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -560,6 +560,7 @@ async function resolveConfig({
|
|
|
560
560
|
}
|
|
561
561
|
let future = {
|
|
562
562
|
unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
|
|
563
|
+
unstable_passThroughRequests: userAndPresetConfigs.future?.unstable_passThroughRequests ?? false,
|
|
563
564
|
unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
|
|
564
565
|
unstable_trailingSlashAwareDataRequests: userAndPresetConfigs.future?.unstable_trailingSlashAwareDataRequests ?? false,
|
|
565
566
|
unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
|
|
@@ -641,13 +642,11 @@ async function createConfigLoader({
|
|
|
641
642
|
if (!fsWatcher) {
|
|
642
643
|
fsWatcher = import_chokidar.default.watch([root, appDirectory], {
|
|
643
644
|
ignoreInitial: true,
|
|
644
|
-
ignored: (path10) => {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
dirname4 !== root;
|
|
650
|
-
}
|
|
645
|
+
ignored: (path10) => isIgnoredByWatcher(path10, { root, appDirectory })
|
|
646
|
+
});
|
|
647
|
+
fsWatcher.on("error", (error) => {
|
|
648
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
649
|
+
console.warn(import_picocolors.default.yellow(`File watcher error: ${message}`));
|
|
651
650
|
});
|
|
652
651
|
fsWatcher.on("all", async (...args) => {
|
|
653
652
|
let [event, rawFilepath] = args;
|
|
@@ -856,6 +855,25 @@ function isEntryFileDependency(moduleGraph, entryFilepath, filepath, visited = /
|
|
|
856
855
|
}
|
|
857
856
|
return false;
|
|
858
857
|
}
|
|
858
|
+
function isIgnoredByWatcher(path10, { root, appDirectory }) {
|
|
859
|
+
let dirname4 = import_pathe3.default.dirname(path10);
|
|
860
|
+
let ignoredByPath = !dirname4.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
|
|
861
|
+
// that are at the root level, not nested in subdirectories
|
|
862
|
+
path10 !== root && // Watch the root directory itself
|
|
863
|
+
dirname4 !== root;
|
|
864
|
+
if (ignoredByPath) {
|
|
865
|
+
return true;
|
|
866
|
+
}
|
|
867
|
+
try {
|
|
868
|
+
let stat = import_node_fs.default.statSync(path10, { throwIfNoEntry: false });
|
|
869
|
+
if (stat && !stat.isFile() && !stat.isDirectory()) {
|
|
870
|
+
return true;
|
|
871
|
+
}
|
|
872
|
+
} catch {
|
|
873
|
+
return true;
|
|
874
|
+
}
|
|
875
|
+
return false;
|
|
876
|
+
}
|
|
859
877
|
|
|
860
878
|
// typegen/context.ts
|
|
861
879
|
async function createContext2({
|
|
@@ -4523,15 +4541,17 @@ ${new TextDecoder().decode(contents)}`
|
|
|
4523
4541
|
if (redirectStatusCodes.has(response.status)) {
|
|
4524
4542
|
let location = response.headers.get("Location");
|
|
4525
4543
|
let delay = response.status === 302 ? 2 : 0;
|
|
4544
|
+
let escapedLocation = escapeHtml(location ?? "");
|
|
4545
|
+
let escapedPathname = escapeHtml(pathname);
|
|
4526
4546
|
html = `<!doctype html>
|
|
4527
4547
|
<head>
|
|
4528
|
-
<title>Redirecting to: ${
|
|
4529
|
-
<meta http-equiv="refresh" content="${delay};url=${
|
|
4548
|
+
<title>Redirecting to: ${escapedLocation}</title>
|
|
4549
|
+
<meta http-equiv="refresh" content="${delay};url=${escapedLocation}">
|
|
4530
4550
|
<meta name="robots" content="noindex">
|
|
4531
4551
|
</head>
|
|
4532
4552
|
<body>
|
|
4533
|
-
<a href="${
|
|
4534
|
-
Redirecting from <code>${
|
|
4553
|
+
<a href="${escapedLocation}">
|
|
4554
|
+
Redirecting from <code>${escapedPathname}</code> to <code>${escapedLocation}</code>
|
|
4535
4555
|
</a>
|
|
4536
4556
|
</body>
|
|
4537
4557
|
</html>`;
|
|
@@ -4940,15 +4960,17 @@ async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reac
|
|
|
4940
4960
|
if (redirectStatusCodes.has(response.status)) {
|
|
4941
4961
|
let location = response.headers.get("Location");
|
|
4942
4962
|
let delay = response.status === 302 ? 2 : 0;
|
|
4963
|
+
let escapedLocation = escapeHtml(location ?? "");
|
|
4964
|
+
let escapedNormalizedPath = escapeHtml(normalizedPath);
|
|
4943
4965
|
html = `<!doctype html>
|
|
4944
4966
|
<head>
|
|
4945
|
-
<title>Redirecting to: ${
|
|
4946
|
-
<meta http-equiv="refresh" content="${delay};url=${
|
|
4967
|
+
<title>Redirecting to: ${escapedLocation}</title>
|
|
4968
|
+
<meta http-equiv="refresh" content="${delay};url=${escapedLocation}">
|
|
4947
4969
|
<meta name="robots" content="noindex">
|
|
4948
4970
|
</head>
|
|
4949
4971
|
<body>
|
|
4950
|
-
<a href="${
|
|
4951
|
-
Redirecting from <code>${
|
|
4972
|
+
<a href="${escapedLocation}">
|
|
4973
|
+
Redirecting from <code>${escapedNormalizedPath}</code> to <code>${escapedLocation}</code>
|
|
4952
4974
|
</a>
|
|
4953
4975
|
</body>
|
|
4954
4976
|
</html>`;
|
|
@@ -5590,6 +5612,17 @@ function createSpaModeRequest(reactRouterConfig) {
|
|
|
5590
5612
|
metadata: { type: "spa", path: "/" }
|
|
5591
5613
|
};
|
|
5592
5614
|
}
|
|
5615
|
+
var ESCAPE_REGEX = /[&><\u2028\u2029]/g;
|
|
5616
|
+
var ESCAPE_LOOKUP = {
|
|
5617
|
+
"&": "\\u0026",
|
|
5618
|
+
">": "\\u003e",
|
|
5619
|
+
"<": "\\u003c",
|
|
5620
|
+
"\u2028": "\\u2028",
|
|
5621
|
+
"\u2029": "\\u2029"
|
|
5622
|
+
};
|
|
5623
|
+
function escapeHtml(html) {
|
|
5624
|
+
return html.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
|
|
5625
|
+
}
|
|
5593
5626
|
|
|
5594
5627
|
// vite/rsc/plugin.ts
|
|
5595
5628
|
var import_es_module_lexer3 = require("es-module-lexer");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/dev",
|
|
3
|
-
"version": "7.13.
|
|
3
|
+
"version": "7.13.2-pre.0",
|
|
4
4
|
"description": "Dev tools and CLI for React Router",
|
|
5
5
|
"homepage": "https://reactrouter.com",
|
|
6
6
|
"bugs": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"tinyglobby": "^0.2.14",
|
|
93
93
|
"valibot": "^1.2.0",
|
|
94
94
|
"vite-node": "^3.2.2",
|
|
95
|
-
"@react-router/node": "7.13.
|
|
95
|
+
"@react-router/node": "7.13.2-pre.0"
|
|
96
96
|
},
|
|
97
97
|
"devDependencies": {
|
|
98
98
|
"@types/babel__core": "^7.20.5",
|
|
@@ -116,8 +116,8 @@
|
|
|
116
116
|
"vite": "^6.3.0",
|
|
117
117
|
"wireit": "0.14.9",
|
|
118
118
|
"wrangler": "^4.23.0",
|
|
119
|
-
"@react-router/serve": "7.13.
|
|
120
|
-
"react-router": "^7.13.
|
|
119
|
+
"@react-router/serve": "7.13.2-pre.0",
|
|
120
|
+
"react-router": "^7.13.2-pre.0"
|
|
121
121
|
},
|
|
122
122
|
"peerDependencies": {
|
|
123
123
|
"@vitejs/plugin-rsc": "~0.5.7",
|
|
@@ -125,8 +125,8 @@
|
|
|
125
125
|
"typescript": "^5.1.0",
|
|
126
126
|
"vite": "^5.1.0 || ^6.0.0 || ^7.0.0",
|
|
127
127
|
"wrangler": "^3.28.2 || ^4.0.0",
|
|
128
|
-
"@react-router/serve": "^7.13.
|
|
129
|
-
"react-router": "^7.13.
|
|
128
|
+
"@react-router/serve": "^7.13.2-pre.0",
|
|
129
|
+
"react-router": "^7.13.2-pre.0"
|
|
130
130
|
},
|
|
131
131
|
"peerDependenciesMeta": {
|
|
132
132
|
"@vitejs/plugin-rsc": {
|