@farming-labs/theme 0.1.83 → 0.1.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { ChangelogConfig, DocsAnalyticsConfig, DocsAskAIMcpConfig, DocsI18nConfig, DocsMcpConfig, DocsObservabilityConfig, DocsSearchConfig, DocsSitemapConfig, FeedbackConfig, OrderingItem } from "@farming-labs/docs";
1
+ import { ChangelogConfig, DocsAnalyticsConfig, DocsAskAIMcpConfig, DocsI18nConfig, DocsMcpConfig, DocsObservabilityConfig, DocsRobotsConfig, DocsSearchConfig, DocsSitemapConfig, FeedbackConfig, OrderingItem } from "@farming-labs/docs";
2
2
 
3
3
  //#region src/docs-api.d.ts
4
4
  interface AIProviderConfig {
@@ -56,6 +56,8 @@ interface DocsAPIOptions {
56
56
  mcp?: boolean | DocsMcpConfig;
57
57
  /** Sitemap configuration used for sitemap.xml and sitemap.md. */
58
58
  sitemap?: boolean | DocsSitemapConfig;
59
+ /** Robots.txt generation policy used for the agent discovery spec. */
60
+ robots?: boolean | DocsRobotsConfig;
59
61
  }
60
62
  interface DocsMCPAPIOptions {
61
63
  rootDir?: string;
package/dist/docs-api.mjs CHANGED
@@ -46,6 +46,7 @@ const DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE = "/.well-known/llms.txt";
46
46
  const DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE = "/.well-known/llms-full.txt";
47
47
  const DEFAULT_SKILL_MD_ROUTE = "/skill.md";
48
48
  const DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE = "/.well-known/skill.md";
49
+ const DEFAULT_ROBOTS_TXT_ROUTE = "/robots.txt";
49
50
  const DEFAULT_AGENT_FEEDBACK_ROUTE = "/api/docs/agent/feedback";
50
51
  const DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA = {
51
52
  type: "object",
@@ -172,11 +173,17 @@ function isSearchEnabled(search) {
172
173
  if (search && typeof search === "object" && search.enabled === false) return false;
173
174
  return true;
174
175
  }
175
- function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, sitemap }) {
176
+ function isRobotsDiscoveryEnabled(robots) {
177
+ if (robots === false) return false;
178
+ if (robots && typeof robots === "object" && robots.enabled === false) return false;
179
+ return true;
180
+ }
181
+ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, sitemap, robots }) {
176
182
  const normalizedEntry = normalizePathSegment(entry) || "docs";
177
183
  const localesEnabled = i18n !== null;
178
184
  const searchEnabled = isSearchEnabled(search);
179
185
  const sitemapConfig = resolveDocsSitemapConfig(sitemap, { baseUrl: llms.baseUrl });
186
+ const robotsEnabled = isRobotsDiscoveryEnabled(robots);
180
187
  return {
181
188
  version: "1",
182
189
  name: "@farming-labs/docs",
@@ -203,6 +210,7 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, site
203
210
  mcp: mcp.enabled,
204
211
  search: searchEnabled,
205
212
  sitemap: sitemapConfig.enabled,
213
+ robots: robotsEnabled,
206
214
  agentFeedback: feedback.enabled,
207
215
  locales: localesEnabled
208
216
  },
@@ -252,6 +260,11 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, site
252
260
  api: `${DEFAULT_DOCS_API_ROUTE}?format=sitemap-md`
253
261
  }
254
262
  },
263
+ robots: {
264
+ enabled: robotsEnabled,
265
+ route: DEFAULT_ROBOTS_TXT_ROUTE,
266
+ defaultRoute: DEFAULT_ROBOTS_TXT_ROUTE
267
+ },
255
268
  search: {
256
269
  enabled: searchEnabled,
257
270
  endpoint: `${DEFAULT_DOCS_API_ROUTE}?query={query}`,
@@ -915,16 +928,17 @@ function renderMarkdownDocument(page) {
915
928
  lines.push("", page.agentFallbackRawContent ?? page.rawContent ?? page.content);
916
929
  return lines.join("\n");
917
930
  }
918
- function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitemap }) {
931
+ function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitemap, robots }) {
919
932
  const normalizedEntry = normalizePathSegment(entry) || "docs";
920
933
  const siteTitle = compactSkillText(llms.siteTitle ?? "Documentation");
921
934
  const siteDescription = llms.siteDescription ? compactSkillText(llms.siteDescription) : void 0;
922
935
  const searchEnabled = isSearchEnabled(search);
923
936
  const sitemapConfig = resolveDocsSitemapConfig(sitemap, { baseUrl: llms.baseUrl });
937
+ const robotsEnabled = isRobotsDiscoveryEnabled(robots);
924
938
  const lines = [
925
939
  "---",
926
940
  "name: docs",
927
- `description: ${toYamlString(truncateSkillDescription(`Use ${siteTitle} through markdown routes, llms.txt, agent discovery, search, and MCP when available.`))}`,
941
+ `description: ${toYamlString(truncateSkillDescription(`Use ${siteTitle} through markdown routes, llms.txt, robots.txt, agent discovery, search, and MCP when available.`))}`,
928
942
  "---",
929
943
  "",
930
944
  `# ${siteTitle} Skill`,
@@ -939,9 +953,11 @@ function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitem
939
953
  if (sitemapConfig.xml.enabled) lines.push(`- Use ${sitemapConfig.xml.route} to check canonical page freshness.`);
940
954
  if (sitemapConfig.markdown.enabled) lines.push(`- Use ${sitemapConfig.markdown.route} for a semantic docs map.`);
941
955
  }
956
+ if (robotsEnabled) lines.push(`- Check ${DEFAULT_ROBOTS_TXT_ROUTE} for crawler and AI-agent access policy.`);
942
957
  if (mcp.enabled) lines.push(`- Use ${DEFAULT_MCP_WELL_KNOWN_ROUTE} or ${DEFAULT_MCP_PUBLIC_ROUTE} for MCP tools when your environment supports MCP.`);
943
958
  if (feedback.enabled) lines.push(`- Read ${feedback.schemaRoute} before posting agent feedback to ${feedback.route}.`);
944
959
  lines.push("", "## Routes", `- Skill document: ${DEFAULT_SKILL_MD_ROUTE}`, `- Skill well-known alias: ${DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE}`, `- Skill API format: ${DEFAULT_DOCS_API_ROUTE}?format=skill`, `- Agent discovery: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}`, `- Agent discovery fallback: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}`, `- Markdown root: /${normalizedEntry}.md`, `- Markdown pages: /${normalizedEntry}/{slug}.md`);
960
+ if (robotsEnabled) lines.push(`- Robots policy: ${DEFAULT_ROBOTS_TXT_ROUTE}`);
945
961
  if (llms.enabled) lines.push(`- llms.txt: ${DEFAULT_LLMS_TXT_ROUTE}`, `- llms-full.txt: ${DEFAULT_LLMS_FULL_TXT_ROUTE}`, `- llms well-known aliases: ${DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE}, ${DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE}`);
946
962
  if (sitemapConfig.enabled) {
947
963
  if (sitemapConfig.xml.enabled) lines.push(`- Sitemap XML: ${sitemapConfig.xml.route}`);
@@ -1507,6 +1523,31 @@ function readSitemapConfig(root) {
1507
1523
  }
1508
1524
  }
1509
1525
  }
1526
+ function readRobotsConfig(root) {
1527
+ for (const ext of FILE_EXTS) {
1528
+ const configPath = path.join(root, `docs.config.${ext}`);
1529
+ if (!fs.existsSync(configPath)) continue;
1530
+ try {
1531
+ const content = fs.readFileSync(configPath, "utf-8");
1532
+ if (!content.includes("robots")) return void 0;
1533
+ if (/robots\s*:\s*false/.test(content)) return false;
1534
+ if (/robots\s*:\s*true/.test(content)) return true;
1535
+ const robotsBlock = content.match(/robots\s*:\s*\{([\s\S]*?)\n\s*\}/)?.[1] ?? "";
1536
+ const enabledMatch = robotsBlock.match(/enabled\s*:\s*(true|false)/);
1537
+ const pathMatch = robotsBlock.match(/path\s*:\s*["']([^"']+)["']/);
1538
+ const baseUrlMatch = robotsBlock.match(/baseUrl\s*:\s*["']([^"']+)["']/);
1539
+ const aiMatch = robotsBlock.match(/ai\s*:\s*["'](allow|disallow)["']/);
1540
+ return {
1541
+ enabled: enabledMatch ? enabledMatch[1] === "true" : true,
1542
+ path: pathMatch?.[1],
1543
+ baseUrl: baseUrlMatch?.[1],
1544
+ ai: aiMatch?.[1]
1545
+ };
1546
+ } catch {
1547
+ return;
1548
+ }
1549
+ }
1550
+ }
1510
1551
  function generateLlmsTxt(indexes, options) {
1511
1552
  const { siteTitle = "Documentation", siteDescription, baseUrl = "" } = options;
1512
1553
  let llmsTxt = `# ${siteTitle}\n\n`;
@@ -1568,6 +1609,7 @@ function createDocsAPI(options) {
1568
1609
  const searchConfig = options?.search;
1569
1610
  const llmsConfig = readLlmsTxtConfig(root);
1570
1611
  const sitemapConfig = options?.sitemap ?? readSitemapConfig(root);
1612
+ const robotsConfig = options?.robots ?? readRobotsConfig(root);
1571
1613
  const mcpConfig = resolveDocsMcpConfig(options?.mcp ?? readMcpConfig(root), { defaultName: llmsConfig.siteTitle ?? "Documentation" });
1572
1614
  function resolveDocsDirCandidates(locale) {
1573
1615
  const relativeCandidates = /* @__PURE__ */ new Set();
@@ -1708,7 +1750,8 @@ function createDocsAPI(options) {
1708
1750
  mcp: mcpConfig,
1709
1751
  feedback: agentFeedbackConfig,
1710
1752
  llms: llmsConfig,
1711
- sitemap: sitemapConfig
1753
+ sitemap: sitemapConfig,
1754
+ robots: robotsConfig
1712
1755
  }), { headers: {
1713
1756
  "Cache-Control": "public, max-age=0, s-maxage=3600",
1714
1757
  "X-Robots-Tag": "noindex"
@@ -1751,7 +1794,8 @@ function createDocsAPI(options) {
1751
1794
  mcp: mcpConfig,
1752
1795
  feedback: agentFeedbackConfig,
1753
1796
  llms: llmsConfig,
1754
- sitemap: sitemapConfig
1797
+ sitemap: sitemapConfig,
1798
+ robots: robotsConfig
1755
1799
  }), { headers: {
1756
1800
  "Content-Type": "text/markdown; charset=utf-8",
1757
1801
  "Cache-Control": "public, max-age=0, s-maxage=3600",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/theme",
3
- "version": "0.1.83",
3
+ "version": "0.1.84",
4
4
  "description": "Theme package for @farming-labs/docs — layout, provider, MDX components, and styles",
5
5
  "keywords": [
6
6
  "docs",
@@ -139,7 +139,7 @@
139
139
  "tsdown": "^0.20.3",
140
140
  "typescript": "^5.9.3",
141
141
  "vitest": "^3.2.4",
142
- "@farming-labs/docs": "0.1.83"
142
+ "@farming-labs/docs": "0.1.84"
143
143
  },
144
144
  "peerDependencies": {
145
145
  "@farming-labs/docs": ">=0.0.1",