@farming-labs/next 0.1.13 → 0.1.16
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-rail-search.d.mts +46 -0
- package/dist/changelog-rail-search.mjs +416 -0
- package/dist/changelog.d.mts +36 -0
- package/dist/changelog.mjs +447 -0
- package/dist/config.mjs +429 -3
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/package.json +9 -3
package/dist/config.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
+
import matter from "gray-matter";
|
|
4
5
|
import createMDX from "@next/mdx";
|
|
5
6
|
|
|
6
7
|
//#region src/config.ts
|
|
@@ -73,6 +74,7 @@ export const { GET, POST } = createDocsAPI({
|
|
|
73
74
|
entry: docsConfig.entry,
|
|
74
75
|
contentDir: docsConfig.contentDir,
|
|
75
76
|
i18n: docsConfig.i18n,
|
|
77
|
+
changelog: docsConfig.changelog,
|
|
76
78
|
search: docsConfig.search,
|
|
77
79
|
ai: docsConfig.ai,
|
|
78
80
|
});
|
|
@@ -93,6 +95,34 @@ export const { GET, POST, DELETE } = createDocsMCPAPI({
|
|
|
93
95
|
mcp: docsConfig.mcp,
|
|
94
96
|
});
|
|
95
97
|
|
|
98
|
+
export const revalidate = false;
|
|
99
|
+
`;
|
|
100
|
+
const DOCS_MARKDOWN_ROUTE_TEMPLATE = `\
|
|
101
|
+
${GENERATED_BANNER}
|
|
102
|
+
import docsConfig from "@/docs.config";
|
|
103
|
+
import { createDocsAPI } from "@farming-labs/next/api";
|
|
104
|
+
|
|
105
|
+
const handlers = createDocsAPI({
|
|
106
|
+
entry: docsConfig.entry,
|
|
107
|
+
contentDir: docsConfig.contentDir,
|
|
108
|
+
i18n: docsConfig.i18n,
|
|
109
|
+
changelog: docsConfig.changelog,
|
|
110
|
+
search: docsConfig.search,
|
|
111
|
+
ai: docsConfig.ai,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
export async function GET(
|
|
115
|
+
request: Request,
|
|
116
|
+
{ params }: { params: Promise<{ slug?: string[] }> },
|
|
117
|
+
) {
|
|
118
|
+
const { slug = [] } = await params;
|
|
119
|
+
const url = new URL(request.url);
|
|
120
|
+
url.searchParams.set("format", "markdown");
|
|
121
|
+
if (slug.length > 0) url.searchParams.set("path", slug.join("/"));
|
|
122
|
+
else url.searchParams.delete("path");
|
|
123
|
+
return handlers.GET(new Request(url, { headers: request.headers }));
|
|
124
|
+
}
|
|
125
|
+
|
|
96
126
|
export const revalidate = false;
|
|
97
127
|
`;
|
|
98
128
|
const API_REFERENCE_ROUTE_TEMPLATE = `\
|
|
@@ -126,6 +156,14 @@ const ApiReferenceLayout = createNextApiReferenceLayout(docsConfig);
|
|
|
126
156
|
|
|
127
157
|
export default ApiReferenceLayout;
|
|
128
158
|
`;
|
|
159
|
+
const CHANGELOG_SOURCE_LAYOUT_TEMPLATE = `\
|
|
160
|
+
${GENERATED_BANNER}
|
|
161
|
+
import { notFound } from "next/navigation";
|
|
162
|
+
|
|
163
|
+
export default function HiddenChangelogSourceLayout() {
|
|
164
|
+
notFound();
|
|
165
|
+
}
|
|
166
|
+
`;
|
|
129
167
|
const FILE_EXTS = [
|
|
130
168
|
"tsx",
|
|
131
169
|
"ts",
|
|
@@ -174,6 +212,7 @@ function createDocsWorkspaceAliases() {
|
|
|
174
212
|
"@farming-labs/docs/server": "./packages/docs/src/server.ts",
|
|
175
213
|
"@farming-labs/next": "./packages/next/src/index.ts",
|
|
176
214
|
"@farming-labs/next/api": "./packages/next/src/api.ts",
|
|
215
|
+
"@farming-labs/next/changelog": "./packages/next/src/changelog.tsx",
|
|
177
216
|
"@farming-labs/next/client-callbacks": "./packages/next/src/client-callbacks.tsx",
|
|
178
217
|
"@farming-labs/next/layout": "./packages/next/src/layout.tsx",
|
|
179
218
|
"@farming-labs/next/mdx-plugins/rehype-code": "./packages/next/src/mdx-plugins/rehype-code.ts",
|
|
@@ -216,8 +255,8 @@ function readDocsContentDir(root) {
|
|
|
216
255
|
const configPath = join(root, `docs.config.${ext}`);
|
|
217
256
|
if (!existsSync(configPath)) continue;
|
|
218
257
|
try {
|
|
219
|
-
const
|
|
220
|
-
if (
|
|
258
|
+
const contentDir = readTopLevelStringProperty(readFileSync(configPath, "utf-8"), "contentDir");
|
|
259
|
+
if (contentDir) return contentDir;
|
|
221
260
|
} catch {}
|
|
222
261
|
}
|
|
223
262
|
}
|
|
@@ -284,6 +323,223 @@ function readApiReferenceConfig(root) {
|
|
|
284
323
|
routeRoot: "api"
|
|
285
324
|
};
|
|
286
325
|
}
|
|
326
|
+
function readChangelogConfig(root) {
|
|
327
|
+
for (const ext of FILE_EXTS) {
|
|
328
|
+
const configPath = join(root, `docs.config.${ext}`);
|
|
329
|
+
if (!existsSync(configPath)) continue;
|
|
330
|
+
try {
|
|
331
|
+
const content = readFileSync(configPath, "utf-8");
|
|
332
|
+
if (content.match(/changelog\s*:\s*false/)) return {
|
|
333
|
+
enabled: false,
|
|
334
|
+
path: "changelog",
|
|
335
|
+
contentDir: "changelog"
|
|
336
|
+
};
|
|
337
|
+
if (content.match(/changelog\s*:\s*true/)) return {
|
|
338
|
+
enabled: true,
|
|
339
|
+
path: "changelog",
|
|
340
|
+
contentDir: "changelog"
|
|
341
|
+
};
|
|
342
|
+
const block = extractObjectLiteral(content, "changelog");
|
|
343
|
+
if (!block) continue;
|
|
344
|
+
const enabledMatch = block.match(/enabled\s*:\s*(true|false)/);
|
|
345
|
+
const pathMatch = block.match(/path\s*:\s*["']([^"']+)["']/);
|
|
346
|
+
const contentDirMatch = block.match(/contentDir\s*:\s*["']([^"']+)["']/);
|
|
347
|
+
return {
|
|
348
|
+
enabled: enabledMatch ? enabledMatch[1] !== "false" : true,
|
|
349
|
+
path: pathMatch?.[1]?.replace(/^\/+|\/+$/g, "") || "changelog",
|
|
350
|
+
contentDir: contentDirMatch?.[1]?.replace(/\/+$/, "") || "changelog"
|
|
351
|
+
};
|
|
352
|
+
} catch {
|
|
353
|
+
return {
|
|
354
|
+
enabled: false,
|
|
355
|
+
path: "changelog",
|
|
356
|
+
contentDir: "changelog"
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return {
|
|
361
|
+
enabled: false,
|
|
362
|
+
path: "changelog",
|
|
363
|
+
contentDir: "changelog"
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function resolveDocsContentDir(root, appDir, entry) {
|
|
367
|
+
const configuredContentDir = readDocsContentDir(root);
|
|
368
|
+
if (!configuredContentDir) return join(root, appDir, entry);
|
|
369
|
+
return isAbsolute(configuredContentDir) ? configuredContentDir : join(root, configuredContentDir);
|
|
370
|
+
}
|
|
371
|
+
function resolveChangelogContentDir(root, appDir, entry, changelogContentDir) {
|
|
372
|
+
if (isAbsolute(changelogContentDir)) return changelogContentDir;
|
|
373
|
+
return join(resolveDocsContentDir(root, appDir, entry), changelogContentDir);
|
|
374
|
+
}
|
|
375
|
+
function findChangelogSourceEntries(changelogDir) {
|
|
376
|
+
if (!existsSync(changelogDir)) return [];
|
|
377
|
+
const entries = [];
|
|
378
|
+
for (const name of readdirSync(changelogDir).sort()) {
|
|
379
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(name)) continue;
|
|
380
|
+
const entryDir = join(changelogDir, name);
|
|
381
|
+
try {
|
|
382
|
+
if (!statSync(entryDir).isDirectory()) continue;
|
|
383
|
+
} catch {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
const sourceFile = ["page.mdx", "page.md"].map((fileName) => join(entryDir, fileName)).find((value) => existsSync(value));
|
|
387
|
+
if (!sourceFile) continue;
|
|
388
|
+
let metadata = {};
|
|
389
|
+
try {
|
|
390
|
+
metadata = matter(readFileSync(sourceFile, "utf-8")).data;
|
|
391
|
+
} catch {
|
|
392
|
+
metadata = {};
|
|
393
|
+
}
|
|
394
|
+
entries.push({
|
|
395
|
+
slug: name,
|
|
396
|
+
date: name,
|
|
397
|
+
sourceFile,
|
|
398
|
+
metadata
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
return entries.sort((left, right) => right.date.localeCompare(left.date));
|
|
402
|
+
}
|
|
403
|
+
function extractRootObjectLiteral(content) {
|
|
404
|
+
const candidateIndexes = [content.search(/\bdefineDocs\s*\(/), content.search(/\bexport\s+default\b/)].filter((value) => value !== -1);
|
|
405
|
+
for (const startIndex of candidateIndexes) {
|
|
406
|
+
const braceStart = content.indexOf("{", startIndex);
|
|
407
|
+
if (braceStart === -1) continue;
|
|
408
|
+
let depth = 0;
|
|
409
|
+
let inString = null;
|
|
410
|
+
let escaped = false;
|
|
411
|
+
for (let index = braceStart; index < content.length; index += 1) {
|
|
412
|
+
const char = content[index];
|
|
413
|
+
if (inString) {
|
|
414
|
+
if (escaped) {
|
|
415
|
+
escaped = false;
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (char === "\\") {
|
|
419
|
+
escaped = true;
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
if (char === inString) inString = null;
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
if (char === "\"" || char === "'" || char === "`") {
|
|
426
|
+
inString = char;
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
if (char === "{") {
|
|
430
|
+
depth += 1;
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
if (char !== "}") continue;
|
|
434
|
+
depth -= 1;
|
|
435
|
+
if (depth === 0) return content.slice(braceStart + 1, index);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
function readTopLevelStringProperty(content, key) {
|
|
440
|
+
const block = extractRootObjectLiteral(content);
|
|
441
|
+
if (!block) return void 0;
|
|
442
|
+
let objectDepth = 0;
|
|
443
|
+
let arrayDepth = 0;
|
|
444
|
+
let parenDepth = 0;
|
|
445
|
+
let inString = null;
|
|
446
|
+
let inLineComment = false;
|
|
447
|
+
let inBlockComment = false;
|
|
448
|
+
let escaped = false;
|
|
449
|
+
for (let index = 0; index < block.length; index += 1) {
|
|
450
|
+
const char = block[index];
|
|
451
|
+
const next = block[index + 1];
|
|
452
|
+
if (inLineComment) {
|
|
453
|
+
if (char === "\n") inLineComment = false;
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
if (inBlockComment) {
|
|
457
|
+
if (char === "*" && next === "/") {
|
|
458
|
+
inBlockComment = false;
|
|
459
|
+
index += 1;
|
|
460
|
+
}
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (inString) {
|
|
464
|
+
if (escaped) {
|
|
465
|
+
escaped = false;
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
if (char === "\\") {
|
|
469
|
+
escaped = true;
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
if (char === inString) inString = null;
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
if (char === "/" && next === "/") {
|
|
476
|
+
inLineComment = true;
|
|
477
|
+
index += 1;
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
if (char === "/" && next === "*") {
|
|
481
|
+
inBlockComment = true;
|
|
482
|
+
index += 1;
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
if (char === "\"" || char === "'" || char === "`") {
|
|
486
|
+
inString = char;
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
if (char === "{") {
|
|
490
|
+
objectDepth += 1;
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
if (char === "}") {
|
|
494
|
+
objectDepth = Math.max(0, objectDepth - 1);
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (char === "[") {
|
|
498
|
+
arrayDepth += 1;
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
if (char === "]") {
|
|
502
|
+
arrayDepth = Math.max(0, arrayDepth - 1);
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
if (char === "(") {
|
|
506
|
+
parenDepth += 1;
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
if (char === ")") {
|
|
510
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
if (objectDepth !== 0 || arrayDepth !== 0 || parenDepth !== 0) continue;
|
|
514
|
+
if (!block.startsWith(key, index)) continue;
|
|
515
|
+
const before = block[index - 1] ?? "";
|
|
516
|
+
const after = block[index + key.length] ?? "";
|
|
517
|
+
if (/[A-Za-z0-9_$]/.test(before) || /[A-Za-z0-9_$]/.test(after)) continue;
|
|
518
|
+
let cursor = index + key.length;
|
|
519
|
+
while (/\s/.test(block[cursor] ?? "")) cursor += 1;
|
|
520
|
+
if (block[cursor] !== ":") continue;
|
|
521
|
+
cursor += 1;
|
|
522
|
+
while (/\s/.test(block[cursor] ?? "")) cursor += 1;
|
|
523
|
+
const quote = block[cursor];
|
|
524
|
+
if (quote !== "\"" && quote !== "'") continue;
|
|
525
|
+
cursor += 1;
|
|
526
|
+
let value = "";
|
|
527
|
+
for (; cursor < block.length; cursor += 1) {
|
|
528
|
+
const valueChar = block[cursor];
|
|
529
|
+
if (valueChar === "\\") {
|
|
530
|
+
const escapedChar = block[cursor + 1];
|
|
531
|
+
if (escapedChar) {
|
|
532
|
+
value += escapedChar;
|
|
533
|
+
cursor += 1;
|
|
534
|
+
}
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
if (valueChar === quote) return value;
|
|
538
|
+
value += valueChar;
|
|
539
|
+
}
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
287
543
|
function extractObjectLiteral(content, key) {
|
|
288
544
|
const keyIndex = content.search(new RegExp(`${key}\\s*:\\s*\\{`));
|
|
289
545
|
if (keyIndex === -1) return void 0;
|
|
@@ -301,6 +557,84 @@ function extractObjectLiteral(content, key) {
|
|
|
301
557
|
if (depth === 0) return content.slice(braceStart + 1, index);
|
|
302
558
|
}
|
|
303
559
|
}
|
|
560
|
+
function toImportPath(fromFile, toFile) {
|
|
561
|
+
const relativePath = relative(dirname(fromFile), toFile).replaceAll("\\", "/");
|
|
562
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
563
|
+
}
|
|
564
|
+
function buildInlineChangelogEntriesSource(root, pagePath, entryPath, routePath, entries) {
|
|
565
|
+
const imports = [];
|
|
566
|
+
const records = [];
|
|
567
|
+
entries.forEach((entry, index) => {
|
|
568
|
+
const importName = `ChangelogEntry${index + 1}`;
|
|
569
|
+
imports.push(`import ${importName} from "${toImportPath(pagePath, entry.sourceFile)}";`);
|
|
570
|
+
records.push(` {
|
|
571
|
+
slug: ${JSON.stringify(entry.slug)},
|
|
572
|
+
date: ${JSON.stringify(entry.date)},
|
|
573
|
+
url: ${JSON.stringify(`/${entryPath}/${routePath}/${entry.slug}`)},
|
|
574
|
+
sourcePath: ${JSON.stringify(relative(root, entry.sourceFile).replaceAll("\\", "/"))},
|
|
575
|
+
Component: ${importName},
|
|
576
|
+
metadata: ${JSON.stringify(entry.metadata)},
|
|
577
|
+
}`);
|
|
578
|
+
});
|
|
579
|
+
return {
|
|
580
|
+
importsSource: `import type { GeneratedChangelogEntry } from "@farming-labs/next/changelog";
|
|
581
|
+
${imports.join("\n")}`.trimEnd(),
|
|
582
|
+
entriesSource: `export const changelogEntries: GeneratedChangelogEntry[] = [
|
|
583
|
+
${records.join(",\n")}
|
|
584
|
+
];
|
|
585
|
+
`
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
function buildChangelogIndexPageSource(root, pagePath, entryPath, routePath, entries) {
|
|
589
|
+
const { importsSource, entriesSource } = buildInlineChangelogEntriesSource(root, pagePath, entryPath, routePath, entries);
|
|
590
|
+
return `\
|
|
591
|
+
${GENERATED_BANNER}
|
|
592
|
+
import docsConfig from "@/docs.config";
|
|
593
|
+
${importsSource}
|
|
594
|
+
import {
|
|
595
|
+
createNextChangelogIndexMetadata,
|
|
596
|
+
createNextChangelogIndexPage,
|
|
597
|
+
} from "@farming-labs/next/changelog";
|
|
598
|
+
|
|
599
|
+
${entriesSource}
|
|
600
|
+
|
|
601
|
+
export const metadata = createNextChangelogIndexMetadata(docsConfig);
|
|
602
|
+
|
|
603
|
+
const ChangelogPage = createNextChangelogIndexPage(docsConfig, changelogEntries);
|
|
604
|
+
|
|
605
|
+
export default ChangelogPage;
|
|
606
|
+
`;
|
|
607
|
+
}
|
|
608
|
+
function buildChangelogEntryPageSource(root, pagePath, entryPath, routePath, entries) {
|
|
609
|
+
const { importsSource, entriesSource } = buildInlineChangelogEntriesSource(root, pagePath, entryPath, routePath, entries);
|
|
610
|
+
return `\
|
|
611
|
+
${GENERATED_BANNER}
|
|
612
|
+
import docsConfig from "@/docs.config";
|
|
613
|
+
${importsSource}
|
|
614
|
+
import {
|
|
615
|
+
createNextChangelogEntryMetadata,
|
|
616
|
+
createNextChangelogEntryPage,
|
|
617
|
+
createNextChangelogStaticParams,
|
|
618
|
+
} from "@farming-labs/next/changelog";
|
|
619
|
+
|
|
620
|
+
${entriesSource}
|
|
621
|
+
|
|
622
|
+
export const generateStaticParams = createNextChangelogStaticParams(changelogEntries);
|
|
623
|
+
export const generateMetadata = createNextChangelogEntryMetadata(docsConfig, changelogEntries);
|
|
624
|
+
|
|
625
|
+
const ChangelogEntryPage = createNextChangelogEntryPage(docsConfig, changelogEntries);
|
|
626
|
+
|
|
627
|
+
export default ChangelogEntryPage;
|
|
628
|
+
`;
|
|
629
|
+
}
|
|
630
|
+
function resolveManagedChangelogSourceLayoutPath(root, appDir, entry, changelogContentDir) {
|
|
631
|
+
if (isAbsolute(changelogContentDir)) return void 0;
|
|
632
|
+
const appRoot = join(root, appDir);
|
|
633
|
+
const contentRoot = resolveChangelogContentDir(root, appDir, entry, changelogContentDir);
|
|
634
|
+
const relativePath = relative(appRoot, contentRoot);
|
|
635
|
+
if (relativePath.startsWith("..") || isAbsolute(relativePath)) return void 0;
|
|
636
|
+
return join(contentRoot, "layout.tsx");
|
|
637
|
+
}
|
|
304
638
|
function removeManagedFile(filePath) {
|
|
305
639
|
if (isManagedGeneratedFile(filePath)) rmSync(filePath, { force: true });
|
|
306
640
|
}
|
|
@@ -342,6 +676,37 @@ function normalizeRoutePath(route) {
|
|
|
342
676
|
const normalized = `/${route}`.replace(/\/+/g, "/");
|
|
343
677
|
return normalized !== "/" ? normalized.replace(/\/+$/, "") : "/api/docs/mcp";
|
|
344
678
|
}
|
|
679
|
+
function buildDocsMarkdownRewrites(entry) {
|
|
680
|
+
const normalizedEntry = entry.replace(/^\/+|\/+$/g, "") || "docs";
|
|
681
|
+
return [{
|
|
682
|
+
source: `/${normalizedEntry}.md`,
|
|
683
|
+
destination: "/api/docs/markdown"
|
|
684
|
+
}, {
|
|
685
|
+
source: `/${normalizedEntry}/:slug*.md`,
|
|
686
|
+
destination: "/api/docs/markdown/:slug*"
|
|
687
|
+
}];
|
|
688
|
+
}
|
|
689
|
+
function dedupeRewrites(rewrites) {
|
|
690
|
+
const seen = /* @__PURE__ */ new Set();
|
|
691
|
+
const result = [];
|
|
692
|
+
for (const rewrite of rewrites) {
|
|
693
|
+
const key = `${rewrite.source}=>${rewrite.destination}`;
|
|
694
|
+
if (seen.has(key)) continue;
|
|
695
|
+
seen.add(key);
|
|
696
|
+
result.push(rewrite);
|
|
697
|
+
}
|
|
698
|
+
return result;
|
|
699
|
+
}
|
|
700
|
+
function mergeDocsMarkdownRewrites(entry, result) {
|
|
701
|
+
const docsMarkdownRewrites = buildDocsMarkdownRewrites(entry);
|
|
702
|
+
if (!result) return [...docsMarkdownRewrites];
|
|
703
|
+
if (Array.isArray(result)) return dedupeRewrites([...docsMarkdownRewrites, ...result]);
|
|
704
|
+
return {
|
|
705
|
+
beforeFiles: dedupeRewrites([...docsMarkdownRewrites, ...result.beforeFiles ?? []]),
|
|
706
|
+
afterFiles: result.afterFiles ?? [],
|
|
707
|
+
fallback: result.fallback ?? []
|
|
708
|
+
};
|
|
709
|
+
}
|
|
345
710
|
function withDocs(nextConfig = {}) {
|
|
346
711
|
const root = process.cwd();
|
|
347
712
|
const workspaceRoot = findDocsWorkspaceRoot(root);
|
|
@@ -363,6 +728,11 @@ function withDocs(nextConfig = {}) {
|
|
|
363
728
|
mkdirSync(docsApiRouteDir, { recursive: true });
|
|
364
729
|
writeFileSync(join(docsApiRouteDir, "route.ts"), DOCS_API_ROUTE_TEMPLATE);
|
|
365
730
|
}
|
|
731
|
+
const docsMarkdownRouteDir = join(root, appDir, "api", "docs", "markdown", "[[...slug]]");
|
|
732
|
+
if (!isStaticExport && (!hasFile(docsMarkdownRouteDir, "route") || isManagedGeneratedFile(join(docsMarkdownRouteDir, "route.ts")))) {
|
|
733
|
+
mkdirSync(docsMarkdownRouteDir, { recursive: true });
|
|
734
|
+
writeFileSync(join(docsMarkdownRouteDir, "route.ts"), DOCS_MARKDOWN_ROUTE_TEMPLATE);
|
|
735
|
+
}
|
|
366
736
|
const mcp = readMcpConfig(root);
|
|
367
737
|
const docsMcpRouteDir = join(root, appDir, "api", "docs", "mcp");
|
|
368
738
|
if (mcp.enabled && mcp.route === "/api/docs/mcp" && !isStaticExport && !hasFile(docsMcpRouteDir, "route")) {
|
|
@@ -398,6 +768,43 @@ function withDocs(nextConfig = {}) {
|
|
|
398
768
|
}
|
|
399
769
|
}
|
|
400
770
|
}
|
|
771
|
+
const changelog = readChangelogConfig(root);
|
|
772
|
+
if (changelog.enabled) {
|
|
773
|
+
const changelogBaseDir = join(root, appDir, entry, ...changelog.path.split("/"));
|
|
774
|
+
const changelogEntryDir = join(changelogBaseDir, "[slug]");
|
|
775
|
+
const changelogIndexPath = join(changelogBaseDir, "page.tsx");
|
|
776
|
+
const changelogEntryPath = join(changelogEntryDir, "page.tsx");
|
|
777
|
+
const changelogSourceDir = resolveChangelogContentDir(root, appDir, entry, changelog.contentDir);
|
|
778
|
+
const changelogUsesSourcePagesAsDetails = !isAbsolute(changelog.contentDir) && changelog.contentDir === changelog.path;
|
|
779
|
+
const changelogEntries = findChangelogSourceEntries(changelogSourceDir);
|
|
780
|
+
const changelogSourceLayoutPath = resolveManagedChangelogSourceLayoutPath(root, appDir, entry, changelog.contentDir);
|
|
781
|
+
const legacyChangelogBaseDirs = new Set([join(root, appDir, ...changelog.path.split("/")), ...isAbsolute(changelog.contentDir) ? [] : [join(root, appDir, ...changelog.contentDir.split("/"))]]);
|
|
782
|
+
for (const legacyChangelogBaseDir of legacyChangelogBaseDirs) {
|
|
783
|
+
if (legacyChangelogBaseDir === changelogBaseDir) continue;
|
|
784
|
+
removeManagedFile(join(legacyChangelogBaseDir, "[slug]", "page.tsx"));
|
|
785
|
+
removeManagedFile(join(legacyChangelogBaseDir, "page.tsx"));
|
|
786
|
+
removeManagedFile(join(legacyChangelogBaseDir, "__changelog.generated.tsx"));
|
|
787
|
+
}
|
|
788
|
+
mkdirSync(changelogBaseDir, { recursive: true });
|
|
789
|
+
removeManagedFile(join(changelogBaseDir, "__changelog.generated.tsx"));
|
|
790
|
+
if (!hasFile(changelogBaseDir, "page") || isManagedGeneratedFile(changelogIndexPath)) writeFileSync(changelogIndexPath, buildChangelogIndexPageSource(root, changelogIndexPath, entry, changelog.path, changelogEntries));
|
|
791
|
+
if (changelogUsesSourcePagesAsDetails) {
|
|
792
|
+
removeManagedFile(changelogEntryPath);
|
|
793
|
+
if (changelogSourceLayoutPath) removeManagedFile(changelogSourceLayoutPath);
|
|
794
|
+
} else {
|
|
795
|
+
if (!hasFile(changelogEntryDir, "page") || isManagedGeneratedFile(changelogEntryPath)) {
|
|
796
|
+
mkdirSync(changelogEntryDir, { recursive: true });
|
|
797
|
+
writeFileSync(changelogEntryPath, buildChangelogEntryPageSource(root, changelogEntryPath, entry, changelog.path, changelogEntries));
|
|
798
|
+
}
|
|
799
|
+
if (changelogSourceLayoutPath) {
|
|
800
|
+
const changelogSourceLayoutDir = dirname(changelogSourceLayoutPath);
|
|
801
|
+
if (!hasFile(changelogSourceLayoutDir, "layout") || isManagedGeneratedFile(changelogSourceLayoutPath)) {
|
|
802
|
+
mkdirSync(changelogSourceLayoutDir, { recursive: true });
|
|
803
|
+
writeFileSync(changelogSourceLayoutPath, CHANGELOG_SOURCE_LAYOUT_TEMPLATE);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
401
808
|
const ogEndpoint = readOgEndpoint(root);
|
|
402
809
|
const remarkPlugins = ["remark-gfm", "remark-frontmatter"];
|
|
403
810
|
if (ogEndpoint) remarkPlugins.push(["@farming-labs/next/mdx-plugins/remark-og", { endpoint: ogEndpoint }]);
|
|
@@ -450,6 +857,17 @@ function withDocs(nextConfig = {}) {
|
|
|
450
857
|
const resolvedConfig = userWebpack ? userWebpack(config, options) : config;
|
|
451
858
|
resolvedConfig.resolve ??= {};
|
|
452
859
|
resolvedConfig.resolve.alias ??= {};
|
|
860
|
+
if (workspaceRoot) Object.assign(resolvedConfig.resolve.alias, {
|
|
861
|
+
"@farming-labs/docs$": join(workspaceRoot, "packages", "docs", "dist", "index.mjs"),
|
|
862
|
+
"@farming-labs/docs/server": join(workspaceRoot, "packages", "docs", "dist", "server.mjs"),
|
|
863
|
+
"@farming-labs/next$": join(workspaceRoot, "packages", "next", "dist", "index.mjs"),
|
|
864
|
+
"@farming-labs/next/api": join(workspaceRoot, "packages", "next", "dist", "api.mjs"),
|
|
865
|
+
"@farming-labs/next/changelog": join(workspaceRoot, "packages", "next", "dist", "changelog.mjs"),
|
|
866
|
+
"@farming-labs/next/client-callbacks": join(workspaceRoot, "packages", "next", "dist", "client-callbacks.mjs"),
|
|
867
|
+
"@farming-labs/next/layout": join(workspaceRoot, "packages", "next", "dist", "layout.mjs"),
|
|
868
|
+
"@farming-labs/theme$": join(workspaceRoot, "packages", "fumadocs", "dist", "index.mjs"),
|
|
869
|
+
"@farming-labs/theme/api": join(workspaceRoot, "packages", "fumadocs", "dist", "docs-api.mjs")
|
|
870
|
+
});
|
|
453
871
|
resolvedConfig.resolve.alias[INTERNAL_DOCS_CONFIG_ALIAS] = docsConfigAbsolutePath;
|
|
454
872
|
resolvedConfig.resolve.alias["fumadocs-openapi"] = FUMADOCS_OPENAPI_PACKAGE_ALIAS;
|
|
455
873
|
resolvedConfig.resolve.alias["fumadocs-openapi/ui"] = FUMADOCS_OPENAPI_UI_ALIAS;
|
|
@@ -465,9 +883,17 @@ function withDocs(nextConfig = {}) {
|
|
|
465
883
|
};
|
|
466
884
|
const existingTracingIncludes = nextConfig.outputFileTracingIncludes ?? {};
|
|
467
885
|
const docsTraceGlob = docsContentDir.replace(/\\/g, "/").replace(/^\.?\//, "") + "/**/*";
|
|
886
|
+
if (!isStaticExport) {
|
|
887
|
+
const existingRewrites = nextConfig.rewrites;
|
|
888
|
+
nextConfig.rewrites = async () => {
|
|
889
|
+
return mergeDocsMarkdownRewrites(entry, typeof existingRewrites === "function" ? await existingRewrites() : existingRewrites);
|
|
890
|
+
};
|
|
891
|
+
}
|
|
468
892
|
nextConfig.outputFileTracingIncludes = {
|
|
469
893
|
...existingTracingIncludes,
|
|
470
894
|
"/api/docs": [...new Set([...existingTracingIncludes["/api/docs"] ?? [], docsTraceGlob])],
|
|
895
|
+
"/api/docs/markdown": [...new Set([...existingTracingIncludes["/api/docs/markdown"] ?? [], docsTraceGlob])],
|
|
896
|
+
"/api/docs/markdown/[[...slug]]": [...new Set([...existingTracingIncludes["/api/docs/markdown/[[...slug]]"] ?? [], docsTraceGlob])],
|
|
471
897
|
"/api/docs/mcp": [...new Set([...existingTracingIncludes["/api/docs/mcp"] ?? [], docsTraceGlob])]
|
|
472
898
|
};
|
|
473
899
|
return withMDX(nextConfig);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildNextOpenApiDocument, createNextApiReference, createNextApiReferenceLayout, createNextApiReferencePage, getNextApiReferenceMode, getNextApiReferenceSourceState, resolveApiReferenceConfig, withNextApiReferenceBanner } from "./api-reference.mjs";
|
|
2
2
|
import { createDocsAPI, createDocsMCPAPI } from "./api.mjs";
|
|
3
|
+
import { GeneratedChangelogEntry, createNextChangelogEntryMetadata, createNextChangelogEntryPage, createNextChangelogIndexMetadata, createNextChangelogIndexPage, createNextChangelogStaticParams } from "./changelog.mjs";
|
|
3
4
|
import { withDocs } from "./config.mjs";
|
|
4
|
-
export { buildNextOpenApiDocument, createDocsAPI, createDocsMCPAPI, createNextApiReference, createNextApiReferenceLayout, createNextApiReferencePage, getNextApiReferenceMode, getNextApiReferenceSourceState, resolveApiReferenceConfig, withDocs, withNextApiReferenceBanner };
|
|
5
|
+
export { type GeneratedChangelogEntry, buildNextOpenApiDocument, createDocsAPI, createDocsMCPAPI, createNextApiReference, createNextApiReferenceLayout, createNextApiReferencePage, createNextChangelogEntryMetadata, createNextChangelogEntryPage, createNextChangelogIndexMetadata, createNextChangelogIndexPage, createNextChangelogStaticParams, getNextApiReferenceMode, getNextApiReferenceSourceState, resolveApiReferenceConfig, withDocs, withNextApiReferenceBanner };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { withDocs } from "./config.mjs";
|
|
2
2
|
import { createDocsAPI, createDocsMCPAPI } from "./api.mjs";
|
|
3
3
|
import { buildNextOpenApiDocument, createNextApiReference, createNextApiReferenceLayout, createNextApiReferencePage, getNextApiReferenceMode, getNextApiReferenceSourceState, resolveApiReferenceConfig, withNextApiReferenceBanner } from "./api-reference.mjs";
|
|
4
|
+
import { createNextChangelogEntryMetadata, createNextChangelogEntryPage, createNextChangelogIndexMetadata, createNextChangelogIndexPage, createNextChangelogStaticParams } from "./changelog.mjs";
|
|
4
5
|
|
|
5
|
-
export { buildNextOpenApiDocument, createDocsAPI, createDocsMCPAPI, createNextApiReference, createNextApiReferenceLayout, createNextApiReferencePage, getNextApiReferenceMode, getNextApiReferenceSourceState, resolveApiReferenceConfig, withDocs, withNextApiReferenceBanner };
|
|
6
|
+
export { buildNextOpenApiDocument, createDocsAPI, createDocsMCPAPI, createNextApiReference, createNextApiReferenceLayout, createNextApiReferencePage, createNextChangelogEntryMetadata, createNextChangelogEntryPage, createNextChangelogIndexMetadata, createNextChangelogIndexPage, createNextChangelogStaticParams, getNextApiReferenceMode, getNextApiReferenceSourceState, resolveApiReferenceConfig, withDocs, withNextApiReferenceBanner };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -34,6 +34,11 @@
|
|
|
34
34
|
"import": "./dist/api.mjs",
|
|
35
35
|
"default": "./dist/api.mjs"
|
|
36
36
|
},
|
|
37
|
+
"./changelog": {
|
|
38
|
+
"types": "./dist/changelog.d.mts",
|
|
39
|
+
"import": "./dist/changelog.mjs",
|
|
40
|
+
"default": "./dist/changelog.mjs"
|
|
41
|
+
},
|
|
37
42
|
"./client-callbacks": {
|
|
38
43
|
"types": "./dist/client-callbacks.d.mts",
|
|
39
44
|
"import": "./dist/client-callbacks.mjs",
|
|
@@ -78,6 +83,7 @@
|
|
|
78
83
|
"fumadocs-openapi": "^10.7.0",
|
|
79
84
|
"fumadocs-core": "^16.6.1",
|
|
80
85
|
"fumadocs-ui": "^16.6.1",
|
|
86
|
+
"gray-matter": "^4.0.3",
|
|
81
87
|
"remark-frontmatter": "^5.0.0",
|
|
82
88
|
"remark-gfm": "^4.0.1",
|
|
83
89
|
"remark-mdx-frontmatter": "^5.0.0"
|
|
@@ -89,8 +95,8 @@
|
|
|
89
95
|
"tsdown": "^0.20.3",
|
|
90
96
|
"typescript": "^5.9.3",
|
|
91
97
|
"vitest": "^3.2.4",
|
|
92
|
-
"@farming-labs/docs": "0.1.
|
|
93
|
-
"@farming-labs/theme": "0.1.
|
|
98
|
+
"@farming-labs/docs": "0.1.16",
|
|
99
|
+
"@farming-labs/theme": "0.1.16"
|
|
94
100
|
},
|
|
95
101
|
"peerDependencies": {
|
|
96
102
|
"@farming-labs/docs": ">=0.0.1",
|