1 | 'use strict';
|
---|
2 |
|
---|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
---|
4 |
|
---|
5 | var React = require('react');
|
---|
6 | var router = require('@remix-run/router');
|
---|
7 | var reactRouter = require('react-router');
|
---|
8 | var reactRouterDom = require('react-router-dom');
|
---|
9 |
|
---|
10 | function _interopNamespace(e) {
|
---|
11 | if (e && e.__esModule) return e;
|
---|
12 | var n = Object.create(null);
|
---|
13 | if (e) {
|
---|
14 | Object.keys(e).forEach(function (k) {
|
---|
15 | if (k !== 'default') {
|
---|
16 | var d = Object.getOwnPropertyDescriptor(e, k);
|
---|
17 | Object.defineProperty(n, k, d.get ? d : {
|
---|
18 | enumerable: true,
|
---|
19 | get: function () { return e[k]; }
|
---|
20 | });
|
---|
21 | }
|
---|
22 | });
|
---|
23 | }
|
---|
24 | n["default"] = e;
|
---|
25 | return Object.freeze(n);
|
---|
26 | }
|
---|
27 |
|
---|
28 | var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
---|
29 |
|
---|
30 | /**
|
---|
31 | * A `<Router>` that may not navigate to any other location. This is useful
|
---|
32 | * on the server where there is no stateful UI.
|
---|
33 | */
|
---|
34 | function StaticRouter({
|
---|
35 | basename,
|
---|
36 | children,
|
---|
37 | location: locationProp = "/",
|
---|
38 | future
|
---|
39 | }) {
|
---|
40 | if (typeof locationProp === "string") {
|
---|
41 | locationProp = reactRouterDom.parsePath(locationProp);
|
---|
42 | }
|
---|
43 | let action = router.Action.Pop;
|
---|
44 | let location = {
|
---|
45 | pathname: locationProp.pathname || "/",
|
---|
46 | search: locationProp.search || "",
|
---|
47 | hash: locationProp.hash || "",
|
---|
48 | state: locationProp.state != null ? locationProp.state : null,
|
---|
49 | key: locationProp.key || "default"
|
---|
50 | };
|
---|
51 | let staticNavigator = getStatelessNavigator();
|
---|
52 | return /*#__PURE__*/React__namespace.createElement(reactRouterDom.Router, {
|
---|
53 | basename: basename,
|
---|
54 | children: children,
|
---|
55 | location: location,
|
---|
56 | navigationType: action,
|
---|
57 | navigator: staticNavigator,
|
---|
58 | future: future,
|
---|
59 | static: true
|
---|
60 | });
|
---|
61 | }
|
---|
62 | /**
|
---|
63 | * A Data Router that may not navigate to any other location. This is useful
|
---|
64 | * on the server where there is no stateful UI.
|
---|
65 | */
|
---|
66 | function StaticRouterProvider({
|
---|
67 | context,
|
---|
68 | router: router$1,
|
---|
69 | hydrate = true,
|
---|
70 | nonce
|
---|
71 | }) {
|
---|
72 | !(router$1 && context) ? process.env.NODE_ENV !== "production" ? router.UNSAFE_invariant(false, "You must provide `router` and `context` to <StaticRouterProvider>") : router.UNSAFE_invariant(false) : void 0;
|
---|
73 | let dataRouterContext = {
|
---|
74 | router: router$1,
|
---|
75 | navigator: getStatelessNavigator(),
|
---|
76 | static: true,
|
---|
77 | staticContext: context,
|
---|
78 | basename: context.basename || "/"
|
---|
79 | };
|
---|
80 | let fetchersContext = new Map();
|
---|
81 | let hydrateScript = "";
|
---|
82 | if (hydrate !== false) {
|
---|
83 | let data = {
|
---|
84 | loaderData: context.loaderData,
|
---|
85 | actionData: context.actionData,
|
---|
86 | errors: serializeErrors(context.errors)
|
---|
87 | };
|
---|
88 | // Use JSON.parse here instead of embedding a raw JS object here to speed
|
---|
89 | // up parsing on the client. Dual-stringify is needed to ensure all quotes
|
---|
90 | // are properly escaped in the resulting string. See:
|
---|
91 | // https://v8.dev/blog/cost-of-javascript-2019#json
|
---|
92 | let json = htmlEscape(JSON.stringify(JSON.stringify(data)));
|
---|
93 | hydrateScript = `window.__staticRouterHydrationData = JSON.parse(${json});`;
|
---|
94 | }
|
---|
95 | let {
|
---|
96 | state
|
---|
97 | } = dataRouterContext.router;
|
---|
98 | return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(reactRouterDom.UNSAFE_DataRouterContext.Provider, {
|
---|
99 | value: dataRouterContext
|
---|
100 | }, /*#__PURE__*/React__namespace.createElement(reactRouterDom.UNSAFE_DataRouterStateContext.Provider, {
|
---|
101 | value: state
|
---|
102 | }, /*#__PURE__*/React__namespace.createElement(reactRouterDom.UNSAFE_FetchersContext.Provider, {
|
---|
103 | value: fetchersContext
|
---|
104 | }, /*#__PURE__*/React__namespace.createElement(reactRouterDom.UNSAFE_ViewTransitionContext.Provider, {
|
---|
105 | value: {
|
---|
106 | isTransitioning: false
|
---|
107 | }
|
---|
108 | }, /*#__PURE__*/React__namespace.createElement(reactRouterDom.Router, {
|
---|
109 | basename: dataRouterContext.basename,
|
---|
110 | location: state.location,
|
---|
111 | navigationType: state.historyAction,
|
---|
112 | navigator: dataRouterContext.navigator,
|
---|
113 | static: dataRouterContext.static,
|
---|
114 | future: {
|
---|
115 | v7_relativeSplatPath: router$1.future.v7_relativeSplatPath
|
---|
116 | }
|
---|
117 | }, /*#__PURE__*/React__namespace.createElement(DataRoutes, {
|
---|
118 | routes: router$1.routes,
|
---|
119 | future: router$1.future,
|
---|
120 | state: state
|
---|
121 | })))))), hydrateScript ? /*#__PURE__*/React__namespace.createElement("script", {
|
---|
122 | suppressHydrationWarning: true,
|
---|
123 | nonce: nonce,
|
---|
124 | dangerouslySetInnerHTML: {
|
---|
125 | __html: hydrateScript
|
---|
126 | }
|
---|
127 | }) : null);
|
---|
128 | }
|
---|
129 | function DataRoutes({
|
---|
130 | routes,
|
---|
131 | future,
|
---|
132 | state
|
---|
133 | }) {
|
---|
134 | return reactRouter.UNSAFE_useRoutesImpl(routes, undefined, state, future);
|
---|
135 | }
|
---|
136 | function serializeErrors(errors) {
|
---|
137 | if (!errors) return null;
|
---|
138 | let entries = Object.entries(errors);
|
---|
139 | let serialized = {};
|
---|
140 | for (let [key, val] of entries) {
|
---|
141 | // Hey you! If you change this, please change the corresponding logic in
|
---|
142 | // deserializeErrors in react-router-dom/index.tsx :)
|
---|
143 | if (router.isRouteErrorResponse(val)) {
|
---|
144 | serialized[key] = {
|
---|
145 | ...val,
|
---|
146 | __type: "RouteErrorResponse"
|
---|
147 | };
|
---|
148 | } else if (val instanceof Error) {
|
---|
149 | // Do not serialize stack traces from SSR for security reasons
|
---|
150 | serialized[key] = {
|
---|
151 | message: val.message,
|
---|
152 | __type: "Error",
|
---|
153 | // If this is a subclass (i.e., ReferenceError), send up the type so we
|
---|
154 | // can re-create the same type during hydration.
|
---|
155 | ...(val.name !== "Error" ? {
|
---|
156 | __subType: val.name
|
---|
157 | } : {})
|
---|
158 | };
|
---|
159 | } else {
|
---|
160 | serialized[key] = val;
|
---|
161 | }
|
---|
162 | }
|
---|
163 | return serialized;
|
---|
164 | }
|
---|
165 | function getStatelessNavigator() {
|
---|
166 | return {
|
---|
167 | createHref,
|
---|
168 | encodeLocation,
|
---|
169 | push(to) {
|
---|
170 | throw new Error(`You cannot use navigator.push() on the server because it is a stateless ` + `environment. This error was probably triggered when you did a ` + `\`navigate(${JSON.stringify(to)})\` somewhere in your app.`);
|
---|
171 | },
|
---|
172 | replace(to) {
|
---|
173 | throw new Error(`You cannot use navigator.replace() on the server because it is a stateless ` + `environment. This error was probably triggered when you did a ` + `\`navigate(${JSON.stringify(to)}, { replace: true })\` somewhere ` + `in your app.`);
|
---|
174 | },
|
---|
175 | go(delta) {
|
---|
176 | throw new Error(`You cannot use navigator.go() on the server because it is a stateless ` + `environment. This error was probably triggered when you did a ` + `\`navigate(${delta})\` somewhere in your app.`);
|
---|
177 | },
|
---|
178 | back() {
|
---|
179 | throw new Error(`You cannot use navigator.back() on the server because it is a stateless ` + `environment.`);
|
---|
180 | },
|
---|
181 | forward() {
|
---|
182 | throw new Error(`You cannot use navigator.forward() on the server because it is a stateless ` + `environment.`);
|
---|
183 | }
|
---|
184 | };
|
---|
185 | }
|
---|
186 | function createStaticHandler(routes, opts) {
|
---|
187 | return router.createStaticHandler(routes, {
|
---|
188 | ...opts,
|
---|
189 | mapRouteProperties: reactRouter.UNSAFE_mapRouteProperties
|
---|
190 | });
|
---|
191 | }
|
---|
192 | function createStaticRouter(routes, context, opts = {}) {
|
---|
193 | let manifest = {};
|
---|
194 | let dataRoutes = router.UNSAFE_convertRoutesToDataRoutes(routes, reactRouter.UNSAFE_mapRouteProperties, undefined, manifest);
|
---|
195 | // Because our context matches may be from a framework-agnostic set of
|
---|
196 | // routes passed to createStaticHandler(), we update them here with our
|
---|
197 | // newly created/enhanced data routes
|
---|
198 | let matches = context.matches.map(match => {
|
---|
199 | let route = manifest[match.route.id] || match.route;
|
---|
200 | return {
|
---|
201 | ...match,
|
---|
202 | route
|
---|
203 | };
|
---|
204 | });
|
---|
205 | let msg = method => `You cannot use router.${method}() on the server because it is a stateless environment`;
|
---|
206 | return {
|
---|
207 | get basename() {
|
---|
208 | return context.basename;
|
---|
209 | },
|
---|
210 | get future() {
|
---|
211 | return {
|
---|
212 | v7_fetcherPersist: false,
|
---|
213 | v7_normalizeFormMethod: false,
|
---|
214 | v7_partialHydration: opts.future?.v7_partialHydration === true,
|
---|
215 | v7_prependBasename: false,
|
---|
216 | v7_relativeSplatPath: opts.future?.v7_relativeSplatPath === true,
|
---|
217 | v7_skipActionErrorRevalidation: false
|
---|
218 | };
|
---|
219 | },
|
---|
220 | get state() {
|
---|
221 | return {
|
---|
222 | historyAction: router.Action.Pop,
|
---|
223 | location: context.location,
|
---|
224 | matches,
|
---|
225 | loaderData: context.loaderData,
|
---|
226 | actionData: context.actionData,
|
---|
227 | errors: context.errors,
|
---|
228 | initialized: true,
|
---|
229 | navigation: router.IDLE_NAVIGATION,
|
---|
230 | restoreScrollPosition: null,
|
---|
231 | preventScrollReset: false,
|
---|
232 | revalidation: "idle",
|
---|
233 | fetchers: new Map(),
|
---|
234 | blockers: new Map()
|
---|
235 | };
|
---|
236 | },
|
---|
237 | get routes() {
|
---|
238 | return dataRoutes;
|
---|
239 | },
|
---|
240 | get window() {
|
---|
241 | return undefined;
|
---|
242 | },
|
---|
243 | initialize() {
|
---|
244 | throw msg("initialize");
|
---|
245 | },
|
---|
246 | subscribe() {
|
---|
247 | throw msg("subscribe");
|
---|
248 | },
|
---|
249 | enableScrollRestoration() {
|
---|
250 | throw msg("enableScrollRestoration");
|
---|
251 | },
|
---|
252 | navigate() {
|
---|
253 | throw msg("navigate");
|
---|
254 | },
|
---|
255 | fetch() {
|
---|
256 | throw msg("fetch");
|
---|
257 | },
|
---|
258 | revalidate() {
|
---|
259 | throw msg("revalidate");
|
---|
260 | },
|
---|
261 | createHref,
|
---|
262 | encodeLocation,
|
---|
263 | getFetcher() {
|
---|
264 | return router.IDLE_FETCHER;
|
---|
265 | },
|
---|
266 | deleteFetcher() {
|
---|
267 | throw msg("deleteFetcher");
|
---|
268 | },
|
---|
269 | dispose() {
|
---|
270 | throw msg("dispose");
|
---|
271 | },
|
---|
272 | getBlocker() {
|
---|
273 | return router.IDLE_BLOCKER;
|
---|
274 | },
|
---|
275 | deleteBlocker() {
|
---|
276 | throw msg("deleteBlocker");
|
---|
277 | },
|
---|
278 | patchRoutes() {
|
---|
279 | throw msg("patchRoutes");
|
---|
280 | },
|
---|
281 | _internalFetchControllers: new Map(),
|
---|
282 | _internalActiveDeferreds: new Map(),
|
---|
283 | _internalSetRoutes() {
|
---|
284 | throw msg("_internalSetRoutes");
|
---|
285 | }
|
---|
286 | };
|
---|
287 | }
|
---|
288 | function createHref(to) {
|
---|
289 | return typeof to === "string" ? to : reactRouterDom.createPath(to);
|
---|
290 | }
|
---|
291 | function encodeLocation(to) {
|
---|
292 | let href = typeof to === "string" ? to : reactRouterDom.createPath(to);
|
---|
293 | // Treating this as a full URL will strip any trailing spaces so we need to
|
---|
294 | // pre-encode them since they might be part of a matching splat param from
|
---|
295 | // an ancestor route
|
---|
296 | href = href.replace(/ $/, "%20");
|
---|
297 | let encoded = ABSOLUTE_URL_REGEX.test(href) ? new URL(href) : new URL(href, "http://localhost");
|
---|
298 | return {
|
---|
299 | pathname: encoded.pathname,
|
---|
300 | search: encoded.search,
|
---|
301 | hash: encoded.hash
|
---|
302 | };
|
---|
303 | }
|
---|
304 | const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
---|
305 | // This utility is based on https://github.com/zertosh/htmlescape
|
---|
306 | // License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE
|
---|
307 | const ESCAPE_LOOKUP = {
|
---|
308 | "&": "\\u0026",
|
---|
309 | ">": "\\u003e",
|
---|
310 | "<": "\\u003c",
|
---|
311 | "\u2028": "\\u2028",
|
---|
312 | "\u2029": "\\u2029"
|
---|
313 | };
|
---|
314 | const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
|
---|
315 | function htmlEscape(str) {
|
---|
316 | return str.replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]);
|
---|
317 | }
|
---|
318 |
|
---|
319 | exports.StaticRouter = StaticRouter;
|
---|
320 | exports.StaticRouterProvider = StaticRouterProvider;
|
---|
321 | exports.createStaticHandler = createStaticHandler;
|
---|
322 | exports.createStaticRouter = createStaticRouter;
|
---|