@farming-labs/next 0.1.96 → 0.1.98
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.mjs +160 -55
- package/package.json +3 -3
package/dist/config.mjs
CHANGED
|
@@ -78,20 +78,7 @@ ${GENERATED_BANNER}
|
|
|
78
78
|
import docsConfig from "@/docs.config";
|
|
79
79
|
import { createDocsAPI } from "@farming-labs/next/api";
|
|
80
80
|
|
|
81
|
-
export const { GET, POST } = createDocsAPI(
|
|
82
|
-
entry: docsConfig.entry,
|
|
83
|
-
contentDir: docsConfig.contentDir,
|
|
84
|
-
i18n: docsConfig.i18n,
|
|
85
|
-
changelog: docsConfig.changelog,
|
|
86
|
-
feedback: docsConfig.feedback,
|
|
87
|
-
mcp: docsConfig.mcp,
|
|
88
|
-
llmsTxt: docsConfig.llmsTxt,
|
|
89
|
-
sitemap: docsConfig.sitemap,
|
|
90
|
-
search: docsConfig.search,
|
|
91
|
-
analytics: docsConfig.analytics,
|
|
92
|
-
observability: docsConfig.observability,
|
|
93
|
-
ai: docsConfig.ai,
|
|
94
|
-
});
|
|
81
|
+
export const { GET, POST } = createDocsAPI(docsConfig);
|
|
95
82
|
|
|
96
83
|
export const revalidate = false;
|
|
97
84
|
`;
|
|
@@ -100,16 +87,7 @@ ${GENERATED_BANNER}
|
|
|
100
87
|
import docsConfig from "@/docs.config";
|
|
101
88
|
import { createDocsMCPAPI } from "@farming-labs/next/api";
|
|
102
89
|
|
|
103
|
-
export const { GET, POST, DELETE } = createDocsMCPAPI(
|
|
104
|
-
entry: docsConfig.entry,
|
|
105
|
-
contentDir: docsConfig.contentDir,
|
|
106
|
-
nav: docsConfig.nav,
|
|
107
|
-
ordering: docsConfig.ordering,
|
|
108
|
-
search: docsConfig.search,
|
|
109
|
-
analytics: docsConfig.analytics,
|
|
110
|
-
observability: docsConfig.observability,
|
|
111
|
-
mcp: docsConfig.mcp,
|
|
112
|
-
});
|
|
90
|
+
export const { GET, POST, DELETE } = createDocsMCPAPI(docsConfig);
|
|
113
91
|
|
|
114
92
|
export const revalidate = false;
|
|
115
93
|
`;
|
|
@@ -173,6 +151,7 @@ const DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE = "/.well-known/llms.txt";
|
|
|
173
151
|
const DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE = "/.well-known/llms-full.txt";
|
|
174
152
|
const DEFAULT_SKILL_MD_ROUTE = "/skill.md";
|
|
175
153
|
const DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE = "/.well-known/skill.md";
|
|
154
|
+
const DEFAULT_ROBOTS_TXT_ROUTE = "/robots.txt";
|
|
176
155
|
const DEFAULT_SITEMAP_XML_ROUTE = "/sitemap.xml";
|
|
177
156
|
const DEFAULT_SITEMAP_MD_ROUTE = "/sitemap.md";
|
|
178
157
|
const DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE = "/.well-known/sitemap.md";
|
|
@@ -451,9 +430,7 @@ function extractRootObjectLiteral(content) {
|
|
|
451
430
|
}
|
|
452
431
|
}
|
|
453
432
|
}
|
|
454
|
-
function
|
|
455
|
-
const block = extractRootObjectLiteral(content);
|
|
456
|
-
if (!block) return void 0;
|
|
433
|
+
function findTopLevelPropertyValueIndex(block, key) {
|
|
457
434
|
let objectDepth = 0;
|
|
458
435
|
let arrayDepth = 0;
|
|
459
436
|
let parenDepth = 0;
|
|
@@ -535,26 +512,102 @@ function readTopLevelStringProperty(content, key) {
|
|
|
535
512
|
if (block[cursor] !== ":") continue;
|
|
536
513
|
cursor += 1;
|
|
537
514
|
while (/\s/.test(block[cursor] ?? "")) cursor += 1;
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
515
|
+
return cursor;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
function findMatchingObjectEnd(block, start) {
|
|
519
|
+
let depth = 0;
|
|
520
|
+
let inString = null;
|
|
521
|
+
let inLineComment = false;
|
|
522
|
+
let inBlockComment = false;
|
|
523
|
+
let escaped = false;
|
|
524
|
+
for (let index = start; index < block.length; index += 1) {
|
|
525
|
+
const char = block[index];
|
|
526
|
+
const next = block[index + 1];
|
|
527
|
+
if (inLineComment) {
|
|
528
|
+
if (char === "\n") inLineComment = false;
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
if (inBlockComment) {
|
|
532
|
+
if (char === "*" && next === "/") {
|
|
533
|
+
inBlockComment = false;
|
|
534
|
+
index += 1;
|
|
535
|
+
}
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
if (inString) {
|
|
539
|
+
if (escaped) {
|
|
540
|
+
escaped = false;
|
|
550
541
|
continue;
|
|
551
542
|
}
|
|
552
|
-
if (
|
|
553
|
-
|
|
543
|
+
if (char === "\\") {
|
|
544
|
+
escaped = true;
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
if (char === inString) inString = null;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (char === "/" && next === "/") {
|
|
551
|
+
inLineComment = true;
|
|
552
|
+
index += 1;
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
if (char === "/" && next === "*") {
|
|
556
|
+
inBlockComment = true;
|
|
557
|
+
index += 1;
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
if (char === "\"" || char === "'" || char === "`") {
|
|
561
|
+
inString = char;
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
if (char === "{") {
|
|
565
|
+
depth += 1;
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
if (char !== "}") continue;
|
|
569
|
+
depth -= 1;
|
|
570
|
+
if (depth === 0) return index;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
function readTopLevelStringProperty(content, key) {
|
|
574
|
+
const block = extractRootObjectLiteral(content);
|
|
575
|
+
if (!block) return void 0;
|
|
576
|
+
const cursor = findTopLevelPropertyValueIndex(block, key);
|
|
577
|
+
if (cursor === void 0) return void 0;
|
|
578
|
+
const quote = block[cursor];
|
|
579
|
+
if (quote !== "\"" && quote !== "'") return void 0;
|
|
580
|
+
let value = "";
|
|
581
|
+
for (let index = cursor + 1; index < block.length; index += 1) {
|
|
582
|
+
const valueChar = block[index];
|
|
583
|
+
if (valueChar === "\\") {
|
|
584
|
+
const escapedChar = block[index + 1];
|
|
585
|
+
if (escapedChar) {
|
|
586
|
+
value += escapedChar;
|
|
587
|
+
index += 1;
|
|
588
|
+
}
|
|
589
|
+
continue;
|
|
554
590
|
}
|
|
555
|
-
return;
|
|
591
|
+
if (valueChar === quote) return value;
|
|
592
|
+
value += valueChar;
|
|
556
593
|
}
|
|
557
594
|
}
|
|
595
|
+
function readTopLevelBooleanProperty(content, key) {
|
|
596
|
+
const block = extractRootObjectLiteral(content);
|
|
597
|
+
if (!block) return void 0;
|
|
598
|
+
const cursor = findTopLevelPropertyValueIndex(block, key);
|
|
599
|
+
if (cursor === void 0) return void 0;
|
|
600
|
+
if (block.startsWith("true", cursor)) return true;
|
|
601
|
+
if (block.startsWith("false", cursor)) return false;
|
|
602
|
+
}
|
|
603
|
+
function extractTopLevelObjectLiteral(content, key) {
|
|
604
|
+
const block = extractRootObjectLiteral(content);
|
|
605
|
+
if (!block) return void 0;
|
|
606
|
+
const cursor = findTopLevelPropertyValueIndex(block, key);
|
|
607
|
+
if (cursor === void 0 || block[cursor] !== "{") return void 0;
|
|
608
|
+
const end = findMatchingObjectEnd(block, cursor);
|
|
609
|
+
return end === void 0 ? void 0 : block.slice(cursor + 1, end);
|
|
610
|
+
}
|
|
558
611
|
function extractObjectLiteral(content, key) {
|
|
559
612
|
const keyIndex = content.search(new RegExp(`${key}\\s*:\\s*\\{`));
|
|
560
613
|
if (keyIndex === -1) return void 0;
|
|
@@ -759,16 +812,54 @@ function readSitemapConfig(root) {
|
|
|
759
812
|
};
|
|
760
813
|
} catch {
|
|
761
814
|
return {
|
|
762
|
-
enabled:
|
|
815
|
+
enabled: true,
|
|
763
816
|
routePrefix: ""
|
|
764
817
|
};
|
|
765
818
|
}
|
|
766
819
|
}
|
|
767
820
|
return {
|
|
768
|
-
enabled:
|
|
821
|
+
enabled: true,
|
|
769
822
|
routePrefix: ""
|
|
770
823
|
};
|
|
771
824
|
}
|
|
825
|
+
function readRobotsConfig(root) {
|
|
826
|
+
const publicStaticPath = join(root, "public", "robots.txt");
|
|
827
|
+
const appDir = getNextAppDir(root);
|
|
828
|
+
const appStaticPath = join(root, appDir, "robots.txt");
|
|
829
|
+
const appRouteExists = FILE_EXTS.some((ext) => existsSync(join(root, appDir, `robots.${ext}`)));
|
|
830
|
+
const hasStaticFile = existsSync(publicStaticPath) || existsSync(appStaticPath) || appRouteExists;
|
|
831
|
+
for (const ext of FILE_EXTS) {
|
|
832
|
+
const configPath = join(root, `docs.config.${ext}`);
|
|
833
|
+
if (!existsSync(configPath)) continue;
|
|
834
|
+
try {
|
|
835
|
+
const content = readFileSync(configPath, "utf-8");
|
|
836
|
+
if (content.match(/robots\s*:\s*false/)) return {
|
|
837
|
+
enabled: false,
|
|
838
|
+
hasStaticFile
|
|
839
|
+
};
|
|
840
|
+
if (content.match(/robots\s*:\s*true/)) return {
|
|
841
|
+
enabled: true,
|
|
842
|
+
hasStaticFile
|
|
843
|
+
};
|
|
844
|
+
const block = extractObjectLiteral(content, "robots");
|
|
845
|
+
if (!block) continue;
|
|
846
|
+
const enabledMatch = block.match(/enabled\s*:\s*(true|false)/);
|
|
847
|
+
return {
|
|
848
|
+
enabled: enabledMatch ? enabledMatch[1] !== "false" : true,
|
|
849
|
+
hasStaticFile
|
|
850
|
+
};
|
|
851
|
+
} catch {
|
|
852
|
+
return {
|
|
853
|
+
enabled: true,
|
|
854
|
+
hasStaticFile
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return {
|
|
859
|
+
enabled: true,
|
|
860
|
+
hasStaticFile
|
|
861
|
+
};
|
|
862
|
+
}
|
|
772
863
|
function normalizeAgentFeedbackRoute(route, fallback = DEFAULT_AGENT_FEEDBACK_ROUTE) {
|
|
773
864
|
if (!route || route.trim().length === 0) return fallback;
|
|
774
865
|
const normalized = `/${route}`.replace(/\/+/g, "/");
|
|
@@ -776,6 +867,11 @@ function normalizeAgentFeedbackRoute(route, fallback = DEFAULT_AGENT_FEEDBACK_RO
|
|
|
776
867
|
}
|
|
777
868
|
function readAgentFeedbackConfig(root) {
|
|
778
869
|
const defaultRoute = normalizeAgentFeedbackRoute();
|
|
870
|
+
const enabled = {
|
|
871
|
+
enabled: true,
|
|
872
|
+
route: defaultRoute,
|
|
873
|
+
schemaRoute: `${defaultRoute}/schema`
|
|
874
|
+
};
|
|
779
875
|
const disabled = {
|
|
780
876
|
enabled: false,
|
|
781
877
|
route: defaultRoute,
|
|
@@ -785,16 +881,16 @@ function readAgentFeedbackConfig(root) {
|
|
|
785
881
|
const configPath = join(root, `docs.config.${ext}`);
|
|
786
882
|
if (!existsSync(configPath)) continue;
|
|
787
883
|
try {
|
|
788
|
-
const
|
|
789
|
-
|
|
884
|
+
const content = readFileSync(configPath, "utf-8");
|
|
885
|
+
const feedbackBoolean = readTopLevelBooleanProperty(content, "feedback");
|
|
886
|
+
if (feedbackBoolean === false) return disabled;
|
|
887
|
+
if (feedbackBoolean === true) return enabled;
|
|
888
|
+
const feedbackBlock = extractTopLevelObjectLiteral(content, "feedback");
|
|
889
|
+
if (!feedbackBlock) return enabled;
|
|
790
890
|
if (feedbackBlock.match(/agent\s*:\s*false/)) return disabled;
|
|
791
|
-
if (feedbackBlock.match(/agent\s*:\s*true/)) return
|
|
792
|
-
enabled: true,
|
|
793
|
-
route: defaultRoute,
|
|
794
|
-
schemaRoute: `${defaultRoute}/schema`
|
|
795
|
-
};
|
|
891
|
+
if (feedbackBlock.match(/agent\s*:\s*true/)) return enabled;
|
|
796
892
|
const agentBlock = extractObjectLiteral(feedbackBlock, "agent");
|
|
797
|
-
if (!agentBlock)
|
|
893
|
+
if (!agentBlock) return enabled;
|
|
798
894
|
const enabledMatch = agentBlock.match(/enabled\s*:\s*(true|false)/);
|
|
799
895
|
const routeMatch = agentBlock.match(/route\s*:\s*["']([^"']+)["']/);
|
|
800
896
|
const schemaRouteMatch = agentBlock.match(/schemaRoute\s*:\s*["']([^"']+)["']/);
|
|
@@ -808,7 +904,7 @@ function readAgentFeedbackConfig(root) {
|
|
|
808
904
|
return disabled;
|
|
809
905
|
}
|
|
810
906
|
}
|
|
811
|
-
return
|
|
907
|
+
return enabled;
|
|
812
908
|
}
|
|
813
909
|
function buildDocsMarkdownRewrites(entry) {
|
|
814
910
|
const normalizedEntry = entry.replace(/^\/+|\/+$/g, "") || "docs";
|
|
@@ -925,6 +1021,13 @@ function buildSitemapRewrites(config) {
|
|
|
925
1021
|
}
|
|
926
1022
|
];
|
|
927
1023
|
}
|
|
1024
|
+
function buildRobotsRewrites(config) {
|
|
1025
|
+
if (!config.enabled || config.hasStaticFile) return [];
|
|
1026
|
+
return [{
|
|
1027
|
+
source: DEFAULT_ROBOTS_TXT_ROUTE,
|
|
1028
|
+
destination: "/api/docs?format=robots"
|
|
1029
|
+
}];
|
|
1030
|
+
}
|
|
928
1031
|
function buildMcpRewrites(config) {
|
|
929
1032
|
if (!config.enabled) return [];
|
|
930
1033
|
return [DEFAULT_MCP_PUBLIC_ROUTE, DEFAULT_MCP_WELL_KNOWN_ROUTE].filter((source) => source !== config.route).map((source) => ({
|
|
@@ -1058,13 +1161,14 @@ function buildHiddenFolderRedirects(docsDir, entry) {
|
|
|
1058
1161
|
scan(docsDir, []);
|
|
1059
1162
|
return dedupeRedirects(redirects);
|
|
1060
1163
|
}
|
|
1061
|
-
function mergeDocsMarkdownRewrites(entry, mcp, sitemap, agentFeedback, result) {
|
|
1164
|
+
function mergeDocsMarkdownRewrites(entry, mcp, sitemap, agentFeedback, robots, result) {
|
|
1062
1165
|
const autoRewrites = [
|
|
1063
1166
|
...buildAgentSpecRewrites(),
|
|
1064
1167
|
...buildMcpRewrites(mcp),
|
|
1065
1168
|
...buildLlmsTxtRewrites(entry),
|
|
1066
1169
|
...buildSkillMdRewrites(),
|
|
1067
1170
|
...buildSitemapRewrites(sitemap),
|
|
1171
|
+
...buildRobotsRewrites(robots),
|
|
1068
1172
|
...buildDocsMarkdownRewrites(entry),
|
|
1069
1173
|
...buildAgentFeedbackRewrites(agentFeedback)
|
|
1070
1174
|
];
|
|
@@ -1106,6 +1210,7 @@ function withDocs(nextConfig = {}) {
|
|
|
1106
1210
|
}
|
|
1107
1211
|
const mcp = readMcpConfig(root);
|
|
1108
1212
|
const sitemap = readSitemapConfig(root);
|
|
1213
|
+
const robots = readRobotsConfig(root);
|
|
1109
1214
|
const docsMcpRouteDir = join(root, appDir, "api", "docs", "mcp");
|
|
1110
1215
|
if (mcp.enabled && mcp.route === DEFAULT_MCP_ROUTE && !isStaticExport && !hasFile(docsMcpRouteDir, "route")) {
|
|
1111
1216
|
mkdirSync(docsMcpRouteDir, { recursive: true });
|
|
@@ -1268,7 +1373,7 @@ function withDocs(nextConfig = {}) {
|
|
|
1268
1373
|
if (!isStaticExport) {
|
|
1269
1374
|
const existingRewrites = nextConfig.rewrites;
|
|
1270
1375
|
nextConfig.rewrites = async () => {
|
|
1271
|
-
return mergeDocsMarkdownRewrites(entry, mcp, sitemap, agentFeedback, typeof existingRewrites === "function" ? await existingRewrites() : existingRewrites);
|
|
1376
|
+
return mergeDocsMarkdownRewrites(entry, mcp, sitemap, agentFeedback, robots, typeof existingRewrites === "function" ? await existingRewrites() : existingRewrites);
|
|
1272
1377
|
};
|
|
1273
1378
|
const autoRedirects = buildHiddenFolderRedirects(docsContentRoot, entry);
|
|
1274
1379
|
if (autoRedirects.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.98",
|
|
4
4
|
"description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -100,8 +100,8 @@
|
|
|
100
100
|
"tsdown": "^0.20.3",
|
|
101
101
|
"typescript": "^5.9.3",
|
|
102
102
|
"vitest": "^3.2.4",
|
|
103
|
-
"@farming-labs/docs": "0.1.
|
|
104
|
-
"@farming-labs/theme": "0.1.
|
|
103
|
+
"@farming-labs/docs": "0.1.98",
|
|
104
|
+
"@farming-labs/theme": "0.1.98"
|
|
105
105
|
},
|
|
106
106
|
"peerDependencies": {
|
|
107
107
|
"@farming-labs/docs": ">=0.0.1",
|