react-router 8.3.1 → 8.5.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.
Files changed (218) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/development/dom-export.d.ts +2 -1
  3. package/dist/development/dom-export.js +1 -1
  4. package/dist/development/index-react-server-client.js +2 -2
  5. package/dist/development/index-react-server.d.ts +601 -189
  6. package/dist/development/index-react-server.js +100 -48
  7. package/dist/development/index.d.ts +10 -9
  8. package/dist/development/index.js +6 -5
  9. package/dist/development/lib/actions.js +1 -1
  10. package/dist/development/lib/components.js +66 -10
  11. package/dist/development/lib/context.d.ts +19 -6
  12. package/dist/development/lib/context.js +11 -3
  13. package/dist/development/lib/dom/dom.d.ts +3 -0
  14. package/dist/development/lib/dom/dom.js +1 -1
  15. package/dist/development/lib/dom/global.d.ts +35 -0
  16. package/dist/development/lib/dom/lib.d.ts +34 -9
  17. package/dist/development/lib/dom/lib.js +30 -37
  18. package/dist/development/lib/dom/server.d.ts +6 -1
  19. package/dist/development/lib/dom/server.js +41 -15
  20. package/dist/development/lib/dom/ssr/components.js +26 -31
  21. package/dist/development/lib/dom/ssr/data.js +1 -1
  22. package/dist/development/lib/dom/ssr/entry.d.ts +13 -2
  23. package/dist/development/lib/dom/ssr/errorBoundaries.js +1 -1
  24. package/dist/development/lib/dom/ssr/fallback.js +1 -1
  25. package/dist/development/lib/dom/ssr/fog-of-war.d.ts +3 -2
  26. package/dist/development/lib/dom/ssr/fog-of-war.js +46 -22
  27. package/dist/development/lib/dom/ssr/hydration.d.ts +3 -1
  28. package/dist/development/lib/dom/ssr/hydration.js +6 -4
  29. package/dist/development/lib/dom/ssr/invariant.js +1 -1
  30. package/dist/development/lib/dom/ssr/links.js +1 -1
  31. package/dist/development/lib/dom/ssr/markup.js +5 -2
  32. package/dist/development/lib/dom/ssr/route-discovery.d.ts +120 -0
  33. package/dist/development/lib/dom/ssr/route-discovery.js +415 -0
  34. package/dist/development/lib/dom/ssr/routeModules.js +1 -1
  35. package/dist/development/lib/dom/ssr/routes-test-stub.js +2 -2
  36. package/dist/development/lib/dom/ssr/routes.d.ts +2 -2
  37. package/dist/development/lib/dom/ssr/routes.js +8 -8
  38. package/dist/development/lib/dom/ssr/server.js +4 -2
  39. package/dist/development/lib/dom/ssr/single-fetch.d.ts +28 -2
  40. package/dist/development/lib/dom/ssr/single-fetch.js +80 -71
  41. package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
  42. package/dist/development/lib/dom-export/hydrated-router.d.ts +28 -0
  43. package/dist/development/lib/dom-export/hydrated-router.js +33 -12
  44. package/dist/development/lib/errors.js +1 -1
  45. package/dist/development/lib/hooks.d.ts +3 -3
  46. package/dist/development/lib/hooks.js +52 -47
  47. package/dist/development/lib/href.js +1 -1
  48. package/dist/development/lib/router/history.js +1 -1
  49. package/dist/development/lib/router/instrumentation.js +1 -1
  50. package/dist/development/lib/router/matcher-route-pattern.d.ts +2 -0
  51. package/dist/development/lib/router/matcher-route-pattern.js +216 -0
  52. package/dist/development/lib/router/matcher-route-pattern.preload.d.ts +20 -0
  53. package/dist/development/lib/router/matcher-route-pattern.preload.js +36 -0
  54. package/dist/development/lib/router/matcher.d.ts +2 -0
  55. package/dist/development/lib/router/matcher.js +29 -0
  56. package/dist/development/lib/router/navigation.js +1 -1
  57. package/dist/development/lib/router/router.d.ts +19 -7
  58. package/dist/development/lib/router/router.js +235 -128
  59. package/dist/development/lib/router/url.js +1 -1
  60. package/dist/development/lib/router/utils.d.ts +30 -5
  61. package/dist/development/lib/router/utils.js +8 -5
  62. package/dist/development/lib/rsc/browser.js +3 -2
  63. package/dist/development/lib/rsc/errorBoundaries.js +1 -1
  64. package/dist/development/lib/rsc/html-stream/browser.js +1 -1
  65. package/dist/development/lib/rsc/html-stream/server.js +25 -15
  66. package/dist/development/lib/rsc/route-modules.js +1 -1
  67. package/dist/development/lib/rsc/server.rsc.d.ts +10 -2
  68. package/dist/development/lib/rsc/server.ssr.js +25 -21
  69. package/dist/development/lib/server-runtime/build.d.ts +14 -0
  70. package/dist/development/lib/server-runtime/cookies.js +1 -1
  71. package/dist/development/lib/server-runtime/crypto.js +1 -1
  72. package/dist/development/lib/server-runtime/data.js +1 -1
  73. package/dist/development/lib/server-runtime/dev.js +1 -1
  74. package/dist/development/lib/server-runtime/entry.js +1 -1
  75. package/dist/development/lib/server-runtime/errors.js +1 -1
  76. package/dist/development/lib/server-runtime/headers.js +1 -1
  77. package/dist/development/lib/server-runtime/invariant.js +1 -1
  78. package/dist/development/lib/server-runtime/mode.js +1 -1
  79. package/dist/development/lib/server-runtime/routeMatching.js +3 -4
  80. package/dist/development/lib/server-runtime/routes.d.ts +1 -1
  81. package/dist/development/lib/server-runtime/routes.js +1 -1
  82. package/dist/development/lib/server-runtime/server.js +18 -9
  83. package/dist/development/lib/server-runtime/serverHandoff.d.ts +17 -0
  84. package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
  85. package/dist/development/lib/server-runtime/sessions/cookieStorage.js +1 -1
  86. package/dist/development/lib/server-runtime/sessions/memoryStorage.js +1 -1
  87. package/dist/development/lib/server-runtime/sessions.js +1 -1
  88. package/dist/development/lib/server-runtime/single-fetch.js +1 -1
  89. package/dist/development/lib/server-runtime/urls.js +1 -1
  90. package/dist/development/lib/server-runtime/warnings.js +1 -1
  91. package/dist/development/lib/types/internal.js +1 -1
  92. package/dist/development/lib/types/route-data.d.ts +2 -2
  93. package/dist/development/lib/types/route-module-annotations.d.ts +1 -1
  94. package/dist/development/route-pattern.d.ts +3 -0
  95. package/dist/development/route-pattern.js +12 -0
  96. package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
  97. package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +1 -1
  98. package/dist/development/vendor/turbo-stream-v2/unflatten.js +1 -1
  99. package/dist/development/vendor/turbo-stream-v2/utils.js +1 -1
  100. package/dist/production/dom-export.d.ts +2 -1
  101. package/dist/production/dom-export.js +1 -1
  102. package/dist/production/index-react-server-client.js +2 -2
  103. package/dist/production/index-react-server.d.ts +601 -189
  104. package/dist/production/index-react-server.js +100 -48
  105. package/dist/production/index.d.ts +10 -9
  106. package/dist/production/index.js +6 -5
  107. package/dist/production/lib/actions.js +1 -1
  108. package/dist/production/lib/components.js +66 -10
  109. package/dist/production/lib/context.d.ts +19 -6
  110. package/dist/production/lib/context.js +11 -3
  111. package/dist/production/lib/dom/dom.d.ts +3 -0
  112. package/dist/production/lib/dom/dom.js +1 -1
  113. package/dist/production/lib/dom/global.d.ts +35 -0
  114. package/dist/production/lib/dom/lib.d.ts +34 -9
  115. package/dist/production/lib/dom/lib.js +30 -37
  116. package/dist/production/lib/dom/server.d.ts +6 -1
  117. package/dist/production/lib/dom/server.js +41 -15
  118. package/dist/production/lib/dom/ssr/components.js +26 -31
  119. package/dist/production/lib/dom/ssr/data.js +1 -1
  120. package/dist/production/lib/dom/ssr/entry.d.ts +13 -2
  121. package/dist/production/lib/dom/ssr/errorBoundaries.js +1 -1
  122. package/dist/production/lib/dom/ssr/fallback.js +1 -1
  123. package/dist/production/lib/dom/ssr/fog-of-war.d.ts +3 -2
  124. package/dist/production/lib/dom/ssr/fog-of-war.js +46 -22
  125. package/dist/production/lib/dom/ssr/hydration.d.ts +3 -1
  126. package/dist/production/lib/dom/ssr/hydration.js +6 -4
  127. package/dist/production/lib/dom/ssr/invariant.js +1 -1
  128. package/dist/production/lib/dom/ssr/links.js +1 -1
  129. package/dist/production/lib/dom/ssr/markup.js +5 -2
  130. package/dist/production/lib/dom/ssr/route-discovery.d.ts +120 -0
  131. package/dist/production/lib/dom/ssr/route-discovery.js +415 -0
  132. package/dist/production/lib/dom/ssr/routeModules.js +1 -1
  133. package/dist/production/lib/dom/ssr/routes-test-stub.js +2 -2
  134. package/dist/production/lib/dom/ssr/routes.d.ts +2 -2
  135. package/dist/production/lib/dom/ssr/routes.js +8 -8
  136. package/dist/production/lib/dom/ssr/server.js +4 -2
  137. package/dist/production/lib/dom/ssr/single-fetch.d.ts +28 -2
  138. package/dist/production/lib/dom/ssr/single-fetch.js +80 -71
  139. package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
  140. package/dist/production/lib/dom-export/hydrated-router.d.ts +28 -0
  141. package/dist/production/lib/dom-export/hydrated-router.js +33 -12
  142. package/dist/production/lib/errors.js +1 -1
  143. package/dist/production/lib/hooks.d.ts +3 -3
  144. package/dist/production/lib/hooks.js +51 -46
  145. package/dist/production/lib/href.js +1 -1
  146. package/dist/production/lib/router/history.js +1 -1
  147. package/dist/production/lib/router/instrumentation.js +1 -1
  148. package/dist/production/lib/router/matcher-route-pattern.d.ts +2 -0
  149. package/dist/production/lib/router/matcher-route-pattern.js +216 -0
  150. package/dist/production/lib/router/matcher-route-pattern.preload.d.ts +20 -0
  151. package/dist/production/lib/router/matcher-route-pattern.preload.js +36 -0
  152. package/dist/production/lib/router/matcher.d.ts +2 -0
  153. package/dist/production/lib/router/matcher.js +29 -0
  154. package/dist/production/lib/router/navigation.js +1 -1
  155. package/dist/production/lib/router/router.d.ts +19 -7
  156. package/dist/production/lib/router/router.js +235 -128
  157. package/dist/production/lib/router/url.js +1 -1
  158. package/dist/production/lib/router/utils.d.ts +30 -5
  159. package/dist/production/lib/router/utils.js +8 -5
  160. package/dist/production/lib/rsc/browser.js +3 -2
  161. package/dist/production/lib/rsc/errorBoundaries.js +1 -1
  162. package/dist/production/lib/rsc/html-stream/browser.js +1 -1
  163. package/dist/production/lib/rsc/html-stream/server.js +25 -15
  164. package/dist/production/lib/rsc/route-modules.js +1 -1
  165. package/dist/production/lib/rsc/server.rsc.d.ts +10 -2
  166. package/dist/production/lib/rsc/server.ssr.js +25 -21
  167. package/dist/production/lib/server-runtime/build.d.ts +14 -0
  168. package/dist/production/lib/server-runtime/cookies.js +1 -1
  169. package/dist/production/lib/server-runtime/crypto.js +1 -1
  170. package/dist/production/lib/server-runtime/data.js +1 -1
  171. package/dist/production/lib/server-runtime/dev.js +1 -1
  172. package/dist/production/lib/server-runtime/entry.js +1 -1
  173. package/dist/production/lib/server-runtime/errors.js +1 -1
  174. package/dist/production/lib/server-runtime/headers.js +1 -1
  175. package/dist/production/lib/server-runtime/invariant.js +1 -1
  176. package/dist/production/lib/server-runtime/mode.js +1 -1
  177. package/dist/production/lib/server-runtime/routeMatching.js +3 -4
  178. package/dist/production/lib/server-runtime/routes.d.ts +1 -1
  179. package/dist/production/lib/server-runtime/routes.js +1 -1
  180. package/dist/production/lib/server-runtime/server.js +18 -9
  181. package/dist/production/lib/server-runtime/serverHandoff.d.ts +17 -0
  182. package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
  183. package/dist/production/lib/server-runtime/sessions/cookieStorage.js +1 -1
  184. package/dist/production/lib/server-runtime/sessions/memoryStorage.js +1 -1
  185. package/dist/production/lib/server-runtime/sessions.js +1 -1
  186. package/dist/production/lib/server-runtime/single-fetch.js +1 -1
  187. package/dist/production/lib/server-runtime/urls.js +1 -1
  188. package/dist/production/lib/server-runtime/warnings.js +1 -1
  189. package/dist/production/lib/types/internal.js +1 -1
  190. package/dist/production/lib/types/route-data.d.ts +2 -2
  191. package/dist/production/lib/types/route-module-annotations.d.ts +1 -1
  192. package/dist/production/route-pattern.d.ts +3 -0
  193. package/dist/production/route-pattern.js +12 -0
  194. package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
  195. package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +1 -1
  196. package/dist/production/vendor/turbo-stream-v2/unflatten.js +1 -1
  197. package/dist/production/vendor/turbo-stream-v2/utils.js +1 -1
  198. package/docs/explanation/lazy-route-discovery.md +4 -0
  199. package/docs/explanation/sessions-and-cookies.md +108 -4
  200. package/docs/how-to/custom-fetch.md +218 -0
  201. package/docs/how-to/data-strategy.md +23 -1
  202. package/docs/how-to/fetchers.md +6 -1
  203. package/docs/how-to/middleware.md +4 -1
  204. package/docs/how-to/optimize-revalidation.md +178 -5
  205. package/docs/how-to/pre-rendering.md +23 -1
  206. package/docs/how-to/react-server-components.md +26 -3
  207. package/docs/how-to/resource-routes.md +3 -0
  208. package/docs/how-to/route-discovery.md +145 -0
  209. package/docs/how-to/spa.md +2 -0
  210. package/docs/how-to/view-transitions.md +80 -13
  211. package/docs/start/data/actions.md +2 -1
  212. package/docs/start/data/route-object.md +21 -6
  213. package/docs/start/framework/actions.md +4 -2
  214. package/docs/start/framework/navigating.md +5 -9
  215. package/docs/start/framework/rendering.md +37 -0
  216. package/docs/start/framework/route-module.md +32 -5
  217. package/docs/upgrading/future.md +68 -0
  218. package/package.json +19 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -9,12 +9,12 @@
9
9
  * @license MIT
10
10
  */
11
11
  import { ABSOLUTE_URL_REGEX } from "../router/url.js";
12
- import { createPath, invariant, parsePath } from "../router/history.js";
12
+ import { createPath, invariant, parsePath, warning } from "../router/history.js";
13
13
  import { convertRoutesToDataRoutes, isRouteErrorResponse } from "../router/utils.js";
14
14
  import { IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION } from "../router/router.js";
15
- import { DataRouterContext, DataRouterStateContext, FetchersContext, ViewTransitionContext } from "../context.js";
16
- import { DataRoutes, Router } from "../components.js";
15
+ import { DataRouterContext, DataRouterDataContext, DataRouterNavigationContext, DataRouterStateContext, FetchersContext, ViewTransitionContext } from "../context.js";
17
16
  import { escapeHtml } from "./ssr/markup.js";
17
+ import { DataRoutes, Router } from "../components.js";
18
18
  import * as React$1 from "react";
19
19
  //#region lib/dom/server.tsx
20
20
  /**
@@ -91,7 +91,6 @@ function StaticRouterProvider({ context, router, hydrate = true, nonce }) {
91
91
  staticContext: context,
92
92
  basename: context.basename || "/"
93
93
  };
94
- let fetchersContext = /* @__PURE__ */ new Map();
95
94
  let hydrateScript = "";
96
95
  if (hydrate !== false) {
97
96
  let data = {
@@ -102,7 +101,30 @@ function StaticRouterProvider({ context, router, hydrate = true, nonce }) {
102
101
  hydrateScript = `window.__staticRouterHydrationData = JSON.parse(${escapeHtml(JSON.stringify(JSON.stringify(data)))});`;
103
102
  }
104
103
  let { state } = dataRouterContext.router;
105
- return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React$1.createElement(DataRouterStateContext.Provider, { value: state }, /* @__PURE__ */ React$1.createElement(FetchersContext.Provider, { value: fetchersContext }, /* @__PURE__ */ React$1.createElement(ViewTransitionContext.Provider, { value: { isTransitioning: false } }, /* @__PURE__ */ React$1.createElement(Router, {
104
+ let dataRouterState = {
105
+ historyAction: state.historyAction,
106
+ location: state.location,
107
+ matches: state.matches,
108
+ initialized: state.initialized,
109
+ renderFallback: state.renderFallback,
110
+ restoreScrollPosition: state.restoreScrollPosition,
111
+ preventScrollReset: state.preventScrollReset,
112
+ blockers: state.blockers
113
+ };
114
+ let dataRouterNavigation = {
115
+ navigation: state.navigation,
116
+ revalidation: state.revalidation
117
+ };
118
+ let dataRouterData = {
119
+ loaderData: state.loaderData,
120
+ actionData: state.actionData,
121
+ errors: state.errors
122
+ };
123
+ let fetchersContext = {
124
+ fetchers: state.fetchers,
125
+ fetcherData: /* @__PURE__ */ new Map()
126
+ };
127
+ return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React$1.createElement(DataRouterStateContext.Provider, { value: dataRouterState }, /* @__PURE__ */ React$1.createElement(DataRouterNavigationContext.Provider, { value: dataRouterNavigation }, /* @__PURE__ */ React$1.createElement(DataRouterDataContext.Provider, { value: dataRouterData }, /* @__PURE__ */ React$1.createElement(FetchersContext.Provider, { value: fetchersContext }, /* @__PURE__ */ React$1.createElement(ViewTransitionContext.Provider, { value: { isTransitioning: false } }, /* @__PURE__ */ React$1.createElement(Router, {
106
128
  basename: dataRouterContext.basename,
107
129
  location: state.location,
108
130
  navigationType: state.historyAction,
@@ -112,10 +134,9 @@ function StaticRouterProvider({ context, router, hydrate = true, nonce }) {
112
134
  }, /* @__PURE__ */ React$1.createElement(DataRoutes, {
113
135
  manifest: router.manifest,
114
136
  routes: router.routes,
115
- future: router.future,
116
137
  state,
117
138
  isStatic: true
118
- })))))), hydrateScript ? /* @__PURE__ */ React$1.createElement("script", {
139
+ })))))))), hydrateScript ? /* @__PURE__ */ React$1.createElement("script", {
119
140
  suppressHydrationWarning: true,
120
141
  nonce,
121
142
  dangerouslySetInnerHTML: { __html: hydrateScript }
@@ -185,26 +206,31 @@ function getStatelessNavigator() {
185
206
  * `query`
186
207
  * @param opts Options
187
208
  * @param opts.future Future flags for the static {@link DataRouter}
188
- * @param opts.branches Optional pre-computed route branches
209
+ * @param opts.branches Deprecated optional pre-computed route branches. This option
210
+ * is no longer used because branch caching is done automatically inside the static router.
189
211
  * @returns A static {@link DataRouter} that can be used to render the provided routes
190
212
  */
191
213
  function createStaticRouter(routes, context, opts = {}) {
214
+ warning(opts.branches == null, "`createStaticRouter({ branches })` is deprecated and no longer used. Branch caching is done automatically inside the static router.");
192
215
  let manifest = {};
193
216
  let dataRoutes = convertRoutesToDataRoutes(routes, void 0, void 0, manifest);
194
- let matches = context.matches.map((match) => {
217
+ let future = { ...opts?.future };
218
+ let matchRoutes = context._match;
219
+ let mapRouteMatch = (match) => {
195
220
  let route = manifest[match.route.id] || match.route;
196
221
  return {
197
222
  ...match,
198
223
  route
199
224
  };
200
- });
225
+ };
226
+ let matches = context.matches.map(mapRouteMatch);
201
227
  let msg = (method) => `You cannot use router.${method}() on the server because it is a stateless environment`;
202
228
  return {
203
229
  get basename() {
204
230
  return context.basename;
205
231
  },
206
232
  get future() {
207
- return { ...opts?.future };
233
+ return future;
208
234
  },
209
235
  get state() {
210
236
  return {
@@ -227,13 +253,13 @@ function createStaticRouter(routes, context, opts = {}) {
227
253
  get routes() {
228
254
  return dataRoutes;
229
255
  },
230
- get branches() {
231
- return opts.branches;
232
- },
233
256
  get manifest() {
234
257
  return manifest;
235
258
  },
236
259
  get window() {},
260
+ match(locationArg) {
261
+ return matchRoutes(locationArg)?.map(mapRouteMatch) ?? null;
262
+ },
237
263
  initialize() {
238
264
  throw msg("initialize");
239
265
  },
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,27 +8,16 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { matchRoutes } from "../../router/utils.js";
12
- import { DataRouterContext, DataRouterStateContext, useIsRSCRouterContext } from "../../context.js";
13
- import { useLocation } from "../../hooks.js";
14
- import { warnOnce } from "../../server-runtime/warnings.js";
11
+ import { useIsRSCRouterContext } from "../../context.js";
12
+ import { useDataRouterContext, useDataRouterData, useDataRouterState, useLocation } from "../../hooks.js";
15
13
  import invariant from "./invariant.js";
16
14
  import { getKeyedLinksForMatches, getKeyedPrefetchLinks, getModuleLinkHrefs, getNewMatchesForLinks, isPageLinkDescriptor } from "./links.js";
17
15
  import { escapeHtml } from "./markup.js";
18
16
  import { singleFetchUrl } from "./single-fetch.js";
17
+ import { warnOnce } from "../../server-runtime/warnings.js";
19
18
  import { getPartialManifest, isFogOfWarEnabled } from "./fog-of-war.js";
20
19
  import * as React$1 from "react";
21
20
  //#region lib/dom/ssr/components.tsx
22
- function useDataRouterContext() {
23
- let context = React$1.useContext(DataRouterContext);
24
- invariant(context, "You must render this element inside a <DataRouterContext.Provider> element");
25
- return context;
26
- }
27
- function useDataRouterStateContext() {
28
- let context = React$1.useContext(DataRouterStateContext);
29
- invariant(context, "You must render this element inside a <DataRouterStateContext.Provider> element");
30
- return context;
31
- }
32
21
  const FrameworkContext = React$1.createContext(void 0);
33
22
  FrameworkContext.displayName = "FrameworkContext";
34
23
  function useFrameworkContext() {
@@ -142,7 +131,8 @@ const CRITICAL_CSS_DATA_ATTRIBUTE = "data-react-router-critical-css";
142
131
  */
143
132
  function Links({ nonce, crossOrigin }) {
144
133
  let { isSpaMode, manifest, routeModules, criticalCss, nonce: contextNonce } = useFrameworkContext();
145
- let { errors, matches: routerMatches } = useDataRouterStateContext();
134
+ let { matches: routerMatches } = useDataRouterState("Links");
135
+ let { errors } = useDataRouterData("Links");
146
136
  let matches = getActiveMatches(routerMatches, errors, isSpaMode);
147
137
  let keyedLinks = React$1.useMemo(() => getKeyedLinksForMatches(matches, routeModules, manifest), [
148
138
  matches,
@@ -202,11 +192,11 @@ function Links({ nonce, crossOrigin }) {
202
192
  function PrefetchPageLinks({ page, ...linkProps }) {
203
193
  let rsc = useIsRSCRouterContext();
204
194
  let { nonce: contextNonce } = useFrameworkContext();
205
- let { router } = useDataRouterContext();
206
- let matches = React$1.useMemo(() => matchRoutes(router.routes, page, router.basename), [
195
+ let { router } = useDataRouterContext("PrefetchPageLinks");
196
+ let matches = React$1.useMemo(() => router.match(page), [
197
+ router,
207
198
  router.routes,
208
- page,
209
- router.basename
199
+ page
210
200
  ]);
211
201
  if (!matches) return null;
212
202
  if (linkProps.nonce == null && contextNonce) linkProps = {
@@ -244,19 +234,21 @@ function useKeyedPrefetchLinks(matches) {
244
234
  }
245
235
  function RSCPrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
246
236
  let location = useLocation();
237
+ let { unstable_apiServerOrigin } = useFrameworkContext();
247
238
  let dataHrefs = React$1.useMemo(() => {
248
239
  if (page === location.pathname + location.search + location.hash) return [];
249
- let url = singleFetchUrl(page, "rsc");
240
+ let url = singleFetchUrl(page, "rsc", unstable_apiServerOrigin);
250
241
  let hasSomeRoutesWithShouldRevalidate = false;
251
242
  let targetRoutes = [];
252
243
  for (let match of nextMatches) if (typeof match.route.shouldRevalidate === "function") hasSomeRoutesWithShouldRevalidate = true;
253
244
  else targetRoutes.push(match.route.id);
254
245
  if (hasSomeRoutesWithShouldRevalidate && targetRoutes.length > 0) url.searchParams.set("_routes", targetRoutes.join(","));
255
- return [url.pathname + url.search];
246
+ return [unstable_apiServerOrigin ? url.toString() : url.pathname + url.search];
256
247
  }, [
257
248
  page,
258
249
  location,
259
- nextMatches
250
+ nextMatches,
251
+ unstable_apiServerOrigin
260
252
  ]);
261
253
  return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, dataHrefs.map((href) => /* @__PURE__ */ React$1.createElement("link", {
262
254
  key: href,
@@ -268,8 +260,9 @@ function RSCPrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps })
268
260
  }
269
261
  function PrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
270
262
  let location = useLocation();
271
- let { manifest, routeModules } = useFrameworkContext();
272
- let { loaderData, matches } = useDataRouterStateContext();
263
+ let { manifest, routeModules, unstable_apiServerOrigin } = useFrameworkContext();
264
+ let { matches } = useDataRouterState("PrefetchPageLinks");
265
+ let { loaderData } = useDataRouterData("PrefetchPageLinks");
273
266
  let newMatchesForData = React$1.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "data"), [
274
267
  page,
275
268
  nextMatches,
@@ -296,9 +289,9 @@ function PrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
296
289
  else routesParams.add(m.route.id);
297
290
  });
298
291
  if (routesParams.size === 0) return [];
299
- let url = singleFetchUrl(page, "data");
292
+ let url = singleFetchUrl(page, "data", unstable_apiServerOrigin);
300
293
  if (foundOptOutRoute && routesParams.size > 0) url.searchParams.set("_routes", nextMatches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(","));
301
- return [url.pathname + url.search];
294
+ return [unstable_apiServerOrigin ? url.toString() : url.pathname + url.search];
302
295
  }, [
303
296
  loaderData,
304
297
  location,
@@ -306,7 +299,8 @@ function PrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
306
299
  newMatchesForData,
307
300
  nextMatches,
308
301
  page,
309
- routeModules
302
+ routeModules,
303
+ unstable_apiServerOrigin
310
304
  ]);
311
305
  let moduleHrefs = React$1.useMemo(() => getModuleLinkHrefs(newMatchesForAssets, manifest), [newMatchesForAssets, manifest]);
312
306
  let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
@@ -355,7 +349,8 @@ function PrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
355
349
  */
356
350
  function Meta() {
357
351
  let { isSpaMode, routeModules } = useFrameworkContext();
358
- let { errors, matches: routerMatches, loaderData } = useDataRouterStateContext();
352
+ let { matches: routerMatches } = useDataRouterState("Meta");
353
+ let { errors, loaderData } = useDataRouterData("Meta");
359
354
  let location = useLocation();
360
355
  let _matches = getActiveMatches(routerMatches, errors, isSpaMode);
361
356
  let error = null;
@@ -480,8 +475,8 @@ function setIsHydrated() {
480
475
  */
481
476
  function Scripts(scriptProps) {
482
477
  let { manifest, serverHandoffString, isSpaMode, renderMeta, routeDiscovery, ssr, nonce: contextNonce } = useFrameworkContext();
483
- let { router, static: isStatic, staticContext } = useDataRouterContext();
484
- let { matches: routerMatches } = useDataRouterStateContext();
478
+ let { router, static: isStatic, staticContext } = useDataRouterContext("Scripts");
479
+ let { matches: routerMatches } = useDataRouterState("Scripts");
485
480
  let isRSCRouterContext = useIsRSCRouterContext();
486
481
  let enableFogOfWar = isFogOfWarEnabled(routeDiscovery, ssr);
487
482
  if (scriptProps.nonce == null && contextNonce) scriptProps = {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,8 +1,9 @@
1
1
 
2
2
  import { DataRouteObject, RouteBranch, RouteManifest } from "../../router/utils.js";
3
3
  import { StaticHandlerContext } from "../../router/router.js";
4
- import { RouteModules } from "./routeModules.js";
5
4
  import { EntryRoute } from "./routes.js";
5
+ import { RouteModules } from "./routeModules.js";
6
+ import { DiscoveryState, RouteDiscoveryRuntime } from "./route-discovery.js";
6
7
  import { ServerBuild } from "../../server-runtime/build.js";
7
8
 
8
9
  //#region lib/dom/ssr/entry.d.ts
@@ -11,6 +12,8 @@ type SerializedError = {
11
12
  stack?: string;
12
13
  };
13
14
  interface FrameworkContextObject {
15
+ routeDiscoveryRuntime?: RouteDiscoveryRuntime;
16
+ routeDiscoveryState?: DiscoveryState;
14
17
  manifest: AssetsManifest;
15
18
  routeModules: RouteModules;
16
19
  criticalCss?: CriticalCss;
@@ -18,6 +21,8 @@ interface FrameworkContextObject {
18
21
  future: FutureConfig;
19
22
  ssr: boolean;
20
23
  isSpaMode: boolean;
24
+ unstable_apiOnly?: boolean;
25
+ unstable_apiServerOrigin?: string;
21
26
  routeDiscovery: ServerBuild["routeDiscovery"];
22
27
  nonce?: string;
23
28
  serializeError?(error: Error): SerializedError;
@@ -33,11 +38,17 @@ interface FrameworkContextObject {
33
38
  };
34
39
  }
35
40
  interface EntryContext extends FrameworkContextObject {
41
+ /**
42
+ * @deprecated This property was an internal implementation detail and was
43
+ * never intended for use in `entry.server.tsx`. It is always an empty array.
44
+ */
36
45
  branches: RouteBranch<DataRouteObject>[];
37
46
  staticHandlerContext: StaticHandlerContext;
38
47
  serverHandoffStream?: ReadableStream<Uint8Array>;
39
48
  }
40
- type FutureConfig = Record<string, never>;
49
+ interface FutureConfig {
50
+ unstable_customRouteDiscovery?: boolean;
51
+ }
41
52
  type CriticalCss = string | {
42
53
  rel: "stylesheet";
43
54
  href: string;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -2,11 +2,12 @@
2
2
  import { PatchRoutesOnNavigationFunction } from "../../router/utils.js";
3
3
  import { Router } from "../../router/router.js";
4
4
  import { RouteModules } from "./routeModules.js";
5
+ import { RouterFetch } from "./single-fetch.js";
5
6
  import { AssetsManifest } from "./entry.js";
6
7
  import { ServerBuild } from "../../server-runtime/build.js";
7
8
 
8
9
  //#region lib/dom/ssr/fog-of-war.d.ts
9
- declare function getPatchRoutesOnNavigationFunction(getRouter: () => Router, manifest: AssetsManifest, routeModules: RouteModules, ssr: boolean, routeDiscovery: ServerBuild["routeDiscovery"], isSpaMode: boolean, basename: string | undefined): PatchRoutesOnNavigationFunction | undefined;
10
- declare function useFogOFWarDiscovery(router: Router, manifest: AssetsManifest, routeModules: RouteModules, ssr: boolean, routeDiscovery: ServerBuild["routeDiscovery"], isSpaMode: boolean): void;
10
+ declare function getPatchRoutesOnNavigationFunction(getRouter: () => Router, manifest: AssetsManifest, routeModules: RouteModules, ssr: boolean, routeDiscovery: ServerBuild["routeDiscovery"], isSpaMode: boolean, basename: string | undefined, fetchImplementation?: RouterFetch, serverOrigin?: string, isApiOnly?: boolean): PatchRoutesOnNavigationFunction | undefined;
11
+ declare function useFogOFWarDiscovery(router: Router, manifest: AssetsManifest, routeModules: RouteModules, ssr: boolean, routeDiscovery: ServerBuild["routeDiscovery"], isSpaMode: boolean, fetchImplementation?: RouterFetch, serverOrigin?: string, isApiOnly?: boolean): void;
11
12
  //#endregion
12
13
  export { getPatchRoutesOnNavigationFunction, useFogOFWarDiscovery };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -9,7 +9,7 @@
9
9
  * @license MIT
10
10
  */
11
11
  import { createPath } from "../../router/history.js";
12
- import { joinPaths, matchRoutesImpl } from "../../router/utils.js";
12
+ import { joinPaths } from "../../router/utils.js";
13
13
  import { createClientRoutes } from "./routes.js";
14
14
  import * as React$1 from "react";
15
15
  //#region lib/dom/ssr/fog-of-war.ts
@@ -27,7 +27,7 @@ function getPathsWithAncestors(paths) {
27
27
  return Array.from(result);
28
28
  }
29
29
  function isFogOfWarEnabled(routeDiscovery, ssr) {
30
- return routeDiscovery.mode === "lazy" && ssr === true;
30
+ return routeDiscovery.mode === "lazy" && ssr;
31
31
  }
32
32
  function getPartialManifest({ sri, ...manifest }, router) {
33
33
  let routeIds = new Set(router.state.matches.map((m) => m.route.id));
@@ -39,7 +39,7 @@ function getPartialManifest({ sri, ...manifest }, router) {
39
39
  segments.pop();
40
40
  }
41
41
  paths.forEach((path) => {
42
- let matches = matchRoutesImpl(router.routes, path, router.basename || "/", false, router.branches);
42
+ let matches = router.match(path);
43
43
  if (matches) matches.forEach((m) => routeIds.add(m.route.id));
44
44
  });
45
45
  let initialRoutes = [...routeIds].reduce((acc, id) => Object.assign(acc, { [id]: manifest.routes[id] }), {});
@@ -49,15 +49,15 @@ function getPartialManifest({ sri, ...manifest }, router) {
49
49
  sri: sri ? true : void 0
50
50
  };
51
51
  }
52
- function getPatchRoutesOnNavigationFunction(getRouter, manifest, routeModules, ssr, routeDiscovery, isSpaMode, basename) {
52
+ function getPatchRoutesOnNavigationFunction(getRouter, manifest, routeModules, ssr, routeDiscovery, isSpaMode, basename, fetchImplementation = (request) => fetch(request), serverOrigin, isApiOnly = false) {
53
53
  if (!isFogOfWarEnabled(routeDiscovery, ssr)) return;
54
54
  return async ({ path, patch, signal, fetcherKey }) => {
55
55
  if (discoveredPaths.has(path)) return;
56
56
  let { state } = getRouter();
57
- await fetchAndApplyManifestPatches([path], fetcherKey ? window.location.href : createPath(state.navigation.location || state.location), manifest, routeModules, ssr, isSpaMode, basename, routeDiscovery.manifestPath, patch, signal);
57
+ await fetchAndApplyManifestPatches([path], fetcherKey ? window.location.href : createPath(state.navigation.location || state.location), manifest, routeModules, ssr, isSpaMode, basename, routeDiscovery.manifestPath, patch, signal, fetchImplementation, serverOrigin, isApiOnly);
58
58
  };
59
59
  }
60
- function useFogOFWarDiscovery(router, manifest, routeModules, ssr, routeDiscovery, isSpaMode) {
60
+ function useFogOFWarDiscovery(router, manifest, routeModules, ssr, routeDiscovery, isSpaMode, fetchImplementation = (request) => fetch(request), serverOrigin, isApiOnly = false) {
61
61
  React$1.useEffect(() => {
62
62
  if (!isFogOfWarEnabled(routeDiscovery, ssr) || window.navigator?.connection?.saveData === true) return;
63
63
  function registerElement(el) {
@@ -77,7 +77,7 @@ function useFogOFWarDiscovery(router, manifest, routeModules, ssr, routeDiscover
77
77
  });
78
78
  if (lazyPaths.length === 0) return;
79
79
  try {
80
- await fetchAndApplyManifestPatches(lazyPaths, null, manifest, routeModules, ssr, isSpaMode, router.basename, routeDiscovery.manifestPath, router.patchRoutes);
80
+ await fetchAndApplyManifestPatches(lazyPaths, null, manifest, routeModules, ssr, isSpaMode, router.basename, routeDiscovery.manifestPath, router.patchRoutes, void 0, fetchImplementation, serverOrigin, isApiOnly);
81
81
  } catch (e) {
82
82
  console.error("Failed to fetch manifest patches", e);
83
83
  }
@@ -102,7 +102,10 @@ function useFogOFWarDiscovery(router, manifest, routeModules, ssr, routeDiscover
102
102
  manifest,
103
103
  routeModules,
104
104
  router,
105
- routeDiscovery
105
+ routeDiscovery,
106
+ fetchImplementation,
107
+ serverOrigin,
108
+ isApiOnly
106
109
  ]);
107
110
  }
108
111
  function getManifestPath(_manifestPath, basename) {
@@ -110,7 +113,10 @@ function getManifestPath(_manifestPath, basename) {
110
113
  return basename == null ? manifestPath : joinPaths([basename, manifestPath]);
111
114
  }
112
115
  const MANIFEST_VERSION_STORAGE_KEY = "react-router-manifest-version";
116
+ const MANIFEST_RELOAD_TIMEOUT = 5e3;
117
+ let pendingManifestReload;
113
118
  async function handleClientVersionMismatch(needsReload, version, errorReloadPath) {
119
+ if (pendingManifestReload) return pendingManifestReload;
114
120
  if (!needsReload) {
115
121
  try {
116
122
  sessionStorage.removeItem(MANIFEST_VERSION_STORAGE_KEY);
@@ -121,24 +127,42 @@ async function handleClientVersionMismatch(needsReload, version, errorReloadPath
121
127
  console.warn("Detected a manifest version mismatch during eager route discovery. The next navigation/fetch to an undiscovered route will result in a new document navigation to sync up with the latest manifest.");
122
128
  return true;
123
129
  }
130
+ let alreadyReloaded = false;
124
131
  try {
125
- if (sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) === version) {
126
- console.error("Unable to discover routes due to manifest version mismatch.");
127
- return true;
128
- }
129
- sessionStorage.setItem(MANIFEST_VERSION_STORAGE_KEY, version);
132
+ alreadyReloaded = sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) === version;
133
+ if (!alreadyReloaded) sessionStorage.setItem(MANIFEST_VERSION_STORAGE_KEY, version);
130
134
  } catch {}
131
- window.location.href = errorReloadPath;
132
- console.warn("Detected manifest version mismatch, reloading...");
133
- await new Promise(() => {});
134
- return true;
135
+ if (alreadyReloaded) throw new Error("Unable to discover routes due to manifest version mismatch.");
136
+ let rejectReload;
137
+ let reloadPromise = new Promise((_, reject) => {
138
+ rejectReload = reject;
139
+ });
140
+ pendingManifestReload = reloadPromise;
141
+ let failReload = () => {
142
+ clearTimeout(timeout);
143
+ window.removeEventListener("pageshow", onPageShow);
144
+ pendingManifestReload = void 0;
145
+ rejectReload(/* @__PURE__ */ new Error("Unable to discover routes due to manifest version mismatch."));
146
+ };
147
+ let timeout = setTimeout(failReload, MANIFEST_RELOAD_TIMEOUT);
148
+ let onPageShow = (event) => {
149
+ if (event.persisted) failReload();
150
+ };
151
+ window.addEventListener("pageshow", onPageShow);
152
+ try {
153
+ window.location.href = errorReloadPath;
154
+ console.warn("Detected manifest version mismatch, reloading...");
155
+ } catch {
156
+ failReload();
157
+ }
158
+ return reloadPromise;
135
159
  }
136
- async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, routeModules, ssr, isSpaMode, basename, manifestPath, patchRoutes, signal) {
160
+ async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, routeModules, ssr, isSpaMode, basename, manifestPath, patchRoutes, signal, fetchImplementation = (request) => fetch(request), serverOrigin, isApiOnly = false) {
137
161
  paths = getPathsWithAncestors(paths);
138
162
  const searchParams = new URLSearchParams();
139
163
  searchParams.set("paths", paths.sort().join(","));
140
164
  searchParams.set("version", manifest.version);
141
- let url = new URL(getManifestPath(manifestPath, basename), window.location.origin);
165
+ let url = new URL(getManifestPath(manifestPath, basename), serverOrigin ?? window.location.origin);
142
166
  url.search = searchParams.toString();
143
167
  if (url.toString().length > 7680) {
144
168
  nextPaths.clear();
@@ -146,7 +170,7 @@ async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, ro
146
170
  }
147
171
  let serverPatches;
148
172
  try {
149
- let res = await fetch(url, { signal });
173
+ let res = await fetchImplementation(new Request(url, { signal }), { type: "manifest" });
150
174
  if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
151
175
  if (await handleClientVersionMismatch(res.status === 204 && res.headers.has("X-Remix-Reload-Document"), manifest.version, errorReloadPath)) return;
152
176
  serverPatches = await res.json();
@@ -166,7 +190,7 @@ async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, ro
166
190
  Object.values(patches).forEach((patch) => {
167
191
  if (patch && (!patch.parentId || !patches[patch.parentId])) parentIds.add(patch.parentId);
168
192
  });
169
- parentIds.forEach((parentId) => patchRoutes(parentId || null, createClientRoutes(patches, routeModules, null, ssr, isSpaMode, parentId)));
193
+ parentIds.forEach((parentId) => patchRoutes(parentId || null, createClientRoutes(patches, routeModules, null, ssr, isSpaMode, parentId, void 0, void 0, isApiOnly)));
170
194
  }
171
195
  function addToFifoQueue(path, queue) {
172
196
  if (queue.size >= discoveredPathsMaxSize) {
@@ -1,7 +1,7 @@
1
1
 
2
2
  import { Path } from "../../router/history.js";
3
3
  import { DataRouteObject } from "../../router/utils.js";
4
- import { HydrationState, Router } from "../../router/router.js";
4
+ import { FutureConfig, HydrationState, Router } from "../../router/router.js";
5
5
  import { ClientLoaderFunction } from "./routeModules.js";
6
6
 
7
7
  //#region lib/dom/ssr/hydration.d.ts
@@ -11,6 +11,7 @@ declare function getHydrationData({
11
11
  getRouteInfo,
12
12
  location,
13
13
  basename,
14
+ future,
14
15
  isSpaMode
15
16
  }: {
16
17
  state: {
@@ -26,6 +27,7 @@ declare function getHydrationData({
26
27
  };
27
28
  location: Path;
28
29
  basename: string | undefined;
30
+ future: FutureConfig;
29
31
  isSpaMode: boolean;
30
32
  }): HydrationState;
31
33
  //#endregion
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,15 +8,17 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { matchRoutes } from "../../router/utils.js";
11
+ import { createDataRouteMatcher } from "../../router/router.js";
12
12
  import { shouldHydrateRouteLoader } from "./routes.js";
13
13
  //#region lib/dom/ssr/hydration.tsx
14
- function getHydrationData({ state, routes, getRouteInfo, location, basename, isSpaMode }) {
14
+ function getHydrationData({ state, routes, getRouteInfo, location, basename, future, isSpaMode }) {
15
15
  let hydrationData = {
16
16
  ...state,
17
17
  loaderData: { ...state.loaderData }
18
18
  };
19
- let initialMatches = matchRoutes(routes, location, basename);
19
+ let dataRouteMatcher = createDataRouteMatcher(future, basename || "/");
20
+ dataRouteMatcher.update(routes);
21
+ let initialMatches = dataRouteMatcher.match(location);
20
22
  if (initialMatches) for (let match of initialMatches) {
21
23
  let routeId = match.route.id;
22
24
  let routeInfo = getRouteInfo(routeId);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -20,5 +20,8 @@ const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
20
20
  function escapeHtml(html) {
21
21
  return html.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
22
22
  }
23
+ function escapeAttribute(value) {
24
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
25
+ }
23
26
  //#endregion
24
- export { escapeHtml };
27
+ export { escapeAttribute, escapeHtml };