vinext 0.0.26 → 0.0.27

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 (196) hide show
  1. package/README.md +89 -85
  2. package/dist/build/static-export.d.ts.map +1 -1
  3. package/dist/build/static-export.js +3 -8
  4. package/dist/build/static-export.js.map +1 -1
  5. package/dist/check.d.ts.map +1 -1
  6. package/dist/check.js +152 -48
  7. package/dist/check.js.map +1 -1
  8. package/dist/cli.js +10 -11
  9. package/dist/cli.js.map +1 -1
  10. package/dist/cloudflare/kv-cache-handler.d.ts +32 -1
  11. package/dist/cloudflare/kv-cache-handler.d.ts.map +1 -1
  12. package/dist/cloudflare/kv-cache-handler.js +47 -21
  13. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  14. package/dist/cloudflare/tpr.d.ts.map +1 -1
  15. package/dist/cloudflare/tpr.js +15 -4
  16. package/dist/cloudflare/tpr.js.map +1 -1
  17. package/dist/config/config-matchers.d.ts +27 -0
  18. package/dist/config/config-matchers.d.ts.map +1 -1
  19. package/dist/config/config-matchers.js +306 -60
  20. package/dist/config/config-matchers.js.map +1 -1
  21. package/dist/config/dotenv.d.ts.map +1 -1
  22. package/dist/config/dotenv.js +1 -6
  23. package/dist/config/dotenv.js.map +1 -1
  24. package/dist/config/next-config.d.ts +7 -0
  25. package/dist/config/next-config.d.ts.map +1 -1
  26. package/dist/config/next-config.js +44 -19
  27. package/dist/config/next-config.js.map +1 -1
  28. package/dist/deploy.d.ts.map +1 -1
  29. package/dist/deploy.js +36 -19
  30. package/dist/deploy.js.map +1 -1
  31. package/dist/entries/app-rsc-entry.d.ts.map +1 -1
  32. package/dist/entries/app-rsc-entry.js +89 -38
  33. package/dist/entries/app-rsc-entry.js.map +1 -1
  34. package/dist/entries/pages-client-entry.d.ts.map +1 -1
  35. package/dist/entries/pages-client-entry.js +5 -3
  36. package/dist/entries/pages-client-entry.js.map +1 -1
  37. package/dist/entries/pages-server-entry.d.ts.map +1 -1
  38. package/dist/entries/pages-server-entry.js +32 -10
  39. package/dist/entries/pages-server-entry.js.map +1 -1
  40. package/dist/index.d.ts +1 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +204 -118
  43. package/dist/index.js.map +1 -1
  44. package/dist/init.d.ts.map +1 -1
  45. package/dist/init.js +6 -5
  46. package/dist/init.js.map +1 -1
  47. package/dist/routing/app-router.d.ts +2 -0
  48. package/dist/routing/app-router.d.ts.map +1 -1
  49. package/dist/routing/app-router.js +10 -18
  50. package/dist/routing/app-router.js.map +1 -1
  51. package/dist/routing/file-matcher.d.ts.map +1 -1
  52. package/dist/routing/file-matcher.js.map +1 -1
  53. package/dist/routing/pages-router.d.ts +2 -0
  54. package/dist/routing/pages-router.d.ts.map +1 -1
  55. package/dist/routing/pages-router.js +8 -5
  56. package/dist/routing/pages-router.js.map +1 -1
  57. package/dist/routing/utils.d.ts.map +1 -1
  58. package/dist/routing/utils.js.map +1 -1
  59. package/dist/server/api-handler.d.ts.map +1 -1
  60. package/dist/server/api-handler.js +7 -2
  61. package/dist/server/api-handler.js.map +1 -1
  62. package/dist/server/app-router-entry.d.ts +3 -2
  63. package/dist/server/app-router-entry.d.ts.map +1 -1
  64. package/dist/server/app-router-entry.js +8 -4
  65. package/dist/server/app-router-entry.js.map +1 -1
  66. package/dist/server/dev-module-runner.d.ts.map +1 -1
  67. package/dist/server/dev-module-runner.js +1 -1
  68. package/dist/server/dev-module-runner.js.map +1 -1
  69. package/dist/server/dev-origin-check.d.ts.map +1 -1
  70. package/dist/server/dev-origin-check.js.map +1 -1
  71. package/dist/server/dev-server.d.ts.map +1 -1
  72. package/dist/server/dev-server.js +30 -18
  73. package/dist/server/dev-server.js.map +1 -1
  74. package/dist/server/image-optimization.d.ts.map +1 -1
  75. package/dist/server/image-optimization.js.map +1 -1
  76. package/dist/server/instrumentation.js +1 -1
  77. package/dist/server/instrumentation.js.map +1 -1
  78. package/dist/server/isr-cache.d.ts +13 -1
  79. package/dist/server/isr-cache.d.ts.map +1 -1
  80. package/dist/server/isr-cache.js +10 -1
  81. package/dist/server/isr-cache.js.map +1 -1
  82. package/dist/server/metadata-routes.d.ts.map +1 -1
  83. package/dist/server/metadata-routes.js +6 -18
  84. package/dist/server/metadata-routes.js.map +1 -1
  85. package/dist/server/middleware-codegen.d.ts.map +1 -1
  86. package/dist/server/middleware-codegen.js +12 -10
  87. package/dist/server/middleware-codegen.js.map +1 -1
  88. package/dist/server/middleware-request-headers.d.ts +9 -0
  89. package/dist/server/middleware-request-headers.d.ts.map +1 -0
  90. package/dist/server/middleware-request-headers.js +77 -0
  91. package/dist/server/middleware-request-headers.js.map +1 -0
  92. package/dist/server/middleware.d.ts.map +1 -1
  93. package/dist/server/middleware.js +38 -19
  94. package/dist/server/middleware.js.map +1 -1
  95. package/dist/server/normalize-path.js.map +1 -1
  96. package/dist/server/prod-server.d.ts +1 -1
  97. package/dist/server/prod-server.d.ts.map +1 -1
  98. package/dist/server/prod-server.js +53 -38
  99. package/dist/server/prod-server.js.map +1 -1
  100. package/dist/server/request-pipeline.d.ts +2 -1
  101. package/dist/server/request-pipeline.d.ts.map +1 -1
  102. package/dist/server/request-pipeline.js +5 -7
  103. package/dist/server/request-pipeline.js.map +1 -1
  104. package/dist/shims/cache-runtime.d.ts.map +1 -1
  105. package/dist/shims/cache-runtime.js +21 -16
  106. package/dist/shims/cache-runtime.js.map +1 -1
  107. package/dist/shims/cache.d.ts.map +1 -1
  108. package/dist/shims/cache.js +18 -17
  109. package/dist/shims/cache.js.map +1 -1
  110. package/dist/shims/constants.d.ts.map +1 -1
  111. package/dist/shims/constants.js +1 -6
  112. package/dist/shims/constants.js.map +1 -1
  113. package/dist/shims/dynamic.d.ts.map +1 -1
  114. package/dist/shims/dynamic.js +1 -1
  115. package/dist/shims/dynamic.js.map +1 -1
  116. package/dist/shims/error-boundary.d.ts.map +1 -1
  117. package/dist/shims/error-boundary.js +2 -3
  118. package/dist/shims/error-boundary.js.map +1 -1
  119. package/dist/shims/error.d.ts.map +1 -1
  120. package/dist/shims/error.js +1 -3
  121. package/dist/shims/error.js.map +1 -1
  122. package/dist/shims/fetch-cache.d.ts.map +1 -1
  123. package/dist/shims/fetch-cache.js +53 -29
  124. package/dist/shims/fetch-cache.js.map +1 -1
  125. package/dist/shims/font-google-base.d.ts.map +1 -1
  126. package/dist/shims/font-google-base.js +16 -4
  127. package/dist/shims/font-google-base.js.map +1 -1
  128. package/dist/shims/font-google.d.ts +1 -1
  129. package/dist/shims/font-google.d.ts.map +1 -1
  130. package/dist/shims/font-google.generated.d.ts.map +1 -1
  131. package/dist/shims/font-google.generated.js +412 -206
  132. package/dist/shims/font-google.generated.js.map +1 -1
  133. package/dist/shims/font-google.js +1 -1
  134. package/dist/shims/font-google.js.map +1 -1
  135. package/dist/shims/font-local.d.ts.map +1 -1
  136. package/dist/shims/font-local.js +13 -3
  137. package/dist/shims/font-local.js.map +1 -1
  138. package/dist/shims/form.d.ts.map +1 -1
  139. package/dist/shims/form.js +2 -2
  140. package/dist/shims/form.js.map +1 -1
  141. package/dist/shims/head.d.ts.map +1 -1
  142. package/dist/shims/head.js +10 -8
  143. package/dist/shims/head.js.map +1 -1
  144. package/dist/shims/headers.d.ts +23 -5
  145. package/dist/shims/headers.d.ts.map +1 -1
  146. package/dist/shims/headers.js +97 -37
  147. package/dist/shims/headers.js.map +1 -1
  148. package/dist/shims/image.d.ts.map +1 -1
  149. package/dist/shims/image.js +35 -8
  150. package/dist/shims/image.js.map +1 -1
  151. package/dist/shims/legacy-image.d.ts.map +1 -1
  152. package/dist/shims/legacy-image.js +1 -1
  153. package/dist/shims/legacy-image.js.map +1 -1
  154. package/dist/shims/link.d.ts.map +1 -1
  155. package/dist/shims/link.js +29 -15
  156. package/dist/shims/link.js.map +1 -1
  157. package/dist/shims/metadata.d.ts +12 -2
  158. package/dist/shims/metadata.d.ts.map +1 -1
  159. package/dist/shims/metadata.js +10 -8
  160. package/dist/shims/metadata.js.map +1 -1
  161. package/dist/shims/navigation-state.d.ts.map +1 -1
  162. package/dist/shims/navigation-state.js +3 -2
  163. package/dist/shims/navigation-state.js.map +1 -1
  164. package/dist/shims/navigation.d.ts.map +1 -1
  165. package/dist/shims/navigation.js +26 -19
  166. package/dist/shims/navigation.js.map +1 -1
  167. package/dist/shims/request-context.d.ts +50 -0
  168. package/dist/shims/request-context.d.ts.map +1 -0
  169. package/dist/shims/request-context.js +59 -0
  170. package/dist/shims/request-context.js.map +1 -0
  171. package/dist/shims/router-state.d.ts.map +1 -1
  172. package/dist/shims/router-state.js +2 -1
  173. package/dist/shims/router-state.js.map +1 -1
  174. package/dist/shims/router.d.ts.map +1 -1
  175. package/dist/shims/router.js +18 -25
  176. package/dist/shims/router.js.map +1 -1
  177. package/dist/shims/script.d.ts.map +1 -1
  178. package/dist/shims/script.js.map +1 -1
  179. package/dist/shims/server.d.ts +13 -0
  180. package/dist/shims/server.d.ts.map +1 -1
  181. package/dist/shims/server.js +100 -34
  182. package/dist/shims/server.js.map +1 -1
  183. package/dist/shims/url-utils.d.ts.map +1 -1
  184. package/dist/shims/url-utils.js +1 -3
  185. package/dist/shims/url-utils.js.map +1 -1
  186. package/dist/utils/base-path.d.ts +17 -0
  187. package/dist/utils/base-path.d.ts.map +1 -0
  188. package/dist/utils/base-path.js +25 -0
  189. package/dist/utils/base-path.js.map +1 -0
  190. package/dist/utils/project.d.ts.map +1 -1
  191. package/dist/utils/project.js +2 -4
  192. package/dist/utils/project.js.map +1 -1
  193. package/dist/utils/query.d.ts.map +1 -1
  194. package/dist/utils/query.js +3 -1
  195. package/dist/utils/query.js.map +1 -1
  196. package/package.json +47 -33
@@ -1,3 +1,3 @@
1
- export { default, buildGoogleFontsUrl, getSSRFontLinks, getSSRFontStyles, getSSRFontPreloads } from "./font-google-base";
1
+ export { default, buildGoogleFontsUrl, getSSRFontLinks, getSSRFontStyles, getSSRFontPreloads, } from "./font-google-base";
2
2
  export * from "./font-google.generated";
3
3
  //# sourceMappingURL=font-google.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"font-google.js","sourceRoot":"","sources":["../../src/shims/font-google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACzH,cAAc,yBAAyB,CAAC","sourcesContent":["export { default, buildGoogleFontsUrl, getSSRFontLinks, getSSRFontStyles, getSSRFontPreloads } from \"./font-google-base\";\nexport * from \"./font-google.generated\";\n"]}
1
+ {"version":3,"file":"font-google.js","sourceRoot":"","sources":["../../src/shims/font-google.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,yBAAyB,CAAC","sourcesContent":["export {\n default,\n buildGoogleFontsUrl,\n getSSRFontLinks,\n getSSRFontStyles,\n getSSRFontPreloads,\n} from \"./font-google-base\";\nexport * from \"./font-google.generated\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"font-local.d.ts","sourceRoot":"","sources":["../../src/shims/font-local.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA4EH,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,gBAAgB;IACxB,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,YAAY,EAAE,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACtC,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvD;AAED,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAsDD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAE1E;AAiJD,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU,CAkCvE"}
1
+ {"version":3,"file":"font-local.d.ts","sourceRoot":"","sources":["../../src/shims/font-local.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAsFH,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,gBAAgB;IACxB,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,YAAY,EAAE,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACtC,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvD;AAED,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAqDD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAE1E;AA8ID,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU,CAkCvE"}
@@ -52,9 +52,19 @@ function sanitizeCSSVarName(name) {
52
52
  function sanitizeFallback(name) {
53
53
  // CSS generic font families — safe to use unquoted
54
54
  const generics = new Set([
55
- "serif", "sans-serif", "monospace", "cursive", "fantasy",
56
- "system-ui", "ui-serif", "ui-sans-serif", "ui-monospace", "ui-rounded",
57
- "emoji", "math", "fangsong",
55
+ "serif",
56
+ "sans-serif",
57
+ "monospace",
58
+ "cursive",
59
+ "fantasy",
60
+ "system-ui",
61
+ "ui-serif",
62
+ "ui-sans-serif",
63
+ "ui-monospace",
64
+ "ui-rounded",
65
+ "emoji",
66
+ "math",
67
+ "fangsong",
58
68
  ]);
59
69
  const trimmed = name.trim();
60
70
  if (generics.has(trimmed))
@@ -1 +1 @@
1
- {"version":3,"file":"font-local.js","sourceRoot":"","sources":["../../src/shims/font-local.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * next/font/local shim\n *\n * Provides a runtime-compatible shim for Next.js local fonts.\n * Generates @font-face CSS declarations and returns an object\n * with className, style, and variable properties.\n *\n * Supports both client-side injection and SSR collection,\n * matching the patterns used by the Google font shim.\n *\n * Usage:\n * import localFont from 'next/font/local';\n * const myFont = localFont({ src: './my-font.woff2' });\n * // myFont.className -> unique CSS class\n * // myFont.style -> { fontFamily: \"'__local_font_0', sans-serif\" }\n * // myFont.variable -> generated class name (e.g. \"__variable_local_0\")\n */\n\n/**\n * Escape a string for safe interpolation inside a CSS single-quoted string.\n *\n * Prevents CSS injection by escaping characters that could break out of\n * a `'...'` CSS string context: backslashes, single quotes, and newlines.\n */\nfunction escapeCSSString(value: string): string {\n return value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, \"\\\\a \")\n .replace(/\\r/g, \"\\\\d \");\n}\n\n/**\n * Validate a CSS custom property name (e.g. `--font-inter`).\n *\n * Custom properties must start with `--` and only contain alphanumeric\n * characters, hyphens, and underscores. Anything else could be used to\n * break out of the CSS declaration and inject arbitrary rules.\n *\n * Returns the name if valid, undefined otherwise.\n */\nfunction sanitizeCSSVarName(name: string): string | undefined {\n if (/^--[a-zA-Z0-9_-]+$/.test(name)) return name;\n return undefined;\n}\n\n/**\n * Sanitize a CSS font-family fallback name.\n *\n * Generic family names (sans-serif, serif, monospace, etc.) are used as-is.\n * Named families are wrapped in escaped quotes. This prevents injection via\n * crafted fallback values like `); } body { color: red; } .x {`.\n */\nfunction sanitizeFallback(name: string): string {\n // CSS generic font families — safe to use unquoted\n const generics = new Set([\n \"serif\", \"sans-serif\", \"monospace\", \"cursive\", \"fantasy\",\n \"system-ui\", \"ui-serif\", \"ui-sans-serif\", \"ui-monospace\", \"ui-rounded\",\n \"emoji\", \"math\", \"fangsong\",\n ]);\n const trimmed = name.trim();\n if (generics.has(trimmed)) return trimmed;\n // Wrap in single quotes with escaping to prevent CSS injection\n return `'${escapeCSSString(trimmed)}'`;\n}\n\n/**\n * Validate a CSS property name for use in declarations.\n *\n * Only allows standard CSS property names (lowercase letters and hyphens)\n * and custom properties (--prefixed). Rejects anything that could inject\n * CSS rules via crafted property names.\n */\nfunction sanitizeCSSProperty(prop: string): string | undefined {\n if (/^(--)?[a-zA-Z][a-zA-Z0-9-]*$/.test(prop)) return prop;\n return undefined;\n}\n\n/**\n * Sanitize a CSS property value for use in declarations.\n *\n * Rejects values containing characters that could break out of a CSS\n * declaration: `{`, `}`, `;`, and `</` (to prevent closing style tags).\n */\nfunction sanitizeCSSValue(value: string): string | undefined {\n if (/[{}]|<\\//.test(value)) return undefined;\n return value;\n}\n\nlet classCounter = 0;\nconst injectedFonts = new Set<string>();\n\ninterface LocalFontSrc {\n path: string;\n weight?: string;\n style?: string;\n}\n\ninterface LocalFontOptions {\n src: string | LocalFontSrc | LocalFontSrc[];\n display?: string;\n weight?: string;\n style?: string;\n fallback?: string[];\n preload?: boolean;\n variable?: string;\n adjustFontFallback?: boolean | string;\n declarations?: Array<{ prop: string; value: string }>;\n}\n\ninterface FontResult {\n className: string;\n style: { fontFamily: string };\n variable?: string;\n}\n\nfunction generateFontFaceCSS(\n family: string,\n options: LocalFontOptions,\n): string {\n const sources = normalizeSources(options);\n\n const display = options.display ?? \"swap\";\n const rules: string[] = [];\n\n for (const src of sources) {\n const weight = src.weight ?? options.weight ?? \"400\";\n const style = src.style ?? options.style ?? \"normal\";\n const format = src.path.endsWith(\".woff2\")\n ? \"woff2\"\n : src.path.endsWith(\".woff\")\n ? \"woff\"\n : src.path.endsWith(\".ttf\")\n ? \"truetype\"\n : src.path.endsWith(\".otf\")\n ? \"opentype\"\n : \"woff2\";\n\n rules.push(`@font-face {\n font-family: '${escapeCSSString(family)}';\n src: url('${escapeCSSString(src.path)}') format('${format}');\n font-weight: ${weight};\n font-style: ${style};\n font-display: ${display};\n}`);\n }\n\n // Add extra declarations if provided — sanitize prop/value to prevent injection\n if (options.declarations) {\n for (const decl of options.declarations) {\n const safeProp = sanitizeCSSProperty(decl.prop);\n const safeValue = sanitizeCSSValue(decl.value);\n if (safeProp && safeValue) {\n rules.push(`@font-face { font-family: '${escapeCSSString(family)}'; ${safeProp}: ${safeValue}; }`);\n }\n }\n }\n\n return rules.join(\"\\n\");\n}\n\n// SSR: collect font styles for injection in <head>\nconst ssrFontStyles: string[] = [];\n\n// SSR: collect font file URLs for <link rel=\"preload\"> injection\nconst ssrFontPreloads: Array<{ href: string; type: string }> = [];\nconst ssrFontPreloadHrefs = new Set<string>();\n\n/**\n * Get collected SSR font styles (used by the renderer).\n * Note: We don't clear the arrays because fonts are loaded at module import\n * time and need to persist across all requests in the Workers environment.\n */\nexport function getSSRFontStyles(): string[] {\n return [...ssrFontStyles];\n}\n\n/**\n * Get collected SSR font preload data (used by the renderer).\n * Returns an array of { href, type } objects for emitting\n * <link rel=\"preload\" as=\"font\" ...> tags.\n */\nexport function getSSRFontPreloads(): Array<{ href: string; type: string }> {\n return [...ssrFontPreloads];\n}\n\nfunction injectFontFaceCSS(css: string, id: string): void {\n if (injectedFonts.has(id)) return;\n injectedFonts.add(id);\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font\", id);\n document.head.appendChild(style);\n}\n\n/** Track which className CSS rules have been injected. */\nconst injectedClassRules = new Set<string>();\n\n/**\n * Inject a CSS rule that maps a className to a font-family.\n *\n * This is what makes `<div className={font.className}>` apply the font.\n *\n * In Next.js, the .className class ONLY sets font-family — it does NOT\n * set CSS variables. CSS variables are handled separately by the .variable class.\n */\nfunction injectClassNameRule(\n className: string,\n fontFamily: string,\n): void {\n if (injectedClassRules.has(className)) return;\n injectedClassRules.add(className);\n\n const css = `.${className} { font-family: ${fontFamily}; }\\n`;\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-class\", className);\n document.head.appendChild(style);\n}\n\n/** Track which variable class CSS rules have been injected. */\nconst injectedVariableRules = new Set<string>();\n\n/** Track which :root CSS variable rules have been injected. */\nconst injectedRootVariables = new Set<string>();\n\n/**\n * Inject a CSS rule that sets a CSS variable on an element.\n * This is what makes `<html className={font.variable}>` set the CSS variable\n * that can be referenced by other styles (e.g., Tailwind's font-sans).\n *\n * In Next.js, the .variable class ONLY sets the CSS variable — it does NOT\n * set font-family. This is critical because apps commonly apply multiple\n * .variable classes to <body> (e.g., geistSans.variable + geistMono.variable).\n * If we also set font-family here, the last class wins due to CSS cascade,\n * causing all text to use that font (e.g., everything becomes monospace).\n */\nfunction injectVariableClassRule(\n variableClassName: string,\n cssVarName: string,\n fontFamily: string,\n): void {\n if (injectedVariableRules.has(variableClassName)) return;\n injectedVariableRules.add(variableClassName);\n\n // Only set the CSS variable — do NOT set font-family.\n // This matches Next.js behavior where .variable classes only define CSS variables.\n let css = `.${variableClassName} { ${cssVarName}: ${fontFamily}; }\\n`;\n\n // Also inject at :root so CSS variable inheritance works throughout the page.\n // This ensures Tailwind utilities like `font-sans` that reference these\n // variables via var(--font-geist-sans) work correctly.\n if (!injectedRootVariables.has(cssVarName)) {\n injectedRootVariables.add(cssVarName);\n css += `:root { ${cssVarName}: ${fontFamily}; }\\n`;\n }\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-variable\", variableClassName);\n document.head.appendChild(style);\n}\n\n/**\n * Normalize the `src` option into a flat array of `{ path, weight?, style? }`.\n * Handles string, single object, and array forms.\n */\nfunction normalizeSources(options: LocalFontOptions): LocalFontSrc[] {\n if (Array.isArray(options.src)) return options.src;\n if (typeof options.src === \"string\") return [{ path: options.src }];\n return [options.src];\n}\n\n/**\n * Determine the MIME type for a font file based on its extension.\n * Uses endsWith() only — matching the approach in generateFontFaceCSS —\n * to avoid false positives from substring matches (e.g. \".woff\" matching \".woff2\").\n */\nfunction getFontMimeType(pathOrUrl: string): string {\n if (pathOrUrl.endsWith(\".woff2\")) return \"font/woff2\";\n if (pathOrUrl.endsWith(\".woff\")) return \"font/woff\";\n if (pathOrUrl.endsWith(\".ttf\")) return \"font/ttf\";\n if (pathOrUrl.endsWith(\".otf\")) return \"font/opentype\";\n return \"font/woff2\";\n}\n\n/**\n * Collect font source URLs for preload link generation.\n * Only collects on the server (SSR). Deduplicates by href using a Set for O(1) lookups.\n */\nfunction collectFontPreloads(options: LocalFontOptions): void {\n if (typeof document !== \"undefined\") return; // client-side, skip\n\n const sources = normalizeSources(options);\n\n for (const src of sources) {\n const href = src.path;\n // Only collect URLs that are absolute (start with /) — relative paths\n // would resolve incorrectly from different page URLs. The vinext:local-fonts\n // Vite transform should have already resolved them to absolute URLs.\n if (href && href.startsWith(\"/\") && !ssrFontPreloadHrefs.has(href)) {\n ssrFontPreloadHrefs.add(href);\n ssrFontPreloads.push({ href, type: getFontMimeType(href) });\n }\n }\n}\n\nexport default function localFont(options: LocalFontOptions): FontResult {\n const id = classCounter++;\n const family = `__local_font_${id}`;\n const className = `__font_local_${id}`;\n const fallback = options.fallback ?? [\"sans-serif\"];\n // Sanitize each fallback name to prevent CSS injection via crafted values\n const fontFamily = `'${family}', ${fallback.map(sanitizeFallback).join(\", \")}`;\n // Validate CSS variable name — reject anything that could inject CSS\n const cssVarName = options.variable ? sanitizeCSSVarName(options.variable) : undefined;\n // In Next.js, `variable` returns a CLASS NAME that sets the CSS variable.\n // Users apply this class to set the CSS variable on that element.\n const variableClassName = `__variable_local_${id}`;\n\n // Collect font URLs for preload <link> tags (SSR only)\n collectFontPreloads(options);\n\n // Inject @font-face declarations\n const css = generateFontFaceCSS(family, options);\n injectFontFaceCSS(css, family);\n\n // Inject the className -> font-family CSS rule\n injectClassNameRule(className, fontFamily);\n\n // Inject a CSS rule for the variable class name if variable is specified.\n // This is what makes `<html className={font.variable}>` set the CSS variable.\n if (cssVarName) {\n injectVariableClassRule(variableClassName, cssVarName, fontFamily);\n }\n\n return {\n className,\n style: { fontFamily },\n ...(cssVarName ? { variable: variableClassName } : {}),\n };\n}\n"]}
1
+ {"version":3,"file":"font-local.js","sourceRoot":"","sources":["../../src/shims/font-local.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * next/font/local shim\n *\n * Provides a runtime-compatible shim for Next.js local fonts.\n * Generates @font-face CSS declarations and returns an object\n * with className, style, and variable properties.\n *\n * Supports both client-side injection and SSR collection,\n * matching the patterns used by the Google font shim.\n *\n * Usage:\n * import localFont from 'next/font/local';\n * const myFont = localFont({ src: './my-font.woff2' });\n * // myFont.className -> unique CSS class\n * // myFont.style -> { fontFamily: \"'__local_font_0', sans-serif\" }\n * // myFont.variable -> generated class name (e.g. \"__variable_local_0\")\n */\n\n/**\n * Escape a string for safe interpolation inside a CSS single-quoted string.\n *\n * Prevents CSS injection by escaping characters that could break out of\n * a `'...'` CSS string context: backslashes, single quotes, and newlines.\n */\nfunction escapeCSSString(value: string): string {\n return value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, \"\\\\a \")\n .replace(/\\r/g, \"\\\\d \");\n}\n\n/**\n * Validate a CSS custom property name (e.g. `--font-inter`).\n *\n * Custom properties must start with `--` and only contain alphanumeric\n * characters, hyphens, and underscores. Anything else could be used to\n * break out of the CSS declaration and inject arbitrary rules.\n *\n * Returns the name if valid, undefined otherwise.\n */\nfunction sanitizeCSSVarName(name: string): string | undefined {\n if (/^--[a-zA-Z0-9_-]+$/.test(name)) return name;\n return undefined;\n}\n\n/**\n * Sanitize a CSS font-family fallback name.\n *\n * Generic family names (sans-serif, serif, monospace, etc.) are used as-is.\n * Named families are wrapped in escaped quotes. This prevents injection via\n * crafted fallback values like `); } body { color: red; } .x {`.\n */\nfunction sanitizeFallback(name: string): string {\n // CSS generic font families — safe to use unquoted\n const generics = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"emoji\",\n \"math\",\n \"fangsong\",\n ]);\n const trimmed = name.trim();\n if (generics.has(trimmed)) return trimmed;\n // Wrap in single quotes with escaping to prevent CSS injection\n return `'${escapeCSSString(trimmed)}'`;\n}\n\n/**\n * Validate a CSS property name for use in declarations.\n *\n * Only allows standard CSS property names (lowercase letters and hyphens)\n * and custom properties (--prefixed). Rejects anything that could inject\n * CSS rules via crafted property names.\n */\nfunction sanitizeCSSProperty(prop: string): string | undefined {\n if (/^(--)?[a-zA-Z][a-zA-Z0-9-]*$/.test(prop)) return prop;\n return undefined;\n}\n\n/**\n * Sanitize a CSS property value for use in declarations.\n *\n * Rejects values containing characters that could break out of a CSS\n * declaration: `{`, `}`, `;`, and `</` (to prevent closing style tags).\n */\nfunction sanitizeCSSValue(value: string): string | undefined {\n if (/[{}]|<\\//.test(value)) return undefined;\n return value;\n}\n\nlet classCounter = 0;\nconst injectedFonts = new Set<string>();\n\ninterface LocalFontSrc {\n path: string;\n weight?: string;\n style?: string;\n}\n\ninterface LocalFontOptions {\n src: string | LocalFontSrc | LocalFontSrc[];\n display?: string;\n weight?: string;\n style?: string;\n fallback?: string[];\n preload?: boolean;\n variable?: string;\n adjustFontFallback?: boolean | string;\n declarations?: Array<{ prop: string; value: string }>;\n}\n\ninterface FontResult {\n className: string;\n style: { fontFamily: string };\n variable?: string;\n}\n\nfunction generateFontFaceCSS(family: string, options: LocalFontOptions): string {\n const sources = normalizeSources(options);\n\n const display = options.display ?? \"swap\";\n const rules: string[] = [];\n\n for (const src of sources) {\n const weight = src.weight ?? options.weight ?? \"400\";\n const style = src.style ?? options.style ?? \"normal\";\n const format = src.path.endsWith(\".woff2\")\n ? \"woff2\"\n : src.path.endsWith(\".woff\")\n ? \"woff\"\n : src.path.endsWith(\".ttf\")\n ? \"truetype\"\n : src.path.endsWith(\".otf\")\n ? \"opentype\"\n : \"woff2\";\n\n rules.push(`@font-face {\n font-family: '${escapeCSSString(family)}';\n src: url('${escapeCSSString(src.path)}') format('${format}');\n font-weight: ${weight};\n font-style: ${style};\n font-display: ${display};\n}`);\n }\n\n // Add extra declarations if provided — sanitize prop/value to prevent injection\n if (options.declarations) {\n for (const decl of options.declarations) {\n const safeProp = sanitizeCSSProperty(decl.prop);\n const safeValue = sanitizeCSSValue(decl.value);\n if (safeProp && safeValue) {\n rules.push(\n `@font-face { font-family: '${escapeCSSString(family)}'; ${safeProp}: ${safeValue}; }`,\n );\n }\n }\n }\n\n return rules.join(\"\\n\");\n}\n\n// SSR: collect font styles for injection in <head>\nconst ssrFontStyles: string[] = [];\n\n// SSR: collect font file URLs for <link rel=\"preload\"> injection\nconst ssrFontPreloads: Array<{ href: string; type: string }> = [];\nconst ssrFontPreloadHrefs = new Set<string>();\n\n/**\n * Get collected SSR font styles (used by the renderer).\n * Note: We don't clear the arrays because fonts are loaded at module import\n * time and need to persist across all requests in the Workers environment.\n */\nexport function getSSRFontStyles(): string[] {\n return [...ssrFontStyles];\n}\n\n/**\n * Get collected SSR font preload data (used by the renderer).\n * Returns an array of { href, type } objects for emitting\n * <link rel=\"preload\" as=\"font\" ...> tags.\n */\nexport function getSSRFontPreloads(): Array<{ href: string; type: string }> {\n return [...ssrFontPreloads];\n}\n\nfunction injectFontFaceCSS(css: string, id: string): void {\n if (injectedFonts.has(id)) return;\n injectedFonts.add(id);\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font\", id);\n document.head.appendChild(style);\n}\n\n/** Track which className CSS rules have been injected. */\nconst injectedClassRules = new Set<string>();\n\n/**\n * Inject a CSS rule that maps a className to a font-family.\n *\n * This is what makes `<div className={font.className}>` apply the font.\n *\n * In Next.js, the .className class ONLY sets font-family — it does NOT\n * set CSS variables. CSS variables are handled separately by the .variable class.\n */\nfunction injectClassNameRule(className: string, fontFamily: string): void {\n if (injectedClassRules.has(className)) return;\n injectedClassRules.add(className);\n\n const css = `.${className} { font-family: ${fontFamily}; }\\n`;\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-class\", className);\n document.head.appendChild(style);\n}\n\n/** Track which variable class CSS rules have been injected. */\nconst injectedVariableRules = new Set<string>();\n\n/** Track which :root CSS variable rules have been injected. */\nconst injectedRootVariables = new Set<string>();\n\n/**\n * Inject a CSS rule that sets a CSS variable on an element.\n * This is what makes `<html className={font.variable}>` set the CSS variable\n * that can be referenced by other styles (e.g., Tailwind's font-sans).\n *\n * In Next.js, the .variable class ONLY sets the CSS variable — it does NOT\n * set font-family. This is critical because apps commonly apply multiple\n * .variable classes to <body> (e.g., geistSans.variable + geistMono.variable).\n * If we also set font-family here, the last class wins due to CSS cascade,\n * causing all text to use that font (e.g., everything becomes monospace).\n */\nfunction injectVariableClassRule(\n variableClassName: string,\n cssVarName: string,\n fontFamily: string,\n): void {\n if (injectedVariableRules.has(variableClassName)) return;\n injectedVariableRules.add(variableClassName);\n\n // Only set the CSS variable — do NOT set font-family.\n // This matches Next.js behavior where .variable classes only define CSS variables.\n let css = `.${variableClassName} { ${cssVarName}: ${fontFamily}; }\\n`;\n\n // Also inject at :root so CSS variable inheritance works throughout the page.\n // This ensures Tailwind utilities like `font-sans` that reference these\n // variables via var(--font-geist-sans) work correctly.\n if (!injectedRootVariables.has(cssVarName)) {\n injectedRootVariables.add(cssVarName);\n css += `:root { ${cssVarName}: ${fontFamily}; }\\n`;\n }\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-variable\", variableClassName);\n document.head.appendChild(style);\n}\n\n/**\n * Normalize the `src` option into a flat array of `{ path, weight?, style? }`.\n * Handles string, single object, and array forms.\n */\nfunction normalizeSources(options: LocalFontOptions): LocalFontSrc[] {\n if (Array.isArray(options.src)) return options.src;\n if (typeof options.src === \"string\") return [{ path: options.src }];\n return [options.src];\n}\n\n/**\n * Determine the MIME type for a font file based on its extension.\n * Uses endsWith() only — matching the approach in generateFontFaceCSS —\n * to avoid false positives from substring matches (e.g. \".woff\" matching \".woff2\").\n */\nfunction getFontMimeType(pathOrUrl: string): string {\n if (pathOrUrl.endsWith(\".woff2\")) return \"font/woff2\";\n if (pathOrUrl.endsWith(\".woff\")) return \"font/woff\";\n if (pathOrUrl.endsWith(\".ttf\")) return \"font/ttf\";\n if (pathOrUrl.endsWith(\".otf\")) return \"font/opentype\";\n return \"font/woff2\";\n}\n\n/**\n * Collect font source URLs for preload link generation.\n * Only collects on the server (SSR). Deduplicates by href using a Set for O(1) lookups.\n */\nfunction collectFontPreloads(options: LocalFontOptions): void {\n if (typeof document !== \"undefined\") return; // client-side, skip\n\n const sources = normalizeSources(options);\n\n for (const src of sources) {\n const href = src.path;\n // Only collect URLs that are absolute (start with /) — relative paths\n // would resolve incorrectly from different page URLs. The vinext:local-fonts\n // Vite transform should have already resolved them to absolute URLs.\n if (href && href.startsWith(\"/\") && !ssrFontPreloadHrefs.has(href)) {\n ssrFontPreloadHrefs.add(href);\n ssrFontPreloads.push({ href, type: getFontMimeType(href) });\n }\n }\n}\n\nexport default function localFont(options: LocalFontOptions): FontResult {\n const id = classCounter++;\n const family = `__local_font_${id}`;\n const className = `__font_local_${id}`;\n const fallback = options.fallback ?? [\"sans-serif\"];\n // Sanitize each fallback name to prevent CSS injection via crafted values\n const fontFamily = `'${family}', ${fallback.map(sanitizeFallback).join(\", \")}`;\n // Validate CSS variable name — reject anything that could inject CSS\n const cssVarName = options.variable ? sanitizeCSSVarName(options.variable) : undefined;\n // In Next.js, `variable` returns a CLASS NAME that sets the CSS variable.\n // Users apply this class to set the CSS variable on that element.\n const variableClassName = `__variable_local_${id}`;\n\n // Collect font URLs for preload <link> tags (SSR only)\n collectFontPreloads(options);\n\n // Inject @font-face declarations\n const css = generateFontFaceCSS(family, options);\n injectFontFaceCSS(css, family);\n\n // Inject the className -> font-family CSS rule\n injectClassNameRule(className, fontFamily);\n\n // Inject a CSS rule for the variable class name if variable is specified.\n // This is what makes `<html className={font.variable}>` set the CSS variable.\n if (cssVarName) {\n injectVariableClassRule(variableClassName, cssVarName, fontFamily);\n }\n\n return {\n className,\n style: { fontFamily },\n ...(cssVarName ? { variable: variableClassName } : {}),\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/shims/form.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAEL,cAAc,EACd,KAAK,kBAAkB,EAExB,MAAM,OAAO,CAAC;AAIf,OAAO,EAAE,cAAc,EAAE,CAAC;AAuB1B,UAAU,SAAU,SAAQ,kBAAkB,CAAC,eAAe,CAAC;IAC7D,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qDAAqD;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,QAAA,MAAM,IAAI,uGA2ER,CAAC;AAEH,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/shims/form.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAc,cAAc,EAAE,KAAK,kBAAkB,EAAqB,MAAM,OAAO,CAAC;AAI/F,OAAO,EAAE,cAAc,EAAE,CAAC;AAuB1B,UAAU,SAAU,SAAQ,kBAAkB,CAAC,eAAe,CAAC;IAC7D,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qDAAqD;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,QAAA,MAAM,IAAI,uGAiER,CAAC;AAEH,eAAe,IAAI,CAAC"}
@@ -17,7 +17,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
17
17
  * <button type="submit">Search</button>
18
18
  * </Form>
19
19
  */
20
- import { forwardRef, useActionState, } from "react";
20
+ import { forwardRef, useActionState } from "react";
21
21
  import { isDangerousScheme } from "./url-safety.js";
22
22
  // Re-export useActionState from React 19 to match Next.js's next/form module
23
23
  export { useActionState };
@@ -103,7 +103,7 @@ const Form = forwardRef(function Form(props, ref) {
103
103
  window.scrollTo(0, 0);
104
104
  }
105
105
  }
106
- return (_jsx("form", { ref: ref, action: action, onSubmit: handleSubmit, ...rest }));
106
+ return _jsx("form", { ref: ref, action: action, onSubmit: handleSubmit, ...rest });
107
107
  });
108
108
  export default Form;
109
109
  //# sourceMappingURL=form.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/shims/form.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * next/form shim\n *\n * Progressive enhancement form component. In Next.js, this replaces\n * the standard <form> element with one that intercepts submissions\n * and performs client-side navigation for GET forms (search forms).\n *\n * For POST forms with server actions, it delegates to React's built-in\n * form action handling.\n *\n * Usage:\n * import Form from 'next/form';\n * <Form action=\"/search\">\n * <input name=\"q\" />\n * <button type=\"submit\">Search</button>\n * </Form>\n */\n\nimport {\n forwardRef,\n useActionState,\n type FormHTMLAttributes,\n type ForwardedRef,\n} from \"react\";\nimport { isDangerousScheme } from \"./url-safety.js\";\n\n// Re-export useActionState from React 19 to match Next.js's next/form module\nexport { useActionState };\n\nfunction isSafeAction(action: string): boolean {\n // Block dangerous URI schemes\n if (isDangerousScheme(action)) return false;\n // Block protocol-relative URLs (//evil.com/...)\n if (action.startsWith(\"//\")) return false;\n // Block absolute URLs to external origins (client-side: compare origins)\n if (/^https?:\\/\\//i.test(action)) {\n if (typeof window !== \"undefined\") {\n try {\n const actionUrl = new URL(action);\n return actionUrl.origin === window.location.origin;\n } catch {\n return false;\n }\n }\n // Server-side: block all absolute URLs (can't compare origins)\n return false;\n }\n return true;\n}\n\ninterface FormProps extends FormHTMLAttributes<HTMLFormElement> {\n /** Target URL for GET forms, or server action for POST forms */\n action: string | ((formData: FormData) => void | Promise<void>);\n /** Replace instead of push in history (default: false) */\n replace?: boolean;\n /** Scroll to top after navigation (default: true) */\n scroll?: boolean;\n}\n\nconst Form = forwardRef(function Form(\n props: FormProps,\n ref: ForwardedRef<HTMLFormElement>,\n) {\n const { action, replace = false, scroll = true, onSubmit, ...rest } = props;\n\n // If action is a function (server action), pass it directly to React\n if (typeof action === \"function\") {\n return <form ref={ref} action={action as any} onSubmit={onSubmit as any} {...rest} />;\n }\n\n // Block dangerous action URLs. Render <form> without action attribute\n // so it submits to the current page (safe default).\n if (!isSafeAction(action)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(`<Form> blocked unsafe action: ${action}`);\n }\n return <form ref={ref} onSubmit={onSubmit as any} {...rest} />;\n }\n\n async function handleSubmit(e: any) {\n // Call user's onSubmit first\n if (onSubmit) {\n (onSubmit as any)(e);\n if (e.defaultPrevented) return;\n }\n\n // Only intercept GET forms for client-side navigation\n const method = (rest.method ?? \"GET\").toUpperCase();\n if (method !== \"GET\") return;\n\n e.preventDefault();\n\n const formData = new FormData(e.currentTarget);\n const params = new URLSearchParams();\n for (const [key, value] of formData) {\n if (typeof value === \"string\") {\n params.append(key, value);\n }\n }\n\n const url = `${action as string}?${params.toString()}`;\n\n // Navigate client-side\n if (typeof window.__VINEXT_RSC_NAVIGATE__ === \"function\") {\n // App Router: RSC navigation. Await so scroll happens after new content renders.\n if (replace) {\n window.history.replaceState(null, \"\", url);\n } else {\n window.history.pushState(null, \"\", url);\n }\n await window.__VINEXT_RSC_NAVIGATE__(url);\n } else {\n // Pages Router: use router or fallback\n if (replace) {\n window.history.replaceState({}, \"\", url);\n } else {\n window.history.pushState({}, \"\", url);\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n }\n\n if (scroll) {\n window.scrollTo(0, 0);\n }\n }\n\n return (\n <form\n ref={ref}\n action={action}\n onSubmit={handleSubmit}\n {...rest}\n />\n );\n});\n\nexport default Form;\n"]}
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/shims/form.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * next/form shim\n *\n * Progressive enhancement form component. In Next.js, this replaces\n * the standard <form> element with one that intercepts submissions\n * and performs client-side navigation for GET forms (search forms).\n *\n * For POST forms with server actions, it delegates to React's built-in\n * form action handling.\n *\n * Usage:\n * import Form from 'next/form';\n * <Form action=\"/search\">\n * <input name=\"q\" />\n * <button type=\"submit\">Search</button>\n * </Form>\n */\n\nimport { forwardRef, useActionState, type FormHTMLAttributes, type ForwardedRef } from \"react\";\nimport { isDangerousScheme } from \"./url-safety.js\";\n\n// Re-export useActionState from React 19 to match Next.js's next/form module\nexport { useActionState };\n\nfunction isSafeAction(action: string): boolean {\n // Block dangerous URI schemes\n if (isDangerousScheme(action)) return false;\n // Block protocol-relative URLs (//evil.com/...)\n if (action.startsWith(\"//\")) return false;\n // Block absolute URLs to external origins (client-side: compare origins)\n if (/^https?:\\/\\//i.test(action)) {\n if (typeof window !== \"undefined\") {\n try {\n const actionUrl = new URL(action);\n return actionUrl.origin === window.location.origin;\n } catch {\n return false;\n }\n }\n // Server-side: block all absolute URLs (can't compare origins)\n return false;\n }\n return true;\n}\n\ninterface FormProps extends FormHTMLAttributes<HTMLFormElement> {\n /** Target URL for GET forms, or server action for POST forms */\n action: string | ((formData: FormData) => void | Promise<void>);\n /** Replace instead of push in history (default: false) */\n replace?: boolean;\n /** Scroll to top after navigation (default: true) */\n scroll?: boolean;\n}\n\nconst Form = forwardRef(function Form(props: FormProps, ref: ForwardedRef<HTMLFormElement>) {\n const { action, replace = false, scroll = true, onSubmit, ...rest } = props;\n\n // If action is a function (server action), pass it directly to React\n if (typeof action === \"function\") {\n return <form ref={ref} action={action as any} onSubmit={onSubmit as any} {...rest} />;\n }\n\n // Block dangerous action URLs. Render <form> without action attribute\n // so it submits to the current page (safe default).\n if (!isSafeAction(action)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(`<Form> blocked unsafe action: ${action}`);\n }\n return <form ref={ref} onSubmit={onSubmit as any} {...rest} />;\n }\n\n async function handleSubmit(e: any) {\n // Call user's onSubmit first\n if (onSubmit) {\n (onSubmit as any)(e);\n if (e.defaultPrevented) return;\n }\n\n // Only intercept GET forms for client-side navigation\n const method = (rest.method ?? \"GET\").toUpperCase();\n if (method !== \"GET\") return;\n\n e.preventDefault();\n\n const formData = new FormData(e.currentTarget);\n const params = new URLSearchParams();\n for (const [key, value] of formData) {\n if (typeof value === \"string\") {\n params.append(key, value);\n }\n }\n\n const url = `${action as string}?${params.toString()}`;\n\n // Navigate client-side\n if (typeof window.__VINEXT_RSC_NAVIGATE__ === \"function\") {\n // App Router: RSC navigation. Await so scroll happens after new content renders.\n if (replace) {\n window.history.replaceState(null, \"\", url);\n } else {\n window.history.pushState(null, \"\", url);\n }\n await window.__VINEXT_RSC_NAVIGATE__(url);\n } else {\n // Pages Router: use router or fallback\n if (replace) {\n window.history.replaceState({}, \"\", url);\n } else {\n window.history.pushState({}, \"\", url);\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n }\n\n if (scroll) {\n window.scrollTo(0, 0);\n }\n }\n\n return <form ref={ref} action={action} onSubmit={handleSubmit} {...rest} />;\n});\n\nexport default Form;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../../src/shims/head.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAA8C,MAAM,OAAO,CAAC;AAEnE,UAAU,SAAS;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAWD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE;IACrD,kBAAkB,EAAE,MAAM,MAAM,EAAE,CAAC;IACnC,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,GAAG,IAAI,CAGP;AAED,wDAAwD;AACxD,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,kDAAkD;AAClD,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AA0ED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIxE;AAID,iBAAS,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,SAAS,GAAG,IAAI,CAqD3C;AAED,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../../src/shims/head.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAA8C,MAAM,OAAO,CAAC;AAEnE,UAAU,SAAS;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAaD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE;IACrD,kBAAkB,EAAE,MAAM,MAAM,EAAE,CAAC;IACnC,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,GAAG,IAAI,CAGP;AAED,wDAAwD;AACxD,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,kDAAkD;AAClD,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAwED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIxE;AAID,iBAAS,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,SAAS,GAAG,IAAI,CAmD3C;AAED,eAAe,IAAI,CAAC"}
@@ -12,7 +12,9 @@ import { useEffect, Children, isValidElement } from "react";
12
12
  // browser. The ALS-backed implementation lives in head-state.ts (server-only).
13
13
  let _ssrHeadElements = [];
14
14
  let _getSSRHeadElements = () => _ssrHeadElements;
15
- let _resetSSRHeadImpl = () => { _ssrHeadElements = []; };
15
+ let _resetSSRHeadImpl = () => {
16
+ _ssrHeadElements = [];
17
+ };
16
18
  /**
17
19
  * Register ALS-backed state accessors. Called by head-state.ts on import.
18
20
  * @internal
@@ -33,9 +35,7 @@ export function getSSRHeadHTML() {
33
35
  * Tags allowed inside <head>. Anything else is silently dropped.
34
36
  * This prevents injection of dangerous elements like <iframe>, <object>, etc.
35
37
  */
36
- const ALLOWED_HEAD_TAGS = new Set([
37
- "title", "meta", "link", "style", "script", "base", "noscript",
38
- ]);
38
+ const ALLOWED_HEAD_TAGS = new Set(["title", "meta", "link", "style", "script", "base", "noscript"]);
39
39
  /**
40
40
  * Convert a React element to an HTML string for SSR head injection.
41
41
  * Returns an empty string for disallowed tag types.
@@ -95,7 +95,11 @@ function escapeHTML(s) {
95
95
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
96
96
  }
97
97
  export function escapeAttr(s) {
98
- return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
98
+ return s
99
+ .replace(/&/g, "&amp;")
100
+ .replace(/"/g, "&quot;")
101
+ .replace(/</g, "&lt;")
102
+ .replace(/>/g, "&gt;");
99
103
  }
100
104
  /**
101
105
  * Escape content that will be placed inside a raw <script> or <style> tag
@@ -132,9 +136,7 @@ function Head({ children }) {
132
136
  useEffect(() => {
133
137
  const elements = [];
134
138
  // Remove previous vinext-managed head elements
135
- document
136
- .querySelectorAll("[data-vinext-head]")
137
- .forEach((el) => el.remove());
139
+ document.querySelectorAll("[data-vinext-head]").forEach((el) => el.remove());
138
140
  Children.forEach(children, (child) => {
139
141
  if (!isValidElement(child))
140
142
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"head.js","sourceRoot":"","sources":["../../src/shims/head.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * next/head shim\n *\n * In the Pages Router, <Head> manages document <head> elements.\n * - On the server: collects elements into a module-level array that the\n * dev-server reads after render and injects into the HTML <head>.\n * - On the client: uses useEffect + DOM manipulation.\n */\nimport React, { useEffect, Children, isValidElement } from \"react\";\n\ninterface HeadProps {\n children?: React.ReactNode;\n}\n\n// --- SSR head collection ---\n// State uses a registration pattern so this module can be bundled for the\n// browser. The ALS-backed implementation lives in head-state.ts (server-only).\n\nlet _ssrHeadElements: string[] = [];\n\nlet _getSSRHeadElements = (): string[] => _ssrHeadElements;\nlet _resetSSRHeadImpl = (): void => { _ssrHeadElements = []; };\n\n/**\n * Register ALS-backed state accessors. Called by head-state.ts on import.\n * @internal\n */\nexport function _registerHeadStateAccessors(accessors: {\n getSSRHeadElements: () => string[];\n resetSSRHead: () => void;\n}): void {\n _getSSRHeadElements = accessors.getSSRHeadElements;\n _resetSSRHeadImpl = accessors.resetSSRHead;\n}\n\n/** Reset the SSR head collector. Call before render. */\nexport function resetSSRHead(): void {\n _resetSSRHeadImpl();\n}\n\n/** Get collected head HTML. Call after render. */\nexport function getSSRHeadHTML(): string {\n return _getSSRHeadElements().join(\"\\n \");\n}\n\n/**\n * Tags allowed inside <head>. Anything else is silently dropped.\n * This prevents injection of dangerous elements like <iframe>, <object>, etc.\n */\nconst ALLOWED_HEAD_TAGS = new Set([\n \"title\", \"meta\", \"link\", \"style\", \"script\", \"base\", \"noscript\",\n]);\n\n/**\n * Convert a React element to an HTML string for SSR head injection.\n * Returns an empty string for disallowed tag types.\n */\nfunction reactElementToHTML(child: React.ReactElement): string {\n const tag = child.type as string;\n\n if (!ALLOWED_HEAD_TAGS.has(tag)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[vinext] <Head> ignoring disallowed tag <${tag}>. ` +\n `Only ${[...ALLOWED_HEAD_TAGS].join(\", \")} are allowed.`,\n );\n }\n return \"\";\n }\n\n const props = child.props as Record<string, unknown>;\n const attrs: string[] = [];\n let innerHTML = \"\";\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\") {\n if (typeof value === \"string\") {\n innerHTML = escapeHTML(value);\n }\n } else if (key === \"dangerouslySetInnerHTML\") {\n // Intentionally raw — developer explicitly opted in.\n // SECURITY NOTE: This injects raw HTML during SSR. The client-side\n // path (line ~148) skips dangerouslySetInnerHTML for safety. Developers\n // must never pass unsanitized user input here — it is a stored XSS vector.\n const html = value as { __html: string };\n if (html?.__html) innerHTML = html.__html;\n } else if (key === \"className\") {\n attrs.push(`class=\"${escapeAttr(String(value))}\"`);\n } else if (typeof value === \"string\") {\n attrs.push(`${key}=\"${escapeAttr(value)}\"`);\n } else if (typeof value === \"boolean\" && value) {\n attrs.push(key);\n }\n }\n\n const attrStr = attrs.length ? \" \" + attrs.join(\" \") : \"\";\n\n // Self-closing tags\n const selfClosing = [\"meta\", \"link\", \"base\"];\n if (selfClosing.includes(tag)) {\n return `<${tag}${attrStr} data-vinext-head=\"true\" />`;\n }\n\n // For raw-content tags (script, style), escape closing-tag sequences so the\n // HTML parser doesn't prematurely terminate the element.\n const rawContentTags = [\"script\", \"style\"];\n if (rawContentTags.includes(tag) && innerHTML) {\n innerHTML = escapeInlineContent(innerHTML, tag);\n }\n\n return `<${tag}${attrStr} data-vinext-head=\"true\">${innerHTML}</${tag}>`;\n}\n\nfunction escapeHTML(s: string): string {\n return s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nexport function escapeAttr(s: string): string {\n return s.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\n/**\n * Escape content that will be placed inside a raw <script> or <style> tag\n * during SSR. The HTML parser treats `</script>` (or `</style>`) as the end\n * of the block regardless of JavaScript string context, so any occurrence\n * of `</` followed by the tag name must be escaped.\n *\n * We replace `</script` and `</style` (case-insensitive) with `<\\/script`\n * and `<\\/style` respectively. The `<\\/` form is harmless in JS/CSS string\n * context but prevents the HTML parser from seeing a closing tag.\n */\nexport function escapeInlineContent(content: string, tag: string): string {\n // Build a pattern like `<\\/script` or `<\\/style`, case-insensitive\n const pattern = new RegExp(`<\\\\/(${tag})`, \"gi\");\n return content.replace(pattern, \"<\\\\/$1\");\n}\n\n// --- Component ---\n\nfunction Head({ children }: HeadProps): null {\n // SSR path: collect elements for later injection\n if (typeof window === \"undefined\") {\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return;\n if (typeof child.type !== \"string\") return;\n const html = reactElementToHTML(child);\n if (html) _getSSRHeadElements().push(html);\n });\n return null;\n }\n\n // Client path: useEffect DOM manipulation (runs after hydration)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n const elements: Element[] = [];\n\n // Remove previous vinext-managed head elements\n document\n .querySelectorAll(\"[data-vinext-head]\")\n .forEach((el) => el.remove());\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return;\n if (typeof child.type !== \"string\") return;\n if (!ALLOWED_HEAD_TAGS.has(child.type)) return;\n\n const domEl = document.createElement(child.type);\n const props = child.props as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\" && typeof value === \"string\") {\n domEl.textContent = value;\n } else if (key === \"dangerouslySetInnerHTML\") {\n // skip for safety\n } else if (key === \"className\") {\n domEl.setAttribute(\"class\", String(value));\n } else if (key !== \"children\" && typeof value === \"string\") {\n domEl.setAttribute(key, value);\n }\n }\n\n domEl.setAttribute(\"data-vinext-head\", \"true\");\n document.head.appendChild(domEl);\n elements.push(domEl);\n });\n\n return () => {\n elements.forEach((el) => el.remove());\n };\n }, [children]);\n\n return null;\n}\n\nexport default Head;\n"]}
1
+ {"version":3,"file":"head.js","sourceRoot":"","sources":["../../src/shims/head.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * next/head shim\n *\n * In the Pages Router, <Head> manages document <head> elements.\n * - On the server: collects elements into a module-level array that the\n * dev-server reads after render and injects into the HTML <head>.\n * - On the client: uses useEffect + DOM manipulation.\n */\nimport React, { useEffect, Children, isValidElement } from \"react\";\n\ninterface HeadProps {\n children?: React.ReactNode;\n}\n\n// --- SSR head collection ---\n// State uses a registration pattern so this module can be bundled for the\n// browser. The ALS-backed implementation lives in head-state.ts (server-only).\n\nlet _ssrHeadElements: string[] = [];\n\nlet _getSSRHeadElements = (): string[] => _ssrHeadElements;\nlet _resetSSRHeadImpl = (): void => {\n _ssrHeadElements = [];\n};\n\n/**\n * Register ALS-backed state accessors. Called by head-state.ts on import.\n * @internal\n */\nexport function _registerHeadStateAccessors(accessors: {\n getSSRHeadElements: () => string[];\n resetSSRHead: () => void;\n}): void {\n _getSSRHeadElements = accessors.getSSRHeadElements;\n _resetSSRHeadImpl = accessors.resetSSRHead;\n}\n\n/** Reset the SSR head collector. Call before render. */\nexport function resetSSRHead(): void {\n _resetSSRHeadImpl();\n}\n\n/** Get collected head HTML. Call after render. */\nexport function getSSRHeadHTML(): string {\n return _getSSRHeadElements().join(\"\\n \");\n}\n\n/**\n * Tags allowed inside <head>. Anything else is silently dropped.\n * This prevents injection of dangerous elements like <iframe>, <object>, etc.\n */\nconst ALLOWED_HEAD_TAGS = new Set([\"title\", \"meta\", \"link\", \"style\", \"script\", \"base\", \"noscript\"]);\n\n/**\n * Convert a React element to an HTML string for SSR head injection.\n * Returns an empty string for disallowed tag types.\n */\nfunction reactElementToHTML(child: React.ReactElement): string {\n const tag = child.type as string;\n\n if (!ALLOWED_HEAD_TAGS.has(tag)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[vinext] <Head> ignoring disallowed tag <${tag}>. ` +\n `Only ${[...ALLOWED_HEAD_TAGS].join(\", \")} are allowed.`,\n );\n }\n return \"\";\n }\n\n const props = child.props as Record<string, unknown>;\n const attrs: string[] = [];\n let innerHTML = \"\";\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\") {\n if (typeof value === \"string\") {\n innerHTML = escapeHTML(value);\n }\n } else if (key === \"dangerouslySetInnerHTML\") {\n // Intentionally raw — developer explicitly opted in.\n // SECURITY NOTE: This injects raw HTML during SSR. The client-side\n // path (line ~148) skips dangerouslySetInnerHTML for safety. Developers\n // must never pass unsanitized user input here — it is a stored XSS vector.\n const html = value as { __html: string };\n if (html?.__html) innerHTML = html.__html;\n } else if (key === \"className\") {\n attrs.push(`class=\"${escapeAttr(String(value))}\"`);\n } else if (typeof value === \"string\") {\n attrs.push(`${key}=\"${escapeAttr(value)}\"`);\n } else if (typeof value === \"boolean\" && value) {\n attrs.push(key);\n }\n }\n\n const attrStr = attrs.length ? \" \" + attrs.join(\" \") : \"\";\n\n // Self-closing tags\n const selfClosing = [\"meta\", \"link\", \"base\"];\n if (selfClosing.includes(tag)) {\n return `<${tag}${attrStr} data-vinext-head=\"true\" />`;\n }\n\n // For raw-content tags (script, style), escape closing-tag sequences so the\n // HTML parser doesn't prematurely terminate the element.\n const rawContentTags = [\"script\", \"style\"];\n if (rawContentTags.includes(tag) && innerHTML) {\n innerHTML = escapeInlineContent(innerHTML, tag);\n }\n\n return `<${tag}${attrStr} data-vinext-head=\"true\">${innerHTML}</${tag}>`;\n}\n\nfunction escapeHTML(s: string): string {\n return s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nexport function escapeAttr(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\n/**\n * Escape content that will be placed inside a raw <script> or <style> tag\n * during SSR. The HTML parser treats `</script>` (or `</style>`) as the end\n * of the block regardless of JavaScript string context, so any occurrence\n * of `</` followed by the tag name must be escaped.\n *\n * We replace `</script` and `</style` (case-insensitive) with `<\\/script`\n * and `<\\/style` respectively. The `<\\/` form is harmless in JS/CSS string\n * context but prevents the HTML parser from seeing a closing tag.\n */\nexport function escapeInlineContent(content: string, tag: string): string {\n // Build a pattern like `<\\/script` or `<\\/style`, case-insensitive\n const pattern = new RegExp(`<\\\\/(${tag})`, \"gi\");\n return content.replace(pattern, \"<\\\\/$1\");\n}\n\n// --- Component ---\n\nfunction Head({ children }: HeadProps): null {\n // SSR path: collect elements for later injection\n if (typeof window === \"undefined\") {\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return;\n if (typeof child.type !== \"string\") return;\n const html = reactElementToHTML(child);\n if (html) _getSSRHeadElements().push(html);\n });\n return null;\n }\n\n // Client path: useEffect DOM manipulation (runs after hydration)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n const elements: Element[] = [];\n\n // Remove previous vinext-managed head elements\n document.querySelectorAll(\"[data-vinext-head]\").forEach((el) => el.remove());\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return;\n if (typeof child.type !== \"string\") return;\n if (!ALLOWED_HEAD_TAGS.has(child.type)) return;\n\n const domEl = document.createElement(child.type);\n const props = child.props as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\" && typeof value === \"string\") {\n domEl.textContent = value;\n } else if (key === \"dangerouslySetInnerHTML\") {\n // skip for safety\n } else if (key === \"className\") {\n domEl.setAttribute(\"class\", String(value));\n } else if (key !== \"children\" && typeof value === \"string\") {\n domEl.setAttribute(key, value);\n }\n }\n\n domEl.setAttribute(\"data-vinext-head\", \"true\");\n document.head.appendChild(domEl);\n elements.push(domEl);\n });\n\n return () => {\n elements.forEach((el) => el.remove());\n };\n }, [children]);\n\n return null;\n}\n\nexport default Head;\n"]}
@@ -64,15 +64,33 @@ export declare function runWithHeadersContext<T>(ctx: HeadersContext, fn: () =>
64
64
  /**
65
65
  * Apply middleware-forwarded request headers to the current headers context.
66
66
  *
67
- * When Next.js middleware calls `NextResponse.next({ request: { headers } })`,
68
- * the modified headers are encoded as `x-middleware-request-<name>` on the
69
- * middleware response. This function unpacks those prefixed headers and
70
- * replaces the corresponding entries on the live `HeadersContext` so that
71
- * subsequent calls to `headers()` / `cookies()` see the middleware changes.
67
+ * When Next.js middleware calls `NextResponse.next()` or `NextResponse.rewrite()`
68
+ * with `{ request: { headers } }`, the modified headers are encoded on the
69
+ * middleware response. This function decodes that protocol and applies the
70
+ * resulting request header set to the live `HeadersContext`. When an override
71
+ * list is present, omitted headers are deleted as part of the rebuild.
72
72
  */
73
73
  export declare function applyMiddlewareRequestHeaders(middlewareResponseHeaders: Headers): void;
74
74
  /**
75
75
  * Create a HeadersContext from a standard Request object.
76
+ *
77
+ * Performance note: In Workerd (Cloudflare Workers), `new Headers(request.headers)`
78
+ * copies the entire header map across the V8/C++ boundary, which shows up as
79
+ * ~815 ms self-time in production profiles when requests carry many headers.
80
+ * We defer this copy with a lazy proxy:
81
+ *
82
+ * - Reads (`get`, `has`, `entries`, …) are forwarded directly to the original
83
+ * immutable `request.headers` — zero copy cost on the hot path.
84
+ * - The first mutating call (`set`, `delete`, `append`) materialises
85
+ * `new Headers(request.headers)` once, then applies the mutation to the copy.
86
+ * All subsequent operations go to the copy.
87
+ *
88
+ * This means the ~815 ms copy only occurs when middleware actually rewrites
89
+ * request headers via `NextResponse.next({ request: { headers } })`, which is
90
+ * uncommon. Pure read requests (the vast majority) pay zero copy cost.
91
+ *
92
+ * Cookie parsing is also deferred: the `cookie` header string is not split
93
+ * until the first call to `cookies()` or `draftMode()`.
76
94
  */
77
95
  export declare function headersContextFromRequest(request: Request): HeadersContext;
78
96
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/shims/headers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/shims/headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,UAAU,cAAc;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAkCD;;;;GAIG;AAGH;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAyBD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAe7D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAK7C;AAED;;;;;;;;GAQG;AACH;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAEzD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI,CA4BlE;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAShB;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,yBAAyB,EAAE,OAAO,GAAG,IAAI,CA2BtF;AAKD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAgE1E;AAMD;;;;GAIG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAYhD;AAED;;;GAGG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC,CAWvD;AAMD,4EAA4E;AAG5E;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAKpD;AAsBD;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAKxD;AAED,UAAU,eAAe;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC,CA6B1D;AAoCD,cAAM,cAAc;IAClB,OAAO,CAAC,QAAQ,CAAsB;gBAE1B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIxC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAM9D,MAAM,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAQhD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;;OAGG;IACH,GAAG,CACD,aAAa,EACT,MAAM,GACN;QACE,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,IAAI,CAAC;QACf,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;KACtC,EACL,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,IAAI,CAAC;QACf,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;KACtC,GACA,IAAI;IAwCP;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO1B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAgBhF,QAAQ,IAAI,MAAM;CAOnB;AAGD,YAAY,EAAE,cAAc,EAAE,CAAC"}
@@ -8,6 +8,7 @@
8
8
  * We support both the sync (legacy) and async patterns.
9
9
  */
10
10
  import { AsyncLocalStorage } from "node:async_hooks";
11
+ import { buildRequestHeadersFromMiddlewareResponse } from "../server/middleware-request-headers.js";
11
12
  // NOTE:
12
13
  // - This shim can be loaded under multiple module specifiers in Vite's
13
14
  // multi-environment setup (RSC/SSR). Store the AsyncLocalStorage on
@@ -18,7 +19,8 @@ import { AsyncLocalStorage } from "node:async_hooks";
18
19
  const _ALS_KEY = Symbol.for("vinext.nextHeadersShim.als");
19
20
  const _FALLBACK_KEY = Symbol.for("vinext.nextHeadersShim.fallback");
20
21
  const _g = globalThis;
21
- const _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage());
22
+ const _als = (_g[_ALS_KEY] ??=
23
+ new AsyncLocalStorage());
22
24
  const _fallbackState = (_g[_FALLBACK_KEY] ??= {
23
25
  headersContext: null,
24
26
  dynamicUsageDetected: false,
@@ -159,29 +161,29 @@ export function runWithHeadersContext(ctx, fn) {
159
161
  /**
160
162
  * Apply middleware-forwarded request headers to the current headers context.
161
163
  *
162
- * When Next.js middleware calls `NextResponse.next({ request: { headers } })`,
163
- * the modified headers are encoded as `x-middleware-request-<name>` on the
164
- * middleware response. This function unpacks those prefixed headers and
165
- * replaces the corresponding entries on the live `HeadersContext` so that
166
- * subsequent calls to `headers()` / `cookies()` see the middleware changes.
164
+ * When Next.js middleware calls `NextResponse.next()` or `NextResponse.rewrite()`
165
+ * with `{ request: { headers } }`, the modified headers are encoded on the
166
+ * middleware response. This function decodes that protocol and applies the
167
+ * resulting request header set to the live `HeadersContext`. When an override
168
+ * list is present, omitted headers are deleted as part of the rebuild.
167
169
  */
168
170
  export function applyMiddlewareRequestHeaders(middlewareResponseHeaders) {
169
171
  const state = _getState();
170
172
  if (!state.headersContext)
171
173
  return;
172
174
  const ctx = state.headersContext;
173
- const PREFIX = "x-middleware-request-";
174
- for (const [key, value] of middlewareResponseHeaders) {
175
- if (key.startsWith(PREFIX)) {
176
- const realName = key.slice(PREFIX.length);
177
- ctx.headers.set(realName, value);
178
- }
179
- }
175
+ const previousCookieHeader = ctx.headers.get("cookie");
176
+ const nextHeaders = buildRequestHeadersFromMiddlewareResponse(ctx.headers, middlewareResponseHeaders);
177
+ if (!nextHeaders)
178
+ return;
179
+ ctx.headers = nextHeaders;
180
+ const nextCookieHeader = nextHeaders.get("cookie");
181
+ if (previousCookieHeader === nextCookieHeader)
182
+ return;
180
183
  // If middleware modified the cookie header, rebuild the cookies map.
181
- const newCookieHeader = ctx.headers.get("cookie");
182
- if (newCookieHeader !== null) {
183
- ctx.cookies.clear();
184
- for (const part of newCookieHeader.split(";")) {
184
+ ctx.cookies.clear();
185
+ if (nextCookieHeader !== null) {
186
+ for (const part of nextCookieHeader.split(";")) {
185
187
  const [k, ...rest] = part.split("=");
186
188
  if (k) {
187
189
  ctx.cookies.set(k.trim(), rest.join("=").trim());
@@ -189,25 +191,84 @@ export function applyMiddlewareRequestHeaders(middlewareResponseHeaders) {
189
191
  }
190
192
  }
191
193
  }
194
+ /** Methods on `Headers` that mutate state. Hoisted to module scope — static. */
195
+ const _HEADERS_MUTATING_METHODS = new Set(["set", "delete", "append"]);
192
196
  /**
193
197
  * Create a HeadersContext from a standard Request object.
198
+ *
199
+ * Performance note: In Workerd (Cloudflare Workers), `new Headers(request.headers)`
200
+ * copies the entire header map across the V8/C++ boundary, which shows up as
201
+ * ~815 ms self-time in production profiles when requests carry many headers.
202
+ * We defer this copy with a lazy proxy:
203
+ *
204
+ * - Reads (`get`, `has`, `entries`, …) are forwarded directly to the original
205
+ * immutable `request.headers` — zero copy cost on the hot path.
206
+ * - The first mutating call (`set`, `delete`, `append`) materialises
207
+ * `new Headers(request.headers)` once, then applies the mutation to the copy.
208
+ * All subsequent operations go to the copy.
209
+ *
210
+ * This means the ~815 ms copy only occurs when middleware actually rewrites
211
+ * request headers via `NextResponse.next({ request: { headers } })`, which is
212
+ * uncommon. Pure read requests (the vast majority) pay zero copy cost.
213
+ *
214
+ * Cookie parsing is also deferred: the `cookie` header string is not split
215
+ * until the first call to `cookies()` or `draftMode()`.
194
216
  */
195
217
  export function headersContextFromRequest(request) {
196
- const cookies = new Map();
197
- const cookieHeader = request.headers.get("cookie") || "";
198
- for (const part of cookieHeader.split(";")) {
199
- const [key, ...rest] = part.split("=");
200
- if (key) {
201
- cookies.set(key.trim(), rest.join("=").trim());
218
+ // ---------------------------------------------------------------------------
219
+ // Lazy mutable Headers proxy
220
+ // ---------------------------------------------------------------------------
221
+ // `_mutable` holds the materialised copy once a write is needed.
222
+ let _mutable = null;
223
+ const headersProxy = new Proxy(request.headers, {
224
+ get(target, prop, receiver) {
225
+ // Route to the materialised copy if it exists.
226
+ const src = _mutable ?? target;
227
+ if (typeof prop !== "string") {
228
+ return Reflect.get(src, prop, receiver);
229
+ }
230
+ // Intercept mutating methods: materialise on first write.
231
+ if (_HEADERS_MUTATING_METHODS.has(prop)) {
232
+ return (...args) => {
233
+ if (!_mutable) {
234
+ _mutable = new Headers(target);
235
+ }
236
+ return _mutable[prop](...args);
237
+ };
238
+ }
239
+ // Non-mutating method or property: bind to current source.
240
+ const value = Reflect.get(src, prop, src);
241
+ return typeof value === "function" ? value.bind(src) : value;
242
+ },
243
+ });
244
+ // ---------------------------------------------------------------------------
245
+ // Lazy cookie map
246
+ // ---------------------------------------------------------------------------
247
+ // Parsing cookies requires splitting on `;` and `=`, which is cheap but
248
+ // still unnecessary overhead if `cookies()` is never called for this request.
249
+ let _cookies = null;
250
+ function getCookies() {
251
+ if (_cookies)
252
+ return _cookies;
253
+ _cookies = new Map();
254
+ // Read from the proxy so middleware-modified cookie headers are respected.
255
+ const cookieHeader = headersProxy.get("cookie") || "";
256
+ for (const part of cookieHeader.split(";")) {
257
+ const [key, ...rest] = part.split("=");
258
+ if (key) {
259
+ _cookies.set(key.trim(), rest.join("=").trim());
260
+ }
202
261
  }
262
+ return _cookies;
203
263
  }
204
- return {
205
- // Copy into a mutable Headers instance. In Cloudflare Workers the original
206
- // Request.headers is immutable; applyMiddlewareRequestHeaders() needs to
207
- // call .set() on this object after middleware runs.
208
- headers: new Headers(request.headers),
209
- cookies,
264
+ // Expose cookies as a lazy getter that memoises on first access.
265
+ const ctx = {
266
+ headers: headersProxy,
267
+ get cookies() {
268
+ return getCookies();
269
+ },
210
270
  };
271
+ return ctx;
211
272
  }
212
273
  // ---------------------------------------------------------------------------
213
274
  // Public API
@@ -235,8 +296,7 @@ export async function cookies() {
235
296
  throwIfInsideCacheScope("cookies()");
236
297
  const state = _getState();
237
298
  if (!state.headersContext) {
238
- throw new Error("cookies() can only be called from a Server Component, Route Handler, " +
239
- "or Server Action.");
299
+ throw new Error("cookies() can only be called from a Server Component, Route Handler, " + "or Server Action.");
240
300
  }
241
301
  markDynamicUsage();
242
302
  return new RequestCookies(state.headersContext.cookies);
@@ -303,16 +363,14 @@ export async function draftMode() {
303
363
  state.headersContext.cookies.set(DRAFT_MODE_COOKIE, secret);
304
364
  }
305
365
  const secure = typeof process !== "undefined" && process.env?.NODE_ENV === "production" ? "; Secure" : "";
306
- state.draftModeCookieHeader =
307
- `${DRAFT_MODE_COOKIE}=${secret}; Path=/; HttpOnly; SameSite=Lax${secure}`;
366
+ state.draftModeCookieHeader = `${DRAFT_MODE_COOKIE}=${secret}; Path=/; HttpOnly; SameSite=Lax${secure}`;
308
367
  },
309
368
  disable() {
310
369
  if (state.headersContext) {
311
370
  state.headersContext.cookies.delete(DRAFT_MODE_COOKIE);
312
371
  }
313
372
  const secure = typeof process !== "undefined" && process.env?.NODE_ENV === "production" ? "; Secure" : "";
314
- state.draftModeCookieHeader =
315
- `${DRAFT_MODE_COOKIE}=; Path=/; HttpOnly; SameSite=Lax${secure}; Max-Age=0`;
373
+ state.draftModeCookieHeader = `${DRAFT_MODE_COOKIE}=; Path=/; HttpOnly; SameSite=Lax${secure}; Max-Age=0`;
316
374
  },
317
375
  };
318
376
  }
@@ -336,7 +394,7 @@ function validateCookieName(name) {
336
394
  function validateCookieAttributeValue(value, attributeName) {
337
395
  for (let i = 0; i < value.length; i++) {
338
396
  const code = value.charCodeAt(i);
339
- if (code <= 0x1F || code === 0x7F || value[i] === ";") {
397
+ if (code <= 0x1f || code === 0x7f || value[i] === ";") {
340
398
  throw new Error(`Invalid cookie ${attributeName} value: ${JSON.stringify(value)}`);
341
399
  }
342
400
  }
@@ -424,7 +482,9 @@ class RequestCookies {
424
482
  [Symbol.iterator]() {
425
483
  const entries = this._cookies.entries();
426
484
  const iter = {
427
- [Symbol.iterator]() { return iter; },
485
+ [Symbol.iterator]() {
486
+ return iter;
487
+ },
428
488
  next() {
429
489
  const { value, done } = entries.next();
430
490
  if (done)