@expo/router-server 56.0.9 → 56.0.10

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.
@@ -1 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAOjE;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAGjF;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpF;AAID;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,GAAG,GAAG;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAkBA"}
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAMD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAUjE;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAGjF;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpF;AAID;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,GAAG,GAAG;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAkBA"}
@@ -33,6 +33,9 @@ const ESCAPED_CHARACTERS = {
33
33
  function escapeUnsafeCharacters(str) {
34
34
  return str.replace(UNSAFE_CHARACTERS_REGEX, (match) => ESCAPED_CHARACTERS[match] ?? match);
35
35
  }
36
+ function escapeHtmlAttribute(value) {
37
+ return value.replace(/&/g, '&').replace(/"/g, '"');
38
+ }
36
39
  /**
37
40
  * Returns a newline-separated `<link rel="preload">` and `<link rel="stylesheet">` pair for each
38
41
  * CSS href.
@@ -42,10 +45,13 @@ function escapeUnsafeCharacters(str) {
42
45
  */
43
46
  function createInjectedCssAsString(hrefs) {
44
47
  return hrefs
45
- .flatMap((href) => [
46
- `<link rel="preload" href="${href}" as="style">`,
47
- `<link rel="stylesheet" href="${href}">`,
48
- ])
48
+ .flatMap((href) => {
49
+ const safeHref = escapeHtmlAttribute(href);
50
+ return [
51
+ `<link rel="preload" href="${safeHref}" as="style">`,
52
+ `<link rel="stylesheet" href="${safeHref}">`,
53
+ ];
54
+ })
49
55
  .join('\n');
50
56
  }
51
57
  /**
@@ -55,7 +61,7 @@ function createInjectedCssAsString(hrefs) {
55
61
  * HTML document's `<body>` element.
56
62
  */
57
63
  function createInjectedScriptsAsString(srcs) {
58
- return srcs.map((src) => `<script src="${src}" defer></script>`).join('\n');
64
+ return srcs.map((src) => `<script src="${escapeHtmlAttribute(src)}" defer></script>`).join('\n');
59
65
  }
60
66
  /**
61
67
  * Returns the string content of the hydration flag script, which sets the
@@ -1 +1 @@
1
- {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAqBH,wDAEC;AASD,8DAOC;AAQD,sEAEC;AAQD,wEAEC;AASD,wEAEC;AAQD,kEAGC;AASD,wEAEC;AAUD,sDAsBC;AA1HD,mIAAmI;AACnI,sGAAsG;AAEtG,iEAAiE;AACjE,uGAAuG;AAEvG,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AACrD,MAAM,kBAAkB,GAAgC;IACtD,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,SAAS;CACpB,CAAC;AAEF;;;GAGG;AACH,SAAgB,sBAAsB,CAAC,GAAW;IAChD,OAAO,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;AAC7F,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,yBAAyB,CAAC,KAAe;IACvD,OAAO,KAAK;SACT,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACjB,6BAA6B,IAAI,eAAe;QAChD,gCAAgC,IAAI,IAAI;KACzC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,6BAA6B,CAAC,IAAc;IAC1D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,SAAgB,8BAA8B;IAC5C,OAAO,0CAA0C,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,8BAA8B;IAC5C,OAAO,yBAAyB,8BAA8B,EAAE,WAAW,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,SAAgB,2BAA2B,CAAC,IAA6B;IACvE,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,OAAO,uDAAuD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC7F,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,8BAA8B,CAAC,IAA6B;IAC1E,OAAO,iCAAiC,2BAA2B,CAAC,IAAI,CAAC,WAAW,CAAC;AACvF,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAC;AAE3F;;;;;GAKG;AACH,SAAgB,qBAAqB,CAAC,MAAW;IAK/C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;IAED,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC;QACvC,IAAI,MAAM,EAAE,CAAC;YACX,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvD,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE;KACxD,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// See: https://github.com/urql-graphql/urql/blob/ad0276ae616b2b2f2cd01a527b4217ae35c3fa2d/packages/next-urql/src/htmlescape.ts#L10\n// License: https://github.com/urql-graphql/urql/blob/ad0276ae616b2b2f2cd01a527b4217ae35c3fa2d/LICENSE\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst UNSAFE_CHARACTERS_REGEX = /[&><\\u2028\\u2029]/g;\nconst ESCAPED_CHARACTERS: { [match: string]: string } = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n};\n\n/**\n * Replaces unsafe characters in a string with their escaped equivalents. This is to safely\n * embed data in an HTML context to prevent XSS.\n */\nexport function escapeUnsafeCharacters(str: string): string {\n return str.replace(UNSAFE_CHARACTERS_REGEX, (match) => ESCAPED_CHARACTERS[match] ?? match);\n}\n\n/**\n * Returns a newline-separated `<link rel=\"preload\">` and `<link rel=\"stylesheet\">` pair for each\n * CSS href.\n *\n * Used by both `renderStaticContent()` and `serializeHtml()` to inject CSS bundles into the HTML\n * document's `<body>` element.\n */\nexport function createInjectedCssAsString(hrefs: string[]): string {\n return hrefs\n .flatMap((href) => [\n `<link rel=\"preload\" href=\"${href}\" as=\"style\">`,\n `<link rel=\"stylesheet\" href=\"${href}\">`,\n ])\n .join('\\n');\n}\n\n/**\n * Returns newline-separated `<script defer>` HTML strings for each JavaScript source URL.\n *\n * Used by both `renderStaticContent()` and `serializeHtml()` to inject JavaScript bundles into the\n * HTML document's `<body>` element.\n */\nexport function createInjectedScriptsAsString(srcs: string[]): string {\n return srcs.map((src) => `<script src=\"${src}\" defer></script>`).join('\\n');\n}\n\n/**\n * Returns the string content of the hydration flag script, which sets the\n * `__EXPO_ROUTER_HYDRATE__` global flag to `true`.\n *\n * @see {@link getHydrationFlagScriptAsString} for the full `<script>` tag wrapper.\n */\nexport function getHydrationFlagScriptContents(): string {\n return `globalThis.__EXPO_ROUTER_HYDRATE__=true;`;\n}\n\n/**\n * Returns a module script that sets the `__EXPO_ROUTER_HYDRATE__` global flag, which tells the\n * client-side Expo Router entrypoint to hydrate the server-rendered markup instead of performing\n * a full client render.\n *\n * @see packages/expo/src/launch/registerRootComponent.tsx\n */\nexport function getHydrationFlagScriptAsString(): string {\n return `<script type=\"module\">${getHydrationFlagScriptContents()}</script>`;\n}\n\n/**\n * Returns the string content of the loader data script, which sets\n * `globalThis.__EXPO_ROUTER_LOADER_DATA__` to the given data using double-serialized JSON.\n *\n * @see {@link createLoaderDataScriptAsString} for the full `<script>` tag wrapper.\n */\nexport function getLoaderDataScriptContents(data: Record<string, unknown>): string {\n const safeJson = escapeUnsafeCharacters(JSON.stringify(data));\n return `globalThis.__EXPO_ROUTER_LOADER_DATA__ = JSON.parse(${JSON.stringify(safeJson)});`;\n}\n\n/**\n * Returns a synchronous inline `<script>` that sets `globalThis.__EXPO_ROUTER_LOADER_DATA__`\n * with the given data, safely embedded as JSON.\n *\n * Uses double-serialization so the client can fast-parse via native `JSON.parse()`.\n * @see https://v8.dev/blog/cost-of-javascript-2019#json\n */\nexport function createLoaderDataScriptAsString(data: Record<string, unknown>): string {\n return `<script id=\"expo-router-data\">${getLoaderDataScriptContents(data)}</script>`;\n}\n\nconst HELMET_HEAD_KEYS = ['title', 'priority', 'meta', 'link', 'script', 'style'] as const;\n\n/**\n * Extracts head tags and document attributes from a `react-helmet-async` helmet instance.\n *\n * `<head>` keys are serialized in document order: title, priority, meta, link, script, style.\n * Returns empty strings when `helmet` is `null`/`undefined`.\n */\nexport function serializeHelmetToHtml(helmet: any): {\n headTags: string;\n htmlAttributes: string;\n bodyAttributes: string;\n} {\n if (!helmet) {\n return { headTags: '', htmlAttributes: '', bodyAttributes: '' };\n }\n\n const headParts: string[] = [];\n for (const key of HELMET_HEAD_KEYS) {\n const result = helmet[key]?.toString();\n if (result) {\n headParts.push(result);\n }\n }\n\n return {\n headTags: headParts.join(''),\n htmlAttributes: helmet.htmlAttributes?.toString() ?? '',\n bodyAttributes: helmet.bodyAttributes?.toString() ?? '',\n };\n}\n"]}
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// See: https://github.com/urql-graphql/urql/blob/ad0276ae616b2b2f2cd01a527b4217ae35c3fa2d/packages/next-urql/src/htmlescape.ts#L10\n// License: https://github.com/urql-graphql/urql/blob/ad0276ae616b2b2f2cd01a527b4217ae35c3fa2d/LICENSE\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst UNSAFE_CHARACTERS_REGEX = /[&><\\u2028\\u2029]/g;\nconst ESCAPED_CHARACTERS: { [match: string]: string } = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n};\n\n/**\n * Replaces unsafe characters in a string with their escaped equivalents. This is to safely\n * embed data in an HTML context to prevent XSS.\n */\nexport function escapeUnsafeCharacters(str: string): string {\n return str.replace(UNSAFE_CHARACTERS_REGEX, (match) => ESCAPED_CHARACTERS[match] ?? match);\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value.replace(/&/g, '&amp;').replace(/\"/g, '&quot;');\n}\n\n/**\n * Returns a newline-separated `<link rel=\"preload\">` and `<link rel=\"stylesheet\">` pair for each\n * CSS href.\n *\n * Used by both `renderStaticContent()` and `serializeHtml()` to inject CSS bundles into the HTML\n * document's `<body>` element.\n */\nexport function createInjectedCssAsString(hrefs: string[]): string {\n return hrefs\n .flatMap((href) => {\n const safeHref = escapeHtmlAttribute(href);\n return [\n `<link rel=\"preload\" href=\"${safeHref}\" as=\"style\">`,\n `<link rel=\"stylesheet\" href=\"${safeHref}\">`,\n ];\n })\n .join('\\n');\n}\n\n/**\n * Returns newline-separated `<script defer>` HTML strings for each JavaScript source URL.\n *\n * Used by both `renderStaticContent()` and `serializeHtml()` to inject JavaScript bundles into the\n * HTML document's `<body>` element.\n */\nexport function createInjectedScriptsAsString(srcs: string[]): string {\n return srcs.map((src) => `<script src=\"${escapeHtmlAttribute(src)}\" defer></script>`).join('\\n');\n}\n\n/**\n * Returns the string content of the hydration flag script, which sets the\n * `__EXPO_ROUTER_HYDRATE__` global flag to `true`.\n *\n * @see {@link getHydrationFlagScriptAsString} for the full `<script>` tag wrapper.\n */\nexport function getHydrationFlagScriptContents(): string {\n return `globalThis.__EXPO_ROUTER_HYDRATE__=true;`;\n}\n\n/**\n * Returns a module script that sets the `__EXPO_ROUTER_HYDRATE__` global flag, which tells the\n * client-side Expo Router entrypoint to hydrate the server-rendered markup instead of performing\n * a full client render.\n *\n * @see packages/expo/src/launch/registerRootComponent.tsx\n */\nexport function getHydrationFlagScriptAsString(): string {\n return `<script type=\"module\">${getHydrationFlagScriptContents()}</script>`;\n}\n\n/**\n * Returns the string content of the loader data script, which sets\n * `globalThis.__EXPO_ROUTER_LOADER_DATA__` to the given data using double-serialized JSON.\n *\n * @see {@link createLoaderDataScriptAsString} for the full `<script>` tag wrapper.\n */\nexport function getLoaderDataScriptContents(data: Record<string, unknown>): string {\n const safeJson = escapeUnsafeCharacters(JSON.stringify(data));\n return `globalThis.__EXPO_ROUTER_LOADER_DATA__ = JSON.parse(${JSON.stringify(safeJson)});`;\n}\n\n/**\n * Returns a synchronous inline `<script>` that sets `globalThis.__EXPO_ROUTER_LOADER_DATA__`\n * with the given data, safely embedded as JSON.\n *\n * Uses double-serialization so the client can fast-parse via native `JSON.parse()`.\n * @see https://v8.dev/blog/cost-of-javascript-2019#json\n */\nexport function createLoaderDataScriptAsString(data: Record<string, unknown>): string {\n return `<script id=\"expo-router-data\">${getLoaderDataScriptContents(data)}</script>`;\n}\n\nconst HELMET_HEAD_KEYS = ['title', 'priority', 'meta', 'link', 'script', 'style'] as const;\n\n/**\n * Extracts head tags and document attributes from a `react-helmet-async` helmet instance.\n *\n * `<head>` keys are serialized in document order: title, priority, meta, link, script, style.\n * Returns empty strings when `helmet` is `null`/`undefined`.\n */\nexport function serializeHelmetToHtml(helmet: any): {\n headTags: string;\n htmlAttributes: string;\n bodyAttributes: string;\n} {\n if (!helmet) {\n return { headTags: '', htmlAttributes: '', bodyAttributes: '' };\n }\n\n const headParts: string[] = [];\n for (const key of HELMET_HEAD_KEYS) {\n const result = helmet[key]?.toString();\n if (result) {\n headParts.push(result);\n }\n }\n\n return {\n headTags: headParts.join(''),\n htmlAttributes: helmet.htmlAttributes?.toString() ?? '',\n bodyAttributes: helmet.bodyAttributes?.toString() ?? '',\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/router-server",
3
- "version": "56.0.9",
3
+ "version": "56.0.10",
4
4
  "description": "Expo Router is a file-based router for React Native and web applications.",
5
5
  "author": "650 Industries, Inc.",
6
6
  "license": "MIT",
@@ -24,12 +24,12 @@
24
24
  "expo"
25
25
  ],
26
26
  "peerDependencies": {
27
- "@expo/metro-runtime": "^56.0.9",
27
+ "@expo/metro-runtime": "^56.0.10",
28
28
  "expo": "*",
29
- "expo-constants": "^56.0.12",
29
+ "expo-constants": "^56.0.13",
30
30
  "expo-font": "^56.0.5",
31
31
  "expo-router": "*",
32
- "expo-server": "^56.0.3",
32
+ "expo-server": "^56.0.4",
33
33
  "react": "*",
34
34
  "react-dom": "*",
35
35
  "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1"
@@ -59,8 +59,8 @@
59
59
  "react-server-dom-webpack": "~19.0.6",
60
60
  "tsd": "^0.33.0",
61
61
  "tsd-lite": "^0.9.0",
62
- "expo": "56.0.0-preview.13",
63
- "expo-router": "56.2.2"
62
+ "expo": "56.0.0",
63
+ "expo-router": "56.2.3"
64
64
  },
65
65
  "dependencies": {
66
66
  "debug": "^4.3.4"
@@ -68,7 +68,7 @@
68
68
  "publishConfig": {
69
69
  "access": "public"
70
70
  },
71
- "gitHead": "290368bc41026449a05a4ebf991b85c3a2fb0e3a",
71
+ "gitHead": "c4c9867a0bcbb188e55ecaec4998e38d33108a5d",
72
72
  "scripts": {
73
73
  "build": "expo-module build",
74
74
  "clean": "expo-module clean",