@farming-labs/theme 0.1.99 → 0.1.101
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.
- package/dist/docs-api.d.mts +5 -1
- package/dist/docs-api.mjs +98 -7
- package/package.json +2 -2
package/dist/docs-api.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChangelogConfig, DocsAnalyticsConfig, DocsAskAIMcpConfig, DocsI18nConfig, DocsMcpConfig, DocsObservabilityConfig, DocsRobotsConfig, DocsSearchConfig, DocsSitemapConfig, FeedbackConfig, LlmsTxtConfig, OrderingItem } from "@farming-labs/docs";
|
|
1
|
+
import { ChangelogConfig, DocsAnalyticsConfig, DocsAskAIMcpConfig, DocsConfig, DocsI18nConfig, DocsMcpConfig, DocsObservabilityConfig, DocsRobotsConfig, DocsSearchConfig, DocsSitemapConfig, FeedbackConfig, LlmsTxtConfig, OrderingItem } from "@farming-labs/docs";
|
|
2
2
|
|
|
3
3
|
//#region src/docs-api.d.ts
|
|
4
4
|
interface AIProviderConfig {
|
|
@@ -60,6 +60,10 @@ interface DocsAPIOptions {
|
|
|
60
60
|
sitemap?: boolean | DocsSitemapConfig;
|
|
61
61
|
/** Robots.txt generation policy used for the agent discovery spec. */
|
|
62
62
|
robots?: boolean | DocsRobotsConfig;
|
|
63
|
+
/** API reference / OpenAPI schema configuration used for agent discovery. */
|
|
64
|
+
apiReference?: DocsConfig["apiReference"];
|
|
65
|
+
/** Metadata used in generated OpenAPI documents. */
|
|
66
|
+
metadata?: DocsConfig["metadata"];
|
|
63
67
|
}
|
|
64
68
|
interface DocsMCPAPIOptions {
|
|
65
69
|
rootDir?: string;
|
package/dist/docs-api.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import fs from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import matter from "gray-matter";
|
|
6
6
|
import { buildDocsAskAIContext, createDocsAgentTraceContext, createDocsAgentTraceId, createDocsRobotsResponse, createDocsSitemapResponse, emitDocsAgentTraceEvent, emitDocsAnalyticsEvent, formatDocsAskAIPackageHints, getDocsLlmsTxtMaxCharsIssue, getDocsMarkdownCanonicalLinkHeader, getDocsMarkdownVaryHeader, hasDocsMarkdownSignatureAgent, normalizeDocsRelated, performDocsSearch, renderDocsLlmsTxt, renderDocsMarkdownNotFound, renderDocsRelatedMarkdownLines, resolveAskAISearchRequestConfig, resolveChangelogConfig, resolveDocsI18n, resolveDocsLlmsTxtRequest, resolveDocsLlmsTxtSections, resolveDocsLocale, resolveDocsSitemapConfig, resolvePageSidebarFolderIndexBehavior, resolveSearchRequestConfig, selectDocsLlmsTxtContent } from "@farming-labs/docs";
|
|
7
|
-
import { createDocsMcpHttpHandler, createFilesystemDocsMcpSource, readDocsSitemapManifest, resolveDocsMcpConfig } from "@farming-labs/docs/server";
|
|
7
|
+
import { buildApiReferenceOpenApiDocumentAsync, createDocsMcpHttpHandler, createFilesystemDocsMcpSource, readDocsSitemapManifest, resolveApiReferenceConfig, resolveDocsMcpConfig } from "@farming-labs/docs/server";
|
|
8
8
|
|
|
9
9
|
//#region src/docs-api.ts
|
|
10
10
|
/**
|
|
@@ -181,7 +181,21 @@ function isRobotsDiscoveryEnabled(robots) {
|
|
|
181
181
|
if (robots && typeof robots === "object" && robots.enabled === false) return false;
|
|
182
182
|
return true;
|
|
183
183
|
}
|
|
184
|
-
function
|
|
184
|
+
function isApiReferenceOpenApiRequest(url) {
|
|
185
|
+
return url.searchParams.get("format")?.trim() === "openapi";
|
|
186
|
+
}
|
|
187
|
+
function resolveApiReferenceOpenApiDiscovery(value) {
|
|
188
|
+
const apiReference = resolveApiReferenceConfig(value);
|
|
189
|
+
if (!apiReference.enabled) return { enabled: false };
|
|
190
|
+
return {
|
|
191
|
+
enabled: true,
|
|
192
|
+
url: `${DEFAULT_DOCS_API_ROUTE}?format=openapi`,
|
|
193
|
+
source: apiReference.specUrl ? "configured" : "generated",
|
|
194
|
+
specUrl: apiReference.specUrl,
|
|
195
|
+
apiReferencePath: `/${apiReference.path}`
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, sitemap, robots, openapi }) {
|
|
185
199
|
const normalizedEntry = normalizePathSegment(entry) || "docs";
|
|
186
200
|
const localesEnabled = i18n !== null;
|
|
187
201
|
const searchEnabled = isSearchEnabled(search);
|
|
@@ -216,6 +230,8 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, site
|
|
|
216
230
|
sitemap: sitemapConfig.enabled,
|
|
217
231
|
robots: robotsEnabled,
|
|
218
232
|
structuredData: true,
|
|
233
|
+
apiReference: openapi.enabled,
|
|
234
|
+
openapi: openapi.enabled,
|
|
219
235
|
agentFeedback: feedback.enabled,
|
|
220
236
|
locales: localesEnabled
|
|
221
237
|
},
|
|
@@ -226,7 +242,8 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, site
|
|
|
226
242
|
agentSpecFallback: DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE,
|
|
227
243
|
agentSpecWellKnown: DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE,
|
|
228
244
|
agentSpecWellKnownJson: DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE,
|
|
229
|
-
agentSpecQuery: `${DEFAULT_DOCS_API_ROUTE}?agent=spec
|
|
245
|
+
agentSpecQuery: `${DEFAULT_DOCS_API_ROUTE}?agent=spec`,
|
|
246
|
+
openapi: `${DEFAULT_DOCS_API_ROUTE}?format=openapi`
|
|
230
247
|
},
|
|
231
248
|
markdown: {
|
|
232
249
|
enabled: true,
|
|
@@ -291,6 +308,14 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, site
|
|
|
291
308
|
canonicalUrlField: "url",
|
|
292
309
|
breadcrumbType: "BreadcrumbList"
|
|
293
310
|
},
|
|
311
|
+
openapi: {
|
|
312
|
+
enabled: openapi.enabled,
|
|
313
|
+
url: openapi.url ?? null,
|
|
314
|
+
source: openapi.source ?? null,
|
|
315
|
+
specUrl: openapi.specUrl ?? null,
|
|
316
|
+
apiReferencePath: openapi.apiReferencePath ?? null,
|
|
317
|
+
format: "OpenAPI 3.1"
|
|
318
|
+
},
|
|
294
319
|
search: {
|
|
295
320
|
enabled: searchEnabled,
|
|
296
321
|
endpoint: `${DEFAULT_DOCS_API_ROUTE}?query={query}`,
|
|
@@ -334,6 +359,7 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, site
|
|
|
334
359
|
instructions: {
|
|
335
360
|
preferMarkdownRoutes: true,
|
|
336
361
|
useMcpWhenAvailable: true,
|
|
362
|
+
useOpenApiWhenAvailable: true,
|
|
337
363
|
readFeedbackSchemaBeforeSubmitting: true,
|
|
338
364
|
doNotAssumeFeedbackPayloadShape: true
|
|
339
365
|
}
|
|
@@ -948,7 +974,7 @@ function renderMarkdownDocument(page, options = {}) {
|
|
|
948
974
|
lines.push("", page.agentFallbackRawContent ?? page.rawContent ?? page.content);
|
|
949
975
|
return lines.join("\n");
|
|
950
976
|
}
|
|
951
|
-
function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitemap, robots }) {
|
|
977
|
+
function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitemap, robots, openapi }) {
|
|
952
978
|
const normalizedEntry = normalizePathSegment(entry) || "docs";
|
|
953
979
|
const siteTitle = compactSkillText(llms.siteTitle ?? "Documentation");
|
|
954
980
|
const siteDescription = llms.siteDescription ? compactSkillText(llms.siteDescription) : void 0;
|
|
@@ -969,6 +995,7 @@ function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitem
|
|
|
969
995
|
if (siteDescription) lines.push(`Description: ${siteDescription}`);
|
|
970
996
|
lines.push("", "## When To Use", "Use this skill when you need to read or implement against this documentation site.", "", "## Start Here", `- Fetch ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}; fall back to ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE} or ${DEFAULT_AGENT_SPEC_ROUTE}.`, `- Fetch /${normalizedEntry}.md for the root docs page.`, `- Fetch /${normalizedEntry}/{slug}.md for page-specific context.`, "- You can also request text/markdown from normal page URLs.");
|
|
971
997
|
if (searchEnabled) lines.push(`- Search with ${DEFAULT_DOCS_API_ROUTE}?query={query} when you do not know the page.`);
|
|
998
|
+
if (openapi.enabled && openapi.url) lines.push(`- Fetch ${openapi.url} for the machine-readable OpenAPI schema before scraping API reference pages.`);
|
|
972
999
|
if (llms.enabled) {
|
|
973
1000
|
lines.push(`- Use ${DEFAULT_LLMS_TXT_ROUTE} for a compact docs index.`, `- Use ${DEFAULT_LLMS_FULL_TXT_ROUTE} for full markdown context.`);
|
|
974
1001
|
for (const section of llmsSections) lines.push(`- Use ${section.route} for the ${section.title} llms.txt section.`);
|
|
@@ -989,6 +1016,10 @@ function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitem
|
|
|
989
1016
|
lines.push(`- ${section.title} llms-full.txt: ${section.fullRoute}`);
|
|
990
1017
|
}
|
|
991
1018
|
}
|
|
1019
|
+
if (openapi.enabled && openapi.url) {
|
|
1020
|
+
lines.push(`- OpenAPI schema: ${openapi.url}`);
|
|
1021
|
+
if (openapi.apiReferencePath) lines.push(`- API reference: ${openapi.apiReferencePath}`);
|
|
1022
|
+
}
|
|
992
1023
|
if (sitemapConfig.enabled) {
|
|
993
1024
|
if (sitemapConfig.xml.enabled) lines.push(`- Sitemap XML: ${sitemapConfig.xml.route}`);
|
|
994
1025
|
if (sitemapConfig.markdown.enabled) lines.push(`- Sitemap Markdown: ${sitemapConfig.markdown.route}`, `- Sitemap well-known alias: ${sitemapConfig.markdown.wellKnownRoute}`);
|
|
@@ -1597,6 +1628,37 @@ function readRobotsConfig(root) {
|
|
|
1597
1628
|
}
|
|
1598
1629
|
}
|
|
1599
1630
|
}
|
|
1631
|
+
function readApiReferenceConfig(root) {
|
|
1632
|
+
for (const ext of FILE_EXTS) {
|
|
1633
|
+
const configPath = path.join(root, `docs.config.${ext}`);
|
|
1634
|
+
if (!fs.existsSync(configPath)) continue;
|
|
1635
|
+
try {
|
|
1636
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
1637
|
+
if (!content.includes("apiReference")) return void 0;
|
|
1638
|
+
if (/apiReference\s*:\s*false/.test(content)) return false;
|
|
1639
|
+
if (/apiReference\s*:\s*true/.test(content)) return true;
|
|
1640
|
+
const block = content.match(/apiReference\s*:\s*\{([\s\S]*?)\n\s*\}/)?.[1] ?? "";
|
|
1641
|
+
const enabledMatch = block.match(/enabled\s*:\s*(true|false)/);
|
|
1642
|
+
const pathMatch = block.match(/path\s*:\s*["']([^"']+)["']/);
|
|
1643
|
+
const routeRootMatch = block.match(/routeRoot\s*:\s*["']([^"']+)["']/);
|
|
1644
|
+
const specUrlMatch = block.match(/specUrl\s*:\s*["']([^"']+)["']/);
|
|
1645
|
+
const rendererMatch = block.match(/renderer\s*:\s*["'](fumadocs|scalar)["']/);
|
|
1646
|
+
const excludeMatch = block.match(/exclude\s*:\s*\[([\s\S]*?)\]/);
|
|
1647
|
+
const exclude = excludeMatch?.[1] === void 0 ? void 0 : Array.from(excludeMatch[1].matchAll(/["']([^"']+)["']/g)).map((match) => match[1]).filter(Boolean);
|
|
1648
|
+
const renderer = rendererMatch?.[1] === "fumadocs" || rendererMatch?.[1] === "scalar" ? rendererMatch[1] : void 0;
|
|
1649
|
+
return {
|
|
1650
|
+
enabled: enabledMatch ? enabledMatch[1] === "true" : true,
|
|
1651
|
+
path: pathMatch?.[1],
|
|
1652
|
+
routeRoot: routeRootMatch?.[1],
|
|
1653
|
+
specUrl: specUrlMatch?.[1],
|
|
1654
|
+
renderer,
|
|
1655
|
+
exclude
|
|
1656
|
+
};
|
|
1657
|
+
} catch {
|
|
1658
|
+
return;
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1600
1662
|
function generateLlmsTxt(indexes, options) {
|
|
1601
1663
|
return renderDocsLlmsTxt(indexes, options);
|
|
1602
1664
|
}
|
|
@@ -1639,6 +1701,13 @@ function createDocsAPI(options) {
|
|
|
1639
1701
|
const llmsConfig = resolveLlmsTxtConfig(options?.llmsTxt, readLlmsTxtConfig(root));
|
|
1640
1702
|
const sitemapConfig = options?.sitemap ?? readSitemapConfig(root);
|
|
1641
1703
|
const robotsConfig = options?.robots ?? readRobotsConfig(root);
|
|
1704
|
+
const apiReferenceConfig = options?.apiReference ?? readApiReferenceConfig(root);
|
|
1705
|
+
const apiReferenceDocsConfig = {
|
|
1706
|
+
...options,
|
|
1707
|
+
entry,
|
|
1708
|
+
apiReference: apiReferenceConfig
|
|
1709
|
+
};
|
|
1710
|
+
const openapiDiscovery = resolveApiReferenceOpenApiDiscovery(apiReferenceConfig);
|
|
1642
1711
|
const mcpConfig = resolveDocsMcpConfig(options?.mcp ?? readMcpConfig(root), { defaultName: llmsConfig.siteTitle ?? "Documentation" });
|
|
1643
1712
|
function resolveDocsDirCandidates(locale) {
|
|
1644
1713
|
const relativeCandidates = /* @__PURE__ */ new Set();
|
|
@@ -1755,7 +1824,8 @@ function createDocsAPI(options) {
|
|
|
1755
1824
|
siteDescription: llmsConfig.siteDescription,
|
|
1756
1825
|
baseUrl: llmsConfig.baseUrl ?? "",
|
|
1757
1826
|
maxChars: llmsConfig.maxChars,
|
|
1758
|
-
sections: llmsConfig.sections
|
|
1827
|
+
sections: llmsConfig.sections,
|
|
1828
|
+
openapi: openapiDiscovery
|
|
1759
1829
|
});
|
|
1760
1830
|
llmsCacheByLocale.set(key, next);
|
|
1761
1831
|
return next;
|
|
@@ -1782,12 +1852,32 @@ function createDocsAPI(options) {
|
|
|
1782
1852
|
feedback: agentFeedbackConfig,
|
|
1783
1853
|
llms: llmsConfig,
|
|
1784
1854
|
sitemap: sitemapConfig,
|
|
1785
|
-
robots: robotsConfig
|
|
1855
|
+
robots: robotsConfig,
|
|
1856
|
+
openapi: openapiDiscovery
|
|
1786
1857
|
}), { headers: {
|
|
1787
1858
|
"Cache-Control": "public, max-age=0, s-maxage=3600",
|
|
1788
1859
|
"X-Robots-Tag": "noindex"
|
|
1789
1860
|
} });
|
|
1790
1861
|
}
|
|
1862
|
+
if (isApiReferenceOpenApiRequest(url)) {
|
|
1863
|
+
if (!openapiDiscovery.enabled) return new Response("Not Found", {
|
|
1864
|
+
status: 404,
|
|
1865
|
+
headers: {
|
|
1866
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
1867
|
+
"X-Robots-Tag": "noindex"
|
|
1868
|
+
}
|
|
1869
|
+
});
|
|
1870
|
+
const document = await buildApiReferenceOpenApiDocumentAsync(apiReferenceDocsConfig, {
|
|
1871
|
+
framework: "next",
|
|
1872
|
+
rootDir: root,
|
|
1873
|
+
baseUrl: url.origin
|
|
1874
|
+
});
|
|
1875
|
+
return new Response(JSON.stringify(document, null, 2), { headers: {
|
|
1876
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
1877
|
+
"Cache-Control": "public, max-age=0, s-maxage=3600",
|
|
1878
|
+
"X-Robots-Tag": "noindex"
|
|
1879
|
+
} });
|
|
1880
|
+
}
|
|
1791
1881
|
const agentFeedbackRequest = resolveAgentFeedbackRequest(url, agentFeedbackConfig);
|
|
1792
1882
|
if (agentFeedbackRequest) {
|
|
1793
1883
|
if (agentFeedbackRequest.kind === "submit") return Response.json({ error: "Method Not Allowed" }, {
|
|
@@ -1826,7 +1916,8 @@ function createDocsAPI(options) {
|
|
|
1826
1916
|
feedback: agentFeedbackConfig,
|
|
1827
1917
|
llms: llmsConfig,
|
|
1828
1918
|
sitemap: sitemapConfig,
|
|
1829
|
-
robots: robotsConfig
|
|
1919
|
+
robots: robotsConfig,
|
|
1920
|
+
openapi: openapiDiscovery
|
|
1830
1921
|
}), { headers: {
|
|
1831
1922
|
"Content-Type": "text/markdown; charset=utf-8",
|
|
1832
1923
|
"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.
|
|
3
|
+
"version": "0.1.101",
|
|
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.
|
|
142
|
+
"@farming-labs/docs": "0.1.101"
|
|
143
143
|
},
|
|
144
144
|
"peerDependencies": {
|
|
145
145
|
"@farming-labs/docs": ">=0.0.1",
|