@farming-labs/docs 0.0.20 → 0.0.22
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/cli/index.mjs +60 -23
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -79,6 +79,17 @@ function detectGlobalCssFiles(cwd) {
|
|
|
79
79
|
return GLOBAL_CSS_CANDIDATES.filter((rel) => fs.existsSync(path.join(cwd, rel)));
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
|
+
* Detect whether the Next.js project uses `app` or `src/app` for the App Router.
|
|
83
|
+
* Returns the directory that exists; if both exist, prefers src/app; if neither, returns null.
|
|
84
|
+
*/
|
|
85
|
+
function detectNextAppDir(cwd) {
|
|
86
|
+
const hasSrcApp = fs.existsSync(path.join(cwd, "src", "app"));
|
|
87
|
+
const hasApp = fs.existsSync(path.join(cwd, "app"));
|
|
88
|
+
if (hasSrcApp) return "src/app";
|
|
89
|
+
if (hasApp) return "app";
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
82
93
|
* Run a shell command synchronously, inheriting stdio.
|
|
83
94
|
*/
|
|
84
95
|
function exec(command, cwd) {
|
|
@@ -257,13 +268,15 @@ function customThemeCssTemplate(themeName) {
|
|
|
257
268
|
}
|
|
258
269
|
`;
|
|
259
270
|
}
|
|
260
|
-
/** Config import for Next.js
|
|
261
|
-
function nextRootLayoutConfigImport(useAlias) {
|
|
262
|
-
|
|
271
|
+
/** Config import for Next.js root layout → root docs.config */
|
|
272
|
+
function nextRootLayoutConfigImport(useAlias, nextAppDir = "app") {
|
|
273
|
+
if (useAlias) return "@/docs.config";
|
|
274
|
+
return nextAppDir === "src/app" ? "../../docs.config" : "../docs.config";
|
|
263
275
|
}
|
|
264
276
|
/** Config import for Next.js app/{entry}/layout.tsx → root docs.config */
|
|
265
|
-
function nextDocsLayoutConfigImport(useAlias) {
|
|
266
|
-
|
|
277
|
+
function nextDocsLayoutConfigImport(useAlias, nextAppDir = "app") {
|
|
278
|
+
if (useAlias) return "@/docs.config";
|
|
279
|
+
return nextAppDir === "src/app" ? "../../../docs.config" : "../../docs.config";
|
|
267
280
|
}
|
|
268
281
|
/** Config import for SvelteKit src/lib/docs.server.ts → src/lib/docs.config */
|
|
269
282
|
function svelteServerConfigImport(useAlias) {
|
|
@@ -363,10 +376,11 @@ function rootLayoutTemplate(cfg, globalCssRelPath = "app/globals.css") {
|
|
|
363
376
|
if (globalCssRelPath.startsWith("app/")) cssImport = "./" + globalCssRelPath.slice(4);
|
|
364
377
|
else if (globalCssRelPath.startsWith("src/app/")) cssImport = "./" + globalCssRelPath.slice(8);
|
|
365
378
|
else cssImport = "../" + globalCssRelPath;
|
|
379
|
+
const appDir = cfg.nextAppDir ?? "app";
|
|
366
380
|
return `\
|
|
367
381
|
import type { Metadata } from "next";
|
|
368
382
|
import { RootProvider } from "@farming-labs/theme";
|
|
369
|
-
import docsConfig from "${nextRootLayoutConfigImport(cfg.useAlias)}";
|
|
383
|
+
import docsConfig from "${nextRootLayoutConfigImport(cfg.useAlias, appDir)}";
|
|
370
384
|
import "${cssImport}";
|
|
371
385
|
|
|
372
386
|
export const metadata: Metadata = {
|
|
@@ -440,8 +454,9 @@ function injectCssImport(existingContent, theme, customThemeName, globalCssRelPa
|
|
|
440
454
|
return lines.join("\n");
|
|
441
455
|
}
|
|
442
456
|
function docsLayoutTemplate(cfg) {
|
|
457
|
+
const appDir = cfg.nextAppDir ?? "app";
|
|
443
458
|
return `\
|
|
444
|
-
import docsConfig from "${nextDocsLayoutConfigImport(cfg.useAlias)}";
|
|
459
|
+
import docsConfig from "${nextDocsLayoutConfigImport(cfg.useAlias, appDir)}";
|
|
445
460
|
import { createDocsLayout, createDocsMetadata } from "@farming-labs/theme";
|
|
446
461
|
|
|
447
462
|
export const metadata = createDocsMetadata(docsConfig);
|
|
@@ -494,6 +509,7 @@ function tsconfigTemplate(useAlias = false) {
|
|
|
494
509
|
`;
|
|
495
510
|
}
|
|
496
511
|
function welcomePageTemplate(cfg) {
|
|
512
|
+
const appDir = cfg.nextAppDir ?? "app";
|
|
497
513
|
return `\
|
|
498
514
|
---
|
|
499
515
|
title: "Documentation"
|
|
@@ -505,7 +521,7 @@ description: "Welcome to ${cfg.projectName} documentation"
|
|
|
505
521
|
Get started with our documentation. Browse the pages on the left to learn more.
|
|
506
522
|
|
|
507
523
|
<Callout type="info">
|
|
508
|
-
This documentation was generated by \`@farming-labs/docs\`. Edit the MDX files in
|
|
524
|
+
This documentation was generated by \`@farming-labs/docs\`. Edit the MDX files in \`${appDir}/${cfg.entry}/\` to customize.
|
|
509
525
|
</Callout>
|
|
510
526
|
|
|
511
527
|
## Overview
|
|
@@ -571,7 +587,7 @@ export default defineDocs({
|
|
|
571
587
|
## Project Structure
|
|
572
588
|
|
|
573
589
|
\`\`\`
|
|
574
|
-
app/
|
|
590
|
+
${cfg.nextAppDir ?? "app"}/
|
|
575
591
|
${cfg.entry}/
|
|
576
592
|
layout.tsx # Docs layout
|
|
577
593
|
page.mdx # /${cfg.entry}
|
|
@@ -602,13 +618,13 @@ This guide walks you through creating your first documentation page.
|
|
|
602
618
|
|
|
603
619
|
## Creating a Page
|
|
604
620
|
|
|
605
|
-
Create a new folder under
|
|
621
|
+
Create a new folder under \`${cfg.nextAppDir ?? "app"}/${cfg.entry}/\` with a \`page.mdx\` file:
|
|
606
622
|
|
|
607
623
|
\`\`\`bash
|
|
608
|
-
mkdir -p app/${cfg.entry}/my-page
|
|
624
|
+
mkdir -p ${cfg.nextAppDir ?? "app"}/${cfg.entry}/my-page
|
|
609
625
|
\`\`\`
|
|
610
626
|
|
|
611
|
-
Then create
|
|
627
|
+
Then create \`${cfg.nextAppDir ?? "app"}/${cfg.entry}/my-page/page.mdx\`:
|
|
612
628
|
|
|
613
629
|
\`\`\`mdx
|
|
614
630
|
---
|
|
@@ -1832,6 +1848,7 @@ async function init(options = {}) {
|
|
|
1832
1848
|
}
|
|
1833
1849
|
const devCmd = pmFresh === "yarn" ? "yarn dev" : pmFresh === "npm" ? "npm run dev" : pmFresh === "bun" ? "bun dev" : "pnpm dev";
|
|
1834
1850
|
p.outro(pc.green(`Done! Run ${pc.cyan(`cd ${projectName} && ${devCmd}`)} to start the dev server and navigate to the /docs.`));
|
|
1851
|
+
p.outro(pc.green("Happy documenting!"));
|
|
1835
1852
|
process.exit(0);
|
|
1836
1853
|
}
|
|
1837
1854
|
let framework = detectFramework(cwd);
|
|
@@ -1871,6 +1888,24 @@ async function init(options = {}) {
|
|
|
1871
1888
|
}
|
|
1872
1889
|
framework = picked;
|
|
1873
1890
|
}
|
|
1891
|
+
let nextAppDir = "app";
|
|
1892
|
+
if (framework === "nextjs") {
|
|
1893
|
+
const detected = detectNextAppDir(cwd);
|
|
1894
|
+
if (detected) {
|
|
1895
|
+
nextAppDir = detected;
|
|
1896
|
+
p.log.info(`Using App Router at ${pc.cyan(nextAppDir)} (detected ${detected === "src/app" ? "src directory" : "root app"})`);
|
|
1897
|
+
} else {
|
|
1898
|
+
const useSrcApp = await p.confirm({
|
|
1899
|
+
message: "Do you use the src directory for the App Router? (e.g. src/app instead of app)",
|
|
1900
|
+
initialValue: false
|
|
1901
|
+
});
|
|
1902
|
+
if (p.isCancel(useSrcApp)) {
|
|
1903
|
+
p.outro(pc.red("Init cancelled."));
|
|
1904
|
+
process.exit(0);
|
|
1905
|
+
}
|
|
1906
|
+
nextAppDir = useSrcApp ? "src/app" : "app";
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1874
1909
|
const theme = await p.select({
|
|
1875
1910
|
message: "Which theme would you like to use?",
|
|
1876
1911
|
options: [
|
|
@@ -1998,7 +2033,7 @@ async function init(options = {}) {
|
|
|
1998
2033
|
const entryPath = entry.trim() || defaultEntry;
|
|
1999
2034
|
const detectedCssFiles = detectGlobalCssFiles(cwd);
|
|
2000
2035
|
let globalCssRelPath;
|
|
2001
|
-
const defaultCssPath = framework === "sveltekit" ? "src/app.css" : framework === "astro" ? "src/styles/global.css" : framework === "nuxt" ? "assets/css/main.css" : "app/globals.css";
|
|
2036
|
+
const defaultCssPath = framework === "sveltekit" ? "src/app.css" : framework === "astro" ? "src/styles/global.css" : framework === "nuxt" ? "assets/css/main.css" : framework === "nextjs" ? `${nextAppDir}/globals.css` : "app/globals.css";
|
|
2002
2037
|
if (detectedCssFiles.length === 1) {
|
|
2003
2038
|
globalCssRelPath = detectedCssFiles[0];
|
|
2004
2039
|
p.log.info(`Found global CSS at ${pc.cyan(globalCssRelPath)}`);
|
|
@@ -2041,7 +2076,8 @@ async function init(options = {}) {
|
|
|
2041
2076
|
projectName,
|
|
2042
2077
|
framework,
|
|
2043
2078
|
useAlias,
|
|
2044
|
-
astroAdapter
|
|
2079
|
+
astroAdapter,
|
|
2080
|
+
...framework === "nextjs" && { nextAppDir }
|
|
2045
2081
|
};
|
|
2046
2082
|
const s = p.spinner();
|
|
2047
2083
|
s.start("Scaffolding docs files");
|
|
@@ -2183,6 +2219,7 @@ async function init(options = {}) {
|
|
|
2183
2219
|
}
|
|
2184
2220
|
}
|
|
2185
2221
|
function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
2222
|
+
const appDir = cfg.nextAppDir ?? "app";
|
|
2186
2223
|
if (cfg.theme === "custom" && cfg.customThemeName) {
|
|
2187
2224
|
const baseName = cfg.customThemeName.replace(/\.(ts|css)$/i, "");
|
|
2188
2225
|
write(`themes/${baseName}.ts`, customThemeTsTemplate(baseName));
|
|
@@ -2198,16 +2235,16 @@ function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
2198
2235
|
written.push(configFile + " (updated)");
|
|
2199
2236
|
} else skipped.push(configFile + " (already configured)");
|
|
2200
2237
|
} else write("next.config.ts", nextConfigTemplate());
|
|
2201
|
-
const rootLayoutPath = path.join(cwd,
|
|
2238
|
+
const rootLayoutPath = path.join(cwd, `${appDir}/layout.tsx`);
|
|
2202
2239
|
const existingRootLayout = readFileSafe(rootLayoutPath);
|
|
2203
|
-
if (!existingRootLayout) write(
|
|
2240
|
+
if (!existingRootLayout) write(`${appDir}/layout.tsx`, rootLayoutTemplate(cfg, globalCssRelPath), true);
|
|
2204
2241
|
else if (!existingRootLayout.includes("RootProvider")) {
|
|
2205
2242
|
const injected = injectRootProviderIntoLayout(existingRootLayout);
|
|
2206
2243
|
if (injected) {
|
|
2207
2244
|
writeFileSafe(rootLayoutPath, injected, true);
|
|
2208
|
-
written.push(
|
|
2209
|
-
} else skipped.push(
|
|
2210
|
-
} else skipped.push(
|
|
2245
|
+
written.push(`${appDir}/layout.tsx (injected RootProvider)`);
|
|
2246
|
+
} else skipped.push(`${appDir}/layout.tsx (could not inject RootProvider)`);
|
|
2247
|
+
} else skipped.push(`${appDir}/layout.tsx (already has RootProvider)`);
|
|
2211
2248
|
const globalCssAbsPath = path.join(cwd, globalCssRelPath);
|
|
2212
2249
|
const existingGlobalCss = readFileSafe(globalCssAbsPath);
|
|
2213
2250
|
if (existingGlobalCss) {
|
|
@@ -2217,12 +2254,12 @@ function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
2217
2254
|
written.push(globalCssRelPath + " (updated)");
|
|
2218
2255
|
} else skipped.push(globalCssRelPath + " (already configured)");
|
|
2219
2256
|
} else write(globalCssRelPath, globalCssTemplate(cfg.theme, cfg.customThemeName, globalCssRelPath));
|
|
2220
|
-
write(
|
|
2257
|
+
write(`${appDir}/${cfg.entry}/layout.tsx`, docsLayoutTemplate(cfg));
|
|
2221
2258
|
write("postcss.config.mjs", postcssConfigTemplate());
|
|
2222
2259
|
if (!fileExists(path.join(cwd, "tsconfig.json"))) write("tsconfig.json", tsconfigTemplate(cfg.useAlias));
|
|
2223
|
-
write(
|
|
2224
|
-
write(
|
|
2225
|
-
write(
|
|
2260
|
+
write(`${appDir}/${cfg.entry}/page.mdx`, welcomePageTemplate(cfg));
|
|
2261
|
+
write(`${appDir}/${cfg.entry}/installation/page.mdx`, installationPageTemplate(cfg));
|
|
2262
|
+
write(`${appDir}/${cfg.entry}/quickstart/page.mdx`, quickstartPageTemplate(cfg));
|
|
2226
2263
|
}
|
|
2227
2264
|
function scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
2228
2265
|
if (cfg.theme === "custom" && cfg.customThemeName) {
|