@farming-labs/next 0.1.73 → 0.1.75

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 (2) hide show
  1. package/dist/config.mjs +72 -3
  2. package/package.json +3 -3
package/dist/config.mjs CHANGED
@@ -85,6 +85,7 @@ export const { GET, POST } = createDocsAPI({
85
85
  changelog: docsConfig.changelog,
86
86
  feedback: docsConfig.feedback,
87
87
  mcp: docsConfig.mcp,
88
+ sitemap: docsConfig.sitemap,
88
89
  search: docsConfig.search,
89
90
  analytics: docsConfig.analytics,
90
91
  observability: docsConfig.observability,
@@ -171,6 +172,10 @@ const DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE = "/.well-known/llms.txt";
171
172
  const DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE = "/.well-known/llms-full.txt";
172
173
  const DEFAULT_SKILL_MD_ROUTE = "/skill.md";
173
174
  const DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE = "/.well-known/skill.md";
175
+ const DEFAULT_SITEMAP_XML_ROUTE = "/sitemap.xml";
176
+ const DEFAULT_SITEMAP_MD_ROUTE = "/sitemap.md";
177
+ const DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE = "/.well-known/sitemap.md";
178
+ const DEFAULT_SITEMAP_MANIFEST_PATH = ".farming-labs/sitemap-manifest.json";
174
179
  const MARKDOWN_ACCEPT_HEADER_VALUE = [
175
180
  "(?:^|.*,\\s*)",
176
181
  "text/markdown",
@@ -720,6 +725,48 @@ function normalizeRoutePath(route) {
720
725
  const normalized = `/${route}`.replace(/\/+/g, "/");
721
726
  return normalized !== "/" ? normalized.replace(/\/+$/, "") : DEFAULT_MCP_ROUTE;
722
727
  }
728
+ function normalizeRoutePrefix(prefix) {
729
+ if (!prefix) return "";
730
+ const normalized = `/${prefix.replace(/^\/+|\/+$/g, "")}`.replace(/\/+/g, "/");
731
+ return normalized === "/" ? "" : normalized;
732
+ }
733
+ function joinPublicRoute(prefix, route) {
734
+ return `${prefix}/${route.replace(/^\/+/, "")}`.replace(/\/+/g, "/");
735
+ }
736
+ function readSitemapConfig(root) {
737
+ for (const ext of FILE_EXTS) {
738
+ const configPath = join(root, `docs.config.${ext}`);
739
+ if (!existsSync(configPath)) continue;
740
+ try {
741
+ const content = readFileSync(configPath, "utf-8");
742
+ if (content.match(/sitemap\s*:\s*false/)) return {
743
+ enabled: false,
744
+ routePrefix: ""
745
+ };
746
+ if (content.match(/sitemap\s*:\s*true/)) return {
747
+ enabled: true,
748
+ routePrefix: ""
749
+ };
750
+ const block = extractObjectLiteral(content, "sitemap");
751
+ if (!block) continue;
752
+ const enabledMatch = block.match(/enabled\s*:\s*(true|false)/);
753
+ const routePrefixMatch = block.match(/routePrefix\s*:\s*["']([^"']+)["']/);
754
+ return {
755
+ enabled: enabledMatch ? enabledMatch[1] !== "false" : true,
756
+ routePrefix: normalizeRoutePrefix(routePrefixMatch?.[1])
757
+ };
758
+ } catch {
759
+ return {
760
+ enabled: false,
761
+ routePrefix: ""
762
+ };
763
+ }
764
+ }
765
+ return {
766
+ enabled: false,
767
+ routePrefix: ""
768
+ };
769
+ }
723
770
  function normalizeAgentFeedbackRoute(route, fallback = DEFAULT_AGENT_FEEDBACK_ROUTE) {
724
771
  if (!route || route.trim().length === 0) return fallback;
725
772
  const normalized = `/${route}`.replace(/\/+/g, "/");
@@ -834,6 +881,24 @@ function buildSkillMdRewrites() {
834
881
  destination: "/api/docs?format=skill"
835
882
  }];
836
883
  }
884
+ function buildSitemapRewrites(config) {
885
+ if (!config.enabled) return [];
886
+ const prefix = config.routePrefix;
887
+ return [
888
+ {
889
+ source: joinPublicRoute(prefix, DEFAULT_SITEMAP_XML_ROUTE),
890
+ destination: "/api/docs?format=sitemap-xml"
891
+ },
892
+ {
893
+ source: joinPublicRoute(prefix, DEFAULT_SITEMAP_MD_ROUTE),
894
+ destination: "/api/docs?format=sitemap-md"
895
+ },
896
+ {
897
+ source: joinPublicRoute(prefix, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE),
898
+ destination: "/api/docs?format=sitemap-md"
899
+ }
900
+ ];
901
+ }
837
902
  function buildMcpRewrites(config) {
838
903
  if (!config.enabled) return [];
839
904
  return [DEFAULT_MCP_PUBLIC_ROUTE, DEFAULT_MCP_WELL_KNOWN_ROUTE].filter((source) => source !== config.route).map((source) => ({
@@ -962,12 +1027,13 @@ function buildHiddenFolderRedirects(docsDir, entry) {
962
1027
  scan(docsDir, []);
963
1028
  return dedupeRedirects(redirects);
964
1029
  }
965
- function mergeDocsMarkdownRewrites(entry, mcp, agentFeedback, result) {
1030
+ function mergeDocsMarkdownRewrites(entry, mcp, sitemap, agentFeedback, result) {
966
1031
  const autoRewrites = [
967
1032
  ...buildAgentSpecRewrites(),
968
1033
  ...buildMcpRewrites(mcp),
969
1034
  ...buildLlmsTxtRewrites(),
970
1035
  ...buildSkillMdRewrites(),
1036
+ ...buildSitemapRewrites(sitemap),
971
1037
  ...buildDocsMarkdownRewrites(entry),
972
1038
  ...buildAgentFeedbackRewrites(agentFeedback)
973
1039
  ];
@@ -1008,6 +1074,7 @@ function withDocs(nextConfig = {}) {
1008
1074
  writeFileSync(join(docsApiRouteDir, "route.ts"), DOCS_API_ROUTE_TEMPLATE);
1009
1075
  }
1010
1076
  const mcp = readMcpConfig(root);
1077
+ const sitemap = readSitemapConfig(root);
1011
1078
  const docsMcpRouteDir = join(root, appDir, "api", "docs", "mcp");
1012
1079
  if (mcp.enabled && mcp.route === DEFAULT_MCP_ROUTE && !isStaticExport && !hasFile(docsMcpRouteDir, "route")) {
1013
1080
  mkdirSync(docsMcpRouteDir, { recursive: true });
@@ -1158,11 +1225,12 @@ function withDocs(nextConfig = {}) {
1158
1225
  const existingTracingIncludes = nextConfig.outputFileTracingIncludes ?? {};
1159
1226
  const docsTraceGlob = docsContentDir.replace(/\\/g, "/").replace(/^\.?\//, "") + "/**/*";
1160
1227
  const skillTraceFile = "skill.md";
1228
+ const sitemapManifestTraceFile = DEFAULT_SITEMAP_MANIFEST_PATH;
1161
1229
  const docsContentRoot = isAbsolute(docsContentDir) ? docsContentDir : join(root, docsContentDir);
1162
1230
  if (!isStaticExport) {
1163
1231
  const existingRewrites = nextConfig.rewrites;
1164
1232
  nextConfig.rewrites = async () => {
1165
- return mergeDocsMarkdownRewrites(entry, mcp, agentFeedback, typeof existingRewrites === "function" ? await existingRewrites() : existingRewrites);
1233
+ return mergeDocsMarkdownRewrites(entry, mcp, sitemap, agentFeedback, typeof existingRewrites === "function" ? await existingRewrites() : existingRewrites);
1166
1234
  };
1167
1235
  const autoRedirects = buildHiddenFolderRedirects(docsContentRoot, entry);
1168
1236
  if (autoRedirects.length > 0) {
@@ -1177,7 +1245,8 @@ function withDocs(nextConfig = {}) {
1177
1245
  "/api/docs": [...new Set([
1178
1246
  ...existingTracingIncludes["/api/docs"] ?? [],
1179
1247
  docsTraceGlob,
1180
- skillTraceFile
1248
+ skillTraceFile,
1249
+ sitemapManifestTraceFile
1181
1250
  ])],
1182
1251
  [DEFAULT_MCP_ROUTE]: [...new Set([...existingTracingIncludes[DEFAULT_MCP_ROUTE] ?? [], docsTraceGlob])]
1183
1252
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/next",
3
- "version": "0.1.73",
3
+ "version": "0.1.75",
4
4
  "description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
5
5
  "keywords": [
6
6
  "docs",
@@ -95,8 +95,8 @@
95
95
  "tsdown": "^0.20.3",
96
96
  "typescript": "^5.9.3",
97
97
  "vitest": "^3.2.4",
98
- "@farming-labs/docs": "0.1.73",
99
- "@farming-labs/theme": "0.1.73"
98
+ "@farming-labs/docs": "0.1.75",
99
+ "@farming-labs/theme": "0.1.75"
100
100
  },
101
101
  "peerDependencies": {
102
102
  "@farming-labs/docs": ">=0.0.1",