@farm.js/core 0.1.0-beta.11 → 0.1.0-beta.14

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 (238) hide show
  1. package/dist/chunk-53MVSX3R.mjs +168 -0
  2. package/dist/chunk-53MVSX3R.mjs.map +1 -0
  3. package/dist/{chunk-AW6I64AP.mjs → chunk-6ZXIQSXE.mjs} +16 -1
  4. package/dist/chunk-6ZXIQSXE.mjs.map +1 -0
  5. package/dist/chunk-7ZVN3YZI.mjs +333 -0
  6. package/dist/chunk-7ZVN3YZI.mjs.map +1 -0
  7. package/dist/{chunk-5EVQFRL2.mjs → chunk-ARCGE2VT.mjs} +2 -2
  8. package/dist/chunk-ARCGE2VT.mjs.map +1 -0
  9. package/dist/{chunk-7N62DNSO.mjs → chunk-H3TE3LOV.mjs} +2 -2
  10. package/dist/{chunk-QTZZ2ISQ.mjs → chunk-KLA67WKG.mjs} +1 -1
  11. package/dist/chunk-KLA67WKG.mjs.map +1 -0
  12. package/dist/{chunk-K5ZTUF22.mjs → chunk-L2PE36GQ.mjs} +7 -3
  13. package/dist/chunk-L2PE36GQ.mjs.map +1 -0
  14. package/dist/{chunk-4LND3PXF.mjs → chunk-OPHK6OJN.mjs} +513 -48
  15. package/dist/chunk-OPHK6OJN.mjs.map +1 -0
  16. package/dist/{chunk-77BOAQHI.mjs → chunk-PNFQQSRA.mjs} +754 -156
  17. package/dist/chunk-PNFQQSRA.mjs.map +1 -0
  18. package/dist/chunk-USLFXFFH.mjs +46 -0
  19. package/dist/chunk-USLFXFFH.mjs.map +1 -0
  20. package/dist/{chunk-4677KXB7.mjs → chunk-VUL55IAX.mjs} +368 -103
  21. package/dist/chunk-VUL55IAX.mjs.map +1 -0
  22. package/dist/client.cjs.map +1 -1
  23. package/dist/client.mjs +1 -1
  24. package/dist/{devtools-A22KUJZT.mjs → devtools-GAZ7F3KL.mjs} +4 -3
  25. package/dist/{devtools-A22KUJZT.mjs.map → devtools-GAZ7F3KL.mjs.map} +1 -1
  26. package/dist/docs.cjs +622 -124
  27. package/dist/docs.cjs.map +1 -1
  28. package/dist/docs.mjs +5 -3
  29. package/dist/font.cjs +19 -2
  30. package/dist/font.cjs.map +1 -1
  31. package/dist/font.mjs +7 -3
  32. package/dist/index.cjs +2235 -689
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.mjs +27 -19
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/internal/build-runtime.cjs +2062 -525
  37. package/dist/internal/build-runtime.cjs.map +1 -1
  38. package/dist/internal/build-runtime.mjs +13 -10
  39. package/dist/internal/client-runtime.cjs +169 -2
  40. package/dist/internal/client-runtime.cjs.map +1 -1
  41. package/dist/internal/client-runtime.mjs +170 -2
  42. package/dist/internal/client-runtime.mjs.map +1 -1
  43. package/dist/internal/config-runtime.cjs +22 -0
  44. package/dist/internal/config-runtime.cjs.map +1 -1
  45. package/dist/internal/config-runtime.mjs +3 -2
  46. package/dist/internal/metadata-image-runtime.cjs +199 -0
  47. package/dist/internal/metadata-image-runtime.cjs.map +1 -0
  48. package/dist/internal/metadata-image-runtime.mjs +8 -0
  49. package/dist/internal/metadata-image-runtime.mjs.map +1 -0
  50. package/dist/internal/production-runtime.cjs +310 -0
  51. package/dist/internal/production-runtime.cjs.map +1 -1
  52. package/dist/internal/production-runtime.mjs +10 -0
  53. package/dist/internal/production-runtime.mjs.map +1 -1
  54. package/dist/navigation.cjs.map +1 -1
  55. package/dist/navigation.mjs +2 -2
  56. package/dist/plugin.cjs +1550 -348
  57. package/dist/plugin.cjs.map +1 -1
  58. package/dist/plugin.mjs +9 -5
  59. package/dist/server.cjs +1663 -419
  60. package/dist/server.cjs.map +1 -1
  61. package/dist/server.mjs +17 -19
  62. package/dist/server.mjs.map +1 -1
  63. package/dist/version.cjs +1 -1
  64. package/dist/version.cjs.map +1 -1
  65. package/dist/version.mjs +1 -1
  66. package/dist/vite.cjs +1604 -358
  67. package/dist/vite.cjs.map +1 -1
  68. package/dist/vite.mjs +9 -5
  69. package/package.json +10 -1
  70. package/types/client.d.ts +115 -4
  71. package/dist/after.d.mts +0 -25
  72. package/dist/after.d.ts +0 -25
  73. package/dist/agent-runtime.d.mts +0 -94
  74. package/dist/agent-runtime.d.ts +0 -94
  75. package/dist/api/route-manager.d.mts +0 -66
  76. package/dist/api/route-manager.d.ts +0 -66
  77. package/dist/api/runtime.d.mts +0 -3
  78. package/dist/api/runtime.d.ts +0 -3
  79. package/dist/api.d.mts +0 -48
  80. package/dist/api.d.ts +0 -48
  81. package/dist/app-BNE2FoZ4.d.mts +0 -302
  82. package/dist/app-DRGUmJ3s.d.ts +0 -302
  83. package/dist/app-markdown.d.mts +0 -22
  84. package/dist/app-markdown.d.ts +0 -22
  85. package/dist/cache.d.mts +0 -192
  86. package/dist/cache.d.ts +0 -192
  87. package/dist/chunk-4677KXB7.mjs.map +0 -1
  88. package/dist/chunk-4LND3PXF.mjs.map +0 -1
  89. package/dist/chunk-5EVQFRL2.mjs.map +0 -1
  90. package/dist/chunk-77BOAQHI.mjs.map +0 -1
  91. package/dist/chunk-AW6I64AP.mjs.map +0 -1
  92. package/dist/chunk-K5ZTUF22.mjs.map +0 -1
  93. package/dist/chunk-QM746KUO.mjs +0 -56
  94. package/dist/chunk-QM746KUO.mjs.map +0 -1
  95. package/dist/chunk-QTZZ2ISQ.mjs.map +0 -1
  96. package/dist/client-BT1mFQas.d.mts +0 -447
  97. package/dist/client-Nn0q4eO4.d.ts +0 -447
  98. package/dist/client-cache-CIlyBlmx.d.ts +0 -6
  99. package/dist/client-cache-D-EZ7XVW.d.mts +0 -6
  100. package/dist/client-plugins-Bc5jHcNr.d.ts +0 -1927
  101. package/dist/client-plugins-jsk-ZLzJ.d.mts +0 -1927
  102. package/dist/client-plugins.d.mts +0 -22
  103. package/dist/client-plugins.d.ts +0 -22
  104. package/dist/client.d.mts +0 -447
  105. package/dist/client.d.ts +0 -447
  106. package/dist/config.d.mts +0 -29
  107. package/dist/config.d.ts +0 -29
  108. package/dist/cron.d.mts +0 -78
  109. package/dist/cron.d.ts +0 -78
  110. package/dist/deferred.d.mts +0 -42
  111. package/dist/deferred.d.ts +0 -42
  112. package/dist/deployment.d.mts +0 -34
  113. package/dist/deployment.d.ts +0 -34
  114. package/dist/docs.d.mts +0 -69
  115. package/dist/docs.d.ts +0 -69
  116. package/dist/env-types.d.mts +0 -12
  117. package/dist/env-types.d.ts +0 -12
  118. package/dist/env.d.mts +0 -45
  119. package/dist/env.d.ts +0 -45
  120. package/dist/environment/vite.d.mts +0 -22
  121. package/dist/environment/vite.d.ts +0 -22
  122. package/dist/environment.d.mts +0 -18
  123. package/dist/environment.d.ts +0 -18
  124. package/dist/font.d.mts +0 -70
  125. package/dist/font.d.ts +0 -70
  126. package/dist/headers.d.mts +0 -22
  127. package/dist/headers.d.ts +0 -22
  128. package/dist/i18n/client.d.mts +0 -32
  129. package/dist/i18n/client.d.ts +0 -32
  130. package/dist/i18n/index.d.mts +0 -20
  131. package/dist/i18n/index.d.ts +0 -20
  132. package/dist/i18n/server.d.mts +0 -30
  133. package/dist/i18n/server.d.ts +0 -30
  134. package/dist/image/server.d.mts +0 -37
  135. package/dist/image/server.d.ts +0 -37
  136. package/dist/image/sharp.d.mts +0 -7
  137. package/dist/image/sharp.d.ts +0 -7
  138. package/dist/image-config-Duob7wER.d.mts +0 -50
  139. package/dist/image-config-Duob7wER.d.ts +0 -50
  140. package/dist/image.d.mts +0 -39
  141. package/dist/image.d.ts +0 -39
  142. package/dist/index.d.mts +0 -455
  143. package/dist/index.d.ts +0 -455
  144. package/dist/integration-api-CHT2OKAf.d.mts +0 -93
  145. package/dist/integration-api-CHT2OKAf.d.ts +0 -93
  146. package/dist/integrations.d.mts +0 -22
  147. package/dist/integrations.d.ts +0 -22
  148. package/dist/internal/build-runtime.d.mts +0 -39
  149. package/dist/internal/build-runtime.d.ts +0 -39
  150. package/dist/internal/client-runtime.d.mts +0 -2
  151. package/dist/internal/client-runtime.d.ts +0 -2
  152. package/dist/internal/config-runtime.d.mts +0 -39
  153. package/dist/internal/config-runtime.d.ts +0 -39
  154. package/dist/internal/production-node-env.d.mts +0 -12
  155. package/dist/internal/production-node-env.d.ts +0 -12
  156. package/dist/internal/production-runtime.d.mts +0 -41
  157. package/dist/internal/production-runtime.d.ts +0 -41
  158. package/dist/markdown.d.mts +0 -60
  159. package/dist/markdown.d.ts +0 -60
  160. package/dist/metadata-7ffpT3jr.d.mts +0 -22
  161. package/dist/metadata-JHn-8eht.d.ts +0 -22
  162. package/dist/middleware.d.mts +0 -164
  163. package/dist/middleware.d.ts +0 -164
  164. package/dist/navigation-errors-Dvwpzaer.d.mts +0 -13
  165. package/dist/navigation-errors-Dvwpzaer.d.ts +0 -13
  166. package/dist/navigation.d.mts +0 -14
  167. package/dist/navigation.d.ts +0 -14
  168. package/dist/observability.d.mts +0 -335
  169. package/dist/observability.d.ts +0 -335
  170. package/dist/params-BALtrRim.d.ts +0 -15
  171. package/dist/params-ry-lxqmy.d.mts +0 -15
  172. package/dist/plugin-BJDf43dc.d.mts +0 -165
  173. package/dist/plugin-BJDf43dc.d.ts +0 -165
  174. package/dist/plugin.d.mts +0 -22
  175. package/dist/plugin.d.ts +0 -22
  176. package/dist/production-runtime-9KG7GuvW.d.ts +0 -79
  177. package/dist/production-runtime-B-fweKts.d.mts +0 -79
  178. package/dist/production-runtime-C_B79w2P.d.mts +0 -28
  179. package/dist/production-runtime-DDEM1D2q.d.ts +0 -28
  180. package/dist/query/client.d.mts +0 -61
  181. package/dist/query/client.d.ts +0 -61
  182. package/dist/query/index.d.mts +0 -90
  183. package/dist/query/index.d.ts +0 -90
  184. package/dist/query/parsers.d.mts +0 -25
  185. package/dist/query/parsers.d.ts +0 -25
  186. package/dist/query/server.d.mts +0 -55
  187. package/dist/query/server.d.ts +0 -55
  188. package/dist/request-Dsq4kGW0.d.mts +0 -6
  189. package/dist/request-udtobOLv.d.ts +0 -6
  190. package/dist/request.d.mts +0 -2
  191. package/dist/request.d.ts +0 -2
  192. package/dist/resolver-DJqjLMg_.d.mts +0 -14
  193. package/dist/resolver-IH4RmPEl.d.ts +0 -14
  194. package/dist/route-runtime-DoOHzCAD.d.mts +0 -38
  195. package/dist/route-runtime-DoOHzCAD.d.ts +0 -38
  196. package/dist/router.d.mts +0 -36
  197. package/dist/router.d.ts +0 -36
  198. package/dist/routes.d.mts +0 -224
  199. package/dist/routes.d.ts +0 -224
  200. package/dist/runtime-9nQjVM7X.d.mts +0 -206
  201. package/dist/runtime-Cxpq6xZN.d.mts +0 -27
  202. package/dist/runtime-DgeS2skB.d.ts +0 -206
  203. package/dist/runtime-bv63eUiO.d.ts +0 -27
  204. package/dist/server-action-security.d.mts +0 -43
  205. package/dist/server-action-security.d.ts +0 -43
  206. package/dist/server-fn-client.d.mts +0 -32
  207. package/dist/server-fn-client.d.ts +0 -32
  208. package/dist/server-fn.d.mts +0 -93
  209. package/dist/server-fn.d.ts +0 -93
  210. package/dist/server-plugins.d.mts +0 -55
  211. package/dist/server-plugins.d.ts +0 -55
  212. package/dist/server-query-client.d.mts +0 -50
  213. package/dist/server-query-client.d.ts +0 -50
  214. package/dist/server-query.d.mts +0 -36
  215. package/dist/server-query.d.ts +0 -36
  216. package/dist/server.d.mts +0 -48
  217. package/dist/server.d.ts +0 -48
  218. package/dist/storage.d.mts +0 -52
  219. package/dist/storage.d.ts +0 -52
  220. package/dist/testing.d.mts +0 -101
  221. package/dist/testing.d.ts +0 -101
  222. package/dist/transport-BmbGTXA5.d.mts +0 -49
  223. package/dist/transport-BmbGTXA5.d.ts +0 -49
  224. package/dist/types-BMxWr97v.d.mts +0 -81
  225. package/dist/types-BMxWr97v.d.ts +0 -81
  226. package/dist/types-C9N-nk5R.d.mts +0 -53
  227. package/dist/types-C9N-nk5R.d.ts +0 -53
  228. package/dist/types-D1A6-XvH.d.mts +0 -73
  229. package/dist/types-D1A6-XvH.d.ts +0 -73
  230. package/dist/utils-CA0z0c-2.d.ts +0 -23
  231. package/dist/utils-mYVkSOt2.d.mts +0 -23
  232. package/dist/version.d.mts +0 -3
  233. package/dist/version.d.ts +0 -3
  234. package/dist/vite.d.mts +0 -22
  235. package/dist/vite.d.ts +0 -22
  236. package/dist/workflows.d.mts +0 -110
  237. package/dist/workflows.d.ts +0 -110
  238. /package/dist/{chunk-7N62DNSO.mjs.map → chunk-H3TE3LOV.mjs.map} +0 -0
package/dist/docs.cjs CHANGED
@@ -644,17 +644,54 @@ __export(docs_exports, {
644
644
  module.exports = __toCommonJS(docs_exports);
645
645
 
646
646
  // src/docs/handler.ts
647
- var import_node_fs3 = require("fs");
647
+ var import_node_fs4 = require("fs");
648
648
  var import_node_module2 = require("module");
649
- var import_node_path3 = __toESM(require("path"));
649
+ var import_node_path4 = __toESM(require("path"));
650
650
  var import_docs = require("@farming-labs/docs");
651
651
  var import_marked = require("marked");
652
652
  var import_sugar_high = require("sugar-high");
653
653
 
654
- // src/docs/last-modified.ts
655
- var import_node_child_process = require("child_process");
654
+ // src/docs/fonts.ts
655
+ var import_node_crypto = require("crypto");
656
656
  var import_node_fs = require("fs");
657
657
  var import_node_path = __toESM(require("path"));
658
+ var FARM_DOCS_FONT_SOURCES = [
659
+ {
660
+ family: "Geist Sans",
661
+ packagePath: "geist/dist/fonts/geist-sans/Geist-Variable.woff2"
662
+ },
663
+ {
664
+ family: "Geist Mono",
665
+ packagePath: "geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
666
+ }
667
+ ];
668
+ function resolveFarmDocsFontAssets(root) {
669
+ return FARM_DOCS_FONT_SOURCES.flatMap(({ family, packagePath }) => {
670
+ const sourcePath = import_node_path.default.join(root, "node_modules", packagePath);
671
+ if (!(0, import_node_fs.existsSync)(sourcePath)) return [];
672
+ const source = (0, import_node_fs.readFileSync)(sourcePath);
673
+ const fingerprint = (0, import_node_crypto.createHash)("sha256").update(source).digest("hex").slice(0, 12);
674
+ const extension = import_node_path.default.extname(packagePath);
675
+ const baseName = import_node_path.default.basename(packagePath, extension);
676
+ return [
677
+ {
678
+ family,
679
+ sourcePath,
680
+ url: `/assets/fonts/${baseName}-h${fingerprint}${extension}`
681
+ }
682
+ ];
683
+ });
684
+ }
685
+ __name(resolveFarmDocsFontAssets, "resolveFarmDocsFontAssets");
686
+ function toFarmDocsPublicFontAssets(assets) {
687
+ return assets.map(({ family, url }) => ({ family, url }));
688
+ }
689
+ __name(toFarmDocsPublicFontAssets, "toFarmDocsPublicFontAssets");
690
+
691
+ // src/docs/last-modified.ts
692
+ var import_node_child_process = require("child_process");
693
+ var import_node_fs2 = require("fs");
694
+ var import_node_path2 = __toESM(require("path"));
658
695
  var FARM_DOCS_LAST_MODIFIED_MANIFEST = ".farm-docs-last-modified.json";
659
696
  var COMMIT_MARKER = "__FARM_DOCS_COMMIT__";
660
697
  var DOCS_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx"]);
@@ -665,24 +702,24 @@ function normalizeRelativePath(value) {
665
702
  __name(normalizeRelativePath, "normalizeRelativePath");
666
703
  function resolveExistingPath(filePath) {
667
704
  try {
668
- return (0, import_node_fs.realpathSync)(filePath);
705
+ return (0, import_node_fs2.realpathSync)(filePath);
669
706
  } catch {
670
- return import_node_path.default.resolve(filePath);
707
+ return import_node_path2.default.resolve(filePath);
671
708
  }
672
709
  }
673
710
  __name(resolveExistingPath, "resolveExistingPath");
674
711
  function isDocsSourceFile(filePath) {
675
- return DOCS_FILE_EXTENSIONS.has(import_node_path.default.extname(filePath).toLowerCase());
712
+ return DOCS_FILE_EXTENSIONS.has(import_node_path2.default.extname(filePath).toLowerCase());
676
713
  }
677
714
  __name(isDocsSourceFile, "isDocsSourceFile");
678
715
  function discoverDocsSourceFiles(contentDir) {
679
716
  const files = [];
680
717
  const visit = /* @__PURE__ */ __name((dir) => {
681
- for (const entry of (0, import_node_fs.readdirSync)(dir, { withFileTypes: true }).sort(
718
+ for (const entry of (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true }).sort(
682
719
  (a, b) => a.name.localeCompare(b.name)
683
720
  )) {
684
721
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
685
- const absolutePath = import_node_path.default.join(dir, entry.name);
722
+ const absolutePath = import_node_path2.default.join(dir, entry.name);
686
723
  if (entry.isDirectory()) {
687
724
  visit(absolutePath);
688
725
  } else if (entry.isFile() && isDocsSourceFile(absolutePath)) {
@@ -690,7 +727,7 @@ function discoverDocsSourceFiles(contentDir) {
690
727
  }
691
728
  }
692
729
  }, "visit");
693
- if ((0, import_node_fs.existsSync)(contentDir)) visit(contentDir);
730
+ if ((0, import_node_fs2.existsSync)(contentDir)) visit(contentDir);
694
731
  return files;
695
732
  }
696
733
  __name(discoverDocsSourceFiles, "discoverDocsSourceFiles");
@@ -701,7 +738,7 @@ function getGitLastModifiedDates(contentDir) {
701
738
  stdio: ["ignore", "pipe", "ignore"]
702
739
  }).trim();
703
740
  if (!gitRoot) return {};
704
- const contentPathspec = normalizeRelativePath(import_node_path.default.relative(gitRoot, contentDir)) || ".";
741
+ const contentPathspec = normalizeRelativePath(import_node_path2.default.relative(gitRoot, contentDir)) || ".";
705
742
  const contentPrefix = contentPathspec === "." ? "" : `${contentPathspec}/`;
706
743
  const history = (0, import_node_child_process.execFileSync)(
707
744
  "git",
@@ -744,11 +781,11 @@ function getGitLastModifiedDates(contentDir) {
744
781
  }
745
782
  __name(getGitLastModifiedDates, "getGitLastModifiedDates");
746
783
  function readManifest(contentDir) {
747
- const manifestPath = import_node_path.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
748
- if (!(0, import_node_fs.existsSync)(manifestPath)) return null;
784
+ const manifestPath = import_node_path2.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
785
+ if (!(0, import_node_fs2.existsSync)(manifestPath)) return null;
749
786
  try {
750
787
  const parsed = JSON.parse(
751
- (0, import_node_fs.readFileSync)(manifestPath, "utf8")
788
+ (0, import_node_fs2.readFileSync)(manifestPath, "utf8")
752
789
  );
753
790
  if (parsed.version !== 1 || !parsed.pages || typeof parsed.pages !== "object") return null;
754
791
  const pages = Object.fromEntries(
@@ -768,16 +805,16 @@ function createFarmDocsLastModifiedManifest(contentDir, options = {}) {
768
805
  const fallbackDate = (options.now ?? /* @__PURE__ */ new Date()).toISOString();
769
806
  const pages = {};
770
807
  for (const sourcePath of discoverDocsSourceFiles(resolvedContentDir)) {
771
- const relativePath = normalizeRelativePath(import_node_path.default.relative(resolvedContentDir, sourcePath));
772
- pages[relativePath] = gitDates[relativePath] || (options.fallback === "now" ? fallbackDate : (0, import_node_fs.statSync)(sourcePath).mtime.toISOString());
808
+ const relativePath = normalizeRelativePath(import_node_path2.default.relative(resolvedContentDir, sourcePath));
809
+ pages[relativePath] = gitDates[relativePath] || (options.fallback === "now" ? fallbackDate : (0, import_node_fs2.statSync)(sourcePath).mtime.toISOString());
773
810
  }
774
811
  return { version: 1, pages };
775
812
  }
776
813
  __name(createFarmDocsLastModifiedManifest, "createFarmDocsLastModifiedManifest");
777
814
  function getLastModifiedManifest(contentDir) {
778
815
  const resolvedContentDir = resolveExistingPath(contentDir);
779
- const manifestPath = import_node_path.default.join(resolvedContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
780
- const manifestStat = (0, import_node_fs.existsSync)(manifestPath) ? (0, import_node_fs.statSync)(manifestPath) : null;
816
+ const manifestPath = import_node_path2.default.join(resolvedContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
817
+ const manifestStat = (0, import_node_fs2.existsSync)(manifestPath) ? (0, import_node_fs2.statSync)(manifestPath) : null;
781
818
  const signature = manifestStat ? `file:${manifestStat.mtimeMs}:${manifestStat.size}` : "generated";
782
819
  const cached = manifestCache.get(resolvedContentDir);
783
820
  if (cached?.signature === signature) return cached.manifest;
@@ -791,13 +828,13 @@ function resolveFarmDocsPageLastModified(contentDir, sourcePath, frontmatter) {
791
828
  if (configured) return configured;
792
829
  const resolvedContentDir = resolveExistingPath(contentDir);
793
830
  const resolvedSourcePath = resolveExistingPath(sourcePath);
794
- const relativePath = normalizeRelativePath(import_node_path.default.relative(resolvedContentDir, resolvedSourcePath));
795
- const isInsideContentDir = relativePath !== ".." && !relativePath.startsWith("../") && !import_node_path.default.isAbsolute(relativePath);
831
+ const relativePath = normalizeRelativePath(import_node_path2.default.relative(resolvedContentDir, resolvedSourcePath));
832
+ const isInsideContentDir = relativePath !== ".." && !relativePath.startsWith("../") && !import_node_path2.default.isAbsolute(relativePath);
796
833
  if (isInsideContentDir) {
797
834
  const generated = getLastModifiedManifest(resolvedContentDir).pages[relativePath];
798
835
  if (generated) return generated;
799
836
  }
800
- return (0, import_node_fs.statSync)(resolvedSourcePath).mtime.toISOString();
837
+ return (0, import_node_fs2.statSync)(resolvedSourcePath).mtime.toISOString();
801
838
  }
802
839
  __name(resolveFarmDocsPageLastModified, "resolveFarmDocsPageLastModified");
803
840
 
@@ -842,8 +879,8 @@ var farmDocsPixelBorderCss = String.raw`
842
879
  --scrollbar-thumb-hover: var(--color-fd-ring);
843
880
  --scrollbar-track: transparent;
844
881
  --radius: 0px;
845
- --font-geist-sans: "Geist Sans";
846
- --font-geist-mono: "Geist Mono";
882
+ --font-geist-sans: ui-sans-serif, system-ui, sans-serif;
883
+ --font-geist-mono: ui-monospace, monospace;
847
884
  }
848
885
 
849
886
  .dark {
@@ -856,28 +893,6 @@ body,
856
893
  background-color: var(--color-fd-background) !important;
857
894
  }
858
895
 
859
- @font-face {
860
- font-family: "Geist Sans";
861
- font-display: block;
862
- font-style: normal;
863
- font-weight: 100 900;
864
- src:
865
- local("Geist Sans"),
866
- url("/assets/Geist-Variable-CrgPqtmy.woff2") format("woff2"),
867
- url("/node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2") format("woff2");
868
- }
869
-
870
- @font-face {
871
- font-family: "Geist Mono";
872
- font-display: block;
873
- font-style: normal;
874
- font-weight: 100 900;
875
- src:
876
- local("Geist Mono"),
877
- url("/assets/GeistMono-Variable-BNLlm6Cd.woff2") format("woff2"),
878
- url("/node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2") format("woff2");
879
- }
880
-
881
896
  * {
882
897
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
883
898
  scrollbar-width: thin;
@@ -2067,9 +2082,9 @@ code:not(pre code) {
2067
2082
  `;
2068
2083
 
2069
2084
  // src/docs/search-client.ts
2070
- var import_node_fs2 = require("fs");
2085
+ var import_node_fs3 = require("fs");
2071
2086
  var import_node_module = require("module");
2072
- var import_node_path2 = __toESM(require("path"));
2087
+ var import_node_path3 = __toESM(require("path"));
2073
2088
  function isFarmDocsSearchEnabled(docs) {
2074
2089
  if (!docs?.enabled) return false;
2075
2090
  const search = docs.config.search;
@@ -2082,22 +2097,421 @@ function generateFarmDocsSearchBootstrapRuntime() {
2082
2097
  }
2083
2098
  __name(generateFarmDocsSearchBootstrapRuntime, "generateFarmDocsSearchBootstrapRuntime");
2084
2099
 
2100
+ // src/docs/social-image.ts
2101
+ var import_node_crypto2 = require("crypto");
2102
+ var FARM_DOCS_SOCIAL_IMAGE_WIDTH = 1200;
2103
+ var FARM_DOCS_SOCIAL_IMAGE_HEIGHT = 630;
2104
+ var FARM_DOCS_SOCIAL_IMAGE_VERSION = 3;
2105
+ function normalizeEntry(entry) {
2106
+ if (!entry || entry === "/") return "";
2107
+ return `/${entry.replace(/^\/+|\/+$/g, "")}`;
2108
+ }
2109
+ __name(normalizeEntry, "normalizeEntry");
2110
+ function encodeSlugPath(slug) {
2111
+ return slug.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
2112
+ }
2113
+ __name(encodeSlugPath, "encodeSlugPath");
2114
+ function getSocialImageConfig(docs) {
2115
+ return typeof docs.config.socialImage === "object" && docs.config.socialImage ? docs.config.socialImage : void 0;
2116
+ }
2117
+ __name(getSocialImageConfig, "getSocialImageConfig");
2118
+ function getNavTitle(docs) {
2119
+ if (typeof docs.config.nav !== "object" || !docs.config.nav || !("title" in docs.config.nav)) {
2120
+ return "Farm.js";
2121
+ }
2122
+ return String(docs.config.nav.title || "Farm.js");
2123
+ }
2124
+ __name(getNavTitle, "getNavTitle");
2125
+ function isFalse(value) {
2126
+ return value ? /^(false|no|none|off|disabled)$/i.test(value.trim()) : false;
2127
+ }
2128
+ __name(isFalse, "isFalse");
2129
+ function isExternalOrRootPath(value) {
2130
+ return /^(https?:)?\/\//i.test(value) || value.startsWith("/");
2131
+ }
2132
+ __name(isExternalOrRootPath, "isExternalOrRootPath");
2133
+ function isFarmDocsSocialImageEnabled(page, docs) {
2134
+ if (docs.config.socialImage === false || getSocialImageConfig(docs)?.enabled === false) {
2135
+ return false;
2136
+ }
2137
+ return !isFalse(page.frontmatter.socialImage);
2138
+ }
2139
+ __name(isFarmDocsSocialImageEnabled, "isFarmDocsSocialImageEnabled");
2140
+ function getFarmDocsCustomSocialImage(page) {
2141
+ const value = page.frontmatter.socialImage || page.frontmatter.openGraphImage || page.frontmatter.ogImage;
2142
+ return value && !isFalse(value) && isExternalOrRootPath(value) ? value : void 0;
2143
+ }
2144
+ __name(getFarmDocsCustomSocialImage, "getFarmDocsCustomSocialImage");
2145
+ function resolveIllustration(page) {
2146
+ const explicit = page.frontmatter.socialIllustration?.toLowerCase();
2147
+ if (explicit === "auth" || explicit === "cache" || explicit === "cli" || explicit === "integrations" || explicit === "project" || explicit === "routing" || explicit === "runtime") {
2148
+ return explicit;
2149
+ }
2150
+ const source = `${page.slug} ${page.title} ${page.section || ""}`.toLowerCase();
2151
+ if (/auth|session|security|csrf/.test(source)) return "auth";
2152
+ if (/cache|ppr|render|static|revalid|stream/.test(source)) return "cache";
2153
+ if (/integration|stripe|prisma|better.auth|email|job|workflow/.test(source)) {
2154
+ return "integrations";
2155
+ }
2156
+ if (/cli|test|deploy|preview|upgrade|migration|install/.test(source)) return "cli";
2157
+ if (/project|structure|config|environment|markdown|docs.engine/.test(source)) {
2158
+ return "project";
2159
+ }
2160
+ if (/rout|endpoint|middleware|navigation|server.function|server.action|api/.test(source)) {
2161
+ return "routing";
2162
+ }
2163
+ return "runtime";
2164
+ }
2165
+ __name(resolveIllustration, "resolveIllustration");
2166
+ function createHashValue(value) {
2167
+ return (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 16);
2168
+ }
2169
+ __name(createHashValue, "createHashValue");
2170
+ function resolveBaseUrl(requestUrl, config) {
2171
+ return config?.baseUrl ? new URL(config.baseUrl) : new URL(requestUrl.origin);
2172
+ }
2173
+ __name(resolveBaseUrl, "resolveBaseUrl");
2174
+ function createFarmDocsSocialImageDescriptor(page, docs, requestUrl) {
2175
+ const config = getSocialImageConfig(docs);
2176
+ const siteName = config?.siteName || getNavTitle(docs);
2177
+ const brand = config?.brand || siteName;
2178
+ const title = page.frontmatter.socialTitle || page.title;
2179
+ const description = page.frontmatter.socialDescription || page.description || docs.config.metadata?.description || `Documentation for ${siteName}`;
2180
+ const section = page.frontmatter.section || page.section || "Documentation";
2181
+ const illustration = resolveIllustration(page);
2182
+ const entry = normalizeEntry(docs.entry);
2183
+ const slugPath = encodeSlugPath(page.slug) || "index";
2184
+ const imagePath = `${entry}/_social/${slugPath}/opengraph-image.svg`;
2185
+ const baseUrl = resolveBaseUrl(requestUrl, config);
2186
+ const pageUrl = new URL(page.href, baseUrl).href;
2187
+ const imageAlt = `${title} \u2014 ${siteName} documentation`;
2188
+ const hash = createHashValue({
2189
+ version: FARM_DOCS_SOCIAL_IMAGE_VERSION,
2190
+ title,
2191
+ description,
2192
+ section,
2193
+ siteName,
2194
+ brand,
2195
+ pageHref: page.href,
2196
+ illustration,
2197
+ fonts: config?.fonts
2198
+ });
2199
+ return {
2200
+ title,
2201
+ description,
2202
+ section,
2203
+ siteName,
2204
+ brand,
2205
+ pageHref: page.href,
2206
+ pageUrl,
2207
+ imagePath,
2208
+ imageUrl: new URL(`${imagePath}?v=${hash}`, baseUrl).href,
2209
+ imageAlt,
2210
+ illustration,
2211
+ fonts: config?.fonts,
2212
+ hash
2213
+ };
2214
+ }
2215
+ __name(createFarmDocsSocialImageDescriptor, "createFarmDocsSocialImageDescriptor");
2216
+ function getFarmDocsSocialImageSlug(docs, requestUrl) {
2217
+ const entry = normalizeEntry(docs.entry);
2218
+ const prefix = `${entry}/_social/`;
2219
+ const suffix = "/opengraph-image.svg";
2220
+ if (!requestUrl.pathname.startsWith(prefix) || !requestUrl.pathname.endsWith(suffix)) {
2221
+ return null;
2222
+ }
2223
+ const rawSlug = requestUrl.pathname.slice(prefix.length, -suffix.length);
2224
+ if (!rawSlug) return null;
2225
+ try {
2226
+ const slug = rawSlug.split("/").map((segment) => decodeURIComponent(segment)).join("/");
2227
+ if (slug.split("/").some((segment) => !segment || segment === ".." || segment === ".")) {
2228
+ return null;
2229
+ }
2230
+ return slug === "index" ? "" : slug;
2231
+ } catch {
2232
+ return null;
2233
+ }
2234
+ }
2235
+ __name(getFarmDocsSocialImageSlug, "getFarmDocsSocialImageSlug");
2236
+ function escapeXml(value) {
2237
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
2238
+ }
2239
+ __name(escapeXml, "escapeXml");
2240
+ function truncate(value, length) {
2241
+ if (value.length <= length) return value;
2242
+ return `${value.slice(0, Math.max(0, length - 1)).trimEnd()}\u2026`;
2243
+ }
2244
+ __name(truncate, "truncate");
2245
+ function wrapText(value, maxCharacters, maxLines) {
2246
+ const words = value.trim().split(/\s+/).filter(Boolean);
2247
+ const lines = [];
2248
+ let current = "";
2249
+ let consumedWords = 0;
2250
+ for (const word of words) {
2251
+ const candidate = current ? `${current} ${word}` : word;
2252
+ if (candidate.length <= maxCharacters || !current) {
2253
+ current = candidate;
2254
+ consumedWords += 1;
2255
+ continue;
2256
+ }
2257
+ lines.push(current);
2258
+ if (lines.length === maxLines) break;
2259
+ current = word;
2260
+ consumedWords += 1;
2261
+ }
2262
+ if (current && lines.length < maxLines) lines.push(current);
2263
+ if (consumedWords < words.length && lines.length) {
2264
+ lines[lines.length - 1] = truncate(`${lines[lines.length - 1]}\u2026`, maxCharacters);
2265
+ }
2266
+ return lines;
2267
+ }
2268
+ __name(wrapText, "wrapText");
2269
+ function renderTextLines(lines, x, y, lineHeight, attributes) {
2270
+ return lines.map(
2271
+ (line, index) => `<text x="${x}" y="${y + index * lineHeight}" ${attributes}>${escapeXml(line)}</text>`
2272
+ ).join("");
2273
+ }
2274
+ __name(renderTextLines, "renderTextLines");
2275
+ function renderEmbeddedFont(name, source, weight) {
2276
+ if (!source) return "";
2277
+ return `@font-face{font-family:"${name}";src:url("${escapeXml(source)}") format("woff2");font-style:normal;font-weight:${weight};font-display:block;}`;
2278
+ }
2279
+ __name(renderEmbeddedFont, "renderEmbeddedFont");
2280
+ function renderArrow(x1, y, x2, color = "#8b8b8b") {
2281
+ return `<path d="M${x1} ${y}H${x2 - 9}" fill="none" stroke="${color}"/><path d="m${x2 - 9} ${y - 5} 9 5-9 5" fill="none" stroke="${color}"/>`;
2282
+ }
2283
+ __name(renderArrow, "renderArrow");
2284
+ function renderPanelHeader(label, status) {
2285
+ return `<text x="819" y="171" class="label">${escapeXml(label)}</text><text x="1134" y="171" class="label bright" text-anchor="end">${escapeXml(status)}</text>`;
2286
+ }
2287
+ __name(renderPanelHeader, "renderPanelHeader");
2288
+ function renderRoutingIllustration() {
2289
+ return `${renderPanelHeader("ROUTE BLUEPRINT", "TYPED")}
2290
+ <rect x="819" y="296" width="92" height="54" fill="#a3a3a3"/>
2291
+ <text x="832" y="327" class="diagram-title ink">src/app</text>
2292
+ <path d="M911 323h41M952 232v181M952 232h44M952 323h44M952 413h44" fill="none" stroke="#696969"/>
2293
+ <rect x="996" y="205" width="138" height="54" fill="#0a0a0a" stroke="#414141"/>
2294
+ <text x="1010" y="228" class="diagram-title">/</text><text x="1010" y="246" class="micro">STATIC</text>
2295
+ <rect x="996" y="296" width="138" height="54" fill="#0a0a0a" stroke="#414141"/>
2296
+ <text x="1010" y="319" class="diagram-title">/blog/:slug</text><text x="1010" y="337" class="micro">DYNAMIC</text>
2297
+ <rect x="996" y="386" width="138" height="55" fill="#f0f0f0"/>
2298
+ <text x="1010" y="410" class="diagram-title ink">/docs/:path*</text><text x="1010" y="428" class="micro ink-muted">CATCH-ALL</text>
2299
+ <line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
2300
+ <text x="819" y="475" class="label bright">FILE ROUTES</text><text x="1134" y="475" class="label" text-anchor="end">TYPES INCLUDED</text>`;
2301
+ }
2302
+ __name(renderRoutingIllustration, "renderRoutingIllustration");
2303
+ function renderAuthIllustration() {
2304
+ return `${renderPanelHeader("REQUEST GUARD", "SERVER VERIFIED")}
2305
+ <rect x="819" y="269" width="86" height="54" fill="#0a0a0a" stroke="#454545"/>
2306
+ <text x="837" y="292" class="micro bright">REQUEST</text><text x="837" y="310" class="diagram-title">GET /app</text>
2307
+ ${renderArrow(905, 296, 943)}
2308
+ <rect x="943" y="224" width="104" height="118" fill="#f0f0f0"/>
2309
+ <path d="M974 271v-12a21 21 0 0 1 42 0v12M968 271h54v45h-54z" fill="#050505"/>
2310
+ <circle cx="995" cy="292" r="4" fill="#f0f0f0"/><path d="M995 296v8" stroke="#f0f0f0" stroke-width="3"/>
2311
+ <text x="995" y="332" class="micro ink" text-anchor="middle">auth()</text>
2312
+ ${renderArrow(1047, 296, 1071)}
2313
+ <rect x="1071" y="269" width="63" height="54" fill="#0a0a0a" stroke="#454545"/>
2314
+ <text x="1082" y="292" class="micro bright">ALLOW</text><text x="1082" y="310" class="micro">/app</text>
2315
+ <rect x="819" y="372" width="315" height="38" fill="#090909" stroke="#3d3d3d"/>
2316
+ <rect x="832" y="385" width="11" height="11" fill="#a3a3a3"/>
2317
+ <text x="856" y="395" class="code">session.user / verified</text>
2318
+ <line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
2319
+ <text x="819" y="475" class="label bright">SESSION TYPED</text><text x="1134" y="475" class="label" text-anchor="end">CSRF PROTECTED</text>`;
2320
+ }
2321
+ __name(renderAuthIllustration, "renderAuthIllustration");
2322
+ function renderCacheIllustration() {
2323
+ return `${renderPanelHeader("PAGE / PRODUCT", "CACHE + PPR")}
2324
+ <rect x="819" y="204" width="315" height="54" fill="#f0f0f0"/>
2325
+ <text x="836" y="235" class="diagram-title ink">STATIC SHELL</text><text x="1116" y="235" class="micro ink-muted" text-anchor="end">BUILD</text>
2326
+ <rect x="819" y="271" width="198" height="76" fill="#a3a3a3"/>
2327
+ <text x="836" y="301" class="diagram-title ink">CACHED DATA</text><text x="836" y="326" class="micro ink-muted">tag: products</text>
2328
+ <rect x="1029" y="271" width="105" height="76" fill="#0a0a0a" stroke="#555"/>
2329
+ <text x="1045" y="301" class="diagram-title">LIVE</text><text x="1045" y="326" class="micro">stream</text>
2330
+ <path d="M1081 347v43m-8-9 8 9 8-9" fill="none" stroke="#d4d4d4"/>
2331
+ <line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
2332
+ <text x="819" y="475" class="label bright">STATIC FIRST</text><text x="1134" y="475" class="label" text-anchor="end">DYNAMIC WHERE NEEDED</text>`;
2333
+ }
2334
+ __name(renderCacheIllustration, "renderCacheIllustration");
2335
+ function renderIntegrationsIllustration() {
2336
+ return `${renderPanelHeader("INTEGRATION GRAPH", "ONE PRODUCT")}
2337
+ <path d="M976 309H879V247M976 309H879v87M1030 309h93V247M1030 309h93v87" fill="none" stroke="#4a4a4a"/>
2338
+ <rect x="819" y="214" width="120" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="839" y="247" class="diagram-title">BETTER AUTH</text>
2339
+ <rect x="819" y="368" width="120" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="851" y="401" class="diagram-title">PRISMA</text>
2340
+ <rect x="1061" y="214" width="73" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="1077" y="247" class="diagram-title">STRIPE</text>
2341
+ <rect x="1061" y="368" width="73" height="57" fill="#a3a3a3"/><text x="1075" y="401" class="diagram-title ink">VERCEL</text>
2342
+ <rect x="976" y="277" width="94" height="64" fill="#f0f0f0"/>
2343
+ <text x="994" y="304" class="diagram-title ink">FARM.JS</text><text x="994" y="324" class="micro ink-muted">CORE</text>
2344
+ <line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
2345
+ <text x="819" y="475" class="label bright">BRING YOUR STACK</text><text x="1134" y="475" class="label" text-anchor="end">CONNECTED ONCE</text>`;
2346
+ }
2347
+ __name(renderIntegrationsIllustration, "renderIntegrationsIllustration");
2348
+ function renderCliIllustration() {
2349
+ return `${renderPanelHeader("TERMINAL", "PRODUCTION OUTPUT")}
2350
+ <rect x="819" y="203" width="315" height="213" fill="#050505" stroke="#555"/>
2351
+ <line x1="819" y1="236" x2="1134" y2="236" stroke="#555"/>
2352
+ <circle cx="837" cy="220" r="4" fill="#5d5d5d"/><circle cx="850" cy="220" r="4" fill="#7a7a7a"/><circle cx="863" cy="220" r="4" fill="#a3a3a3"/>
2353
+ <text x="837" y="273" class="code bright"><tspan fill="#7a7a7a">$</tspan> farm build</text>
2354
+ <rect x="837" y="293" width="11" height="11" fill="#a3a3a3"/><path d="m839 298 3 3 6-7" fill="none" stroke="#050505" stroke-width="1.5"/>
2355
+ <text x="861" y="303" class="code">64 routes discovered</text>
2356
+ <rect x="837" y="320" width="11" height="11" fill="#a3a3a3"/><path d="m839 325 3 3 6-7" fill="none" stroke="#050505" stroke-width="1.5"/>
2357
+ <text x="861" y="330" class="code">client + server bundles</text>
2358
+ <rect x="837" y="355" width="126" height="30" fill="#f0f0f0"/><text x="853" y="374" class="micro ink">BUILD COMPLETE</text>
2359
+ <text x="1115" y="374" class="micro" text-anchor="end">/dist</text>
2360
+ <line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
2361
+ <text x="819" y="475" class="label bright">REAL COMMANDS</text><text x="1134" y="475" class="label" text-anchor="end">842MS</text>`;
2362
+ }
2363
+ __name(renderCliIllustration, "renderCliIllustration");
2364
+ function renderProjectIllustration() {
2365
+ return `${renderPanelHeader("PROJECT MAP", "CONVENTION TYPED")}
2366
+ <rect x="819" y="202" width="315" height="216" fill="#050505" stroke="#555"/>
2367
+ <text x="837" y="227" class="diagram-title bright">my-app/</text>
2368
+ <path d="M847 243v143M847 259h23M847 293h23M847 327h23M847 361h23" fill="none" stroke="#666"/>
2369
+ <rect x="870" y="243" width="246" height="33" fill="#0a0a0a" stroke="#444"/><text x="886" y="264" class="code">src/app</text><text x="1098" y="264" class="micro" text-anchor="end">ROUTES</text>
2370
+ <rect x="870" y="277" width="246" height="33" fill="#f0f0f0"/><text x="886" y="298" class="code ink">src/app/page.tsx</text>
2371
+ <rect x="870" y="311" width="246" height="33" fill="#0a0a0a" stroke="#444"/><text x="886" y="332" class="code">src/app/api/users/route.ts</text><text x="1098" y="332" class="micro" text-anchor="end">API</text>
2372
+ <rect x="870" y="345" width="246" height="33" fill="#0a0a0a" stroke="#444"/><text x="886" y="366" class="code">farm.config.ts</text><text x="1098" y="366" class="micro" text-anchor="end">CONFIG</text>
2373
+ <line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
2374
+ <text x="819" y="475" class="label bright">FILES BECOME FEATURES</text><text x="1134" y="475" class="label" text-anchor="end">ONE CONFIG</text>`;
2375
+ }
2376
+ __name(renderProjectIllustration, "renderProjectIllustration");
2377
+ function renderRuntimeIllustration() {
2378
+ return `${renderPanelHeader("PRODUCT ARCHITECTURE", "FULL STACK")}
2379
+ <rect x="819" y="211" width="315" height="55" fill="#f0f0f0"/>
2380
+ <text x="836" y="244" class="diagram-title ink">PRODUCT SURFACE</text><text x="1116" y="244" class="micro ink-muted" text-anchor="end">UI + ROUTES</text>
2381
+ <path d="M976 266v20m0 61v20" stroke="#727272"/>
2382
+ <rect x="855" y="286" width="242" height="61" fill="#a3a3a3"/>
2383
+ <text x="874" y="314" class="diagram-title ink">APPLICATION CORE</text><text x="874" y="334" class="micro ink-muted">APIS \xB7 MIDDLEWARE</text>
2384
+ <rect x="819" y="367" width="315" height="55" fill="#4c4c4c"/>
2385
+ <text x="836" y="400" class="diagram-title bright">CONNECTED STACK</text><text x="1116" y="400" class="micro" text-anchor="end">DATA \xB7 AUTH \xB7 DEPLOY</text>
2386
+ <line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
2387
+ <text x="819" y="475" class="label bright">ONE FRAMEWORK</text><text x="1134" y="475" class="label" text-anchor="end">ONE DEPLOYMENT MODEL</text>`;
2388
+ }
2389
+ __name(renderRuntimeIllustration, "renderRuntimeIllustration");
2390
+ function renderIllustration(type) {
2391
+ switch (type) {
2392
+ case "auth":
2393
+ return renderAuthIllustration();
2394
+ case "cache":
2395
+ return renderCacheIllustration();
2396
+ case "cli":
2397
+ return renderCliIllustration();
2398
+ case "integrations":
2399
+ return renderIntegrationsIllustration();
2400
+ case "project":
2401
+ return renderProjectIllustration();
2402
+ case "routing":
2403
+ return renderRoutingIllustration();
2404
+ default:
2405
+ return renderRuntimeIllustration();
2406
+ }
2407
+ }
2408
+ __name(renderIllustration, "renderIllustration");
2409
+ function renderFarmDocsSocialImageSvg(descriptor) {
2410
+ const titleLines = wrapText(descriptor.title, 22, 2);
2411
+ const longestTitleLine = Math.max(...titleLines.map((line) => line.length));
2412
+ const titleSize = titleLines.length === 1 ? longestTitleLine > 17 ? 62 : 74 : 56;
2413
+ const titleLineHeight = Math.round(titleSize * 0.98);
2414
+ const titleY = titleLines.length === 1 ? 294 : 266;
2415
+ const descriptionY = titleY + (titleLines.length - 1) * titleLineHeight + 59;
2416
+ const descriptionLines = wrapText(descriptor.description, 68, 2);
2417
+ const routeY = Math.max(418, descriptionY + descriptionLines.length * 29 + 24);
2418
+ const section = truncate(descriptor.section.toUpperCase(), 27);
2419
+ const route = truncate(descriptor.pageHref, 42);
2420
+ const footerUrl = truncate(descriptor.pageUrl.replace(/^https?:\/\//, ""), 70);
2421
+ const brand = truncate(descriptor.brand.toUpperCase(), 25);
2422
+ const titleId = `farm-docs-og-${descriptor.hash}`;
2423
+ return `<?xml version="1.0" encoding="UTF-8"?>
2424
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${FARM_DOCS_SOCIAL_IMAGE_WIDTH}" height="${FARM_DOCS_SOCIAL_IMAGE_HEIGHT}" viewBox="0 0 ${FARM_DOCS_SOCIAL_IMAGE_WIDTH} ${FARM_DOCS_SOCIAL_IMAGE_HEIGHT}" role="img" aria-labelledby="${titleId}-title ${titleId}-description">
2425
+ <title id="${titleId}-title">${escapeXml(descriptor.imageAlt)}</title>
2426
+ <desc id="${titleId}-description">${escapeXml(descriptor.description)}</desc>
2427
+ <metadata>${escapeXml(JSON.stringify({ generator: "Farm.js docs", page: descriptor.pageUrl, illustration: descriptor.illustration }))}</metadata>
2428
+ <style type="text/css">
2429
+ ${renderEmbeddedFont("Farm Sans", descriptor.fonts?.sans, "100 900")}
2430
+ ${renderEmbeddedFont("Farm Mono", descriptor.fonts?.mono, "100 900")}
2431
+ ${renderEmbeddedFont("Farm Pixel", descriptor.fonts?.display, "400 700")}
2432
+ .sans{font-family:"Farm Sans","Arial",sans-serif}.mono,.label,.code,.diagram-title,.micro{font-family:"Farm Mono","Menlo","DejaVu Sans Mono",monospace}.pixel{font-family:"Farm Pixel","Farm Mono",monospace}.label{fill:#8b8b8b;font-size:10px;font-weight:600;letter-spacing:1.2px}.code{fill:#8b8b8b;font-size:11px}.diagram-title{fill:#e7e7e7;font-size:11px;font-weight:650}.micro{fill:#777;font-size:8px;letter-spacing:.45px}.bright{fill:#f5f5f4}.ink{fill:#050505}.ink-muted{fill:#4c4c4c}
2433
+ </style>
2434
+ <defs>
2435
+ <pattern id="canvas-grid" width="40" height="40" patternUnits="userSpaceOnUse"><path d="M40 0H0V40" fill="none" stroke="#151515"/></pattern>
2436
+ <pattern id="diagonal" width="12" height="12" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="12" stroke="#171717" stroke-width="2"/></pattern>
2437
+ <clipPath id="frame-clip"><rect x="28" y="28" width="1144" height="574"/></clipPath>
2438
+ </defs>
2439
+ <rect width="1200" height="630" fill="#050505"/>
2440
+ <rect width="1200" height="630" fill="url(#canvas-grid)"/>
2441
+ <g clip-path="url(#frame-clip)">
2442
+ <rect x="28" y="28" width="1144" height="574" fill="#020202"/>
2443
+ <rect x="782" y="114" width="390" height="411" fill="url(#diagonal)"/>
2444
+ </g>
2445
+ <rect x="28.5" y="28.5" width="1143" height="573" fill="none" stroke="#323232"/>
2446
+ <path d="M28 114.5h1144M28 525.5h1144M781.5 114v411" fill="none" stroke="#303030"/>
2447
+
2448
+ <g transform="translate(71 51)">
2449
+ <rect width="11" height="11" rx="1" fill="#f5f5f4"/><rect x="15" width="28" height="11" rx="1" fill="#f5f5f4"/>
2450
+ <rect y="15" width="11" height="11" rx="1" fill="#9b9b9b"/><rect x="15" y="15" width="28" height="11" rx="1" fill="#9b9b9b"/>
2451
+ <rect y="30" width="11" height="11" rx="1" fill="#5f5f5f"/><rect x="15" y="30" width="20" height="11" rx="1" fill="#5f5f5f"/>
2452
+ <text x="61" y="24" class="mono bright" font-size="24" font-weight="550">FARM<tspan fill="#777">.JS</tspan></text>
2453
+ <text x="61" y="43" class="label">BY FARMING LABS</text>
2454
+ </g>
2455
+ <text x="1134" y="72" class="label" text-anchor="end">${escapeXml(brand)} \xB7 DOCUMENTATION</text>
2456
+
2457
+ <text x="71" y="198" class="mono bright" font-size="13" font-weight="650">DOCS</text>
2458
+ <line x1="117" y1="193" x2="155" y2="193" stroke="#696969"/>
2459
+ <text x="166" y="198" class="mono" fill="#9b9b9b" font-size="13">${escapeXml(section)}</text>
2460
+ ${renderTextLines(titleLines, 71, titleY, titleLineHeight, `class="pixel bright" font-size="${titleSize}" font-weight="500" letter-spacing="-2.4"`)}
2461
+ ${renderTextLines(descriptionLines, 71, descriptionY, 29, 'class="sans" fill="#a3a3a3" font-size="20" font-weight="430" letter-spacing="-.3"')}
2462
+ <rect x="71" y="${routeY}" width="${Math.min(390, 56 + route.length * 8)}" height="36" fill="#050505" stroke="#3c3c3c"/>
2463
+ <text x="85" y="${routeY + 23}" class="mono bright" font-size="11" font-weight="600">GET</text>
2464
+ <text x="119" y="${routeY + 23}" class="mono" fill="#898989" font-size="11">${escapeXml(route)}</text>
2465
+
2466
+ ${renderIllustration(descriptor.illustration)}
2467
+
2468
+ <text x="71" y="570" class="mono bright" font-size="13" font-weight="550">${escapeXml(footerUrl)}</text>
2469
+ <text x="1134" y="570" class="mono" fill="#9b9b9b" font-size="12" text-anchor="end">FARM.JS DOCUMENTATION</text>
2470
+ <path d="M20 20h10M20 20v10M1180 20h-10M1180 20v10M20 610h10M20 610v-10M1180 610h-10M1180 610v-10" fill="none" stroke="#9b9b9b"/>
2471
+ </svg>`;
2472
+ }
2473
+ __name(renderFarmDocsSocialImageSvg, "renderFarmDocsSocialImageSvg");
2474
+ function renderFarmDocsSocialMetadata(descriptor, customImage) {
2475
+ const imageUrl = customImage ? new URL(customImage, descriptor.pageUrl).href : descriptor.imageUrl;
2476
+ const customExtension = customImage?.toLowerCase().split(/[?#]/, 1)[0];
2477
+ const imageType = customExtension?.endsWith(".webp") ? "image/webp" : customExtension?.endsWith(".png") ? "image/png" : customExtension?.match(/\.jpe?g$/) ? "image/jpeg" : "image/svg+xml";
2478
+ const tag = /* @__PURE__ */ __name((property, content, name = false) => `<meta ${name ? "name" : "property"}="${property}" content="${escapeXml(content)}">`, "tag");
2479
+ return [
2480
+ tag("og:type", "article"),
2481
+ tag("og:site_name", descriptor.siteName),
2482
+ tag("og:title", descriptor.title),
2483
+ tag("og:description", descriptor.description),
2484
+ tag("og:url", descriptor.pageUrl),
2485
+ tag("og:image", imageUrl),
2486
+ tag("og:image:type", imageType),
2487
+ ...customImage ? [] : [
2488
+ tag("og:image:width", String(FARM_DOCS_SOCIAL_IMAGE_WIDTH)),
2489
+ tag("og:image:height", String(FARM_DOCS_SOCIAL_IMAGE_HEIGHT))
2490
+ ],
2491
+ tag("og:image:alt", descriptor.imageAlt),
2492
+ tag("twitter:card", "summary_large_image", true),
2493
+ tag("twitter:title", descriptor.title, true),
2494
+ tag("twitter:description", descriptor.description, true),
2495
+ tag("twitter:image", imageUrl, true),
2496
+ tag("twitter:image:alt", descriptor.imageAlt, true)
2497
+ ].join("\n ");
2498
+ }
2499
+ __name(renderFarmDocsSocialMetadata, "renderFarmDocsSocialMetadata");
2500
+
2085
2501
  // src/docs/handler.ts
2086
2502
  var DOCS_FILE_NAMES = ["page.mdx", "page.md", "index.mdx", "index.md"];
2087
2503
  var DOCS_FILE_EXTENSIONS2 = [".mdx", ".md"];
2088
2504
  var FARM_DOCS_FALLBACK_FAVICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='black'/%3E%3Cpath d='M7 8h18v3H10v5h12v3H10v5H7z' fill='white'/%3E%3C/svg%3E";
2089
2505
  var FARM_DOCS_FAVICON_FILES = ["favicon.svg", "favicon.ico", "favicon.png"];
2090
- var GEIST_SANS_FONT_URL = "/assets/Geist-Variable-CrgPqtmy.woff2";
2091
- var GEIST_MONO_FONT_URL = "/assets/GeistMono-Variable-BNLlm6Cd.woff2";
2092
2506
  function trimSlashes(value) {
2093
2507
  return value.replace(/^\/+|\/+$/g, "");
2094
2508
  }
2095
2509
  __name(trimSlashes, "trimSlashes");
2096
- function normalizeEntry(entry) {
2510
+ function normalizeEntry2(entry) {
2097
2511
  if (!entry || entry === "/") return "/";
2098
2512
  return `/${trimSlashes(entry)}`;
2099
2513
  }
2100
- __name(normalizeEntry, "normalizeEntry");
2514
+ __name(normalizeEntry2, "normalizeEntry");
2101
2515
  function normalizeSlug(value) {
2102
2516
  return trimSlashes(decodeURIComponent(value)).replace(/\.(mdx?|markdown)$/i, "");
2103
2517
  }
@@ -2107,10 +2521,10 @@ function resolveFarmDocsFavicon(docs, options) {
2107
2521
  if (typeof configuredFavicon === "string" && configuredFavicon.trim()) {
2108
2522
  return configuredFavicon.trim();
2109
2523
  }
2110
- const publicDir = import_node_path3.default.join(import_node_path3.default.resolve(options.root), "public");
2524
+ const publicDir = import_node_path4.default.join(import_node_path4.default.resolve(options.root), "public");
2111
2525
  for (const fileName of FARM_DOCS_FAVICON_FILES) {
2112
- const faviconPath = import_node_path3.default.join(publicDir, fileName);
2113
- if ((0, import_node_fs3.existsSync)(faviconPath) && (0, import_node_fs3.statSync)(faviconPath).isFile()) {
2526
+ const faviconPath = import_node_path4.default.join(publicDir, fileName);
2527
+ if ((0, import_node_fs4.existsSync)(faviconPath) && (0, import_node_fs4.statSync)(faviconPath).isFile()) {
2114
2528
  return `/${fileName}`;
2115
2529
  }
2116
2530
  }
@@ -2149,10 +2563,10 @@ function isSafeSegment(segment) {
2149
2563
  }
2150
2564
  __name(isSafeSegment, "isSafeSegment");
2151
2565
  function resolveInside(root, target) {
2152
- const resolvedRoot = import_node_path3.default.resolve(root);
2153
- const resolvedTarget = import_node_path3.default.resolve(target);
2154
- const relative = import_node_path3.default.relative(resolvedRoot, resolvedTarget);
2155
- if (relative === "" || !relative.startsWith("..") && !import_node_path3.default.isAbsolute(relative)) {
2566
+ const resolvedRoot = import_node_path4.default.resolve(root);
2567
+ const resolvedTarget = import_node_path4.default.resolve(target);
2568
+ const relative = import_node_path4.default.relative(resolvedRoot, resolvedTarget);
2569
+ if (relative === "" || !relative.startsWith("..") && !import_node_path4.default.isAbsolute(relative)) {
2156
2570
  return resolvedTarget;
2157
2571
  }
2158
2572
  return null;
@@ -2162,40 +2576,40 @@ function isFarmDocsRequest(docs, request) {
2162
2576
  if (!docs?.enabled) return false;
2163
2577
  if (request.method !== "GET" && request.method !== "HEAD") return false;
2164
2578
  const pathname = new URL(request.url).pathname;
2165
- const entry = normalizeEntry(docs.entry);
2579
+ const entry = normalizeEntry2(docs.entry);
2166
2580
  if (entry === "/") return true;
2167
2581
  return pathname === entry || pathname === `${entry}.md` || pathname.startsWith(`${entry}/`);
2168
2582
  }
2169
2583
  __name(isFarmDocsRequest, "isFarmDocsRequest");
2170
2584
  function resolveFarmDocsContentDir(docs, options) {
2171
- const root = import_node_path3.default.resolve(options.root);
2585
+ const root = import_node_path4.default.resolve(options.root);
2172
2586
  const srcDir = options.srcDir || "src";
2173
2587
  const configuredContentDir = docs.contentDir || docs.config.contentDir;
2174
2588
  if (configuredContentDir) {
2175
- return import_node_path3.default.isAbsolute(configuredContentDir) ? configuredContentDir : import_node_path3.default.join(root, configuredContentDir);
2589
+ return import_node_path4.default.isAbsolute(configuredContentDir) ? configuredContentDir : import_node_path4.default.join(root, configuredContentDir);
2176
2590
  }
2177
2591
  const entryDir = docs.config.entry || trimSlashes(docs.entry) || "docs";
2178
- const appDocsDir = import_node_path3.default.join(root, srcDir, "app", entryDir);
2179
- if ((0, import_node_fs3.existsSync)(appDocsDir)) return appDocsDir;
2180
- return import_node_path3.default.join(root, entryDir);
2592
+ const appDocsDir = import_node_path4.default.join(root, srcDir, "app", entryDir);
2593
+ if ((0, import_node_fs4.existsSync)(appDocsDir)) return appDocsDir;
2594
+ return import_node_path4.default.join(root, entryDir);
2181
2595
  }
2182
2596
  __name(resolveFarmDocsContentDir, "resolveFarmDocsContentDir");
2183
2597
  function getFarmDocsRouteTypeEntries(docs) {
2184
2598
  if (!docs?.enabled) return [];
2185
- const entry = normalizeEntry(docs.entry);
2599
+ const entry = normalizeEntry2(docs.entry);
2186
2600
  if (entry === "/") return ["/", "/[...docs]"];
2187
2601
  return [entry, `${entry}/[...docs]`];
2188
2602
  }
2189
2603
  __name(getFarmDocsRouteTypeEntries, "getFarmDocsRouteTypeEntries");
2190
2604
  function getFarmDocsDocumentNavigationMatchers(docs) {
2191
2605
  if (!docs?.enabled) return [];
2192
- const entry = normalizeEntry(docs.entry);
2606
+ const entry = normalizeEntry2(docs.entry);
2193
2607
  return [entry === "/" ? "/(.*)" : `${entry}(.*)`];
2194
2608
  }
2195
2609
  __name(getFarmDocsDocumentNavigationMatchers, "getFarmDocsDocumentNavigationMatchers");
2196
2610
  function getRequestSlug(docs, request) {
2197
2611
  const pathname = new URL(request.url).pathname;
2198
- const entry = normalizeEntry(docs.entry);
2612
+ const entry = normalizeEntry2(docs.entry);
2199
2613
  if (entry === "/") return normalizeSlug(pathname);
2200
2614
  if (pathname === entry || pathname === `${entry}.md`) return "";
2201
2615
  return normalizeSlug(pathname.slice(entry.length));
@@ -2204,14 +2618,14 @@ __name(getRequestSlug, "getRequestSlug");
2204
2618
  function findDocsPageFile(contentDir, slug) {
2205
2619
  const segments = slug ? slug.split("/").filter(Boolean) : [];
2206
2620
  if (!segments.every(isSafeSegment)) return null;
2207
- const slugDir = import_node_path3.default.join(contentDir, ...segments);
2208
- const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) => import_node_path3.default.join(contentDir, filename)) : [
2209
- ...DOCS_FILE_NAMES.map((filename) => import_node_path3.default.join(slugDir, filename)),
2210
- ...DOCS_FILE_EXTENSIONS2.map((extension) => import_node_path3.default.join(contentDir, `${slug}${extension}`))
2621
+ const slugDir = import_node_path4.default.join(contentDir, ...segments);
2622
+ const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) => import_node_path4.default.join(contentDir, filename)) : [
2623
+ ...DOCS_FILE_NAMES.map((filename) => import_node_path4.default.join(slugDir, filename)),
2624
+ ...DOCS_FILE_EXTENSIONS2.map((extension) => import_node_path4.default.join(contentDir, `${slug}${extension}`))
2211
2625
  ];
2212
2626
  for (const candidate of candidates) {
2213
2627
  const safePath = resolveInside(contentDir, candidate);
2214
- if (safePath && (0, import_node_fs3.existsSync)(safePath) && (0, import_node_fs3.statSync)(safePath).isFile()) {
2628
+ if (safePath && (0, import_node_fs4.existsSync)(safePath) && (0, import_node_fs4.statSync)(safePath).isFile()) {
2215
2629
  return safePath;
2216
2630
  }
2217
2631
  }
@@ -2250,7 +2664,7 @@ __name(titleFromMarkdown, "titleFromMarkdown");
2250
2664
  function loadFarmDocsPage(contentDir, docs, slug) {
2251
2665
  const sourcePath = findDocsPageFile(contentDir, slug);
2252
2666
  if (!sourcePath) return null;
2253
- const source = (0, import_node_fs3.readFileSync)(sourcePath, "utf8");
2667
+ const source = (0, import_node_fs4.readFileSync)(sourcePath, "utf8");
2254
2668
  const { frontmatter, body } = parseFrontmatter(source);
2255
2669
  const title = frontmatter.title || titleFromMarkdown(body, titleFromSlug(slug));
2256
2670
  const href = createDocsHref(docs.entry, slug);
@@ -2258,6 +2672,7 @@ function loadFarmDocsPage(contentDir, docs, slug) {
2258
2672
  slug,
2259
2673
  title,
2260
2674
  description: frontmatter.description,
2675
+ section: frontmatter.section,
2261
2676
  href,
2262
2677
  sourcePath,
2263
2678
  lastModified: resolveFarmDocsPageLastModified(contentDir, sourcePath, frontmatter),
@@ -2267,16 +2682,16 @@ function loadFarmDocsPage(contentDir, docs, slug) {
2267
2682
  }
2268
2683
  __name(loadFarmDocsPage, "loadFarmDocsPage");
2269
2684
  function createDocsHref(entry, slug) {
2270
- const normalizedEntry = normalizeEntry(entry);
2685
+ const normalizedEntry = normalizeEntry2(entry);
2271
2686
  const normalizedSlug = trimSlashes(slug);
2272
2687
  if (normalizedEntry === "/") return normalizedSlug ? `/${normalizedSlug}` : "/";
2273
2688
  return normalizedSlug ? `${normalizedEntry}/${normalizedSlug}` : normalizedEntry;
2274
2689
  }
2275
2690
  __name(createDocsHref, "createDocsHref");
2276
2691
  function pathToSlug(contentDir, filePath) {
2277
- const relative = import_node_path3.default.relative(contentDir, filePath).replace(/\\/g, "/");
2692
+ const relative = import_node_path4.default.relative(contentDir, filePath).replace(/\\/g, "/");
2278
2693
  if (relative.startsWith("..")) return null;
2279
- const extension = import_node_path3.default.extname(relative);
2694
+ const extension = import_node_path4.default.extname(relative);
2280
2695
  if (!DOCS_FILE_EXTENSIONS2.includes(extension)) return null;
2281
2696
  const withoutExtension = relative.slice(0, -extension.length);
2282
2697
  if (withoutExtension === "page" || withoutExtension === "index") return "";
@@ -2291,12 +2706,12 @@ function loadPage(contentDir, docs, request) {
2291
2706
  }
2292
2707
  __name(loadPage, "loadPage");
2293
2708
  function discoverFarmDocsPages(contentDir, docs) {
2294
- if (!(0, import_node_fs3.existsSync)(contentDir)) return [];
2709
+ if (!(0, import_node_fs4.existsSync)(contentDir)) return [];
2295
2710
  const pages = [];
2296
2711
  const visit = /* @__PURE__ */ __name((dir) => {
2297
- for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
2712
+ for (const entry of (0, import_node_fs4.readdirSync)(dir, { withFileTypes: true })) {
2298
2713
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
2299
- const absolutePath = import_node_path3.default.join(dir, entry.name);
2714
+ const absolutePath = import_node_path4.default.join(dir, entry.name);
2300
2715
  if (entry.isDirectory()) {
2301
2716
  visit(absolutePath);
2302
2717
  continue;
@@ -2304,7 +2719,7 @@ function discoverFarmDocsPages(contentDir, docs) {
2304
2719
  if (!entry.isFile()) continue;
2305
2720
  const slug = pathToSlug(contentDir, absolutePath);
2306
2721
  if (slug === null) continue;
2307
- const source = (0, import_node_fs3.readFileSync)(absolutePath, "utf8");
2722
+ const source = (0, import_node_fs4.readFileSync)(absolutePath, "utf8");
2308
2723
  const { frontmatter, body } = parseFrontmatter(source);
2309
2724
  pages.push({
2310
2725
  slug,
@@ -3238,7 +3653,7 @@ function renderPixelBreadcrumb(page, docs) {
3238
3653
  const parentSegments = segments.slice(0, -1);
3239
3654
  const parentSegment = parentSegments[parentSegments.length - 1];
3240
3655
  const currentSegment = segments[segments.length - 1];
3241
- const entry = normalizeEntry(docs.entry);
3656
+ const entry = normalizeEntry2(docs.entry);
3242
3657
  const parentPath = parentSegments.join("/");
3243
3658
  const parentHref = entry === "/" ? `/${parentPath}` : `${entry}/${parentPath}`;
3244
3659
  return `<nav class="fd-breadcrumb" aria-label="Breadcrumb">
@@ -3281,7 +3696,7 @@ ${items.map(
3281
3696
  }
3282
3697
  __name(renderPixelToc, "renderPixelToc");
3283
3698
  function renderDocsRuntimeScript(docs) {
3284
- const docsEntry = JSON.stringify(normalizeEntry(docs.entry));
3699
+ const docsEntry = JSON.stringify(normalizeEntry2(docs.entry));
3285
3700
  return `<script>(()=>{if(window.__farmDocsRuntime)return;window.__farmDocsRuntime=true;document.documentElement.dataset.farmDocsRuntime="true";document.documentElement.dataset.farmDocsRuntimeId=Math.random().toString(36).slice(2);const docsEntry=${docsEntry};let cleanupToc=()=>{};let closeMobileSidebar=()=>{};const normalizePath=(path)=>path.length>1?path.replace(/\\/+$/,""):path;const isDocsPath=(path)=>{const next=normalizePath(path);const entry=normalizePath(docsEntry);if(next.endsWith(".md"))return false;if(entry==="/")return true;return next===entry||next.startsWith(entry+"/")};const initToc=()=>{cleanupToc();const toc=document.getElementById("nd-toc");if(!toc){cleanupToc=()=>{};return}const links=Array.from(toc.querySelectorAll("[data-toc-item]"));const thumb=toc.querySelector("[data-toc-thumb]");const pairs=links.map((link)=>{let id=link.hash.slice(1);try{id=decodeURIComponent(id)}catch{}return{link,heading:document.getElementById(id)}}).filter((item)=>item.heading);const setActive=(active)=>{for(const {link} of pairs)link.dataset.active=link===active.link?"true":"false";if(!thumb)return;const styles=getComputedStyle(active.link);const top=active.link.offsetTop+parseFloat(styles.paddingTop||"0");const bottom=active.link.offsetTop+active.link.clientHeight-parseFloat(styles.paddingBottom||"0");thumb.style.clipPath="polygon(0 "+top+"px,100% "+top+"px,100% "+bottom+"px,0 "+bottom+"px)"};const update=()=>{if(pairs.length===0)return;const offset=Math.min(window.innerHeight*0.3,160);let active=pairs[0];for(const pair of pairs){if(pair.heading.getBoundingClientRect().top<=offset)active=pair;else break}setActive(active)};let frame=0;const schedule=()=>{if(frame)return;frame=requestAnimationFrame(()=>{frame=0;update()})};const onHashChange=()=>setTimeout(schedule,0);window.addEventListener("scroll",schedule,{passive:true});window.addEventListener("resize",schedule);window.addEventListener("hashchange",onHashChange);cleanupToc=()=>{window.removeEventListener("scroll",schedule);window.removeEventListener("resize",schedule);window.removeEventListener("hashchange",onHashChange);if(frame)cancelAnimationFrame(frame);frame=0};update()};const getSidebar=()=>document.getElementById("nd-sidebar");const ensureActiveVisible=()=>{const sidebar=getSidebar();if(!sidebar)return;const active=sidebar.querySelector('a[data-active="true"]');if(!(active instanceof HTMLElement))return;const activeRect=active.getBoundingClientRect();const sidebarRect=sidebar.getBoundingClientRect();if(activeRect.top<sidebarRect.top||activeRect.bottom>sidebarRect.bottom)sidebar.scrollTop+=activeRect.top-sidebarRect.top-(sidebar.clientHeight-activeRect.height)/2};const setSidebarActive=(path)=>{const sidebar=getSidebar();if(!sidebar)return;const current=normalizePath(path);for(const link of Array.from(sidebar.querySelectorAll("a[href]"))){try{link.dataset.active=normalizePath(new URL(link.href,location.href).pathname)===current?"true":"false"}catch{}}ensureActiveVisible()};const initMobileSidebar=()=>{const layout=document.getElementById("nd-docs-layout");const sidebar=getSidebar();const toggle=document.querySelector("[data-sidebar-toggle]");const backdrop=document.querySelector("[data-sidebar-backdrop]");if(!layout||!sidebar||!(toggle instanceof HTMLButtonElement))return;const setOpen=(open)=>{layout.dataset.sidebarOpen=open?"true":"false";document.documentElement.dataset.farmDocsSidebar=open?"open":"closed";toggle.setAttribute("aria-expanded",open?"true":"false");toggle.setAttribute("aria-label",open?"Close menu":"Open menu")};const toggleOpen=()=>setOpen(layout.dataset.sidebarOpen!=="true");closeMobileSidebar=()=>setOpen(false);toggle.addEventListener("click",(event)=>{event.preventDefault();toggleOpen()});backdrop?.addEventListener("click",()=>closeMobileSidebar());document.addEventListener("keydown",(event)=>{if(event.key==="Escape")closeMobileSidebar()});sidebar.addEventListener("click",(event)=>{const target=event.target instanceof Element?event.target.closest("a[href]"):null;if(target)closeMobileSidebar()});closeMobileSidebar()};const initSidebarScroll=()=>{const sidebar=getSidebar();if(!sidebar)return;const key="farmdocs:sidebar-scroll:"+location.origin;const getStorage=()=>{try{return window.sessionStorage}catch{return null}};const readSaved=()=>{try{const raw=getStorage()?.getItem(key);if(!raw)return null;const parsed=JSON.parse(raw);return parsed&&typeof parsed==="object"?parsed:null}catch{return null}};const save=(path=location.pathname)=>{try{getStorage()?.setItem(key,JSON.stringify({path,scrollTop:sidebar.scrollTop}))}catch{}};const saved=readSaved();if(saved?.path===location.pathname&&Number.isFinite(Number(saved.scrollTop)))sidebar.scrollTop=Number(saved.scrollTop);ensureActiveVisible();save();sidebar.addEventListener("scroll",()=>save(),{passive:true});sidebar.addEventListener("click",(event)=>{const target=event.target instanceof Element?event.target.closest("a[href]"):null;if(!target)return;try{save(new URL(target.href,location.href).pathname)}catch{save()}});window.addEventListener("beforeunload",()=>save())};let navigateController=null;const getPageKey=(root)=>{const article=root.getElementById("nd-page");if(!article)return"";return article.querySelector("h1")?.textContent?.trim()||article.textContent?.replace(/\\s+/g," ").trim().slice(0,160)||""};const swapDocsPage=(html,url)=>{const nextDoc=new DOMParser().parseFromString(html,"text/html");const nextArticle=nextDoc.getElementById("nd-page");const currentArticle=document.getElementById("nd-page");if(!nextArticle||!currentArticle)return false;const nextKey=getPageKey(nextDoc);const importedArticle=document.importNode(nextArticle,true);currentArticle.replaceWith(importedArticle);const renderedArticle=document.getElementById("nd-page");if(!renderedArticle||renderedArticle===currentArticle||(nextKey&&getPageKey(document)!==nextKey))return false;const nextToc=nextDoc.getElementById("nd-toc");const currentToc=document.getElementById("nd-toc");if(nextToc&&currentToc)currentToc.replaceWith(document.importNode(nextToc,true));if(nextDoc.title)document.title=nextDoc.title;const nextDescription=nextDoc.querySelector('meta[name="description"]');const currentDescription=document.querySelector('meta[name="description"]');if(nextDescription&&currentDescription)currentDescription.setAttribute("content",nextDescription.getAttribute("content")||"");setSidebarActive(url.pathname);initToc();closeMobileSidebar();return true};const navigateDocs=async(url,{replace=false,scroll=true}={})=>{if(!isDocsPath(url.pathname))return false;if(navigateController)navigateController.abort();const controller=new AbortController();navigateController=controller;document.documentElement.dataset.farmDocsNavigating="true";try{const response=await fetch(url.href,{cache:"no-store",headers:{accept:"text/html","x-farm-docs-navigate":"1"},signal:controller.signal});if(!response.ok||!((response.headers.get("content-type")||"").includes("text/html")))return false;const html=await response.text();if(!swapDocsPage(html,url))return false;if(replace)history.replaceState({farmDocs:true},"",url.href);else history.pushState({farmDocs:true},"",url.href);if(scroll){if(url.hash){let id=url.hash.slice(1);try{id=decodeURIComponent(id)}catch{}document.getElementById(id)?.scrollIntoView({block:"start"})}else window.scrollTo({top:0,left:0})}return true}catch(error){if(error?.name==="AbortError")return true;return false}finally{if(navigateController===controller){delete document.documentElement.dataset.farmDocsNavigating;navigateController=null}}};const initClientNavigation=()=>{document.addEventListener("click",(event)=>{if(event.defaultPrevented||event.button!==0||event.metaKey||event.ctrlKey||event.shiftKey||event.altKey)return;const target=event.target instanceof Element?event.target.closest("a[href]"):null;if(!target||target.target||target.hasAttribute("download"))return;let url;try{url=new URL(target.href,location.href)}catch{return}if(url.origin!==location.origin||!isDocsPath(url.pathname))return;if(normalizePath(url.pathname)===normalizePath(location.pathname)&&url.hash)return;event.preventDefault();navigateDocs(url).then((handled)=>{if(!handled)location.href=url.href})});window.addEventListener("popstate",()=>{navigateDocs(new URL(location.href),{replace:true,scroll:false}).then((handled)=>{if(!handled)location.reload()})})};const init=()=>{initToc();initMobileSidebar();initSidebarScroll();initClientNavigation()};if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",init,{once:true});else init()})();</script>`;
3286
3701
  }
3287
3702
  __name(renderDocsRuntimeScript, "renderDocsRuntimeScript");
@@ -3301,13 +3716,13 @@ ${renderDocsPageActionsRuntimeScript()}`;
3301
3716
  __name(renderDocsRuntimeScripts, "renderDocsRuntimeScripts");
3302
3717
  var themeCssCache = /* @__PURE__ */ new Map();
3303
3718
  function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
3304
- const resolved = import_node_path3.default.resolve(filePath);
3719
+ const resolved = import_node_path4.default.resolve(filePath);
3305
3720
  if (seen.has(resolved)) return "";
3306
3721
  seen.add(resolved);
3307
- const source = (0, import_node_fs3.readFileSync)(resolved, "utf8");
3722
+ const source = (0, import_node_fs4.readFileSync)(resolved, "utf8");
3308
3723
  return source.replace(/@import\s+["']([^"']+)["'];?/g, (_match, importPath) => {
3309
3724
  try {
3310
- const importedPath = importPath.startsWith(".") ? import_node_path3.default.resolve(import_node_path3.default.dirname(resolved), importPath) : (0, import_node_module2.createRequire)(resolved).resolve(importPath);
3725
+ const importedPath = importPath.startsWith(".") ? import_node_path4.default.resolve(import_node_path4.default.dirname(resolved), importPath) : (0, import_node_module2.createRequire)(resolved).resolve(importPath);
3311
3726
  return readCssWithImports(importedPath, seen);
3312
3727
  } catch {
3313
3728
  return "";
@@ -3316,11 +3731,11 @@ function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
3316
3731
  }
3317
3732
  __name(readCssWithImports, "readCssWithImports");
3318
3733
  function resolvePixelBorderThemeCss(options) {
3319
- const cacheKey = import_node_path3.default.resolve(options.root);
3734
+ const cacheKey = import_node_path4.default.resolve(options.root);
3320
3735
  const cached = themeCssCache.get(cacheKey);
3321
3736
  if (cached !== void 0) return cached;
3322
3737
  try {
3323
- const requireFromApp = (0, import_node_module2.createRequire)(import_node_path3.default.join(cacheKey, "package.json"));
3738
+ const requireFromApp = (0, import_node_module2.createRequire)(import_node_path4.default.join(cacheKey, "package.json"));
3324
3739
  const themeCssPath = requireFromApp.resolve("@farming-labs/theme/pixel-border/css");
3325
3740
  const requireFromTheme = (0, import_node_module2.createRequire)(themeCssPath);
3326
3741
  const fumadocsCssPath = requireFromTheme.resolve("fumadocs-ui/style.css");
@@ -3334,17 +3749,28 @@ ${readCssWithImports(themeCssPath)}`;
3334
3749
  }
3335
3750
  }
3336
3751
  __name(resolvePixelBorderThemeCss, "resolvePixelBorderThemeCss");
3337
- function renderFarmDocsBridgeCss(docs) {
3752
+ function renderFarmDocsBridgeCss(docs, fontAssets, layoutFonts) {
3338
3753
  const sidebarWidth = getThemeLayoutValue(docs, "sidebarWidth", 320);
3339
3754
  const contentWidth = getThemeLayoutValue(docs, "contentWidth", 860);
3755
+ const fontFaces = fontAssets.map(
3756
+ ({ family, url }) => `@font-face { font-family: "${family}"; src: url("${url}") format("woff2"); font-style: normal; font-weight: 100 900; font-display: block; }`
3757
+ ).join("\n");
3758
+ const fontVariables = [
3759
+ fontAssets.some(({ family }) => family === "Geist Sans") ? '--font-geist-sans: "Geist Sans", ui-sans-serif, system-ui, sans-serif;' : "",
3760
+ fontAssets.some(({ family }) => family === "Geist Mono") ? '--font-geist-mono: "Geist Mono", ui-monospace, monospace;' : ""
3761
+ ].filter(Boolean).join(" ");
3762
+ const fontCss = fontFaces ? `${fontFaces}
3763
+ :root { ${fontVariables} }` : "";
3764
+ const layoutFontVariables = [
3765
+ renderFarmDocsLayoutFontVariable("--fd-layout-font-body", layoutFonts?.body),
3766
+ renderFarmDocsLayoutFontVariable("--fd-layout-font-code", layoutFonts?.code)
3767
+ ].filter(Boolean).join(" ");
3340
3768
  return `
3341
- @font-face { font-family: "Geist Sans"; src: local("Geist Sans"), url("${GEIST_SANS_FONT_URL}") format("woff2"), url("/node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2") format("woff2"); font-display: block; font-style: normal; font-weight: 100 900; }
3342
- @font-face { font-family: "Geist Mono"; src: local("Geist Mono"), url("${GEIST_MONO_FONT_URL}") format("woff2"), url("/node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2") format("woff2"); font-display: block; font-style: normal; font-weight: 100 900; }
3343
- :root { color-scheme: dark; --font-geist-sans: "Geist Sans"; --font-geist-mono: "Geist Mono"; --fd-sidebar-width: ${sidebarWidth}px; --fd-content-width: ${contentWidth}px; --fd-toc-width: 240px; --fd-docs-height: 100vh; --fd-docs-row-1: var(--fd-nav-height, 44px); --fd-docs-font-sans: var(--font-geist-sans, "Geist Sans", var(--font-sans, system-ui, -apple-system, sans-serif)); --fd-docs-font-mono: var(--font-geist-mono, "Geist Mono", var(--font-mono, ui-monospace, monospace)); --fd-font-sans: var(--fd-docs-font-sans); --fd-font-mono: var(--fd-docs-font-mono); --fd-pixel-rail-width: 12px; --fd-sidebar-edge: calc(var(--fd-pixel-rail-width) + 18px); --fd-sidebar-guide-x: calc(var(--fd-sidebar-edge) + 16px); --fd-sidebar-link-x: calc(var(--fd-sidebar-guide-x) + 22px); --fd-sidebar-sub-guide-x: calc(var(--fd-sidebar-link-x) + 7px); --fd-sidebar-sub-link-x: calc(var(--fd-sidebar-sub-guide-x) + 28px); --fd-sidebar-branch-gap: 0px; --fd-sidebar-nested-icon-gap: 0px; --fd-sidebar-line-color: color-mix(in srgb, var(--color-fd-border, hsl(0 0% 15%)) 88%, transparent); }
3769
+ :root { color-scheme: dark; --font-geist-sans: ui-sans-serif, system-ui, sans-serif; --font-geist-mono: ui-monospace, monospace; ${layoutFontVariables} --fd-sidebar-width: ${sidebarWidth}px; --fd-content-width: ${contentWidth}px; --fd-toc-width: 240px; --fd-docs-height: 100vh; --fd-docs-row-1: var(--fd-nav-height, 44px); --fd-docs-font-sans: var(--fd-layout-font-body, var(--font-geist-sans, var(--font-sans, system-ui, -apple-system, sans-serif))); --fd-docs-font-mono: var(--fd-layout-font-code, var(--font-geist-mono, var(--font-mono, ui-monospace, monospace))); --fd-font-sans: var(--fd-docs-font-sans); --fd-font-mono: var(--fd-docs-font-mono); --fd-pixel-rail-width: 12px; --fd-sidebar-edge: calc(var(--fd-pixel-rail-width) + 18px); --fd-sidebar-guide-x: calc(var(--fd-sidebar-edge) + 16px); --fd-sidebar-link-x: calc(var(--fd-sidebar-guide-x) + 22px); --fd-sidebar-sub-guide-x: calc(var(--fd-sidebar-link-x) + 7px); --fd-sidebar-sub-link-x: calc(var(--fd-sidebar-sub-guide-x) + 28px); --fd-sidebar-branch-gap: 0px; --fd-sidebar-nested-icon-gap: 0px; --fd-sidebar-line-color: color-mix(in srgb, var(--color-fd-border, hsl(0 0% 15%)) 88%, transparent); }
3344
3770
  * { box-sizing: border-box; }
3345
3771
  html { background: var(--color-fd-background, hsl(0 0% 2%)); scroll-padding-top: calc(var(--fd-nav-height, 44px) + 24px); }
3346
3772
  html[data-farm-docs-sidebar="open"], html[data-farm-docs-sidebar="open"] body { overflow: hidden; }
3347
- body { margin: 0; min-height: 100vh; background: var(--color-fd-background, hsl(0 0% 2%)); color: var(--color-fd-foreground, oklch(0.985 0.001 106.423)); font-family: var(--fd-docs-font-sans); text-rendering: optimizeLegibility; }
3773
+ body { margin: 0; min-height: 100vh; background: var(--color-fd-background, hsl(0 0% 2%)); color: var(--color-fd-foreground, oklch(0.985 0.001 106.423)); font-family: var(--fd-docs-font-sans); font-synthesis: none; text-rendering: optimizeLegibility; }
3348
3774
  ::selection { background: var(--color-fd-foreground, #fff); color: var(--color-fd-background, #000); }
3349
3775
  a { color: inherit; }
3350
3776
  #nd-docs-layout { --fd-sidebar-col: var(--fd-sidebar-width); display: grid; grid-template: "sidebar header header" var(--fd-nav-height, 44px) "sidebar main toc" 1fr / var(--fd-sidebar-width) minmax(0, 1fr) var(--fd-toc-width) !important; min-height: 100vh; border-top: 1px solid var(--color-fd-border, hsl(0 0% 15%)); background: var(--color-fd-background, hsl(0 0% 2%)); }
@@ -3524,15 +3950,51 @@ function renderFarmDocsBridgeCss(docs) {
3524
3950
  .sh__line { min-height: 1.6em; }
3525
3951
  }
3526
3952
  ${farmDocsPixelBorderCss}
3953
+ ${fontCss}
3527
3954
  `;
3528
3955
  }
3529
3956
  __name(renderFarmDocsBridgeCss, "renderFarmDocsBridgeCss");
3530
- function renderPixelDocsHtml(page, pages, docs, themeCss, clientEntry, faviconHref) {
3957
+ function renderFarmDocsLayoutFontVariable(name, font) {
3958
+ const family = font?.style.fontFamily;
3959
+ if (!family || /[;{}<>]/.test(family)) return "";
3960
+ return `${name}: ${family};`;
3961
+ }
3962
+ __name(renderFarmDocsLayoutFontVariable, "renderFarmDocsLayoutFontVariable");
3963
+ function renderFarmDocsFontPreloads(fontAssets) {
3964
+ return fontAssets.map(
3965
+ ({ url }) => `<link rel="preload" href="${escapeAttribute(url)}" as="font" type="font/woff2" crossorigin>`
3966
+ ).join("\n ");
3967
+ }
3968
+ __name(renderFarmDocsFontPreloads, "renderFarmDocsFontPreloads");
3969
+ function renderFarmDocsFontPreloadHeader(fontAssets) {
3970
+ return fontAssets.map(({ url }) => `<${url}>; rel=preload; as=font; type=font/woff2; crossorigin`).join(", ");
3971
+ }
3972
+ __name(renderFarmDocsFontPreloadHeader, "renderFarmDocsFontPreloadHeader");
3973
+ function getFarmLayoutFontPreloads(layoutFonts) {
3974
+ const seen = /* @__PURE__ */ new Set();
3975
+ return [layoutFonts?.body, layoutFonts?.code].flatMap(
3976
+ (font) => (font?.preloads || []).filter(({ href }) => {
3977
+ if (seen.has(href)) return false;
3978
+ seen.add(href);
3979
+ return true;
3980
+ })
3981
+ );
3982
+ }
3983
+ __name(getFarmLayoutFontPreloads, "getFarmLayoutFontPreloads");
3984
+ function renderFarmLayoutFontPreloadHeader(layoutFonts) {
3985
+ return getFarmLayoutFontPreloads(layoutFonts).map(({ href, type }) => `<${href}>; rel=preload; as=font; type=${type}; crossorigin`).join(", ");
3986
+ }
3987
+ __name(renderFarmLayoutFontPreloadHeader, "renderFarmLayoutFontPreloadHeader");
3988
+ function renderPixelDocsHtml(page, pages, docs, themeCss, clientEntry, faviconHref, requestUrl, fontAssets, layoutFonts, fontStylesheetHref) {
3531
3989
  const navTitle = typeof docs.config.nav === "object" && docs.config.nav && "title" in docs.config.nav ? String(docs.config.nav.title || "Docs") : "Docs";
3532
3990
  const description = page.description || docs.config.metadata?.description || "";
3533
3991
  const tocItems = extractTocItems(page.body, getThemeTocDepth(docs));
3534
3992
  const themeName = getThemeName(docs);
3535
3993
  const searchEnabled = isFarmDocsSearchEnabled(docs);
3994
+ const socialMetadata = isFarmDocsSocialImageEnabled(page, docs) ? renderFarmDocsSocialMetadata(
3995
+ createFarmDocsSocialImageDescriptor(page, docs, requestUrl),
3996
+ getFarmDocsCustomSocialImage(page)
3997
+ ) : "";
3536
3998
  return `<!DOCTYPE html>
3537
3999
  <html class="dark" lang="en" data-docs-theme="${escapeAttribute(themeName)}">
3538
4000
  <head>
@@ -3541,11 +4003,12 @@ function renderPixelDocsHtml(page, pages, docs, themeCss, clientEntry, faviconHr
3541
4003
  <meta name="generator" content="@farming-labs/docs via Farm.js">
3542
4004
  <title>${escapeHtml(page.title)}</title>
3543
4005
  ${renderFarmDocsFaviconLink(faviconHref)}
3544
- <link rel="preload" href="${GEIST_SANS_FONT_URL}" as="font" type="font/woff2" crossorigin>
3545
- <link rel="preload" href="${GEIST_MONO_FONT_URL}" as="font" type="font/woff2" crossorigin>
4006
+ ${renderFarmDocsFontPreloads(fontAssets)}
4007
+ ${fontStylesheetHref ? `<link rel="stylesheet" href="${escapeAttribute(fontStylesheetHref)}">` : ""}
3546
4008
  ${description ? `<meta name="description" content="${escapeHtml(description)}">` : ""}
4009
+ ${socialMetadata}
3547
4010
  <style>${themeCss}
3548
- ${renderFarmDocsBridgeCss(docs)}</style>
4011
+ ${renderFarmDocsBridgeCss(docs, fontAssets, layoutFonts)}</style>
3549
4012
  ${searchEnabled ? renderDocsSearchBootstrapScript() : ""}
3550
4013
  </head>
3551
4014
  <body>
@@ -3598,9 +4061,34 @@ ${renderMarkdownHtmlWithTitleMeta(page, docs)}
3598
4061
  __name(renderPixelDocsHtml, "renderPixelDocsHtml");
3599
4062
  function createFarmDocsHandler(docs, options) {
3600
4063
  const faviconHref = resolveFarmDocsFavicon(docs, options);
4064
+ const fontAssets = options.fontAssets ?? toFarmDocsPublicFontAssets(resolveFarmDocsFontAssets(options.root));
4065
+ const fallbackFontPreloadHeader = renderFarmDocsFontPreloadHeader(fontAssets);
3601
4066
  return /* @__PURE__ */ __name(async function handleFarmDocsRequest(request) {
3602
4067
  if (!docs?.enabled || request.method !== "GET" && request.method !== "HEAD") return null;
3603
4068
  const contentDir = resolveFarmDocsContentDir(docs, options);
4069
+ const requestUrl = new URL(request.url);
4070
+ const socialImageSlug = getFarmDocsSocialImageSlug(docs, requestUrl);
4071
+ if (socialImageSlug !== null) {
4072
+ const socialImagePage = loadFarmDocsPage(contentDir, docs, socialImageSlug);
4073
+ if (!socialImagePage || !isFarmDocsSocialImageEnabled(socialImagePage, docs) || getFarmDocsCustomSocialImage(socialImagePage)) {
4074
+ return null;
4075
+ }
4076
+ const descriptor = createFarmDocsSocialImageDescriptor(socialImagePage, docs, requestUrl);
4077
+ if (requestUrl.pathname !== descriptor.imagePath) return null;
4078
+ const etag = `"${descriptor.hash}"`;
4079
+ const immutable = requestUrl.searchParams.get("v") === descriptor.hash;
4080
+ const headers = new Headers({
4081
+ "Content-Type": "image/svg+xml; charset=utf-8",
4082
+ "Cache-Control": immutable ? "public, max-age=31536000, immutable" : "public, max-age=0, must-revalidate",
4083
+ ETag: etag,
4084
+ "X-Content-Type-Options": "nosniff"
4085
+ });
4086
+ if (request.headers.get("if-none-match") === etag) {
4087
+ return new Response(null, { status: 304, headers });
4088
+ }
4089
+ if (request.method === "HEAD") return new Response(null, { status: 200, headers });
4090
+ return new Response(renderFarmDocsSocialImageSvg(descriptor), { status: 200, headers });
4091
+ }
3604
4092
  const publicResponse = createFarmDocsPublicResponse(contentDir, docs, request);
3605
4093
  if (publicResponse) return publicResponse;
3606
4094
  if (!isFarmDocsRequest(docs, request)) return null;
@@ -3623,6 +4111,11 @@ function createFarmDocsHandler(docs, options) {
3623
4111
  }
3624
4112
  );
3625
4113
  }
4114
+ const pathname = new URL(request.url).pathname;
4115
+ const layoutFonts = await options.resolveLayoutFonts?.(pathname);
4116
+ const usesLayoutFonts = Boolean(layoutFonts?.body || layoutFonts?.code);
4117
+ const activeFontAssets = usesLayoutFonts ? [] : fontAssets;
4118
+ const fontPreloadHeader = usesLayoutFonts ? renderFarmLayoutFontPreloadHeader(layoutFonts) : fallbackFontPreloadHeader;
3626
4119
  return new Response(
3627
4120
  renderPixelDocsHtml(
3628
4121
  page,
@@ -3630,13 +4123,18 @@ function createFarmDocsHandler(docs, options) {
3630
4123
  docs,
3631
4124
  resolvePixelBorderThemeCss(options),
3632
4125
  options.clientEntry || "/farm-client.js",
3633
- faviconHref
4126
+ faviconHref,
4127
+ requestUrl,
4128
+ activeFontAssets,
4129
+ layoutFonts,
4130
+ usesLayoutFonts ? options.fontStylesheetHref : void 0
3634
4131
  ),
3635
4132
  {
3636
4133
  status: 200,
3637
4134
  headers: {
3638
4135
  "Content-Type": "text/html; charset=utf-8",
3639
- "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300"
4136
+ "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
4137
+ ...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
3640
4138
  }
3641
4139
  }
3642
4140
  );
@@ -3732,9 +4230,9 @@ var import_node_events = require("events");
3732
4230
 
3733
4231
  // src/integrations.ts
3734
4232
  var FARM_INTEGRATION_INTERNAL_DISPATCH_CONTEXT_KEY = "farm.integration.internalDispatch";
3735
- function defineTypedIntegrationRoute(method, path8, input) {
4233
+ function defineTypedIntegrationRoute(method, path9, input) {
3736
4234
  return {
3737
- path: path8,
4235
+ path: path9,
3738
4236
  method,
3739
4237
  middleware: input.middleware,
3740
4238
  before: input.before,
@@ -3744,7 +4242,7 @@ function defineTypedIntegrationRoute(method, path8, input) {
3744
4242
  input: normalizeIntegrationRouteInputSchemas(input),
3745
4243
  handler: input.handler,
3746
4244
  __operation: defineIntegrationAPIOperation({
3747
- path: path8,
4245
+ path: path9,
3748
4246
  method,
3749
4247
  bodyFormat: input.bodyFormat,
3750
4248
  responseFormat: input.responseFormat,
@@ -3757,52 +4255,52 @@ function defineTypedIntegrationRoute(method, path8, input) {
3757
4255
  __name(defineTypedIntegrationRoute, "defineTypedIntegrationRoute");
3758
4256
  function createIntegrationRouteFactory() {
3759
4257
  return {
3760
- get(path8, input) {
4258
+ get(path9, input) {
3761
4259
  return defineTypedIntegrationRoute(
3762
4260
  "GET",
3763
- path8,
4261
+ path9,
3764
4262
  input
3765
4263
  );
3766
4264
  },
3767
- post(path8, input) {
4265
+ post(path9, input) {
3768
4266
  return defineTypedIntegrationRoute(
3769
4267
  "POST",
3770
- path8,
4268
+ path9,
3771
4269
  {
3772
4270
  bodyFormat: "json",
3773
4271
  ...input
3774
4272
  }
3775
4273
  );
3776
4274
  },
3777
- put(path8, input) {
4275
+ put(path9, input) {
3778
4276
  return defineTypedIntegrationRoute(
3779
4277
  "PUT",
3780
- path8,
4278
+ path9,
3781
4279
  {
3782
4280
  bodyFormat: "json",
3783
4281
  ...input
3784
4282
  }
3785
4283
  );
3786
4284
  },
3787
- patch(path8, input) {
3788
- return defineTypedIntegrationRoute("PATCH", path8, {
4285
+ patch(path9, input) {
4286
+ return defineTypedIntegrationRoute("PATCH", path9, {
3789
4287
  bodyFormat: "json",
3790
4288
  ...input
3791
4289
  });
3792
4290
  },
3793
- delete(path8, input) {
3794
- return defineTypedIntegrationRoute("DELETE", path8, {
4291
+ delete(path9, input) {
4292
+ return defineTypedIntegrationRoute("DELETE", path9, {
3795
4293
  bodyFormat: "json",
3796
4294
  ...input
3797
4295
  });
3798
4296
  },
3799
- options(path8, input) {
3800
- return defineTypedIntegrationRoute("OPTIONS", path8, input);
4297
+ options(path9, input) {
4298
+ return defineTypedIntegrationRoute("OPTIONS", path9, input);
3801
4299
  },
3802
- head(path8, input) {
4300
+ head(path9, input) {
3803
4301
  return defineTypedIntegrationRoute(
3804
4302
  "HEAD",
3805
- path8,
4303
+ path9,
3806
4304
  input
3807
4305
  );
3808
4306
  }
@@ -4041,8 +4539,8 @@ function normalizeIntegrationValidationIssues(source, error) {
4041
4539
  ];
4042
4540
  }
4043
4541
  __name(normalizeIntegrationValidationIssues, "normalizeIntegrationValidationIssues");
4044
- function normalizeIntegrationValidationPath(path8) {
4045
- return (path8 || []).map((segment) => {
4542
+ function normalizeIntegrationValidationPath(path9) {
4543
+ return (path9 || []).map((segment) => {
4046
4544
  const key = typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment;
4047
4545
  return typeof key === "symbol" ? key.description || key.toString() : key;
4048
4546
  });
@@ -4815,22 +5313,22 @@ function getServerActionStorage() {
4815
5313
  __name(getServerActionStorage, "getServerActionStorage");
4816
5314
 
4817
5315
  // src/layers.ts
4818
- var import_node_fs4 = require("fs");
5316
+ var import_node_fs5 = require("fs");
4819
5317
  var import_promises = require("fs/promises");
4820
5318
  var import_node_module3 = require("module");
4821
- var import_node_path4 = __toESM(require("path"));
5319
+ var import_node_path5 = __toESM(require("path"));
4822
5320
  var import_node_url = require("url");
4823
5321
 
4824
5322
  // src/config.ts
4825
5323
  var import_path = __toESM(require("path"));
4826
5324
 
4827
5325
  // src/i18n/config.ts
4828
- var import_node_path5 = __toESM(require("path"));
5326
+ var import_node_path6 = __toESM(require("path"));
4829
5327
  var DEFAULT_FARM_I18N_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
4830
5328
 
4831
5329
  // src/auth-config.ts
4832
5330
  var import_node_module4 = require("module");
4833
- var import_node_path6 = __toESM(require("path"));
5331
+ var import_node_path7 = __toESM(require("path"));
4834
5332
  var import_node_url2 = require("url");
4835
5333
 
4836
5334
  // src/config.ts
@@ -4902,18 +5400,18 @@ function sanitizeDocsConfig(config) {
4902
5400
  }
4903
5401
  __name(sanitizeDocsConfig, "sanitizeDocsConfig");
4904
5402
  async function findDocsConfigPath(rootDir, configPath) {
4905
- const { existsSync: existsSync5 } = await import("fs");
5403
+ const { existsSync: existsSync6 } = await import("fs");
4906
5404
  const root = import_path.default.resolve(rootDir || process.cwd());
4907
5405
  if (configPath) {
4908
5406
  const resolvedPath = import_path.default.isAbsolute(configPath) ? configPath : import_path.default.join(root, configPath);
4909
- if (!existsSync5(resolvedPath)) {
5407
+ if (!existsSync6(resolvedPath)) {
4910
5408
  throw new Error(`Could not find docs config at ${configPath}.`);
4911
5409
  }
4912
5410
  return import_path.default.resolve(resolvedPath);
4913
5411
  }
4914
5412
  for (const filename of DOCS_CONFIG_FILENAMES) {
4915
5413
  const resolvedPath = import_path.default.join(root, filename);
4916
- if (existsSync5(resolvedPath)) {
5414
+ if (existsSync6(resolvedPath)) {
4917
5415
  return resolvedPath;
4918
5416
  }
4919
5417
  }