@farming-labs/farmjs 0.2.98 → 0.2.99
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/config.d.ts +9 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -0
- package/dist/config.js.map +1 -1
- package/dist/content.d.ts +1 -0
- package/dist/content.d.ts.map +1 -1
- package/dist/content.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +6 -0
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +55 -18
- package/dist/react.js.map +1 -1
- package/dist/server.d.ts +45 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +317 -11
- package/dist/server.js.map +1 -1
- package/dist/vite.d.ts +16 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +66 -6
- package/dist/vite.js.map +1 -1
- package/package.json +7 -4
package/dist/server.js
CHANGED
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { PassThrough } from "node:stream";
|
|
3
5
|
import matter from "gray-matter";
|
|
6
|
+
import { createElement } from "react";
|
|
7
|
+
import * as ReactDOMServer from "react-dom/server";
|
|
4
8
|
import { applySidebarFolderIndexBehavior, buildDocsAskAIContext, buildDocsSearchFacets, buildDocsAgentDiscoverySpec, buildDocsConfigMap, buildDocsDiagnostics, createDocsContentChangeFeed, createDocsContentChangesHttpResponse, createDocsCacheableResponse, createDocsStandardsDiscoveryResponse, createDocsMarkdownResponse, createDocsRobotsResponse, createDocsSitemapResponse, createDocsAgentTraceContext, createDocsAgentTraceId, emitDocsAgentTraceEvent, emitDocsAnalyticsEvent, emitDocsTelemetryAgentSurfaceEvent, emitDocsTelemetryProjectEvent, formatDocsAskAIPackageHints, findDocsMarkdownPage, getDocsLlmsTxtMaxCharsIssue, getDocsAgentManifestLinkHeader, getDocsDiscoveryLinkHeader, isDocsAgentDiscoveryRequest, isDocsContentChangesRequest, isDocsAgentsRequest, isDocsConfigRequest, isDocsDiagnosticsRequest, isDocsSkillRequest, normalizeDocsRelated, normalizePageAgentFrontmatter, parseDocsAgentFeedbackData, performDocsSearch, performDocsSearchWithMetadata, renderDocsMarkdownDocument, renderDocsLlmsTxt, renderDocsAgentsDocument, renderDocsSkillDocument, readDocsSitemapManifestFromContentMap, stripGeneratedAgentProvenance, resolveDocsAudienceMdxContent, resolveDocsAgentFeedbackConfig, resolveDocsAgentFeedbackRequest, resolvePageSidebarFolderIndexBehavior, resolveAskAISearchRequestConfig, resolveDocsSearchAudience, resolveDocsSearchError, resolveDocsSearchRequest, resolveSearchRequestConfig, resolveDocsI18n, resolveDocsLlmsTxtRequest, resolveDocsLocale, resolveDocsMarkdownRequest, resolveDocsMetadataBaseUrl, resolveDocsContentChangesConfig, resolveDocsRequestApiRoute, resolveDocsRetrievalLastModified, resolveDocsPublishedAgentSkill, resolveDocsStandardsDiscoveryRequest, resolveDocsPath, resolvePageReadingTime, resolveReadingTimeOptions, resolveDocsSitemapPageLastmod, resolveDocsAgentsFormat, resolveDocsSkillFormat, inferDocsTelemetryAgentSurface, renderDocsPageStructuredDataJson, selectDocsLlmsTxtContent, validateDocsAgentFeedbackPayload, } from "@farming-labs/docs";
|
|
5
9
|
import { buildApiReferenceOpenApiDocumentAsync, createDocsMcpHttpHandler, readDocsSitemapManifest, resolveApiReferenceOpenApiDiscovery, resolveDocsMcpConfig, resolveConfiguredAgentSkills, } from "@farming-labs/docs/server";
|
|
6
10
|
import { loadDocsNavTree, loadDocsContent, flattenNavTree, normalizeDocsFrontmatterLastmod, } from "./content.js";
|
|
7
11
|
export { createFarmjsApiReference } from "./api-reference.js";
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const FARM_DOCS_BROWSER_CSS_PATH = "/__farm_docs/browser.css";
|
|
14
|
+
function loadFarmDocsBrowserCss() {
|
|
15
|
+
return fs.readFileSync(require.resolve("@farming-labs/theme/browser/css"), "utf8");
|
|
16
|
+
}
|
|
17
|
+
async function renderFarmDocsMarkup(element) {
|
|
18
|
+
const server = ReactDOMServer;
|
|
19
|
+
if (server.renderToReadableStream) {
|
|
20
|
+
const stream = await server.renderToReadableStream(element);
|
|
21
|
+
await stream.allReady;
|
|
22
|
+
return new Response(stream).text();
|
|
23
|
+
}
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const destination = new PassThrough();
|
|
26
|
+
const chunks = [];
|
|
27
|
+
destination.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
28
|
+
destination.on("error", reject);
|
|
29
|
+
destination.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
30
|
+
const renderer = server.renderToPipeableStream(element, {
|
|
31
|
+
onAllReady() {
|
|
32
|
+
renderer.pipe(destination);
|
|
33
|
+
},
|
|
34
|
+
onShellError(error) {
|
|
35
|
+
reject(error);
|
|
36
|
+
},
|
|
37
|
+
onError(error) {
|
|
38
|
+
if (!destination.readableEnded)
|
|
39
|
+
destination.destroy(error);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
8
44
|
function isApiReferenceOpenApiRequest(url) {
|
|
9
45
|
return url.searchParams.get("format")?.trim() === "openapi";
|
|
10
46
|
}
|
|
@@ -37,6 +73,64 @@ function safeUrlOrigin(value) {
|
|
|
37
73
|
return value;
|
|
38
74
|
}
|
|
39
75
|
}
|
|
76
|
+
function navigationItemName(item) {
|
|
77
|
+
return item.label?.trim() || item.title?.trim() || item.slug?.trim() || "Documentation";
|
|
78
|
+
}
|
|
79
|
+
function navigationItemUrl(item, entry) {
|
|
80
|
+
if (item.href?.trim())
|
|
81
|
+
return item.href.trim();
|
|
82
|
+
if (typeof item.slug !== "string")
|
|
83
|
+
return undefined;
|
|
84
|
+
const slug = item.slug.replace(/^\/+|\/+$/g, "");
|
|
85
|
+
return slug ? `/${entry}/${slug}` : `/${entry}`;
|
|
86
|
+
}
|
|
87
|
+
function navTreeFromNavigation(config, entry) {
|
|
88
|
+
const configured = config.navigation?.sidebar;
|
|
89
|
+
if (!Array.isArray(configured) || configured.length === 0)
|
|
90
|
+
return null;
|
|
91
|
+
const defaultOpen = config.theme?.name === "fumadocs-pixel-border";
|
|
92
|
+
function toNode(item) {
|
|
93
|
+
const children = item.children ?? item.items ?? [];
|
|
94
|
+
const name = navigationItemName(item);
|
|
95
|
+
const url = navigationItemUrl(item, entry);
|
|
96
|
+
if (children.length > 0) {
|
|
97
|
+
const mappedChildren = children.map(toNode).filter((node) => node !== null);
|
|
98
|
+
return {
|
|
99
|
+
type: "folder",
|
|
100
|
+
name,
|
|
101
|
+
...(defaultOpen ? { defaultOpen: true } : {}),
|
|
102
|
+
...(item.icon ? { icon: item.icon } : {}),
|
|
103
|
+
...(url
|
|
104
|
+
? {
|
|
105
|
+
index: {
|
|
106
|
+
type: "page",
|
|
107
|
+
name,
|
|
108
|
+
url,
|
|
109
|
+
...(item.icon ? { icon: item.icon } : {}),
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
: {}),
|
|
113
|
+
children: mappedChildren,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (!url)
|
|
117
|
+
return null;
|
|
118
|
+
return {
|
|
119
|
+
type: "page",
|
|
120
|
+
name,
|
|
121
|
+
url,
|
|
122
|
+
...(item.icon ? { icon: item.icon } : {}),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
name: typeof config.nav?.title === "string" && config.nav.title.trim()
|
|
127
|
+
? config.nav.title.trim()
|
|
128
|
+
: "Docs",
|
|
129
|
+
children: configured
|
|
130
|
+
.map((item) => toNode(item))
|
|
131
|
+
.filter((node) => node !== null),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
40
134
|
function resolvePreloadedContent(value) {
|
|
41
135
|
if (!value || typeof value !== "object")
|
|
42
136
|
return null;
|
|
@@ -74,6 +168,17 @@ function stripMarkdownText(content) {
|
|
|
74
168
|
.replace(/\n{3,}/g, "\n\n")
|
|
75
169
|
.trim();
|
|
76
170
|
}
|
|
171
|
+
function markdownStartsWithDescription(content, description) {
|
|
172
|
+
if (!description?.trim())
|
|
173
|
+
return false;
|
|
174
|
+
const withoutLeadingTitle = content
|
|
175
|
+
.trimStart()
|
|
176
|
+
.replace(/^#\s+[^\r\n]+(?:\r?\n|$)/, "")
|
|
177
|
+
.trimStart();
|
|
178
|
+
const firstBlock = withoutLeadingTitle.split(/\r?\n\s*\r?\n/, 1)[0] ?? "";
|
|
179
|
+
const normalize = (value) => stripMarkdownText(value).replace(/\s+/g, " ").trim();
|
|
180
|
+
return normalize(firstBlock) === normalize(description);
|
|
181
|
+
}
|
|
77
182
|
function normalizePathSegment(value) {
|
|
78
183
|
return value.replace(/^\/+|\/+$/g, "");
|
|
79
184
|
}
|
|
@@ -400,7 +505,7 @@ export function createDocsServer(config) {
|
|
|
400
505
|
? githubRaw.replace(/\/$/, "")
|
|
401
506
|
: githubRaw?.url.replace(/\/$/, "");
|
|
402
507
|
const githubBranch = typeof githubRaw === "object" ? (githubRaw.branch ?? "main") : "main";
|
|
403
|
-
const
|
|
508
|
+
const githubDirectory = typeof githubRaw === "object" ? githubRaw.directory?.replace(/^\/|\/$/g, "") : undefined;
|
|
404
509
|
const readingTimeOptions = resolveReadingTimeOptions(config.readingTime);
|
|
405
510
|
const aiConfig = { enabled: false, ...config.ai };
|
|
406
511
|
if (config.apiKey && !aiConfig.apiKey) {
|
|
@@ -471,9 +576,11 @@ export function createDocsServer(config) {
|
|
|
471
576
|
async function load({ pathname, locale }) {
|
|
472
577
|
const resolvedLocale = (i18n && locale && i18n.locales.includes(locale) ? locale : undefined) ?? i18n?.defaultLocale;
|
|
473
578
|
const ctx = resolveContextFromPath(pathname, resolvedLocale);
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
|
|
579
|
+
const configuredNavigation = navTreeFromNavigation(config, entry);
|
|
580
|
+
const tree = applySidebarFolderIndexBehavior(configuredNavigation ??
|
|
581
|
+
(preloaded
|
|
582
|
+
? navTreeFromMap(preloaded, ctx.dirPrefix, entry, ordering)
|
|
583
|
+
: loadDocsNavTree(ctx.contentDirAbs, entry, ordering)), {
|
|
477
584
|
sidebar: config.sidebar,
|
|
478
585
|
defaultBehavior: "link",
|
|
479
586
|
});
|
|
@@ -560,16 +667,24 @@ export function createDocsServer(config) {
|
|
|
560
667
|
const previousPage = currentIndex > 0 ? flatPages[currentIndex - 1] : null;
|
|
561
668
|
const nextPage = currentIndex < flatPages.length - 1 ? flatPages[currentIndex + 1] : null;
|
|
562
669
|
let editOnGithub;
|
|
563
|
-
if (githubRepo
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
670
|
+
if (githubRepo) {
|
|
671
|
+
const contentPath = normalizePathSegment(path.isAbsolute(ctx.contentDirRel)
|
|
672
|
+
? toPosixPath(path.relative(rootDir, ctx.contentDirRel))
|
|
673
|
+
: toPosixPath(ctx.contentDirRel));
|
|
674
|
+
const configuredDirectory = normalizePathSegment(githubDirectory ?? "");
|
|
675
|
+
const sourceDirectory = configuredDirectory &&
|
|
676
|
+
(contentPath === configuredDirectory || contentPath.startsWith(`${configuredDirectory}/`))
|
|
677
|
+
? contentPath
|
|
678
|
+
: joinPathParts(configuredDirectory, contentPath);
|
|
679
|
+
const sourcePath = joinPathParts(sourceDirectory, toPosixPath(relPath));
|
|
680
|
+
editOnGithub = `${githubRepo}/edit/${githubBranch}/${sourcePath}`;
|
|
567
681
|
}
|
|
568
682
|
const fallbackTitle = isIndex
|
|
569
683
|
? "Documentation"
|
|
570
684
|
: (slug.split("/").pop()?.replace(/-/g, " ") ?? "Documentation");
|
|
571
685
|
const title = data.title ?? fallbackTitle;
|
|
572
686
|
const description = data.description;
|
|
687
|
+
const descriptionInBody = markdownStartsWithDescription(humanRawContent, description);
|
|
573
688
|
const structuredData = renderDocsPageStructuredDataJson({
|
|
574
689
|
title,
|
|
575
690
|
description,
|
|
@@ -585,6 +700,7 @@ export function createDocsServer(config) {
|
|
|
585
700
|
url: currentUrl,
|
|
586
701
|
title,
|
|
587
702
|
description,
|
|
703
|
+
descriptionInBody,
|
|
588
704
|
rawContent: humanRawContent,
|
|
589
705
|
readingTime,
|
|
590
706
|
readingTimeFormat: readingTimeOptions.format,
|
|
@@ -1598,9 +1714,10 @@ export function createDocsServer(config) {
|
|
|
1598
1714
|
},
|
|
1599
1715
|
getNavigation(locale) {
|
|
1600
1716
|
const ctx = resolveContextFromPath(`/${entry}`, resolveLocaleForMcp(locale));
|
|
1601
|
-
return applySidebarFolderIndexBehavior(
|
|
1602
|
-
|
|
1603
|
-
|
|
1717
|
+
return applySidebarFolderIndexBehavior(navTreeFromNavigation(config, entry) ??
|
|
1718
|
+
(preloaded
|
|
1719
|
+
? navTreeFromMap(preloaded, ctx.dirPrefix, entry, ordering)
|
|
1720
|
+
: loadDocsNavTree(ctx.contentDirAbs, entry, ordering)), {
|
|
1604
1721
|
sidebar: config.sidebar,
|
|
1605
1722
|
defaultBehavior: "link",
|
|
1606
1723
|
});
|
|
@@ -1722,4 +1839,193 @@ export function createDocsServer(config) {
|
|
|
1722
1839
|
}
|
|
1723
1840
|
return { load, GET, HEAD, POST, MCP, handle };
|
|
1724
1841
|
}
|
|
1842
|
+
function escapeDocumentText(value) {
|
|
1843
|
+
return String(value ?? "")
|
|
1844
|
+
.replace(/&/g, "&")
|
|
1845
|
+
.replace(/</g, "<")
|
|
1846
|
+
.replace(/>/g, ">")
|
|
1847
|
+
.replace(/"/g, """);
|
|
1848
|
+
}
|
|
1849
|
+
function serializeInlineJson(value) {
|
|
1850
|
+
return JSON.stringify(value)
|
|
1851
|
+
.replace(/</g, "\\u003c")
|
|
1852
|
+
.replace(/>/g, "\\u003e")
|
|
1853
|
+
.replace(/\u2028/g, "\\u2028")
|
|
1854
|
+
.replace(/\u2029/g, "\\u2029");
|
|
1855
|
+
}
|
|
1856
|
+
function createClientDocsConfig(config) {
|
|
1857
|
+
const { apiKey: _apiKey, rootDir: _rootDir, contentDir: _contentDir, _preloadedContent, _preloadedAgentSkills, socialImage, ...clientConfig } = config;
|
|
1858
|
+
const ai = clientConfig.ai && typeof clientConfig.ai === "object"
|
|
1859
|
+
? {
|
|
1860
|
+
...clientConfig.ai,
|
|
1861
|
+
apiKey: undefined,
|
|
1862
|
+
providers: clientConfig.ai.providers && typeof clientConfig.ai.providers === "object"
|
|
1863
|
+
? Object.fromEntries(Object.entries(clientConfig.ai.providers).map(([name, provider]) => [
|
|
1864
|
+
name,
|
|
1865
|
+
provider && typeof provider === "object"
|
|
1866
|
+
? { ...provider, apiKey: undefined }
|
|
1867
|
+
: provider,
|
|
1868
|
+
]))
|
|
1869
|
+
: clientConfig.ai.providers,
|
|
1870
|
+
}
|
|
1871
|
+
: clientConfig.ai;
|
|
1872
|
+
return {
|
|
1873
|
+
...clientConfig,
|
|
1874
|
+
...(ai ? { ai } : {}),
|
|
1875
|
+
...(socialImage === false ? { socialImage: false } : {}),
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
function normalizedPublicRoute(value, fallback) {
|
|
1879
|
+
const normalized = typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
1880
|
+
if (normalized === "/")
|
|
1881
|
+
return "/";
|
|
1882
|
+
return `/${normalized.replace(/^\/+|\/+$/g, "")}`;
|
|
1883
|
+
}
|
|
1884
|
+
function isHtmlDocsPageRequest(config, request) {
|
|
1885
|
+
const method = request.method.toUpperCase();
|
|
1886
|
+
if (method !== "GET" && method !== "HEAD")
|
|
1887
|
+
return false;
|
|
1888
|
+
const url = new URL(request.url);
|
|
1889
|
+
const pathname = url.pathname === "/" ? "/" : url.pathname.replace(/\/+$/, "");
|
|
1890
|
+
const docsPath = normalizedPublicRoute(config.docsPath, `/${config.entry ?? "docs"}`);
|
|
1891
|
+
const isPagePath = docsPath === "/"
|
|
1892
|
+
? !pathname.endsWith(".md")
|
|
1893
|
+
: pathname === docsPath || pathname.startsWith(`${docsPath}/`);
|
|
1894
|
+
if (!isPagePath || pathname.endsWith(".md"))
|
|
1895
|
+
return false;
|
|
1896
|
+
const accept = request.headers.get("accept")?.toLowerCase() ?? "";
|
|
1897
|
+
return !accept.includes("text/markdown");
|
|
1898
|
+
}
|
|
1899
|
+
function runtimeFontClasses(fonts) {
|
|
1900
|
+
return Array.from(new Set([fonts?.body?.className, fonts?.body?.variable, fonts?.code?.variable].filter((value) => typeof value === "string" && value.length > 0))).join(" ");
|
|
1901
|
+
}
|
|
1902
|
+
function runtimeFontStyle(fonts) {
|
|
1903
|
+
const declarations = [];
|
|
1904
|
+
const bodyFontFamily = fonts?.body?.style?.fontFamily?.trim();
|
|
1905
|
+
const codeFontFamily = fonts?.code?.style?.fontFamily?.trim();
|
|
1906
|
+
if (bodyFontFamily) {
|
|
1907
|
+
declarations.push(`--font-sans:${bodyFontFamily}`, `--fd-font-sans:${bodyFontFamily}`);
|
|
1908
|
+
}
|
|
1909
|
+
if (codeFontFamily) {
|
|
1910
|
+
declarations.push(`--font-mono:${codeFontFamily}`, `--fd-font-mono:${codeFontFamily}`);
|
|
1911
|
+
}
|
|
1912
|
+
return declarations.join(";");
|
|
1913
|
+
}
|
|
1914
|
+
function runtimeFontPreloads(fonts) {
|
|
1915
|
+
const seen = new Set();
|
|
1916
|
+
const values = [fonts?.body, fonts?.code].flatMap((font) => font?.preloads ?? []);
|
|
1917
|
+
const unique = values.filter(({ href }) => {
|
|
1918
|
+
if (seen.has(href))
|
|
1919
|
+
return false;
|
|
1920
|
+
seen.add(href);
|
|
1921
|
+
return true;
|
|
1922
|
+
});
|
|
1923
|
+
return {
|
|
1924
|
+
markup: unique
|
|
1925
|
+
.map(({ href, type }) => `<link rel="preload" href="${escapeDocumentText(href)}" as="font" type="${escapeDocumentText(type)}" crossorigin>`)
|
|
1926
|
+
.join("\n "),
|
|
1927
|
+
header: unique
|
|
1928
|
+
.map(({ href, type }) => `<${href}>; rel=preload; as=font; type=${type}; crossorigin`)
|
|
1929
|
+
.join(", "),
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
function renderFarmDocsDocument(input) {
|
|
1933
|
+
const { config, data } = input;
|
|
1934
|
+
const description = data.description ?? config.metadata?.description;
|
|
1935
|
+
const themeName = config.theme?.name ?? "default";
|
|
1936
|
+
const favicon = typeof config.favicon === "string" ? config.favicon : undefined;
|
|
1937
|
+
const rootClasses = runtimeFontClasses(input.fonts);
|
|
1938
|
+
const rootStyle = runtimeFontStyle(input.fonts);
|
|
1939
|
+
const fontPreloads = runtimeFontPreloads(input.fonts).markup;
|
|
1940
|
+
return `<!doctype html>
|
|
1941
|
+
<html class="dark" lang="${escapeDocumentText(data.locale ?? "en")}" data-docs-theme="${escapeDocumentText(themeName)}" data-farm-docs-runtime="true">
|
|
1942
|
+
<head>
|
|
1943
|
+
<meta charset="utf-8">
|
|
1944
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1945
|
+
<meta name="generator" content="@farming-labs/farmjs">
|
|
1946
|
+
<title>${escapeDocumentText(data.title)}</title>
|
|
1947
|
+
${description ? `<meta name="description" content="${escapeDocumentText(description)}">` : ""}
|
|
1948
|
+
${favicon ? `<link rel="icon" href="${escapeDocumentText(favicon)}">` : ""}
|
|
1949
|
+
${fontPreloads}
|
|
1950
|
+
<link rel="stylesheet" href="${FARM_DOCS_BROWSER_CSS_PATH}">
|
|
1951
|
+
${input.stylesheets
|
|
1952
|
+
.map((href) => `<link rel="stylesheet" href="${escapeDocumentText(href)}">`)
|
|
1953
|
+
.join("\n ")}
|
|
1954
|
+
</head>
|
|
1955
|
+
<body>
|
|
1956
|
+
<div id="root"><div id="farm-docs-root"${rootClasses ? ` class="${escapeDocumentText(rootClasses)}"` : ""}${rootStyle ? ` style="${escapeDocumentText(rootStyle)}"` : ""}>${input.markup}</div></div>
|
|
1957
|
+
<script>window.__FARM_DOCS_ADAPTER__={config:${serializeInlineJson(createClientDocsConfig(config))},data:${serializeInlineJson(data)}};</script>
|
|
1958
|
+
<script type="module" src="${escapeDocumentText(input.clientEntry)}"></script>
|
|
1959
|
+
</body>
|
|
1960
|
+
</html>`;
|
|
1961
|
+
}
|
|
1962
|
+
/**
|
|
1963
|
+
* Create the complete Farm docs runtime owned by this adapter.
|
|
1964
|
+
*
|
|
1965
|
+
* Farm core supplies host assets and module loading; this adapter owns route
|
|
1966
|
+
* classification, docs APIs, content loading, React rendering, and hydration
|
|
1967
|
+
* state for every documentation request.
|
|
1968
|
+
*/
|
|
1969
|
+
export function createFarmDocsRuntimeHandler(config, options = {}) {
|
|
1970
|
+
const runtimeConfig = {
|
|
1971
|
+
...config,
|
|
1972
|
+
rootDir: options.rootDir ?? config.rootDir ?? process.cwd(),
|
|
1973
|
+
};
|
|
1974
|
+
const docsServer = createDocsServer(runtimeConfig);
|
|
1975
|
+
return async function handleFarmDocsRuntimeRequest(request) {
|
|
1976
|
+
const url = new URL(request.url);
|
|
1977
|
+
if (url.pathname === FARM_DOCS_BROWSER_CSS_PATH) {
|
|
1978
|
+
return new Response(request.method.toUpperCase() === "HEAD" ? null : loadFarmDocsBrowserCss(), {
|
|
1979
|
+
status: 200,
|
|
1980
|
+
headers: {
|
|
1981
|
+
"Content-Type": "text/css; charset=utf-8",
|
|
1982
|
+
"Cache-Control": "public, max-age=31536000, immutable",
|
|
1983
|
+
},
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
if (!isHtmlDocsPageRequest(runtimeConfig, request)) {
|
|
1987
|
+
return docsServer.handle(request);
|
|
1988
|
+
}
|
|
1989
|
+
let data;
|
|
1990
|
+
try {
|
|
1991
|
+
data = await docsServer.load({ pathname: url.pathname });
|
|
1992
|
+
}
|
|
1993
|
+
catch (error) {
|
|
1994
|
+
const status = error &&
|
|
1995
|
+
typeof error === "object" &&
|
|
1996
|
+
typeof error.status === "number"
|
|
1997
|
+
? error.status
|
|
1998
|
+
: 500;
|
|
1999
|
+
if (status === 404)
|
|
2000
|
+
return null;
|
|
2001
|
+
throw error;
|
|
2002
|
+
}
|
|
2003
|
+
const reactModule = options.loadReactModule
|
|
2004
|
+
? await options.loadReactModule()
|
|
2005
|
+
: (await import("./react.js"));
|
|
2006
|
+
const markup = await renderFarmDocsMarkup(createElement(reactModule.FarmDocsPage, {
|
|
2007
|
+
config: runtimeConfig,
|
|
2008
|
+
data,
|
|
2009
|
+
}));
|
|
2010
|
+
const fonts = await options.resolveLayoutFonts?.(url.pathname);
|
|
2011
|
+
const fontPreloadHeader = runtimeFontPreloads(fonts).header;
|
|
2012
|
+
const html = renderFarmDocsDocument({
|
|
2013
|
+
config: runtimeConfig,
|
|
2014
|
+
data,
|
|
2015
|
+
markup,
|
|
2016
|
+
clientEntry: options.clientEntry ?? "/farm-client.js",
|
|
2017
|
+
stylesheets: options.stylesheets ?? [],
|
|
2018
|
+
fonts,
|
|
2019
|
+
});
|
|
2020
|
+
return new Response(request.method.toUpperCase() === "HEAD" ? null : html, {
|
|
2021
|
+
status: 200,
|
|
2022
|
+
headers: {
|
|
2023
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
2024
|
+
"Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
|
|
2025
|
+
"X-Farm-Docs-Adapter": "@farming-labs/farmjs",
|
|
2026
|
+
...(fontPreloadHeader ? { Link: fontPreloadHeader } : {}),
|
|
2027
|
+
},
|
|
2028
|
+
});
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
1725
2031
|
//# sourceMappingURL=server.js.map
|