@farming-labs/theme 0.1.83 → 0.1.85
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 +3 -1
- package/dist/docs-api.mjs +64 -5
- package/dist/docs-layout.mjs +38 -1
- package/dist/docs-page-client.d.mts +6 -0
- package/dist/docs-page-client.mjs +8 -3
- package/dist/json-ld.mjs +7 -0
- package/dist/tanstack-layout.d.mts +2 -0
- package/dist/tanstack-layout.mjs +9 -3
- package/package.json +2 -2
package/dist/docs-api.d.mts
CHANGED
|
@@ -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
|
|
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,8 @@ 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,
|
|
214
|
+
structuredData: true,
|
|
206
215
|
agentFeedback: feedback.enabled,
|
|
207
216
|
locales: localesEnabled
|
|
208
217
|
},
|
|
@@ -252,6 +261,25 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, site
|
|
|
252
261
|
api: `${DEFAULT_DOCS_API_ROUTE}?format=sitemap-md`
|
|
253
262
|
}
|
|
254
263
|
},
|
|
264
|
+
robots: {
|
|
265
|
+
enabled: robotsEnabled,
|
|
266
|
+
route: DEFAULT_ROBOTS_TXT_ROUTE,
|
|
267
|
+
defaultRoute: DEFAULT_ROBOTS_TXT_ROUTE
|
|
268
|
+
},
|
|
269
|
+
structuredData: {
|
|
270
|
+
enabled: true,
|
|
271
|
+
format: "application/ld+json",
|
|
272
|
+
schema: "https://schema.org/TechArticle",
|
|
273
|
+
fields: [
|
|
274
|
+
"headline",
|
|
275
|
+
"description",
|
|
276
|
+
"url",
|
|
277
|
+
"dateModified",
|
|
278
|
+
"breadcrumb"
|
|
279
|
+
],
|
|
280
|
+
canonicalUrlField: "url",
|
|
281
|
+
breadcrumbType: "BreadcrumbList"
|
|
282
|
+
},
|
|
255
283
|
search: {
|
|
256
284
|
enabled: searchEnabled,
|
|
257
285
|
endpoint: `${DEFAULT_DOCS_API_ROUTE}?query={query}`,
|
|
@@ -915,16 +943,17 @@ function renderMarkdownDocument(page) {
|
|
|
915
943
|
lines.push("", page.agentFallbackRawContent ?? page.rawContent ?? page.content);
|
|
916
944
|
return lines.join("\n");
|
|
917
945
|
}
|
|
918
|
-
function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitemap }) {
|
|
946
|
+
function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitemap, robots }) {
|
|
919
947
|
const normalizedEntry = normalizePathSegment(entry) || "docs";
|
|
920
948
|
const siteTitle = compactSkillText(llms.siteTitle ?? "Documentation");
|
|
921
949
|
const siteDescription = llms.siteDescription ? compactSkillText(llms.siteDescription) : void 0;
|
|
922
950
|
const searchEnabled = isSearchEnabled(search);
|
|
923
951
|
const sitemapConfig = resolveDocsSitemapConfig(sitemap, { baseUrl: llms.baseUrl });
|
|
952
|
+
const robotsEnabled = isRobotsDiscoveryEnabled(robots);
|
|
924
953
|
const lines = [
|
|
925
954
|
"---",
|
|
926
955
|
"name: docs",
|
|
927
|
-
`description: ${toYamlString(truncateSkillDescription(`Use ${siteTitle} through markdown routes, llms.txt, agent discovery, search, and MCP when available.`))}`,
|
|
956
|
+
`description: ${toYamlString(truncateSkillDescription(`Use ${siteTitle} through markdown routes, llms.txt, robots.txt, agent discovery, search, and MCP when available.`))}`,
|
|
928
957
|
"---",
|
|
929
958
|
"",
|
|
930
959
|
`# ${siteTitle} Skill`,
|
|
@@ -939,9 +968,11 @@ function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitem
|
|
|
939
968
|
if (sitemapConfig.xml.enabled) lines.push(`- Use ${sitemapConfig.xml.route} to check canonical page freshness.`);
|
|
940
969
|
if (sitemapConfig.markdown.enabled) lines.push(`- Use ${sitemapConfig.markdown.route} for a semantic docs map.`);
|
|
941
970
|
}
|
|
971
|
+
if (robotsEnabled) lines.push(`- Check ${DEFAULT_ROBOTS_TXT_ROUTE} for crawler and AI-agent access policy.`);
|
|
942
972
|
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
973
|
if (feedback.enabled) lines.push(`- Read ${feedback.schemaRoute} before posting agent feedback to ${feedback.route}.`);
|
|
944
974
|
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`);
|
|
975
|
+
if (robotsEnabled) lines.push(`- Robots policy: ${DEFAULT_ROBOTS_TXT_ROUTE}`);
|
|
945
976
|
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
977
|
if (sitemapConfig.enabled) {
|
|
947
978
|
if (sitemapConfig.xml.enabled) lines.push(`- Sitemap XML: ${sitemapConfig.xml.route}`);
|
|
@@ -1507,6 +1538,31 @@ function readSitemapConfig(root) {
|
|
|
1507
1538
|
}
|
|
1508
1539
|
}
|
|
1509
1540
|
}
|
|
1541
|
+
function readRobotsConfig(root) {
|
|
1542
|
+
for (const ext of FILE_EXTS) {
|
|
1543
|
+
const configPath = path.join(root, `docs.config.${ext}`);
|
|
1544
|
+
if (!fs.existsSync(configPath)) continue;
|
|
1545
|
+
try {
|
|
1546
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
1547
|
+
if (!content.includes("robots")) return void 0;
|
|
1548
|
+
if (/robots\s*:\s*false/.test(content)) return false;
|
|
1549
|
+
if (/robots\s*:\s*true/.test(content)) return true;
|
|
1550
|
+
const robotsBlock = content.match(/robots\s*:\s*\{([\s\S]*?)\n\s*\}/)?.[1] ?? "";
|
|
1551
|
+
const enabledMatch = robotsBlock.match(/enabled\s*:\s*(true|false)/);
|
|
1552
|
+
const pathMatch = robotsBlock.match(/path\s*:\s*["']([^"']+)["']/);
|
|
1553
|
+
const baseUrlMatch = robotsBlock.match(/baseUrl\s*:\s*["']([^"']+)["']/);
|
|
1554
|
+
const aiMatch = robotsBlock.match(/ai\s*:\s*["'](allow|disallow)["']/);
|
|
1555
|
+
return {
|
|
1556
|
+
enabled: enabledMatch ? enabledMatch[1] === "true" : true,
|
|
1557
|
+
path: pathMatch?.[1],
|
|
1558
|
+
baseUrl: baseUrlMatch?.[1],
|
|
1559
|
+
ai: aiMatch?.[1]
|
|
1560
|
+
};
|
|
1561
|
+
} catch {
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1510
1566
|
function generateLlmsTxt(indexes, options) {
|
|
1511
1567
|
const { siteTitle = "Documentation", siteDescription, baseUrl = "" } = options;
|
|
1512
1568
|
let llmsTxt = `# ${siteTitle}\n\n`;
|
|
@@ -1568,6 +1624,7 @@ function createDocsAPI(options) {
|
|
|
1568
1624
|
const searchConfig = options?.search;
|
|
1569
1625
|
const llmsConfig = readLlmsTxtConfig(root);
|
|
1570
1626
|
const sitemapConfig = options?.sitemap ?? readSitemapConfig(root);
|
|
1627
|
+
const robotsConfig = options?.robots ?? readRobotsConfig(root);
|
|
1571
1628
|
const mcpConfig = resolveDocsMcpConfig(options?.mcp ?? readMcpConfig(root), { defaultName: llmsConfig.siteTitle ?? "Documentation" });
|
|
1572
1629
|
function resolveDocsDirCandidates(locale) {
|
|
1573
1630
|
const relativeCandidates = /* @__PURE__ */ new Set();
|
|
@@ -1708,7 +1765,8 @@ function createDocsAPI(options) {
|
|
|
1708
1765
|
mcp: mcpConfig,
|
|
1709
1766
|
feedback: agentFeedbackConfig,
|
|
1710
1767
|
llms: llmsConfig,
|
|
1711
|
-
sitemap: sitemapConfig
|
|
1768
|
+
sitemap: sitemapConfig,
|
|
1769
|
+
robots: robotsConfig
|
|
1712
1770
|
}), { headers: {
|
|
1713
1771
|
"Cache-Control": "public, max-age=0, s-maxage=3600",
|
|
1714
1772
|
"X-Robots-Tag": "noindex"
|
|
@@ -1751,7 +1809,8 @@ function createDocsAPI(options) {
|
|
|
1751
1809
|
mcp: mcpConfig,
|
|
1752
1810
|
feedback: agentFeedbackConfig,
|
|
1753
1811
|
llms: llmsConfig,
|
|
1754
|
-
sitemap: sitemapConfig
|
|
1812
|
+
sitemap: sitemapConfig,
|
|
1813
|
+
robots: robotsConfig
|
|
1755
1814
|
}), { headers: {
|
|
1756
1815
|
"Content-Type": "text/markdown; charset=utf-8",
|
|
1757
1816
|
"Cache-Control": "public, max-age=0, s-maxage=3600",
|
package/dist/docs-layout.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import path from "node:path";
|
|
|
11
11
|
import matter from "gray-matter";
|
|
12
12
|
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
|
13
13
|
import { Suspense } from "react";
|
|
14
|
-
import { applySidebarFolderIndexBehavior, buildPageOpenGraph, buildPageTwitter, resolveChangelogConfig, resolveDocsAgentMdxContent, resolveDocsAnalyticsConfig, resolvePageSidebarFolderIndexBehavior, toDocsMarkdownUrl } from "@farming-labs/docs";
|
|
14
|
+
import { applySidebarFolderIndexBehavior, buildPageOpenGraph, buildPageTwitter, renderDocsPageStructuredDataJson, resolveChangelogConfig, resolveDocsAgentMdxContent, resolveDocsAnalyticsConfig, resolveDocsMetadataBaseUrl, resolvePageSidebarFolderIndexBehavior, toDocsMarkdownUrl } from "@farming-labs/docs";
|
|
15
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
16
|
|
|
17
17
|
//#region src/docs-layout.tsx
|
|
@@ -380,6 +380,41 @@ function buildReadingTimeMap(config, ctx, options) {
|
|
|
380
380
|
scan(docsDir, []);
|
|
381
381
|
return map;
|
|
382
382
|
}
|
|
383
|
+
function findDocsPageFile(dir) {
|
|
384
|
+
return ["page.mdx", "page.md"].map((fileName) => path.join(dir, fileName)).find(fs.existsSync);
|
|
385
|
+
}
|
|
386
|
+
function buildStructuredDataMap(config, ctx) {
|
|
387
|
+
const docsDir = ctx.docsDir;
|
|
388
|
+
const map = {};
|
|
389
|
+
const excludedDirs = getExcludedDocsDirs(config, ctx);
|
|
390
|
+
const baseUrl = resolveDocsMetadataBaseUrl(config);
|
|
391
|
+
function scan(dir, slugParts) {
|
|
392
|
+
if (!fs.existsSync(dir)) return;
|
|
393
|
+
if (isExcludedDir(dir, excludedDirs)) return;
|
|
394
|
+
const pagePath = findDocsPageFile(dir);
|
|
395
|
+
if (pagePath) {
|
|
396
|
+
const { data } = matter(fs.readFileSync(pagePath, "utf-8"));
|
|
397
|
+
const route = slugParts.length === 0 ? `/${ctx.entryPath}` : `/${ctx.entryPath}/${slugParts.join("/")}`;
|
|
398
|
+
const title = typeof data.title === "string" ? data.title : slugParts.at(-1)?.replace(/-/g, " ") || "Documentation";
|
|
399
|
+
const description = typeof data.description === "string" ? data.description : void 0;
|
|
400
|
+
const stat = fs.statSync(pagePath);
|
|
401
|
+
map[route] = renderDocsPageStructuredDataJson({
|
|
402
|
+
title,
|
|
403
|
+
description,
|
|
404
|
+
url: withLangInUrl(route, ctx.locale),
|
|
405
|
+
baseUrl,
|
|
406
|
+
entry: ctx.entryPath,
|
|
407
|
+
dateModified: stat.mtime.toISOString()
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
for (const name of fs.readdirSync(dir)) {
|
|
411
|
+
const full = path.join(dir, name);
|
|
412
|
+
if (fs.statSync(full).isDirectory()) scan(full, [...slugParts, name]);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
scan(docsDir, []);
|
|
416
|
+
return map;
|
|
417
|
+
}
|
|
383
418
|
/**
|
|
384
419
|
* Build a Next.js Metadata object from the docs config.
|
|
385
420
|
*
|
|
@@ -638,6 +673,7 @@ function createDocsLayout(config, options) {
|
|
|
638
673
|
enabledByDefault: readingTimeEnabledByDefault,
|
|
639
674
|
wordsPerMinute: readingTimeWordsPerMinute
|
|
640
675
|
});
|
|
676
|
+
const structuredDataMap = buildStructuredDataMap(config, localeContext);
|
|
641
677
|
const readingTimeEnabled = readingTimeEnabledByDefault || Object.keys(readingTimeMap).length > 0;
|
|
642
678
|
return function DocsLayoutWrapper({ children }) {
|
|
643
679
|
const tree = applySidebarFolderIndexBehavior(buildTree(config, localeContext, !!sidebarFlat), {
|
|
@@ -736,6 +772,7 @@ function createDocsLayout(config, options) {
|
|
|
736
772
|
lastUpdatedPosition,
|
|
737
773
|
readingTimeEnabled,
|
|
738
774
|
readingTimeMap,
|
|
775
|
+
structuredDataMap,
|
|
739
776
|
llmsTxtEnabled,
|
|
740
777
|
descriptionMap,
|
|
741
778
|
feedbackEnabled: feedbackConfig.enabled,
|
|
@@ -43,6 +43,10 @@ interface DocsPageClientProps {
|
|
|
43
43
|
readingTimeMap?: Record<string, number>;
|
|
44
44
|
/** Direct reading-time override for the current page. */
|
|
45
45
|
readingTime?: number | null;
|
|
46
|
+
/** Map of pathname → serialized Schema.org JSON-LD. */
|
|
47
|
+
structuredDataMap?: Record<string, string>;
|
|
48
|
+
/** Direct serialized Schema.org JSON-LD override for the current page. */
|
|
49
|
+
structuredData?: string;
|
|
46
50
|
/**
|
|
47
51
|
* Whether path-based reading time values should render by default.
|
|
48
52
|
* Explicit `readingTime` overrides can still render when this is false.
|
|
@@ -90,6 +94,8 @@ declare function DocsPageClient({
|
|
|
90
94
|
lastModified: lastModifiedProp,
|
|
91
95
|
readingTimeMap,
|
|
92
96
|
readingTime: readingTimeProp,
|
|
97
|
+
structuredDataMap,
|
|
98
|
+
structuredData: structuredDataProp,
|
|
93
99
|
readingTimeEnabled,
|
|
94
100
|
lastUpdatedEnabled,
|
|
95
101
|
lastUpdatedPosition,
|
|
@@ -5,6 +5,7 @@ import { PageActions } from "./page-actions.mjs";
|
|
|
5
5
|
import { useWindowSearchParams } from "./client-location.mjs";
|
|
6
6
|
import { DocsFeedback } from "./docs-feedback.mjs";
|
|
7
7
|
import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
|
|
8
|
+
import { escapeJsonLdForScript } from "./json-ld.mjs";
|
|
8
9
|
import { Children, Fragment, cloneElement, isValidElement, useEffect, useState } from "react";
|
|
9
10
|
import { DocsBody, DocsPage, EditOnGitHub } from "fumadocs-ui/layouts/docs/page";
|
|
10
11
|
import { createPortal } from "react-dom";
|
|
@@ -163,7 +164,7 @@ function TitleDecorations({ description, belowTitle }) {
|
|
|
163
164
|
if (!description && !belowTitle) return null;
|
|
164
165
|
return /* @__PURE__ */ jsx(Fragment$1, { children: Children.toArray([description, belowTitle].filter(Boolean)) });
|
|
165
166
|
}
|
|
166
|
-
function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled = true, changelogBasePath, entry = "docs", locale, copyMarkdown = false, openDocs = false, openDocsProviders, pageActionsPosition = "below-title", pageActionsAlignment = "left", githubUrl, contentDir, githubBranch = "main", githubDirectory, editOnGithubUrl, lastModifiedMap, lastModified: lastModifiedProp, readingTimeMap, readingTime: readingTimeProp, readingTimeEnabled = false, lastUpdatedEnabled = true, lastUpdatedPosition = "footer", llmsTxtEnabled = false, descriptionMap, description, feedbackEnabled = false, feedbackQuestion, feedbackPlaceholder, feedbackPositiveLabel, feedbackNegativeLabel, feedbackSubmitLabel, feedbackOnFeedback, analytics = false, children }) {
|
|
167
|
+
function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled = true, changelogBasePath, entry = "docs", locale, copyMarkdown = false, openDocs = false, openDocsProviders, pageActionsPosition = "below-title", pageActionsAlignment = "left", githubUrl, contentDir, githubBranch = "main", githubDirectory, editOnGithubUrl, lastModifiedMap, lastModified: lastModifiedProp, readingTimeMap, readingTime: readingTimeProp, structuredDataMap, structuredData: structuredDataProp, readingTimeEnabled = false, lastUpdatedEnabled = true, lastUpdatedPosition = "footer", llmsTxtEnabled = false, descriptionMap, description, feedbackEnabled = false, feedbackQuestion, feedbackPlaceholder, feedbackPositiveLabel, feedbackNegativeLabel, feedbackSubmitLabel, feedbackOnFeedback, analytics = false, children }) {
|
|
167
168
|
const fdTocStyle = tocStyle === "directional" ? "clerk" : void 0;
|
|
168
169
|
const [toc, setToc] = useState([]);
|
|
169
170
|
const [titlePortalHost, setTitlePortalHost] = useState(null);
|
|
@@ -175,6 +176,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
175
176
|
const normalizedPath = (browserPath ?? pathname).replace(/\/$/, "") || "/";
|
|
176
177
|
const isChangelogRoute = !!(changelogBasePath && (normalizedPath === changelogBasePath || normalizedPath.startsWith(`${changelogBasePath}/`)));
|
|
177
178
|
const matchedReadingTime = readingTimeMap?.[normalizedPath];
|
|
179
|
+
const structuredDataJson = !isChangelogRoute ? structuredDataProp ?? structuredDataMap?.[normalizedPath] : void 0;
|
|
178
180
|
useEffect(() => {
|
|
179
181
|
if (!analytics) return;
|
|
180
182
|
emitClientAnalyticsEvent({
|
|
@@ -341,7 +343,10 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
341
343
|
belowTitle: belowTitleBlock
|
|
342
344
|
}), titlePortalHost) : null;
|
|
343
345
|
const renderedChildren = Children.toArray(decoratedChildren);
|
|
344
|
-
return /* @__PURE__ */ jsxs(
|
|
346
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [structuredDataJson && /* @__PURE__ */ jsx("script", {
|
|
347
|
+
type: "application/ld+json",
|
|
348
|
+
dangerouslySetInnerHTML: { __html: escapeJsonLdForScript(structuredDataJson) }
|
|
349
|
+
}), /* @__PURE__ */ jsxs(DocsPage, {
|
|
345
350
|
full: false,
|
|
346
351
|
toc,
|
|
347
352
|
tableOfContent: {
|
|
@@ -428,7 +433,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
428
433
|
]
|
|
429
434
|
})
|
|
430
435
|
]
|
|
431
|
-
});
|
|
436
|
+
})] });
|
|
432
437
|
}
|
|
433
438
|
|
|
434
439
|
//#endregion
|
package/dist/json-ld.mjs
ADDED
|
@@ -31,6 +31,7 @@ interface TanstackDocsLayoutProps {
|
|
|
31
31
|
description?: string;
|
|
32
32
|
readingTime?: number | null;
|
|
33
33
|
lastModified?: string;
|
|
34
|
+
structuredData?: string;
|
|
34
35
|
editOnGithubUrl?: string;
|
|
35
36
|
children: ReactNode;
|
|
36
37
|
}
|
|
@@ -41,6 +42,7 @@ declare function TanstackDocsLayout({
|
|
|
41
42
|
description,
|
|
42
43
|
readingTime,
|
|
43
44
|
lastModified,
|
|
45
|
+
structuredData,
|
|
44
46
|
editOnGithubUrl,
|
|
45
47
|
children
|
|
46
48
|
}: TanstackDocsLayoutProps): react_jsx_runtime0.JSX.Element;
|
package/dist/tanstack-layout.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { withLangInUrl } from "./i18n.mjs";
|
|
2
|
+
import { escapeJsonLdForScript } from "./json-ld.mjs";
|
|
2
3
|
import { DocsPageClient } from "./docs-page-client.mjs";
|
|
3
4
|
import { DocsAIFeatures } from "./docs-ai-features.mjs";
|
|
4
5
|
import { DocsCommandSearch } from "./docs-command-search.mjs";
|
|
@@ -8,7 +9,7 @@ import { LocaleThemeControl } from "./locale-theme-control.mjs";
|
|
|
8
9
|
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
|
9
10
|
import { Suspense } from "react";
|
|
10
11
|
import { applySidebarFolderIndexBehavior, resolveDocsAnalyticsConfig } from "@farming-labs/docs";
|
|
11
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
13
|
|
|
13
14
|
//#region src/tanstack-layout.tsx
|
|
14
15
|
function resolveTreeIcon(icon, registry) {
|
|
@@ -207,7 +208,7 @@ function resolveFeedbackConfig(feedback) {
|
|
|
207
208
|
function ForcedThemeScript({ theme }) {
|
|
208
209
|
return /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: `document.documentElement.classList.remove('light','dark');document.documentElement.classList.add('${theme === "light" || theme === "dark" ? theme : "light"}');` } });
|
|
209
210
|
}
|
|
210
|
-
function TanstackDocsLayout({ config, tree, locale, description, readingTime, lastModified, editOnGithubUrl, children }) {
|
|
211
|
+
function TanstackDocsLayout({ config, tree, locale, description, readingTime, lastModified, structuredData, editOnGithubUrl, children }) {
|
|
211
212
|
const tocConfig = config.theme?.ui?.layout?.toc;
|
|
212
213
|
const tocEnabled = tocConfig?.enabled !== false;
|
|
213
214
|
const tocStyle = tocConfig?.style;
|
|
@@ -290,7 +291,7 @@ function TanstackDocsLayout({ config, tree, locale, description, readingTime, la
|
|
|
290
291
|
collapsible: sidebarProps.collapsible !== false,
|
|
291
292
|
flat: !!sidebarFlat
|
|
292
293
|
});
|
|
293
|
-
|
|
294
|
+
const layout = /* @__PURE__ */ jsxs(DocsLayout, {
|
|
294
295
|
tree: resolvedTree,
|
|
295
296
|
nav: {
|
|
296
297
|
title: navTitle,
|
|
@@ -364,6 +365,11 @@ function TanstackDocsLayout({ config, tree, locale, description, readingTime, la
|
|
|
364
365
|
})
|
|
365
366
|
]
|
|
366
367
|
});
|
|
368
|
+
if (!structuredData) return layout;
|
|
369
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("script", {
|
|
370
|
+
type: "application/ld+json",
|
|
371
|
+
dangerouslySetInnerHTML: { __html: escapeJsonLdForScript(structuredData) }
|
|
372
|
+
}), layout] });
|
|
367
373
|
}
|
|
368
374
|
|
|
369
375
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/theme",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.85",
|
|
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.85"
|
|
143
143
|
},
|
|
144
144
|
"peerDependencies": {
|
|
145
145
|
"@farming-labs/docs": ">=0.0.1",
|