@farming-labs/docs 0.0.4 → 0.0.5
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.d.mts +5 -1
- package/dist/cli/index.mjs +155 -8
- package/package.json +6 -3
package/dist/cli/index.d.mts
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/cli/index.d.ts
|
|
2
|
+
/** Parse flags like --template next, --name my-docs, --theme darksharp, --entry docs, --framework astro (exported for tests). */
|
|
3
|
+
declare function parseFlags(argv: string[]): Record<string, string | undefined>;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { parseFlags };
|
package/dist/cli/index.mjs
CHANGED
|
@@ -286,7 +286,7 @@ function nextConfigMergedTemplate(existingContent) {
|
|
|
286
286
|
const lastImportIdx = lines.reduce((acc, l, i) => l.trimStart().startsWith("import ") ? i : acc, -1);
|
|
287
287
|
if (lastImportIdx >= 0) lines.splice(lastImportIdx + 1, 0, importLine);
|
|
288
288
|
else lines.unshift(importLine, "");
|
|
289
|
-
const adjustedExportIdx = exportIdx + (lastImportIdx >= 0
|
|
289
|
+
const adjustedExportIdx = exportIdx + (lastImportIdx >= 0 ? exportIdx > lastImportIdx ? 1 : 0 : 2);
|
|
290
290
|
const simpleMatch = lines[adjustedExportIdx].match(/^(\s*export\s+default\s+)(.*?)(;?\s*)$/);
|
|
291
291
|
if (simpleMatch) {
|
|
292
292
|
const [, prefix, value, suffix] = simpleMatch;
|
|
@@ -328,6 +328,32 @@ export default function RootLayout({
|
|
|
328
328
|
}
|
|
329
329
|
`;
|
|
330
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Injects RootProvider (import + wrapper) into an existing root layout without overwriting.
|
|
333
|
+
* Returns the modified content, or null if RootProvider is already present or injection isn't possible.
|
|
334
|
+
*/
|
|
335
|
+
function injectRootProviderIntoLayout(content) {
|
|
336
|
+
if (!content || content.includes("RootProvider")) return null;
|
|
337
|
+
let out = content;
|
|
338
|
+
const themeImport = "import { RootProvider } from \"@farming-labs/theme\";";
|
|
339
|
+
if (!out.includes("@farming-labs/theme")) {
|
|
340
|
+
const lines = out.split("\n");
|
|
341
|
+
let lastImportIdx = -1;
|
|
342
|
+
for (let i = 0; i < lines.length; i++) {
|
|
343
|
+
const trimmed = lines[i].trimStart();
|
|
344
|
+
if (trimmed.startsWith("import ") || trimmed.startsWith("import type ")) lastImportIdx = i;
|
|
345
|
+
}
|
|
346
|
+
if (lastImportIdx >= 0) {
|
|
347
|
+
lines.splice(lastImportIdx + 1, 0, themeImport);
|
|
348
|
+
out = lines.join("\n");
|
|
349
|
+
} else out = themeImport + "\n" + out;
|
|
350
|
+
}
|
|
351
|
+
if (!out.includes("<RootProvider>")) {
|
|
352
|
+
const childrenPattern = /\{children\}/;
|
|
353
|
+
if (childrenPattern.test(out)) out = out.replace(childrenPattern, "<RootProvider>{children}</RootProvider>");
|
|
354
|
+
}
|
|
355
|
+
return out === content ? null : out;
|
|
356
|
+
}
|
|
331
357
|
function globalCssTemplate(theme) {
|
|
332
358
|
return `\
|
|
333
359
|
@import "tailwindcss";
|
|
@@ -347,9 +373,19 @@ function injectCssImport(existingContent, theme) {
|
|
|
347
373
|
function docsLayoutTemplate(cfg) {
|
|
348
374
|
return `\
|
|
349
375
|
import docsConfig from "${nextDocsLayoutConfigImport(cfg.useAlias)}";
|
|
350
|
-
import { createDocsLayout } from "@farming-labs/theme";
|
|
376
|
+
import { createDocsLayout, createDocsMetadata } from "@farming-labs/theme";
|
|
351
377
|
|
|
352
|
-
export
|
|
378
|
+
export const metadata = createDocsMetadata(docsConfig);
|
|
379
|
+
|
|
380
|
+
const DocsLayout = createDocsLayout(docsConfig);
|
|
381
|
+
|
|
382
|
+
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
383
|
+
return (
|
|
384
|
+
<>
|
|
385
|
+
<DocsLayout>{children}</DocsLayout>
|
|
386
|
+
</>
|
|
387
|
+
);
|
|
388
|
+
}
|
|
353
389
|
`;
|
|
354
390
|
}
|
|
355
391
|
function postcssConfigTemplate() {
|
|
@@ -1820,7 +1856,7 @@ async function init(options = {}) {
|
|
|
1820
1856
|
});
|
|
1821
1857
|
});
|
|
1822
1858
|
} catch (err) {
|
|
1823
|
-
const manualCmd = framework === "sveltekit" ? "npx vite dev" : framework === "astro" ? "npx astro dev" : framework === "nuxt" ? "npx nuxt dev" : "
|
|
1859
|
+
const manualCmd = framework === "sveltekit" ? "npx vite dev" : framework === "astro" ? "npx astro dev" : framework === "nuxt" ? "npx nuxt dev" : "pnpm dev";
|
|
1824
1860
|
p.log.error(`Could not start dev server. Try running manually:
|
|
1825
1861
|
${pc.cyan(manualCmd)}`);
|
|
1826
1862
|
p.outro(pc.yellow("Setup complete. Start the server manually."));
|
|
@@ -1838,7 +1874,16 @@ function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
1838
1874
|
written.push(configFile + " (updated)");
|
|
1839
1875
|
} else skipped.push(configFile + " (already configured)");
|
|
1840
1876
|
} else write("next.config.ts", nextConfigTemplate());
|
|
1841
|
-
|
|
1877
|
+
const rootLayoutPath = path.join(cwd, "app/layout.tsx");
|
|
1878
|
+
const existingRootLayout = readFileSafe(rootLayoutPath);
|
|
1879
|
+
if (!existingRootLayout) write("app/layout.tsx", rootLayoutTemplate(cfg, globalCssRelPath), true);
|
|
1880
|
+
else if (!existingRootLayout.includes("RootProvider")) {
|
|
1881
|
+
const injected = injectRootProviderIntoLayout(existingRootLayout);
|
|
1882
|
+
if (injected) {
|
|
1883
|
+
writeFileSafe(rootLayoutPath, injected, true);
|
|
1884
|
+
written.push("app/layout.tsx (injected RootProvider)");
|
|
1885
|
+
} else skipped.push("app/layout.tsx (could not inject RootProvider)");
|
|
1886
|
+
} else skipped.push("app/layout.tsx (already has RootProvider)");
|
|
1842
1887
|
const globalCssAbsPath = path.join(cwd, globalCssRelPath);
|
|
1843
1888
|
const existingGlobalCss = readFileSafe(globalCssAbsPath);
|
|
1844
1889
|
if (existingGlobalCss) {
|
|
@@ -1948,11 +1993,102 @@ function scaffoldNuxt(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
1948
1993
|
write(`${cfg.entry}/quickstart/page.md`, nuxtQuickstartPageTemplate(cfg));
|
|
1949
1994
|
}
|
|
1950
1995
|
|
|
1996
|
+
//#endregion
|
|
1997
|
+
//#region src/cli/upgrade.ts
|
|
1998
|
+
/**
|
|
1999
|
+
* Upgrade @farming-labs/* packages to latest.
|
|
2000
|
+
* Detects framework from package.json by default, or use --framework (next, nuxt, sveltekit, astro).
|
|
2001
|
+
*/
|
|
2002
|
+
const PRESETS = [
|
|
2003
|
+
"next",
|
|
2004
|
+
"nuxt",
|
|
2005
|
+
"sveltekit",
|
|
2006
|
+
"astro"
|
|
2007
|
+
];
|
|
2008
|
+
const PACKAGES_BY_FRAMEWORK = {
|
|
2009
|
+
nextjs: [
|
|
2010
|
+
"@farming-labs/docs",
|
|
2011
|
+
"@farming-labs/theme",
|
|
2012
|
+
"@farming-labs/next"
|
|
2013
|
+
],
|
|
2014
|
+
nuxt: [
|
|
2015
|
+
"@farming-labs/docs",
|
|
2016
|
+
"@farming-labs/nuxt",
|
|
2017
|
+
"@farming-labs/nuxt-theme"
|
|
2018
|
+
],
|
|
2019
|
+
sveltekit: [
|
|
2020
|
+
"@farming-labs/docs",
|
|
2021
|
+
"@farming-labs/svelte",
|
|
2022
|
+
"@farming-labs/svelte-theme"
|
|
2023
|
+
],
|
|
2024
|
+
astro: [
|
|
2025
|
+
"@farming-labs/docs",
|
|
2026
|
+
"@farming-labs/astro",
|
|
2027
|
+
"@farming-labs/astro-theme"
|
|
2028
|
+
]
|
|
2029
|
+
};
|
|
2030
|
+
function presetFromFramework(fw) {
|
|
2031
|
+
return fw === "nextjs" ? "next" : fw;
|
|
2032
|
+
}
|
|
2033
|
+
function frameworkFromPreset(preset) {
|
|
2034
|
+
return preset === "next" ? "nextjs" : preset;
|
|
2035
|
+
}
|
|
2036
|
+
/** Return package list for a framework (for testing and CLI). */
|
|
2037
|
+
function getPackagesForFramework(framework) {
|
|
2038
|
+
return PACKAGES_BY_FRAMEWORK[framework];
|
|
2039
|
+
}
|
|
2040
|
+
/** Build the install command for upgrade (for testing). */
|
|
2041
|
+
function buildUpgradeCommand(framework, tag, pm) {
|
|
2042
|
+
const packagesWithTag = PACKAGES_BY_FRAMEWORK[framework].map((name) => `${name}@${tag}`);
|
|
2043
|
+
return `${installCommand(pm)} ${packagesWithTag.join(" ")}`;
|
|
2044
|
+
}
|
|
2045
|
+
async function upgrade(options = {}) {
|
|
2046
|
+
const cwd = process.cwd();
|
|
2047
|
+
const tag = options.tag ?? "latest";
|
|
2048
|
+
p.intro(pc.bgCyan(pc.black(" @farming-labs/docs upgrade ")));
|
|
2049
|
+
if (!fileExists(path.join(cwd, "package.json"))) {
|
|
2050
|
+
p.log.error("No package.json found in the current directory. Run this from your project root.");
|
|
2051
|
+
process.exit(1);
|
|
2052
|
+
}
|
|
2053
|
+
let framework = null;
|
|
2054
|
+
let preset;
|
|
2055
|
+
if (options.framework) {
|
|
2056
|
+
const raw = options.framework.toLowerCase().trim();
|
|
2057
|
+
const normalized = raw === "nextjs" ? "next" : raw;
|
|
2058
|
+
if (!PRESETS.includes(normalized)) {
|
|
2059
|
+
p.log.error(`Invalid framework ${pc.cyan(options.framework)}. Use one of: ${PRESETS.map((t) => pc.cyan(t)).join(", ")}`);
|
|
2060
|
+
process.exit(1);
|
|
2061
|
+
}
|
|
2062
|
+
preset = normalized;
|
|
2063
|
+
framework = frameworkFromPreset(preset);
|
|
2064
|
+
} else {
|
|
2065
|
+
framework = detectFramework(cwd);
|
|
2066
|
+
if (!framework) {
|
|
2067
|
+
p.log.error("Could not detect a supported framework (Next.js, Nuxt, SvelteKit, Astro). Use " + pc.cyan("--framework <next|nuxt|sveltekit|astro>") + " to specify.");
|
|
2068
|
+
process.exit(1);
|
|
2069
|
+
}
|
|
2070
|
+
preset = presetFromFramework(framework);
|
|
2071
|
+
}
|
|
2072
|
+
const pm = detectPackageManager(cwd);
|
|
2073
|
+
const cmd = buildUpgradeCommand(framework, tag, pm);
|
|
2074
|
+
const packages = getPackagesForFramework(framework);
|
|
2075
|
+
p.log.step(`Upgrading ${preset} docs packages to ${tag}...`);
|
|
2076
|
+
p.log.message(pc.dim(packages.join(", ")));
|
|
2077
|
+
try {
|
|
2078
|
+
exec(cmd, cwd);
|
|
2079
|
+
p.log.success(`Packages upgraded to ${tag}.`);
|
|
2080
|
+
p.outro(pc.green("Done. Run your dev server to confirm everything works."));
|
|
2081
|
+
} catch {
|
|
2082
|
+
p.log.error("Upgrade failed. Try running manually:\n " + pc.cyan(cmd));
|
|
2083
|
+
process.exit(1);
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
|
|
1951
2087
|
//#endregion
|
|
1952
2088
|
//#region src/cli/index.ts
|
|
1953
2089
|
const args = process.argv.slice(2);
|
|
1954
2090
|
const command = args[0];
|
|
1955
|
-
/** Parse flags like --template next, --name my-docs, --theme darksharp, --entry docs */
|
|
2091
|
+
/** Parse flags like --template next, --name my-docs, --theme darksharp, --entry docs, --framework astro (exported for tests). */
|
|
1956
2092
|
function parseFlags(argv) {
|
|
1957
2093
|
const flags = {};
|
|
1958
2094
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -1976,6 +2112,10 @@ async function main() {
|
|
|
1976
2112
|
entry: flags.entry
|
|
1977
2113
|
};
|
|
1978
2114
|
if (!command || command === "init") await init(initOptions);
|
|
2115
|
+
else if (command === "upgrade") await upgrade({
|
|
2116
|
+
framework: flags.framework ?? (args[1] && !args[1].startsWith("--") ? args[1] : void 0),
|
|
2117
|
+
tag: args.includes("--beta") ? "beta" : "latest"
|
|
2118
|
+
});
|
|
1979
2119
|
else if (command === "--help" || command === "-h") printHelp();
|
|
1980
2120
|
else if (command === "--version" || command === "-v") printVersion();
|
|
1981
2121
|
else {
|
|
@@ -1993,7 +2133,8 @@ ${pc.dim("Usage:")}
|
|
|
1993
2133
|
npx @farming-labs/docs@latest ${pc.cyan("<command>")}
|
|
1994
2134
|
|
|
1995
2135
|
${pc.dim("Commands:")}
|
|
1996
|
-
${pc.cyan("init")}
|
|
2136
|
+
${pc.cyan("init")} Scaffold docs in your project (default)
|
|
2137
|
+
${pc.cyan("upgrade")} Upgrade @farming-labs/* packages to latest (auto-detect or use --framework)
|
|
1997
2138
|
|
|
1998
2139
|
${pc.dim("Supported frameworks:")}
|
|
1999
2140
|
Next.js, SvelteKit, Astro, Nuxt
|
|
@@ -2003,6 +2144,12 @@ ${pc.dim("Options for init:")}
|
|
|
2003
2144
|
${pc.cyan("--name <project>")} Project folder name when using ${pc.cyan("--template")}; prompt if omitted (e.g. ${pc.dim("my-docs")})
|
|
2004
2145
|
${pc.cyan("--theme <name>")} Skip theme prompt (e.g. ${pc.dim("darksharp")}, ${pc.dim("greentree")})
|
|
2005
2146
|
${pc.cyan("--entry <path>")} Skip entry path prompt (e.g. ${pc.dim("docs")})
|
|
2147
|
+
|
|
2148
|
+
${pc.dim("Options for upgrade:")}
|
|
2149
|
+
${pc.cyan("--framework <name>")} Explicit framework (${pc.dim("next")}, ${pc.dim("nuxt")}, ${pc.dim("sveltekit")}, ${pc.dim("astro")}); omit to auto-detect
|
|
2150
|
+
${pc.cyan("--latest")} Install latest stable (default)
|
|
2151
|
+
${pc.cyan("--beta")} Install beta versions
|
|
2152
|
+
|
|
2006
2153
|
${pc.cyan("-h, --help")} Show this help message
|
|
2007
2154
|
${pc.cyan("-v, --version")} Show version
|
|
2008
2155
|
`);
|
|
@@ -2017,4 +2164,4 @@ main().catch((err) => {
|
|
|
2017
2164
|
});
|
|
2018
2165
|
|
|
2019
2166
|
//#endregion
|
|
2020
|
-
export {
|
|
2167
|
+
export { parseFlags };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/docs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -34,11 +34,14 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^22.10.0",
|
|
36
36
|
"tsdown": "^0.20.3",
|
|
37
|
-
"typescript": "^5.9.3"
|
|
37
|
+
"typescript": "^5.9.3",
|
|
38
|
+
"vitest": "^3.2.4"
|
|
38
39
|
},
|
|
39
40
|
"scripts": {
|
|
40
41
|
"build": "tsdown",
|
|
41
42
|
"dev": "tsdown --watch",
|
|
42
|
-
"typecheck": "tsc --noEmit"
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"test:watch": "vitest"
|
|
43
46
|
}
|
|
44
47
|
}
|