@farming-labs/docs 0.0.2-beta.5 → 0.0.2-beta.7
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 +120 -52
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -128,14 +128,65 @@ function spawnAndWaitFor(command, args, cwd, waitFor, timeoutMs = 6e4) {
|
|
|
128
128
|
|
|
129
129
|
//#endregion
|
|
130
130
|
//#region src/cli/templates.ts
|
|
131
|
+
const THEME_INFO = {
|
|
132
|
+
fumadocs: {
|
|
133
|
+
factory: "fumadocs",
|
|
134
|
+
nextImport: "@farming-labs/theme",
|
|
135
|
+
svelteImport: "@farming-labs/svelte-theme",
|
|
136
|
+
nextCssImport: "default",
|
|
137
|
+
svelteCssTheme: "fumadocs"
|
|
138
|
+
},
|
|
139
|
+
darksharp: {
|
|
140
|
+
factory: "darksharp",
|
|
141
|
+
nextImport: "@farming-labs/theme/darksharp",
|
|
142
|
+
svelteImport: "@farming-labs/svelte-theme/darksharp",
|
|
143
|
+
nextCssImport: "darksharp",
|
|
144
|
+
svelteCssTheme: "darksharp"
|
|
145
|
+
},
|
|
146
|
+
"pixel-border": {
|
|
147
|
+
factory: "pixelBorder",
|
|
148
|
+
nextImport: "@farming-labs/theme/pixel-border",
|
|
149
|
+
svelteImport: "@farming-labs/svelte-theme/pixel-border",
|
|
150
|
+
nextCssImport: "pixel-border",
|
|
151
|
+
svelteCssTheme: "pixel-border"
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
function getThemeInfo(theme) {
|
|
155
|
+
return THEME_INFO[theme] ?? THEME_INFO.fumadocs;
|
|
156
|
+
}
|
|
157
|
+
/** Config import for Next.js app/layout.tsx → root docs.config */
|
|
158
|
+
function nextRootLayoutConfigImport(useAlias) {
|
|
159
|
+
return useAlias ? "@/docs.config" : "../docs.config";
|
|
160
|
+
}
|
|
161
|
+
/** Config import for Next.js app/{entry}/layout.tsx → root docs.config */
|
|
162
|
+
function nextDocsLayoutConfigImport(useAlias) {
|
|
163
|
+
return useAlias ? "@/docs.config" : "../../docs.config";
|
|
164
|
+
}
|
|
165
|
+
/** Config import for SvelteKit src/lib/docs.server.ts → src/lib/docs.config.js */
|
|
166
|
+
function svelteServerConfigImport(useAlias) {
|
|
167
|
+
return useAlias ? "$lib/docs.config.js" : "./docs.config.js";
|
|
168
|
+
}
|
|
169
|
+
/** Config import for SvelteKit src/routes/{entry}/+layout.svelte → src/lib/docs.config.js */
|
|
170
|
+
function svelteLayoutConfigImport(useAlias) {
|
|
171
|
+
return useAlias ? "$lib/docs.config.js" : "../../lib/docs.config.js";
|
|
172
|
+
}
|
|
173
|
+
/** Config import for SvelteKit src/routes/{entry}/[...slug]/+page.svelte → src/lib/docs.config.js */
|
|
174
|
+
function sveltePageConfigImport(useAlias) {
|
|
175
|
+
return useAlias ? "$lib/docs.config.js" : "../../../lib/docs.config.js";
|
|
176
|
+
}
|
|
177
|
+
/** Server import for SvelteKit +layout.server.js → src/lib/docs.server.js */
|
|
178
|
+
function svelteLayoutServerImport(useAlias) {
|
|
179
|
+
return useAlias ? "$lib/docs.server.js" : "../../lib/docs.server.js";
|
|
180
|
+
}
|
|
131
181
|
function docsConfigTemplate(cfg) {
|
|
182
|
+
const t = getThemeInfo(cfg.theme);
|
|
132
183
|
return `\
|
|
133
184
|
import { defineDocs } from "@farming-labs/docs";
|
|
134
|
-
import {
|
|
185
|
+
import { ${t.factory} } from "${t.nextImport}";
|
|
135
186
|
|
|
136
187
|
export default defineDocs({
|
|
137
188
|
entry: "${cfg.entry}",
|
|
138
|
-
theme:
|
|
189
|
+
theme: ${t.factory}({
|
|
139
190
|
ui: {
|
|
140
191
|
colors: { primary: "#6366f1" },
|
|
141
192
|
},
|
|
@@ -172,7 +223,7 @@ function nextConfigMergedTemplate(existingContent) {
|
|
|
172
223
|
}
|
|
173
224
|
return lines.join("\n");
|
|
174
225
|
}
|
|
175
|
-
function rootLayoutTemplate(globalCssRelPath = "app/globals.css") {
|
|
226
|
+
function rootLayoutTemplate(cfg, globalCssRelPath = "app/globals.css") {
|
|
176
227
|
let cssImport;
|
|
177
228
|
if (globalCssRelPath.startsWith("app/")) cssImport = "./" + globalCssRelPath.slice(4);
|
|
178
229
|
else if (globalCssRelPath.startsWith("src/app/")) cssImport = "./" + globalCssRelPath.slice(8);
|
|
@@ -180,7 +231,7 @@ function rootLayoutTemplate(globalCssRelPath = "app/globals.css") {
|
|
|
180
231
|
return `\
|
|
181
232
|
import type { Metadata } from "next";
|
|
182
233
|
import { RootProvider } from "@farming-labs/theme";
|
|
183
|
-
import docsConfig from "
|
|
234
|
+
import docsConfig from "${nextRootLayoutConfigImport(cfg.useAlias)}";
|
|
184
235
|
import "${cssImport}";
|
|
185
236
|
|
|
186
237
|
export const metadata: Metadata = {
|
|
@@ -209,25 +260,22 @@ export default function RootLayout({
|
|
|
209
260
|
function globalCssTemplate(theme) {
|
|
210
261
|
return `\
|
|
211
262
|
@import "tailwindcss";
|
|
212
|
-
@import "@farming-labs/${theme}/css";
|
|
263
|
+
@import "@farming-labs/theme/${getThemeInfo(theme).nextCssImport}/css";
|
|
213
264
|
`;
|
|
214
265
|
}
|
|
215
|
-
/**
|
|
216
|
-
* Inject the fumadocs CSS import into an existing global.css.
|
|
217
|
-
* Returns the modified content, or null if already present.
|
|
218
|
-
*/
|
|
219
266
|
function injectCssImport(existingContent, theme) {
|
|
220
|
-
const importLine = `@import "@farming-labs/${theme}/css";`;
|
|
267
|
+
const importLine = `@import "@farming-labs/theme/${getThemeInfo(theme).nextCssImport}/css";`;
|
|
221
268
|
if (existingContent.includes(importLine)) return null;
|
|
269
|
+
if (existingContent.includes("@farming-labs/theme/") && existingContent.includes("/css")) return null;
|
|
222
270
|
const lines = existingContent.split("\n");
|
|
223
271
|
const lastImportIdx = lines.reduce((acc, l, i) => l.trimStart().startsWith("@import") ? i : acc, -1);
|
|
224
272
|
if (lastImportIdx >= 0) lines.splice(lastImportIdx + 1, 0, importLine);
|
|
225
273
|
else lines.unshift(importLine);
|
|
226
274
|
return lines.join("\n");
|
|
227
275
|
}
|
|
228
|
-
function docsLayoutTemplate() {
|
|
276
|
+
function docsLayoutTemplate(cfg) {
|
|
229
277
|
return `\
|
|
230
|
-
import docsConfig from "
|
|
278
|
+
import docsConfig from "${nextDocsLayoutConfigImport(cfg.useAlias)}";
|
|
231
279
|
import { createDocsLayout } from "@farming-labs/theme";
|
|
232
280
|
|
|
233
281
|
export default createDocsLayout(docsConfig);
|
|
@@ -307,6 +355,7 @@ Start by reading the [Installation](/${cfg.entry}/installation) guide, then foll
|
|
|
307
355
|
`;
|
|
308
356
|
}
|
|
309
357
|
function installationPageTemplate(cfg) {
|
|
358
|
+
const t = getThemeInfo(cfg.theme);
|
|
310
359
|
return `\
|
|
311
360
|
---
|
|
312
361
|
title: "Installation"
|
|
@@ -333,11 +382,11 @@ Your project includes a \`docs.config.ts\` at the root:
|
|
|
333
382
|
|
|
334
383
|
\`\`\`ts
|
|
335
384
|
import { defineDocs } from "@farming-labs/docs";
|
|
336
|
-
import {
|
|
385
|
+
import { ${t.factory} } from "${t.nextImport}";
|
|
337
386
|
|
|
338
387
|
export default defineDocs({
|
|
339
388
|
entry: "${cfg.entry}",
|
|
340
|
-
theme:
|
|
389
|
+
theme: ${t.factory}({
|
|
341
390
|
ui: { colors: { primary: "#6366f1" } },
|
|
342
391
|
}),
|
|
343
392
|
});
|
|
@@ -364,6 +413,7 @@ Head to the [Quickstart](/${cfg.entry}/quickstart) guide to start writing your f
|
|
|
364
413
|
`;
|
|
365
414
|
}
|
|
366
415
|
function quickstartPageTemplate(cfg) {
|
|
416
|
+
const t = getThemeInfo(cfg.theme);
|
|
367
417
|
return `\
|
|
368
418
|
---
|
|
369
419
|
title: "Quickstart"
|
|
@@ -426,7 +476,7 @@ console.log(greet("World"));
|
|
|
426
476
|
Edit \`docs.config.ts\` to change colors, typography, and component defaults:
|
|
427
477
|
|
|
428
478
|
\`\`\`ts
|
|
429
|
-
theme:
|
|
479
|
+
theme: ${t.factory}({
|
|
430
480
|
ui: {
|
|
431
481
|
colors: { primary: "#22c55e" },
|
|
432
482
|
},
|
|
@@ -445,14 +495,15 @@ Deploy to Vercel, Netlify, or any Node.js hosting platform.
|
|
|
445
495
|
`;
|
|
446
496
|
}
|
|
447
497
|
function svelteDocsConfigTemplate(cfg) {
|
|
498
|
+
const t = getThemeInfo(cfg.theme);
|
|
448
499
|
return `\
|
|
449
500
|
import { defineDocs } from "@farming-labs/docs";
|
|
450
|
-
import {
|
|
501
|
+
import { ${t.factory} } from "${t.svelteImport}";
|
|
451
502
|
|
|
452
503
|
export default defineDocs({
|
|
453
504
|
entry: "${cfg.entry}",
|
|
454
505
|
contentDir: "${cfg.entry}",
|
|
455
|
-
theme:
|
|
506
|
+
theme: ${t.factory}({
|
|
456
507
|
ui: {
|
|
457
508
|
colors: { primary: "#6366f1" },
|
|
458
509
|
},
|
|
@@ -475,7 +526,7 @@ export default defineDocs({
|
|
|
475
526
|
function svelteDocsServerTemplate(cfg) {
|
|
476
527
|
return `\
|
|
477
528
|
import { createDocsServer } from "@farming-labs/svelte/server";
|
|
478
|
-
import config from "
|
|
529
|
+
import config from "${svelteServerConfigImport(cfg.useAlias)}";
|
|
479
530
|
|
|
480
531
|
export const { load, GET, POST } = createDocsServer(config);
|
|
481
532
|
`;
|
|
@@ -484,7 +535,7 @@ function svelteDocsLayoutTemplate(cfg) {
|
|
|
484
535
|
return `\
|
|
485
536
|
<script>
|
|
486
537
|
import { DocsLayout } from "@farming-labs/svelte-theme";
|
|
487
|
-
import config from "
|
|
538
|
+
import config from "${svelteLayoutConfigImport(cfg.useAlias)}";
|
|
488
539
|
|
|
489
540
|
let { data, children } = $props();
|
|
490
541
|
<\/script>
|
|
@@ -494,16 +545,16 @@ function svelteDocsLayoutTemplate(cfg) {
|
|
|
494
545
|
</DocsLayout>
|
|
495
546
|
`;
|
|
496
547
|
}
|
|
497
|
-
function svelteDocsLayoutServerTemplate() {
|
|
548
|
+
function svelteDocsLayoutServerTemplate(cfg) {
|
|
498
549
|
return `\
|
|
499
|
-
export { load } from "$
|
|
550
|
+
export { load } from "${svelteLayoutServerImport(cfg.useAlias)}";
|
|
500
551
|
`;
|
|
501
552
|
}
|
|
502
553
|
function svelteDocsPageTemplate(cfg) {
|
|
503
554
|
return `\
|
|
504
555
|
<script>
|
|
505
556
|
import { DocsContent } from "@farming-labs/svelte-theme";
|
|
506
|
-
import config from "
|
|
557
|
+
import config from "${sveltePageConfigImport(cfg.useAlias)}";
|
|
507
558
|
|
|
508
559
|
let { data } = $props();
|
|
509
560
|
<\/script>
|
|
@@ -573,6 +624,7 @@ Start by reading the [Installation](/${cfg.entry}/installation) guide, then foll
|
|
|
573
624
|
`;
|
|
574
625
|
}
|
|
575
626
|
function svelteInstallationPageTemplate(cfg) {
|
|
627
|
+
const t = getThemeInfo(cfg.theme);
|
|
576
628
|
return `\
|
|
577
629
|
---
|
|
578
630
|
title: "Installation"
|
|
@@ -596,16 +648,16 @@ pnpm add @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-theme
|
|
|
596
648
|
|
|
597
649
|
## Configuration
|
|
598
650
|
|
|
599
|
-
Your project includes a \`docs.config.ts\`
|
|
651
|
+
Your project includes a \`docs.config.ts\` in \`src/lib/\`:
|
|
600
652
|
|
|
601
|
-
\`\`\`ts title="docs.config.ts"
|
|
653
|
+
\`\`\`ts title="src/lib/docs.config.ts"
|
|
602
654
|
import { defineDocs } from "@farming-labs/docs";
|
|
603
|
-
import {
|
|
655
|
+
import { ${t.factory} } from "${t.svelteImport}";
|
|
604
656
|
|
|
605
657
|
export default defineDocs({
|
|
606
658
|
entry: "${cfg.entry}",
|
|
607
659
|
contentDir: "${cfg.entry}",
|
|
608
|
-
theme:
|
|
660
|
+
theme: ${t.factory}({
|
|
609
661
|
ui: { colors: { primary: "#6366f1" } },
|
|
610
662
|
}),
|
|
611
663
|
});
|
|
@@ -622,6 +674,7 @@ ${cfg.entry}/ # Markdown content
|
|
|
622
674
|
page.md # /${cfg.entry}/quickstart
|
|
623
675
|
src/
|
|
624
676
|
lib/
|
|
677
|
+
docs.config.ts # Docs configuration
|
|
625
678
|
docs.server.ts # Server-side docs loader
|
|
626
679
|
routes/
|
|
627
680
|
${cfg.entry}/
|
|
@@ -629,7 +682,6 @@ src/
|
|
|
629
682
|
+layout.server.js # Layout data loader
|
|
630
683
|
[...slug]/
|
|
631
684
|
+page.svelte # Dynamic doc page
|
|
632
|
-
docs.config.ts # Docs configuration
|
|
633
685
|
\`\`\`
|
|
634
686
|
|
|
635
687
|
## What's Next?
|
|
@@ -638,6 +690,7 @@ Head to the [Quickstart](/${cfg.entry}/quickstart) guide to start writing your f
|
|
|
638
690
|
`;
|
|
639
691
|
}
|
|
640
692
|
function svelteQuickstartPageTemplate(cfg) {
|
|
693
|
+
const t = getThemeInfo(cfg.theme);
|
|
641
694
|
return `\
|
|
642
695
|
---
|
|
643
696
|
title: "Quickstart"
|
|
@@ -685,10 +738,10 @@ console.log(greet("World"));
|
|
|
685
738
|
|
|
686
739
|
## Customizing the Theme
|
|
687
740
|
|
|
688
|
-
Edit \`docs.config.ts\` to change colors, typography, and component defaults:
|
|
741
|
+
Edit \`src/lib/docs.config.ts\` to change colors, typography, and component defaults:
|
|
689
742
|
|
|
690
|
-
\`\`\`ts title="docs.config.ts"
|
|
691
|
-
theme:
|
|
743
|
+
\`\`\`ts title="src/lib/docs.config.ts"
|
|
744
|
+
theme: ${t.factory}({
|
|
692
745
|
ui: {
|
|
693
746
|
colors: { primary: "#22c55e" },
|
|
694
747
|
},
|
|
@@ -736,27 +789,39 @@ async function init() {
|
|
|
736
789
|
}
|
|
737
790
|
framework = picked;
|
|
738
791
|
}
|
|
739
|
-
const themeOptions = framework === "sveltekit" ? [{
|
|
740
|
-
value: "default",
|
|
741
|
-
label: "Default",
|
|
742
|
-
hint: "Clean, modern docs theme with sidebar, search, and dark mode"
|
|
743
|
-
}, {
|
|
744
|
-
value: "pixel-border",
|
|
745
|
-
label: "Pixel Border",
|
|
746
|
-
hint: "Sharp pixel-art inspired theme with monospace text"
|
|
747
|
-
}] : [{
|
|
748
|
-
value: "fumadocs",
|
|
749
|
-
label: "Fumadocs",
|
|
750
|
-
hint: "Clean, modern docs theme with sidebar, search, and dark mode"
|
|
751
|
-
}];
|
|
752
792
|
const theme = await p.select({
|
|
753
793
|
message: "Which theme would you like to use?",
|
|
754
|
-
options:
|
|
794
|
+
options: [
|
|
795
|
+
{
|
|
796
|
+
value: "fumadocs",
|
|
797
|
+
label: "Fumadocs (Default)",
|
|
798
|
+
hint: "Clean, modern docs theme with sidebar, search, and dark mode"
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
value: "darksharp",
|
|
802
|
+
label: "Darksharp",
|
|
803
|
+
hint: "All-black, sharp edges, zero-radius look"
|
|
804
|
+
},
|
|
805
|
+
{
|
|
806
|
+
value: "pixel-border",
|
|
807
|
+
label: "Pixel Border",
|
|
808
|
+
hint: "Rounded borders, pixel-perfect spacing, refined sidebar"
|
|
809
|
+
}
|
|
810
|
+
]
|
|
755
811
|
});
|
|
756
812
|
if (p.isCancel(theme)) {
|
|
757
813
|
p.outro(pc.red("Init cancelled."));
|
|
758
814
|
process.exit(0);
|
|
759
815
|
}
|
|
816
|
+
const aliasHint = framework === "nextjs" ? `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)` : `Uses ${pc.cyan("$lib/")} prefix (SvelteKit built-in)`;
|
|
817
|
+
const useAlias = await p.confirm({
|
|
818
|
+
message: `Use path aliases for imports? ${pc.dim(aliasHint)}`,
|
|
819
|
+
initialValue: false
|
|
820
|
+
});
|
|
821
|
+
if (p.isCancel(useAlias)) {
|
|
822
|
+
p.outro(pc.red("Init cancelled."));
|
|
823
|
+
process.exit(0);
|
|
824
|
+
}
|
|
760
825
|
const entry = await p.text({
|
|
761
826
|
message: "Where should your docs live?",
|
|
762
827
|
placeholder: "docs",
|
|
@@ -807,12 +872,14 @@ async function init() {
|
|
|
807
872
|
}
|
|
808
873
|
globalCssRelPath = cssPath;
|
|
809
874
|
}
|
|
810
|
-
const
|
|
875
|
+
const pkgJsonContent = readFileSafe(path.join(cwd, "package.json"));
|
|
876
|
+
const pkgJson = pkgJsonContent ? JSON.parse(pkgJsonContent) : { name: "my-project" };
|
|
811
877
|
const cfg = {
|
|
812
878
|
entry: entryPath,
|
|
813
879
|
theme,
|
|
814
880
|
projectName: pkgJson.name || "My Project",
|
|
815
|
-
framework
|
|
881
|
+
framework,
|
|
882
|
+
useAlias
|
|
816
883
|
};
|
|
817
884
|
const s = p.spinner();
|
|
818
885
|
s.start("Scaffolding docs files");
|
|
@@ -918,7 +985,7 @@ function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
918
985
|
written.push(configFile + " (updated)");
|
|
919
986
|
} else skipped.push(configFile + " (already configured)");
|
|
920
987
|
} else write("next.config.ts", nextConfigTemplate());
|
|
921
|
-
write("app/layout.tsx", rootLayoutTemplate(globalCssRelPath));
|
|
988
|
+
write("app/layout.tsx", rootLayoutTemplate(cfg, globalCssRelPath));
|
|
922
989
|
const globalCssAbsPath = path.join(cwd, globalCssRelPath);
|
|
923
990
|
const existingGlobalCss = readFileSafe(globalCssAbsPath);
|
|
924
991
|
if (existingGlobalCss) {
|
|
@@ -928,7 +995,7 @@ function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
928
995
|
written.push(globalCssRelPath + " (updated)");
|
|
929
996
|
} else skipped.push(globalCssRelPath + " (already configured)");
|
|
930
997
|
} else write(globalCssRelPath, globalCssTemplate(cfg.theme));
|
|
931
|
-
write(`app/${cfg.entry}/layout.tsx`, docsLayoutTemplate());
|
|
998
|
+
write(`app/${cfg.entry}/layout.tsx`, docsLayoutTemplate(cfg));
|
|
932
999
|
write("postcss.config.mjs", postcssConfigTemplate());
|
|
933
1000
|
if (!fileExists(path.join(cwd, "tsconfig.json"))) write("tsconfig.json", tsconfigTemplate());
|
|
934
1001
|
write(`app/${cfg.entry}/page.mdx`, welcomePageTemplate(cfg));
|
|
@@ -936,18 +1003,19 @@ function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
936
1003
|
write(`app/${cfg.entry}/quickstart/page.mdx`, quickstartPageTemplate(cfg));
|
|
937
1004
|
}
|
|
938
1005
|
function scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
939
|
-
write("docs.config.ts", svelteDocsConfigTemplate(cfg));
|
|
1006
|
+
write("src/lib/docs.config.ts", svelteDocsConfigTemplate(cfg));
|
|
940
1007
|
write("src/lib/docs.server.ts", svelteDocsServerTemplate(cfg));
|
|
941
1008
|
write(`src/routes/${cfg.entry}/+layout.svelte`, svelteDocsLayoutTemplate(cfg));
|
|
942
|
-
write(`src/routes/${cfg.entry}/+layout.server.js`, svelteDocsLayoutServerTemplate());
|
|
1009
|
+
write(`src/routes/${cfg.entry}/+layout.server.js`, svelteDocsLayoutServerTemplate(cfg));
|
|
943
1010
|
write(`src/routes/${cfg.entry}/[...slug]/+page.svelte`, svelteDocsPageTemplate(cfg));
|
|
944
1011
|
if (!readFileSafe(path.join(cwd, "src/routes/+layout.svelte"))) write("src/routes/+layout.svelte", svelteRootLayoutTemplate(globalCssRelPath));
|
|
945
1012
|
const globalCssAbsPath = path.join(cwd, globalCssRelPath);
|
|
946
1013
|
const existingGlobalCss = readFileSafe(globalCssAbsPath);
|
|
947
1014
|
const cssTheme = {
|
|
948
|
-
|
|
1015
|
+
fumadocs: "fumadocs",
|
|
1016
|
+
darksharp: "darksharp",
|
|
949
1017
|
"pixel-border": "pixel-border",
|
|
950
|
-
|
|
1018
|
+
default: "fumadocs"
|
|
951
1019
|
}[cfg.theme] || "fumadocs";
|
|
952
1020
|
if (existingGlobalCss) {
|
|
953
1021
|
const injected = injectSvelteCssImport(existingGlobalCss, cssTheme);
|