@farming-labs/next 0.1.77 → 0.1.79
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/changelog.mjs
CHANGED
|
@@ -438,7 +438,7 @@ function createNextChangelogIndexMetadata(config) {
|
|
|
438
438
|
return createPageMetadata(config, {
|
|
439
439
|
title: changelog.title,
|
|
440
440
|
description: changelog.description
|
|
441
|
-
});
|
|
441
|
+
}, void 0, getListingUrl(config));
|
|
442
442
|
}
|
|
443
443
|
function createNextChangelogEntryMetadata(config, entries) {
|
|
444
444
|
return async function generateMetadata(props) {
|
|
@@ -449,12 +449,12 @@ function createNextChangelogEntryMetadata(config, entries) {
|
|
|
449
449
|
return createPageMetadata(config, {
|
|
450
450
|
title: changelog.title,
|
|
451
451
|
description: changelog.description
|
|
452
|
-
});
|
|
452
|
+
}, void 0, getListingUrl(config));
|
|
453
453
|
}
|
|
454
454
|
return createPageMetadata(config, {
|
|
455
455
|
title: entry.title,
|
|
456
456
|
description: entry.description
|
|
457
|
-
});
|
|
457
|
+
}, void 0, `${getListingUrl(config)}/${entry.slug}`);
|
|
458
458
|
};
|
|
459
459
|
}
|
|
460
460
|
|
package/dist/config.mjs
CHANGED
|
@@ -92,6 +92,44 @@ export const { GET, POST } = createDocsAPI({
|
|
|
92
92
|
ai: docsConfig.ai,
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
+
export const revalidate = false;
|
|
96
|
+
`;
|
|
97
|
+
const DOCS_MARKDOWN_ROUTE_TEMPLATE = `\
|
|
98
|
+
${GENERATED_BANNER}
|
|
99
|
+
import docsConfig from "@/docs.config";
|
|
100
|
+
import { createDocsAPI } from "@farming-labs/next/api";
|
|
101
|
+
|
|
102
|
+
const docsApi = createDocsAPI({
|
|
103
|
+
entry: docsConfig.entry,
|
|
104
|
+
contentDir: docsConfig.contentDir,
|
|
105
|
+
i18n: docsConfig.i18n,
|
|
106
|
+
changelog: docsConfig.changelog,
|
|
107
|
+
feedback: docsConfig.feedback,
|
|
108
|
+
mcp: docsConfig.mcp,
|
|
109
|
+
sitemap: docsConfig.sitemap,
|
|
110
|
+
search: docsConfig.search,
|
|
111
|
+
analytics: docsConfig.analytics,
|
|
112
|
+
observability: docsConfig.observability,
|
|
113
|
+
ai: docsConfig.ai,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
type MarkdownRouteContext = {
|
|
117
|
+
params?: Promise<{ slug?: string[] }> | { slug?: string[] };
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export async function GET(request: Request, context: MarkdownRouteContext = {}) {
|
|
121
|
+
const params = context.params ? await context.params : undefined;
|
|
122
|
+
const slug = params?.slug?.join("/") ?? "";
|
|
123
|
+
const url = new URL(request.url);
|
|
124
|
+
|
|
125
|
+
url.pathname = "/api/docs";
|
|
126
|
+
url.search = "";
|
|
127
|
+
url.searchParams.set("format", "markdown");
|
|
128
|
+
if (slug) url.searchParams.set("path", slug);
|
|
129
|
+
|
|
130
|
+
return docsApi.GET(new Request(url.toString(), request));
|
|
131
|
+
}
|
|
132
|
+
|
|
95
133
|
export const revalidate = false;
|
|
96
134
|
`;
|
|
97
135
|
const DOCS_MCP_ROUTE_TEMPLATE = `\
|
|
@@ -231,6 +269,7 @@ function createDocsWorkspaceAliases() {
|
|
|
231
269
|
"@farming-labs/next/mdx-plugins/rehype-toc": "./packages/next/src/mdx-plugins/rehype-toc.ts",
|
|
232
270
|
"@farming-labs/next/mdx-plugins/remark-heading": "./packages/next/src/mdx-plugins/remark-heading.ts",
|
|
233
271
|
"@farming-labs/next/mdx-plugins/remark-og": "./packages/next/src/mdx-plugins/remark-og.ts",
|
|
272
|
+
"@farming-labs/next/mdx-plugins/remark-markdown-alternate": "./packages/next/src/mdx-plugins/remark-markdown-alternate.ts",
|
|
234
273
|
"@farming-labs/theme": "./packages/fumadocs/src/index.ts",
|
|
235
274
|
"@farming-labs/theme/api": "./packages/fumadocs/src/docs-api.ts",
|
|
236
275
|
"@farming-labs/theme/client-hooks": "./packages/fumadocs/src/docs-client-hooks.tsx",
|
|
@@ -815,6 +854,10 @@ function buildDocsMarkdownRewrites(entry) {
|
|
|
815
854
|
key: "accept",
|
|
816
855
|
value: MARKDOWN_ACCEPT_HEADER_VALUE
|
|
817
856
|
};
|
|
857
|
+
const markdownSignatureAgentHeader = {
|
|
858
|
+
type: "header",
|
|
859
|
+
key: "signature-agent"
|
|
860
|
+
};
|
|
818
861
|
return [
|
|
819
862
|
{
|
|
820
863
|
source: `/${normalizedEntry}.md`,
|
|
@@ -833,6 +876,16 @@ function buildDocsMarkdownRewrites(entry) {
|
|
|
833
876
|
source: `/${normalizedEntry}/:slug*`,
|
|
834
877
|
has: [markdownAcceptHeader],
|
|
835
878
|
destination: "/api/docs?format=markdown&path=:slug*"
|
|
879
|
+
},
|
|
880
|
+
{
|
|
881
|
+
source: `/${normalizedEntry}`,
|
|
882
|
+
has: [markdownSignatureAgentHeader],
|
|
883
|
+
destination: "/api/docs/markdown"
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
source: `/${normalizedEntry}/:slug*`,
|
|
887
|
+
has: [markdownSignatureAgentHeader],
|
|
888
|
+
destination: "/api/docs/markdown/:slug*"
|
|
836
889
|
}
|
|
837
890
|
];
|
|
838
891
|
}
|
|
@@ -920,7 +973,12 @@ function dedupeRewrites(rewrites) {
|
|
|
920
973
|
const seen = /* @__PURE__ */ new Set();
|
|
921
974
|
const result = [];
|
|
922
975
|
for (const rewrite of rewrites) {
|
|
923
|
-
const key =
|
|
976
|
+
const key = JSON.stringify({
|
|
977
|
+
source: rewrite.source,
|
|
978
|
+
destination: rewrite.destination,
|
|
979
|
+
has: rewrite.has ?? [],
|
|
980
|
+
missing: rewrite.missing ?? []
|
|
981
|
+
});
|
|
924
982
|
if (seen.has(key)) continue;
|
|
925
983
|
seen.add(key);
|
|
926
984
|
result.push(rewrite);
|
|
@@ -1073,6 +1131,12 @@ function withDocs(nextConfig = {}) {
|
|
|
1073
1131
|
mkdirSync(docsApiRouteDir, { recursive: true });
|
|
1074
1132
|
writeFileSync(join(docsApiRouteDir, "route.ts"), DOCS_API_ROUTE_TEMPLATE);
|
|
1075
1133
|
}
|
|
1134
|
+
const docsMarkdownRouteDir = join(root, appDir, "api", "docs", "markdown", "[[...slug]]");
|
|
1135
|
+
const docsMarkdownRoutePath = join(docsMarkdownRouteDir, "route.ts");
|
|
1136
|
+
if (!isStaticExport && (!hasFile(docsMarkdownRouteDir, "route") || isManagedGeneratedFile(docsMarkdownRoutePath))) {
|
|
1137
|
+
mkdirSync(docsMarkdownRouteDir, { recursive: true });
|
|
1138
|
+
writeFileSync(docsMarkdownRoutePath, DOCS_MARKDOWN_ROUTE_TEMPLATE);
|
|
1139
|
+
}
|
|
1076
1140
|
const mcp = readMcpConfig(root);
|
|
1077
1141
|
const sitemap = readSitemapConfig(root);
|
|
1078
1142
|
const docsMcpRouteDir = join(root, appDir, "api", "docs", "mcp");
|
|
@@ -1149,6 +1213,12 @@ function withDocs(nextConfig = {}) {
|
|
|
1149
1213
|
const ogEndpoint = readOgEndpoint(root);
|
|
1150
1214
|
const remarkPlugins = ["remark-gfm", "remark-frontmatter"];
|
|
1151
1215
|
if (ogEndpoint) remarkPlugins.push(["@farming-labs/next/mdx-plugins/remark-og", { endpoint: ogEndpoint }]);
|
|
1216
|
+
remarkPlugins.push(["@farming-labs/next/mdx-plugins/remark-markdown-alternate", {
|
|
1217
|
+
entry,
|
|
1218
|
+
appDir,
|
|
1219
|
+
contentDir: docsContentDir,
|
|
1220
|
+
enabled: !isStaticExport
|
|
1221
|
+
}]);
|
|
1152
1222
|
remarkPlugins.push(["remark-mdx-frontmatter", { name: "metadata" }], "@farming-labs/next/mdx-plugins/remark-heading");
|
|
1153
1223
|
const withMDX = createMDX({
|
|
1154
1224
|
extension: /\.mdx?$/,
|
|
@@ -1206,6 +1276,7 @@ function withDocs(nextConfig = {}) {
|
|
|
1206
1276
|
"@farming-labs/next/changelog": join(workspaceRoot, "packages", "next", "dist", "changelog.mjs"),
|
|
1207
1277
|
"@farming-labs/next/client-callbacks": join(workspaceRoot, "packages", "next", "dist", "client-callbacks.mjs"),
|
|
1208
1278
|
"@farming-labs/next/layout": join(workspaceRoot, "packages", "next", "dist", "layout.mjs"),
|
|
1279
|
+
"@farming-labs/next/mdx-plugins/remark-markdown-alternate": join(workspaceRoot, "packages", "next", "dist", "mdx-plugins", "remark-markdown-alternate.mjs"),
|
|
1209
1280
|
"@farming-labs/theme$": join(workspaceRoot, "packages", "fumadocs", "dist", "index.mjs"),
|
|
1210
1281
|
"@farming-labs/theme/api": join(workspaceRoot, "packages", "fumadocs", "dist", "docs-api.mjs")
|
|
1211
1282
|
});
|
|
@@ -1248,6 +1319,18 @@ function withDocs(nextConfig = {}) {
|
|
|
1248
1319
|
skillTraceFile,
|
|
1249
1320
|
sitemapManifestTraceFile
|
|
1250
1321
|
])],
|
|
1322
|
+
"/api/docs/markdown": [...new Set([
|
|
1323
|
+
...existingTracingIncludes["/api/docs/markdown"] ?? [],
|
|
1324
|
+
docsTraceGlob,
|
|
1325
|
+
skillTraceFile,
|
|
1326
|
+
sitemapManifestTraceFile
|
|
1327
|
+
])],
|
|
1328
|
+
"/api/docs/markdown/:path*": [...new Set([
|
|
1329
|
+
...existingTracingIncludes["/api/docs/markdown/:path*"] ?? [],
|
|
1330
|
+
docsTraceGlob,
|
|
1331
|
+
skillTraceFile,
|
|
1332
|
+
sitemapManifestTraceFile
|
|
1333
|
+
])],
|
|
1251
1334
|
[DEFAULT_MCP_ROUTE]: [...new Set([...existingTracingIncludes[DEFAULT_MCP_ROUTE] ?? [], docsTraceGlob])]
|
|
1252
1335
|
};
|
|
1253
1336
|
return withMDX(nextConfig);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/mdx-plugins/remark-markdown-alternate.d.ts
|
|
2
|
+
interface RemarkMarkdownAlternateOptions {
|
|
3
|
+
entry?: string;
|
|
4
|
+
appDir?: string;
|
|
5
|
+
contentDir?: string;
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface MarkdownNode {
|
|
9
|
+
type: string;
|
|
10
|
+
value?: string;
|
|
11
|
+
}
|
|
12
|
+
interface VFileLike {
|
|
13
|
+
path?: string;
|
|
14
|
+
history?: string[];
|
|
15
|
+
}
|
|
16
|
+
declare function remarkMarkdownAlternate(options?: RemarkMarkdownAlternateOptions): (tree: {
|
|
17
|
+
children: MarkdownNode[];
|
|
18
|
+
}, file?: VFileLike) => void;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { remarkMarkdownAlternate as default };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { toDocsMarkdownUrl } from "@farming-labs/docs";
|
|
2
|
+
|
|
3
|
+
//#region src/mdx-plugins/remark-markdown-alternate.ts
|
|
4
|
+
function normalizePath(value) {
|
|
5
|
+
return value.replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
6
|
+
}
|
|
7
|
+
function normalizeSegment(value, fallback) {
|
|
8
|
+
return (value ?? fallback).replace(/^\/+|\/+$/g, "") || fallback;
|
|
9
|
+
}
|
|
10
|
+
function escapeYamlString(value) {
|
|
11
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
12
|
+
}
|
|
13
|
+
function routeFromSourcePath(filePath, options) {
|
|
14
|
+
const normalized = `/${normalizePath(filePath).replace(/^\/+/, "")}`;
|
|
15
|
+
if (!/\/page\.mdx?$/.test(normalized)) return null;
|
|
16
|
+
const entry = normalizeSegment(options.entry, "docs");
|
|
17
|
+
const candidates = [
|
|
18
|
+
options.contentDir,
|
|
19
|
+
options.appDir ? `${options.appDir}/${entry}` : void 0,
|
|
20
|
+
`src/app/${entry}`,
|
|
21
|
+
`app/${entry}`
|
|
22
|
+
].filter((candidate) => typeof candidate === "string" && candidate.length > 0).map((candidate) => normalizePath(candidate).replace(/^\/+|\/+$/g, ""));
|
|
23
|
+
for (const candidate of candidates) {
|
|
24
|
+
const marker = `/${candidate}/`;
|
|
25
|
+
const markerIndex = normalized.lastIndexOf(marker);
|
|
26
|
+
if (markerIndex === -1) continue;
|
|
27
|
+
const relativePath = normalized.slice(markerIndex + marker.length);
|
|
28
|
+
if (!relativePath.endsWith("page.mdx") && !relativePath.endsWith("page.md")) continue;
|
|
29
|
+
const slug = relativePath.replace(/\/?page\.mdx?$/, "").replace(/^\/+|\/+$/g, "");
|
|
30
|
+
return slug ? `/${entry}/${slug}` : `/${entry}`;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
function getFilePath(file) {
|
|
35
|
+
return file?.path ?? file?.history?.[0];
|
|
36
|
+
}
|
|
37
|
+
function hasAlternates(yaml) {
|
|
38
|
+
return /^\s*alternates\s*:/m.test(yaml);
|
|
39
|
+
}
|
|
40
|
+
function alternateYaml(url) {
|
|
41
|
+
return [
|
|
42
|
+
"alternates:",
|
|
43
|
+
" types:",
|
|
44
|
+
` text/markdown: "${escapeYamlString(toDocsMarkdownUrl(url))}"`
|
|
45
|
+
].join("\n");
|
|
46
|
+
}
|
|
47
|
+
function remarkMarkdownAlternate(options = {}) {
|
|
48
|
+
return (tree, file) => {
|
|
49
|
+
if (options.enabled === false) return;
|
|
50
|
+
const filePath = getFilePath(file);
|
|
51
|
+
if (!filePath) return;
|
|
52
|
+
const route = routeFromSourcePath(filePath, options);
|
|
53
|
+
if (!route) return;
|
|
54
|
+
const yamlNode = tree.children.find((node) => node.type === "yaml");
|
|
55
|
+
if (yamlNode?.value) {
|
|
56
|
+
if (hasAlternates(yamlNode.value)) return;
|
|
57
|
+
yamlNode.value += `\n${alternateYaml(route)}`;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
tree.children.unshift({
|
|
61
|
+
type: "yaml",
|
|
62
|
+
value: alternateYaml(route)
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//#endregion
|
|
68
|
+
export { remarkMarkdownAlternate as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.79",
|
|
4
4
|
"description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -73,6 +73,11 @@
|
|
|
73
73
|
"types": "./dist/mdx-plugins/remark-og.d.mts",
|
|
74
74
|
"import": "./dist/mdx-plugins/remark-og.mjs",
|
|
75
75
|
"default": "./dist/mdx-plugins/remark-og.mjs"
|
|
76
|
+
},
|
|
77
|
+
"./mdx-plugins/remark-markdown-alternate": {
|
|
78
|
+
"types": "./dist/mdx-plugins/remark-markdown-alternate.d.mts",
|
|
79
|
+
"import": "./dist/mdx-plugins/remark-markdown-alternate.mjs",
|
|
80
|
+
"default": "./dist/mdx-plugins/remark-markdown-alternate.mjs"
|
|
76
81
|
}
|
|
77
82
|
},
|
|
78
83
|
"dependencies": {
|
|
@@ -95,8 +100,8 @@
|
|
|
95
100
|
"tsdown": "^0.20.3",
|
|
96
101
|
"typescript": "^5.9.3",
|
|
97
102
|
"vitest": "^3.2.4",
|
|
98
|
-
"@farming-labs/docs": "0.1.
|
|
99
|
-
"@farming-labs/theme": "0.1.
|
|
103
|
+
"@farming-labs/docs": "0.1.79",
|
|
104
|
+
"@farming-labs/theme": "0.1.79"
|
|
100
105
|
},
|
|
101
106
|
"peerDependencies": {
|
|
102
107
|
"@farming-labs/docs": ">=0.0.1",
|