@farming-labs/docs 0.0.2-beta.13 → 0.0.2-beta.15
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 +434 -20
- package/dist/index.d.mts +61 -1
- package/dist/index.mjs +1 -0
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -16,6 +16,7 @@ function detectFramework(cwd) {
|
|
|
16
16
|
};
|
|
17
17
|
if (allDeps["next"]) return "nextjs";
|
|
18
18
|
if (allDeps["@sveltejs/kit"]) return "sveltekit";
|
|
19
|
+
if (allDeps["astro"]) return "astro";
|
|
19
20
|
return null;
|
|
20
21
|
}
|
|
21
22
|
function detectPackageManager(cwd) {
|
|
@@ -133,22 +134,28 @@ const THEME_INFO = {
|
|
|
133
134
|
factory: "fumadocs",
|
|
134
135
|
nextImport: "@farming-labs/theme",
|
|
135
136
|
svelteImport: "@farming-labs/svelte-theme",
|
|
137
|
+
astroImport: "@farming-labs/astro-theme",
|
|
136
138
|
nextCssImport: "default",
|
|
137
|
-
svelteCssTheme: "fumadocs"
|
|
139
|
+
svelteCssTheme: "fumadocs",
|
|
140
|
+
astroCssTheme: "fumadocs"
|
|
138
141
|
},
|
|
139
142
|
darksharp: {
|
|
140
143
|
factory: "darksharp",
|
|
141
144
|
nextImport: "@farming-labs/theme/darksharp",
|
|
142
145
|
svelteImport: "@farming-labs/svelte-theme/darksharp",
|
|
146
|
+
astroImport: "@farming-labs/astro-theme/darksharp",
|
|
143
147
|
nextCssImport: "darksharp",
|
|
144
|
-
svelteCssTheme: "darksharp"
|
|
148
|
+
svelteCssTheme: "darksharp",
|
|
149
|
+
astroCssTheme: "darksharp"
|
|
145
150
|
},
|
|
146
151
|
"pixel-border": {
|
|
147
152
|
factory: "pixelBorder",
|
|
148
153
|
nextImport: "@farming-labs/theme/pixel-border",
|
|
149
154
|
svelteImport: "@farming-labs/svelte-theme/pixel-border",
|
|
155
|
+
astroImport: "@farming-labs/astro-theme/pixel-border",
|
|
150
156
|
nextCssImport: "pixel-border",
|
|
151
|
-
svelteCssTheme: "pixel-border"
|
|
157
|
+
svelteCssTheme: "pixel-border",
|
|
158
|
+
astroCssTheme: "pixel-border"
|
|
152
159
|
}
|
|
153
160
|
};
|
|
154
161
|
function getThemeInfo(theme) {
|
|
@@ -178,6 +185,17 @@ function sveltePageConfigImport(useAlias) {
|
|
|
178
185
|
function svelteLayoutServerImport(useAlias) {
|
|
179
186
|
return useAlias ? "$lib/docs.server" : "../../lib/docs.server";
|
|
180
187
|
}
|
|
188
|
+
function astroServerConfigImport(useAlias) {
|
|
189
|
+
return useAlias ? "@/lib/docs.config" : "./docs.config";
|
|
190
|
+
}
|
|
191
|
+
function astroPageConfigImport(useAlias, depth) {
|
|
192
|
+
if (useAlias) return "@/lib/docs.config";
|
|
193
|
+
return `${"../".repeat(depth)}lib/docs.config`;
|
|
194
|
+
}
|
|
195
|
+
function astroPageServerImport(useAlias, depth) {
|
|
196
|
+
if (useAlias) return "@/lib/docs.server";
|
|
197
|
+
return `${"../".repeat(depth)}lib/docs.server`;
|
|
198
|
+
}
|
|
181
199
|
function docsConfigTemplate(cfg) {
|
|
182
200
|
const t = getThemeInfo(cfg.theme);
|
|
183
201
|
return `\
|
|
@@ -527,6 +545,7 @@ function svelteDocsServerTemplate(cfg) {
|
|
|
527
545
|
import { createDocsServer } from "@farming-labs/svelte/server";
|
|
528
546
|
import config from "${svelteServerConfigImport(cfg.useAlias)}";
|
|
529
547
|
|
|
548
|
+
// preload for production
|
|
530
549
|
const contentFiles = import.meta.glob("/${cfg.entry ?? "docs"}/**/*.{md,mdx,svx}", {
|
|
531
550
|
query: "?raw",
|
|
532
551
|
import: "default",
|
|
@@ -764,6 +783,327 @@ Build your docs for production:
|
|
|
764
783
|
pnpm build
|
|
765
784
|
\`\`\`
|
|
766
785
|
|
|
786
|
+
Deploy to Vercel, Netlify, or any Node.js hosting platform.
|
|
787
|
+
`;
|
|
788
|
+
}
|
|
789
|
+
function astroDocsConfigTemplate(cfg) {
|
|
790
|
+
const t = getThemeInfo(cfg.theme);
|
|
791
|
+
return `\
|
|
792
|
+
import { defineDocs } from "@farming-labs/docs";
|
|
793
|
+
import { ${t.factory} } from "${t.astroImport}";
|
|
794
|
+
|
|
795
|
+
export default defineDocs({
|
|
796
|
+
entry: "${cfg.entry}",
|
|
797
|
+
contentDir: "${cfg.entry}",
|
|
798
|
+
theme: ${t.factory}({
|
|
799
|
+
ui: {
|
|
800
|
+
colors: { primary: "#6366f1" },
|
|
801
|
+
},
|
|
802
|
+
}),
|
|
803
|
+
|
|
804
|
+
nav: {
|
|
805
|
+
title: "${cfg.projectName}",
|
|
806
|
+
url: "/${cfg.entry}",
|
|
807
|
+
},
|
|
808
|
+
|
|
809
|
+
breadcrumb: { enabled: true },
|
|
810
|
+
|
|
811
|
+
metadata: {
|
|
812
|
+
titleTemplate: "%s – ${cfg.projectName}",
|
|
813
|
+
description: "Documentation for ${cfg.projectName}",
|
|
814
|
+
},
|
|
815
|
+
});
|
|
816
|
+
`;
|
|
817
|
+
}
|
|
818
|
+
function astroDocsServerTemplate(cfg) {
|
|
819
|
+
return `\
|
|
820
|
+
import { createDocsServer } from "@farming-labs/astro/server";
|
|
821
|
+
import config from "${astroServerConfigImport(cfg.useAlias)}";
|
|
822
|
+
|
|
823
|
+
const contentFiles = import.meta.glob("/${cfg.entry ?? "docs"}/**/*.{md,mdx}", {
|
|
824
|
+
query: "?raw",
|
|
825
|
+
import: "default",
|
|
826
|
+
eager: true,
|
|
827
|
+
}) as Record<string, string>;
|
|
828
|
+
|
|
829
|
+
export const { load, GET, POST } = createDocsServer({
|
|
830
|
+
...config,
|
|
831
|
+
_preloadedContent: contentFiles,
|
|
832
|
+
});
|
|
833
|
+
`;
|
|
834
|
+
}
|
|
835
|
+
const ASTRO_ADAPTER_INFO = {
|
|
836
|
+
vercel: {
|
|
837
|
+
pkg: "@astrojs/vercel",
|
|
838
|
+
import: "@astrojs/vercel"
|
|
839
|
+
},
|
|
840
|
+
netlify: {
|
|
841
|
+
pkg: "@astrojs/netlify",
|
|
842
|
+
import: "@astrojs/netlify"
|
|
843
|
+
},
|
|
844
|
+
node: {
|
|
845
|
+
pkg: "@astrojs/node",
|
|
846
|
+
import: "@astrojs/node"
|
|
847
|
+
},
|
|
848
|
+
cloudflare: {
|
|
849
|
+
pkg: "@astrojs/cloudflare",
|
|
850
|
+
import: "@astrojs/cloudflare"
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
function getAstroAdapterPkg(adapter) {
|
|
854
|
+
return ASTRO_ADAPTER_INFO[adapter]?.pkg ?? ASTRO_ADAPTER_INFO.vercel.pkg;
|
|
855
|
+
}
|
|
856
|
+
function astroConfigTemplate(adapter = "vercel") {
|
|
857
|
+
const info = ASTRO_ADAPTER_INFO[adapter] ?? ASTRO_ADAPTER_INFO.vercel;
|
|
858
|
+
const adapterCall = adapter === "node" ? `${adapter}({ mode: "standalone" })` : `${adapter}()`;
|
|
859
|
+
return `\
|
|
860
|
+
import { defineConfig } from "astro/config";
|
|
861
|
+
import ${adapter} from "${info.import}";
|
|
862
|
+
|
|
863
|
+
export default defineConfig({
|
|
864
|
+
output: "server",
|
|
865
|
+
adapter: ${adapterCall},
|
|
866
|
+
});
|
|
867
|
+
`;
|
|
868
|
+
}
|
|
869
|
+
function astroDocsPageTemplate(cfg) {
|
|
870
|
+
return `\
|
|
871
|
+
---
|
|
872
|
+
import DocsLayout from "@farming-labs/astro-theme/src/components/DocsLayout.astro";
|
|
873
|
+
import DocsContent from "@farming-labs/astro-theme/src/components/DocsContent.astro";
|
|
874
|
+
import SearchDialog from "@farming-labs/astro-theme/src/components/SearchDialog.astro";
|
|
875
|
+
import config from "${astroPageConfigImport(cfg.useAlias, 2)}";
|
|
876
|
+
import { load } from "${astroPageServerImport(cfg.useAlias, 2)}";
|
|
877
|
+
import "${`@farming-labs/astro-theme/${getThemeInfo(cfg.theme).astroCssTheme}/css`}";
|
|
878
|
+
|
|
879
|
+
const data = await load(Astro.url.pathname);
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
<html lang="en">
|
|
883
|
+
<head>
|
|
884
|
+
<meta charset="utf-8" />
|
|
885
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
886
|
+
<title>{data.title} – Docs</title>
|
|
887
|
+
</head>
|
|
888
|
+
<body>
|
|
889
|
+
<DocsLayout tree={data.tree} config={config}>
|
|
890
|
+
<DocsContent data={data} config={config} />
|
|
891
|
+
</DocsLayout>
|
|
892
|
+
<SearchDialog config={config} />
|
|
893
|
+
</body>
|
|
894
|
+
</html>
|
|
895
|
+
`;
|
|
896
|
+
}
|
|
897
|
+
function astroDocsIndexTemplate(cfg) {
|
|
898
|
+
return `\
|
|
899
|
+
---
|
|
900
|
+
import DocsLayout from "@farming-labs/astro-theme/src/components/DocsLayout.astro";
|
|
901
|
+
import DocsContent from "@farming-labs/astro-theme/src/components/DocsContent.astro";
|
|
902
|
+
import SearchDialog from "@farming-labs/astro-theme/src/components/SearchDialog.astro";
|
|
903
|
+
import config from "${astroPageConfigImport(cfg.useAlias, 2)}";
|
|
904
|
+
import { load } from "${astroPageServerImport(cfg.useAlias, 2)}";
|
|
905
|
+
import "${`@farming-labs/astro-theme/${getThemeInfo(cfg.theme).astroCssTheme}/css`}";
|
|
906
|
+
|
|
907
|
+
const data = await load(Astro.url.pathname);
|
|
908
|
+
---
|
|
909
|
+
|
|
910
|
+
<html lang="en">
|
|
911
|
+
<head>
|
|
912
|
+
<meta charset="utf-8" />
|
|
913
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
914
|
+
<title>{data.title} – Docs</title>
|
|
915
|
+
</head>
|
|
916
|
+
<body>
|
|
917
|
+
<DocsLayout tree={data.tree} config={config}>
|
|
918
|
+
<DocsContent data={data} config={config} />
|
|
919
|
+
</DocsLayout>
|
|
920
|
+
<SearchDialog config={config} />
|
|
921
|
+
</body>
|
|
922
|
+
</html>
|
|
923
|
+
`;
|
|
924
|
+
}
|
|
925
|
+
function astroApiRouteTemplate(cfg) {
|
|
926
|
+
return `\
|
|
927
|
+
import type { APIRoute } from "astro";
|
|
928
|
+
import { GET as docsGET, POST as docsPOST } from "${astroPageServerImport(cfg.useAlias, 2)}";
|
|
929
|
+
|
|
930
|
+
export const GET: APIRoute = async ({ request }) => {
|
|
931
|
+
return docsGET({ request });
|
|
932
|
+
};
|
|
933
|
+
|
|
934
|
+
export const POST: APIRoute = async ({ request }) => {
|
|
935
|
+
return docsPOST({ request });
|
|
936
|
+
};
|
|
937
|
+
`;
|
|
938
|
+
}
|
|
939
|
+
function astroGlobalCssTemplate(theme) {
|
|
940
|
+
return `\
|
|
941
|
+
@import "@farming-labs/astro-theme/${theme}/css";
|
|
942
|
+
`;
|
|
943
|
+
}
|
|
944
|
+
function astroCssImportLine(theme) {
|
|
945
|
+
return `@import "@farming-labs/astro-theme/${theme}/css";`;
|
|
946
|
+
}
|
|
947
|
+
function injectAstroCssImport(existingContent, theme) {
|
|
948
|
+
const importLine = astroCssImportLine(theme);
|
|
949
|
+
if (existingContent.includes(importLine)) return null;
|
|
950
|
+
const lines = existingContent.split("\n");
|
|
951
|
+
const lastImportIdx = lines.reduce((acc, l, i) => l.trimStart().startsWith("@import") ? i : acc, -1);
|
|
952
|
+
if (lastImportIdx >= 0) lines.splice(lastImportIdx + 1, 0, importLine);
|
|
953
|
+
else lines.unshift(importLine);
|
|
954
|
+
return lines.join("\n");
|
|
955
|
+
}
|
|
956
|
+
function astroWelcomePageTemplate(cfg) {
|
|
957
|
+
return `\
|
|
958
|
+
---
|
|
959
|
+
title: "Documentation"
|
|
960
|
+
description: "Welcome to ${cfg.projectName} documentation"
|
|
961
|
+
---
|
|
962
|
+
|
|
963
|
+
# Welcome to ${cfg.projectName}
|
|
964
|
+
|
|
965
|
+
Get started with our documentation. Browse the pages on the left to learn more.
|
|
966
|
+
|
|
967
|
+
## Overview
|
|
968
|
+
|
|
969
|
+
This documentation was generated by \`@farming-labs/docs\`. Edit the markdown files in \`${cfg.entry}/\` to customize.
|
|
970
|
+
|
|
971
|
+
## Features
|
|
972
|
+
|
|
973
|
+
- **Markdown Support** — Write docs with standard Markdown
|
|
974
|
+
- **Syntax Highlighting** — Code blocks with automatic highlighting
|
|
975
|
+
- **Dark Mode** — Built-in theme switching
|
|
976
|
+
- **Search** — Full-text search across all pages
|
|
977
|
+
- **Responsive** — Works on any screen size
|
|
978
|
+
|
|
979
|
+
---
|
|
980
|
+
|
|
981
|
+
## Next Steps
|
|
982
|
+
|
|
983
|
+
Start by reading the [Installation](/${cfg.entry}/installation) guide, then follow the [Quickstart](/${cfg.entry}/quickstart) to build something.
|
|
984
|
+
`;
|
|
985
|
+
}
|
|
986
|
+
function astroInstallationPageTemplate(cfg) {
|
|
987
|
+
const t = getThemeInfo(cfg.theme);
|
|
988
|
+
return `\
|
|
989
|
+
---
|
|
990
|
+
title: "Installation"
|
|
991
|
+
description: "How to install and set up ${cfg.projectName}"
|
|
992
|
+
---
|
|
993
|
+
|
|
994
|
+
# Installation
|
|
995
|
+
|
|
996
|
+
Follow these steps to install and configure ${cfg.projectName}.
|
|
997
|
+
|
|
998
|
+
## Prerequisites
|
|
999
|
+
|
|
1000
|
+
- Node.js 18+
|
|
1001
|
+
- A package manager (pnpm, npm, or yarn)
|
|
1002
|
+
|
|
1003
|
+
## Install Dependencies
|
|
1004
|
+
|
|
1005
|
+
\\\`\\\`\\\`bash
|
|
1006
|
+
pnpm add @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme
|
|
1007
|
+
\\\`\\\`\\\`
|
|
1008
|
+
|
|
1009
|
+
## Configuration
|
|
1010
|
+
|
|
1011
|
+
Your project includes a \\\`docs.config.ts\\\` in \\\`src/lib/\\\`:
|
|
1012
|
+
|
|
1013
|
+
\\\`\\\`\\\`ts title="src/lib/docs.config.ts"
|
|
1014
|
+
import { defineDocs } from "@farming-labs/docs";
|
|
1015
|
+
import { ${t.factory} } from "${t.astroImport}";
|
|
1016
|
+
|
|
1017
|
+
export default defineDocs({
|
|
1018
|
+
entry: "${cfg.entry}",
|
|
1019
|
+
contentDir: "${cfg.entry}",
|
|
1020
|
+
theme: ${t.factory}({
|
|
1021
|
+
ui: { colors: { primary: "#6366f1" } },
|
|
1022
|
+
}),
|
|
1023
|
+
});
|
|
1024
|
+
\\\`\\\`\\\`
|
|
1025
|
+
|
|
1026
|
+
## Project Structure
|
|
1027
|
+
|
|
1028
|
+
\\\`\\\`\\\`
|
|
1029
|
+
${cfg.entry}/ # Markdown content
|
|
1030
|
+
page.md # /${cfg.entry}
|
|
1031
|
+
installation/
|
|
1032
|
+
page.md # /${cfg.entry}/installation
|
|
1033
|
+
quickstart/
|
|
1034
|
+
page.md # /${cfg.entry}/quickstart
|
|
1035
|
+
src/
|
|
1036
|
+
lib/
|
|
1037
|
+
docs.config.ts # Docs configuration
|
|
1038
|
+
docs.server.ts # Server-side docs loader
|
|
1039
|
+
pages/
|
|
1040
|
+
${cfg.entry}/
|
|
1041
|
+
index.astro # Docs index page
|
|
1042
|
+
[...slug].astro # Dynamic doc page
|
|
1043
|
+
api/
|
|
1044
|
+
${cfg.entry}.ts # Search/AI API route
|
|
1045
|
+
\\\`\\\`\\\`
|
|
1046
|
+
|
|
1047
|
+
## What's Next?
|
|
1048
|
+
|
|
1049
|
+
Head to the [Quickstart](/${cfg.entry}/quickstart) guide to start writing your first page.
|
|
1050
|
+
`;
|
|
1051
|
+
}
|
|
1052
|
+
function astroQuickstartPageTemplate(cfg) {
|
|
1053
|
+
const t = getThemeInfo(cfg.theme);
|
|
1054
|
+
return `\
|
|
1055
|
+
---
|
|
1056
|
+
title: "Quickstart"
|
|
1057
|
+
description: "Get up and running in minutes"
|
|
1058
|
+
---
|
|
1059
|
+
|
|
1060
|
+
# Quickstart
|
|
1061
|
+
|
|
1062
|
+
This guide walks you through creating your first documentation page.
|
|
1063
|
+
|
|
1064
|
+
## Creating a Page
|
|
1065
|
+
|
|
1066
|
+
Create a new folder under \\\`${cfg.entry}/\\\` with a \\\`page.md\\\` file:
|
|
1067
|
+
|
|
1068
|
+
\\\`\\\`\\\`bash
|
|
1069
|
+
mkdir -p ${cfg.entry}/my-page
|
|
1070
|
+
\\\`\\\`\\\`
|
|
1071
|
+
|
|
1072
|
+
Then create \\\`${cfg.entry}/my-page/page.md\\\`:
|
|
1073
|
+
|
|
1074
|
+
\\\`\\\`\\\`md
|
|
1075
|
+
---
|
|
1076
|
+
title: "My Page"
|
|
1077
|
+
description: "A custom documentation page"
|
|
1078
|
+
---
|
|
1079
|
+
|
|
1080
|
+
# My Page
|
|
1081
|
+
|
|
1082
|
+
Write your content here using **Markdown**.
|
|
1083
|
+
\\\`\\\`\\\`
|
|
1084
|
+
|
|
1085
|
+
Your page is now available at \\\`/${cfg.entry}/my-page\\\`.
|
|
1086
|
+
|
|
1087
|
+
## Customizing the Theme
|
|
1088
|
+
|
|
1089
|
+
Edit \\\`src/lib/docs.config.ts\\\` to change colors, typography, and component defaults:
|
|
1090
|
+
|
|
1091
|
+
\\\`\\\`\\\`ts title="src/lib/docs.config.ts"
|
|
1092
|
+
theme: ${t.factory}({
|
|
1093
|
+
ui: {
|
|
1094
|
+
colors: { primary: "#22c55e" },
|
|
1095
|
+
},
|
|
1096
|
+
}),
|
|
1097
|
+
\\\`\\\`\\\`
|
|
1098
|
+
|
|
1099
|
+
## Deploying
|
|
1100
|
+
|
|
1101
|
+
Build your docs for production:
|
|
1102
|
+
|
|
1103
|
+
\\\`\\\`\\\`bash
|
|
1104
|
+
pnpm build
|
|
1105
|
+
\\\`\\\`\\\`
|
|
1106
|
+
|
|
767
1107
|
Deploy to Vercel, Netlify, or any Node.js hosting platform.
|
|
768
1108
|
`;
|
|
769
1109
|
}
|
|
@@ -775,21 +1115,29 @@ async function init() {
|
|
|
775
1115
|
p.intro(pc.bgCyan(pc.black(" @farming-labs/docs ")));
|
|
776
1116
|
let framework = detectFramework(cwd);
|
|
777
1117
|
if (framework) {
|
|
778
|
-
const frameworkName = framework === "nextjs" ? "Next.js" : "SvelteKit";
|
|
1118
|
+
const frameworkName = framework === "nextjs" ? "Next.js" : framework === "sveltekit" ? "SvelteKit" : "Astro";
|
|
779
1119
|
p.log.success(`Detected framework: ${pc.cyan(frameworkName)}`);
|
|
780
1120
|
} else {
|
|
781
1121
|
p.log.warn("Could not auto-detect a framework from " + pc.cyan("package.json") + ".");
|
|
782
1122
|
const picked = await p.select({
|
|
783
1123
|
message: "Which framework are you using?",
|
|
784
|
-
options: [
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1124
|
+
options: [
|
|
1125
|
+
{
|
|
1126
|
+
value: "nextjs",
|
|
1127
|
+
label: "Next.js",
|
|
1128
|
+
hint: "React framework with App Router"
|
|
1129
|
+
},
|
|
1130
|
+
{
|
|
1131
|
+
value: "sveltekit",
|
|
1132
|
+
label: "SvelteKit",
|
|
1133
|
+
hint: "Svelte framework with file-based routing"
|
|
1134
|
+
},
|
|
1135
|
+
{
|
|
1136
|
+
value: "astro",
|
|
1137
|
+
label: "Astro",
|
|
1138
|
+
hint: "Content-focused framework with island architecture"
|
|
1139
|
+
}
|
|
1140
|
+
]
|
|
793
1141
|
});
|
|
794
1142
|
if (p.isCancel(picked)) {
|
|
795
1143
|
p.outro(pc.red("Init cancelled."));
|
|
@@ -821,7 +1169,7 @@ async function init() {
|
|
|
821
1169
|
p.outro(pc.red("Init cancelled."));
|
|
822
1170
|
process.exit(0);
|
|
823
1171
|
}
|
|
824
|
-
const aliasHint = framework === "nextjs" ? `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)` : `Uses ${pc.cyan("$lib/")} prefix (SvelteKit built-in)`;
|
|
1172
|
+
const aliasHint = framework === "nextjs" ? `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)` : framework === "sveltekit" ? `Uses ${pc.cyan("$lib/")} prefix (SvelteKit built-in)` : `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)`;
|
|
825
1173
|
const useAlias = await p.confirm({
|
|
826
1174
|
message: `Use path aliases for imports? ${pc.dim(aliasHint)}`,
|
|
827
1175
|
initialValue: false
|
|
@@ -830,6 +1178,37 @@ async function init() {
|
|
|
830
1178
|
p.outro(pc.red("Init cancelled."));
|
|
831
1179
|
process.exit(0);
|
|
832
1180
|
}
|
|
1181
|
+
let astroAdapter;
|
|
1182
|
+
if (framework === "astro") {
|
|
1183
|
+
const adapter = await p.select({
|
|
1184
|
+
message: "Where will you deploy?",
|
|
1185
|
+
options: [
|
|
1186
|
+
{
|
|
1187
|
+
value: "vercel",
|
|
1188
|
+
label: "Vercel",
|
|
1189
|
+
hint: "Recommended for most projects"
|
|
1190
|
+
},
|
|
1191
|
+
{
|
|
1192
|
+
value: "netlify",
|
|
1193
|
+
label: "Netlify"
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
value: "cloudflare",
|
|
1197
|
+
label: "Cloudflare Pages"
|
|
1198
|
+
},
|
|
1199
|
+
{
|
|
1200
|
+
value: "node",
|
|
1201
|
+
label: "Node.js / Docker",
|
|
1202
|
+
hint: "Self-hosted standalone server"
|
|
1203
|
+
}
|
|
1204
|
+
]
|
|
1205
|
+
});
|
|
1206
|
+
if (p.isCancel(adapter)) {
|
|
1207
|
+
p.outro(pc.red("Init cancelled."));
|
|
1208
|
+
process.exit(0);
|
|
1209
|
+
}
|
|
1210
|
+
astroAdapter = adapter;
|
|
1211
|
+
}
|
|
833
1212
|
const entry = await p.text({
|
|
834
1213
|
message: "Where should your docs live?",
|
|
835
1214
|
placeholder: "docs",
|
|
@@ -847,7 +1226,7 @@ async function init() {
|
|
|
847
1226
|
const entryPath = entry;
|
|
848
1227
|
const detectedCssFiles = detectGlobalCssFiles(cwd);
|
|
849
1228
|
let globalCssRelPath;
|
|
850
|
-
const defaultCssPath = framework === "sveltekit" ? "src/app.css" : "app/globals.css";
|
|
1229
|
+
const defaultCssPath = framework === "sveltekit" ? "src/app.css" : framework === "astro" ? "src/styles/global.css" : "app/globals.css";
|
|
851
1230
|
if (detectedCssFiles.length === 1) {
|
|
852
1231
|
globalCssRelPath = detectedCssFiles[0];
|
|
853
1232
|
p.log.info(`Found global CSS at ${pc.cyan(globalCssRelPath)}`);
|
|
@@ -887,7 +1266,8 @@ async function init() {
|
|
|
887
1266
|
theme,
|
|
888
1267
|
projectName: pkgJson.name || "My Project",
|
|
889
1268
|
framework,
|
|
890
|
-
useAlias
|
|
1269
|
+
useAlias,
|
|
1270
|
+
astroAdapter
|
|
891
1271
|
};
|
|
892
1272
|
const s = p.spinner();
|
|
893
1273
|
s.start("Scaffolding docs files");
|
|
@@ -898,6 +1278,7 @@ async function init() {
|
|
|
898
1278
|
else skipped.push(rel);
|
|
899
1279
|
}
|
|
900
1280
|
if (framework === "sveltekit") scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written);
|
|
1281
|
+
else if (framework === "astro") scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written);
|
|
901
1282
|
else scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written);
|
|
902
1283
|
s.stop("Files scaffolded");
|
|
903
1284
|
if (written.length > 0) p.log.success(`Created ${written.length} file${written.length > 1 ? "s" : ""}:\n` + written.map((f) => ` ${pc.green("+")} ${f}`).join("\n"));
|
|
@@ -908,7 +1289,10 @@ async function init() {
|
|
|
908
1289
|
s2.start("Installing dependencies");
|
|
909
1290
|
try {
|
|
910
1291
|
if (framework === "sveltekit") exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-theme`, cwd);
|
|
911
|
-
else {
|
|
1292
|
+
else if (framework === "astro") {
|
|
1293
|
+
const adapterPkg = getAstroAdapterPkg(cfg.astroAdapter ?? "vercel");
|
|
1294
|
+
exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme ${adapterPkg}`, cwd);
|
|
1295
|
+
} else {
|
|
912
1296
|
exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/next @farming-labs/theme`, cwd);
|
|
913
1297
|
const devDeps = [
|
|
914
1298
|
"@tailwindcss/postcss",
|
|
@@ -947,6 +1331,10 @@ async function init() {
|
|
|
947
1331
|
cmd: "npx",
|
|
948
1332
|
args: ["vite", "dev"],
|
|
949
1333
|
waitFor: "ready"
|
|
1334
|
+
} : framework === "astro" ? {
|
|
1335
|
+
cmd: "npx",
|
|
1336
|
+
args: ["astro", "dev"],
|
|
1337
|
+
waitFor: "ready"
|
|
950
1338
|
} : {
|
|
951
1339
|
cmd: "npx",
|
|
952
1340
|
args: [
|
|
@@ -956,7 +1344,7 @@ async function init() {
|
|
|
956
1344
|
],
|
|
957
1345
|
waitFor: "Ready"
|
|
958
1346
|
};
|
|
959
|
-
const defaultPort = framework === "sveltekit" ? "5173" : "3000";
|
|
1347
|
+
const defaultPort = framework === "sveltekit" ? "5173" : framework === "astro" ? "4321" : "3000";
|
|
960
1348
|
try {
|
|
961
1349
|
const child = await spawnAndWaitFor(devCommand.cmd, devCommand.args, cwd, devCommand.waitFor, 6e4);
|
|
962
1350
|
const url = `http://localhost:${defaultPort}/${entryPath}`;
|
|
@@ -975,7 +1363,7 @@ async function init() {
|
|
|
975
1363
|
});
|
|
976
1364
|
});
|
|
977
1365
|
} catch (err) {
|
|
978
|
-
const manualCmd = framework === "sveltekit" ? "npx vite dev" : "npx next dev --webpack";
|
|
1366
|
+
const manualCmd = framework === "sveltekit" ? "npx vite dev" : framework === "astro" ? "npx astro dev" : "npx next dev --webpack";
|
|
979
1367
|
p.log.error(`Could not start dev server. Try running manually:
|
|
980
1368
|
${pc.cyan(manualCmd)}`);
|
|
981
1369
|
p.outro(pc.yellow("Setup complete. Start the server manually."));
|
|
@@ -1036,6 +1424,32 @@ function scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written)
|
|
|
1036
1424
|
write(`${cfg.entry}/installation/page.md`, svelteInstallationPageTemplate(cfg));
|
|
1037
1425
|
write(`${cfg.entry}/quickstart/page.md`, svelteQuickstartPageTemplate(cfg));
|
|
1038
1426
|
}
|
|
1427
|
+
function scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
1428
|
+
write("src/lib/docs.config.ts", astroDocsConfigTemplate(cfg));
|
|
1429
|
+
write("src/lib/docs.server.ts", astroDocsServerTemplate(cfg));
|
|
1430
|
+
if (!fileExists(path.join(cwd, "astro.config.mjs")) && !fileExists(path.join(cwd, "astro.config.ts"))) write("astro.config.mjs", astroConfigTemplate(cfg.astroAdapter ?? "vercel"));
|
|
1431
|
+
write(`src/pages/${cfg.entry}/index.astro`, astroDocsIndexTemplate(cfg));
|
|
1432
|
+
write(`src/pages/${cfg.entry}/[...slug].astro`, astroDocsPageTemplate(cfg));
|
|
1433
|
+
write(`src/pages/api/${cfg.entry}.ts`, astroApiRouteTemplate(cfg));
|
|
1434
|
+
const globalCssAbsPath = path.join(cwd, globalCssRelPath);
|
|
1435
|
+
const existingGlobalCss = readFileSafe(globalCssAbsPath);
|
|
1436
|
+
const cssTheme = {
|
|
1437
|
+
fumadocs: "fumadocs",
|
|
1438
|
+
darksharp: "darksharp",
|
|
1439
|
+
"pixel-border": "pixel-border",
|
|
1440
|
+
default: "fumadocs"
|
|
1441
|
+
}[cfg.theme] || "fumadocs";
|
|
1442
|
+
if (existingGlobalCss) {
|
|
1443
|
+
const injected = injectAstroCssImport(existingGlobalCss, cssTheme);
|
|
1444
|
+
if (injected) {
|
|
1445
|
+
writeFileSafe(globalCssAbsPath, injected, true);
|
|
1446
|
+
written.push(globalCssRelPath + " (updated)");
|
|
1447
|
+
} else skipped.push(globalCssRelPath + " (already configured)");
|
|
1448
|
+
} else write(globalCssRelPath, astroGlobalCssTemplate(cssTheme));
|
|
1449
|
+
write(`${cfg.entry}/page.md`, astroWelcomePageTemplate(cfg));
|
|
1450
|
+
write(`${cfg.entry}/installation/page.md`, astroInstallationPageTemplate(cfg));
|
|
1451
|
+
write(`${cfg.entry}/quickstart/page.md`, astroQuickstartPageTemplate(cfg));
|
|
1452
|
+
}
|
|
1039
1453
|
|
|
1040
1454
|
//#endregion
|
|
1041
1455
|
//#region src/cli/index.ts
|
|
@@ -1062,7 +1476,7 @@ ${pc.dim("Commands:")}
|
|
|
1062
1476
|
${pc.cyan("init")} Scaffold docs in your project (default)
|
|
1063
1477
|
|
|
1064
1478
|
${pc.dim("Supported frameworks:")}
|
|
1065
|
-
Next.js, SvelteKit
|
|
1479
|
+
Next.js, SvelteKit, Astro
|
|
1066
1480
|
|
|
1067
1481
|
${pc.dim("Options:")}
|
|
1068
1482
|
${pc.cyan("-h, --help")} Show this help message
|
package/dist/index.d.mts
CHANGED
|
@@ -223,6 +223,8 @@ interface PageFrontmatter {
|
|
|
223
223
|
icon?: string;
|
|
224
224
|
/** Path to custom OG image for this page */
|
|
225
225
|
ogImage?: string;
|
|
226
|
+
/** Sort order in the sidebar. Lower numbers appear first. Pages without `order` are sorted alphabetically after ordered pages. */
|
|
227
|
+
order?: number;
|
|
226
228
|
}
|
|
227
229
|
interface DocsNav {
|
|
228
230
|
/**
|
|
@@ -677,6 +679,30 @@ interface AIConfig {
|
|
|
677
679
|
name: string;
|
|
678
680
|
}) => unknown;
|
|
679
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* A single item in the slug-based sidebar ordering.
|
|
684
|
+
*
|
|
685
|
+
* @example
|
|
686
|
+
* ```ts
|
|
687
|
+
* ordering: [
|
|
688
|
+
* { slug: "installation" },
|
|
689
|
+
* { slug: "cli" },
|
|
690
|
+
* { slug: "themes", children: [
|
|
691
|
+
* { slug: "default" },
|
|
692
|
+
* { slug: "darksharp" },
|
|
693
|
+
* { slug: "pixel-border" },
|
|
694
|
+
* { slug: "creating-themes" },
|
|
695
|
+
* ]},
|
|
696
|
+
* { slug: "reference" },
|
|
697
|
+
* ]
|
|
698
|
+
* ```
|
|
699
|
+
*/
|
|
700
|
+
interface OrderingItem {
|
|
701
|
+
/** Folder name (not the full path, just the directory name at this level) */
|
|
702
|
+
slug: string;
|
|
703
|
+
/** Ordering for child pages within this folder */
|
|
704
|
+
children?: OrderingItem[];
|
|
705
|
+
}
|
|
680
706
|
interface DocsConfig {
|
|
681
707
|
/** Entry folder for docs (e.g. "docs" → /docs) */
|
|
682
708
|
entry: string;
|
|
@@ -849,6 +875,40 @@ interface DocsConfig {
|
|
|
849
875
|
* ```
|
|
850
876
|
*/
|
|
851
877
|
ai?: AIConfig;
|
|
878
|
+
/**
|
|
879
|
+
* Sidebar ordering strategy.
|
|
880
|
+
*
|
|
881
|
+
* - `"alphabetical"` — sort pages alphabetically by folder name (default)
|
|
882
|
+
* - `"numeric"` — sort by frontmatter `order` field (lower first, unset pages last)
|
|
883
|
+
* - `OrderingItem[]` — explicit slug-based ordering with nested children
|
|
884
|
+
*
|
|
885
|
+
* @default "alphabetical"
|
|
886
|
+
*
|
|
887
|
+
* @example
|
|
888
|
+
* ```ts
|
|
889
|
+
* // Alphabetical (default)
|
|
890
|
+
* ordering: "alphabetical",
|
|
891
|
+
*
|
|
892
|
+
* // Use frontmatter `order: 1`, `order: 2`, etc.
|
|
893
|
+
* ordering: "numeric",
|
|
894
|
+
*
|
|
895
|
+
* // Explicit slug-based ordering
|
|
896
|
+
* ordering: [
|
|
897
|
+
* { slug: "installation" },
|
|
898
|
+
* { slug: "cli" },
|
|
899
|
+
* { slug: "configuration" },
|
|
900
|
+
* { slug: "themes", children: [
|
|
901
|
+
* { slug: "default" },
|
|
902
|
+
* { slug: "darksharp" },
|
|
903
|
+
* { slug: "pixel-border" },
|
|
904
|
+
* { slug: "creating-themes" },
|
|
905
|
+
* ]},
|
|
906
|
+
* { slug: "customization" },
|
|
907
|
+
* { slug: "reference" },
|
|
908
|
+
* ]
|
|
909
|
+
* ```
|
|
910
|
+
*/
|
|
911
|
+
ordering?: "alphabetical" | "numeric" | OrderingItem[];
|
|
852
912
|
/** SEO metadata - separate from theme */
|
|
853
913
|
metadata?: DocsMetadata;
|
|
854
914
|
/** Open Graph image handling */
|
|
@@ -924,4 +984,4 @@ declare function resolveTitle(pageTitle: string, metadata?: DocsMetadata): strin
|
|
|
924
984
|
*/
|
|
925
985
|
declare function resolveOGImage(page: PageFrontmatter, ogConfig?: OGConfig, baseUrl?: string): string | undefined;
|
|
926
986
|
//#endregion
|
|
927
|
-
export { type AIConfig, type BreadcrumbConfig, type CopyMarkdownConfig, type DocsConfig, type DocsMetadata, type DocsNav, type DocsTheme, type FontStyle, type GithubConfig, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type PageActionsConfig, type PageFrontmatter, type SidebarConfig, type ThemeToggleConfig, type TypographyConfig, type UIConfig, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
|
|
987
|
+
export { type AIConfig, type BreadcrumbConfig, type CopyMarkdownConfig, type DocsConfig, type DocsMetadata, type DocsNav, type DocsTheme, type FontStyle, type GithubConfig, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type OrderingItem, type PageActionsConfig, type PageFrontmatter, type SidebarConfig, type ThemeToggleConfig, type TypographyConfig, type UIConfig, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
|
package/dist/index.mjs
CHANGED