@farming-labs/docs 0.0.2-beta.15 → 0.0.2-beta.17
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 +393 -11
- package/dist/index.d.mts +40 -8
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -17,6 +17,7 @@ function detectFramework(cwd) {
|
|
|
17
17
|
if (allDeps["next"]) return "nextjs";
|
|
18
18
|
if (allDeps["@sveltejs/kit"]) return "sveltekit";
|
|
19
19
|
if (allDeps["astro"]) return "astro";
|
|
20
|
+
if (allDeps["nuxt"]) return "nuxt";
|
|
20
21
|
return null;
|
|
21
22
|
}
|
|
22
23
|
function detectPackageManager(cwd) {
|
|
@@ -66,7 +67,9 @@ const GLOBAL_CSS_CANDIDATES = [
|
|
|
66
67
|
"styles/globals.css",
|
|
67
68
|
"styles/global.css",
|
|
68
69
|
"src/styles/globals.css",
|
|
69
|
-
"src/styles/global.css"
|
|
70
|
+
"src/styles/global.css",
|
|
71
|
+
"assets/css/main.css",
|
|
72
|
+
"assets/main.css"
|
|
70
73
|
];
|
|
71
74
|
/**
|
|
72
75
|
* Find existing global CSS files in the project.
|
|
@@ -135,27 +138,44 @@ const THEME_INFO = {
|
|
|
135
138
|
nextImport: "@farming-labs/theme",
|
|
136
139
|
svelteImport: "@farming-labs/svelte-theme",
|
|
137
140
|
astroImport: "@farming-labs/astro-theme",
|
|
141
|
+
nuxtImport: "@farming-labs/nuxt-theme",
|
|
138
142
|
nextCssImport: "default",
|
|
139
143
|
svelteCssTheme: "fumadocs",
|
|
140
|
-
astroCssTheme: "fumadocs"
|
|
144
|
+
astroCssTheme: "fumadocs",
|
|
145
|
+
nuxtCssTheme: "fumadocs"
|
|
141
146
|
},
|
|
142
147
|
darksharp: {
|
|
143
148
|
factory: "darksharp",
|
|
144
149
|
nextImport: "@farming-labs/theme/darksharp",
|
|
145
150
|
svelteImport: "@farming-labs/svelte-theme/darksharp",
|
|
146
151
|
astroImport: "@farming-labs/astro-theme/darksharp",
|
|
152
|
+
nuxtImport: "@farming-labs/nuxt-theme/darksharp",
|
|
147
153
|
nextCssImport: "darksharp",
|
|
148
154
|
svelteCssTheme: "darksharp",
|
|
149
|
-
astroCssTheme: "darksharp"
|
|
155
|
+
astroCssTheme: "darksharp",
|
|
156
|
+
nuxtCssTheme: "darksharp"
|
|
150
157
|
},
|
|
151
158
|
"pixel-border": {
|
|
152
159
|
factory: "pixelBorder",
|
|
153
160
|
nextImport: "@farming-labs/theme/pixel-border",
|
|
154
161
|
svelteImport: "@farming-labs/svelte-theme/pixel-border",
|
|
155
162
|
astroImport: "@farming-labs/astro-theme/pixel-border",
|
|
163
|
+
nuxtImport: "@farming-labs/nuxt-theme/pixel-border",
|
|
156
164
|
nextCssImport: "pixel-border",
|
|
157
165
|
svelteCssTheme: "pixel-border",
|
|
158
|
-
astroCssTheme: "pixel-border"
|
|
166
|
+
astroCssTheme: "pixel-border",
|
|
167
|
+
nuxtCssTheme: "pixel-border"
|
|
168
|
+
},
|
|
169
|
+
colorful: {
|
|
170
|
+
factory: "colorful",
|
|
171
|
+
nextImport: "@farming-labs/theme/colorful",
|
|
172
|
+
svelteImport: "@farming-labs/svelte-theme/colorful",
|
|
173
|
+
astroImport: "@farming-labs/astro-theme/colorful",
|
|
174
|
+
nuxtImport: "@farming-labs/nuxt-theme/colorful",
|
|
175
|
+
nextCssImport: "colorful",
|
|
176
|
+
svelteCssTheme: "colorful",
|
|
177
|
+
astroCssTheme: "colorful",
|
|
178
|
+
nuxtCssTheme: "colorful"
|
|
159
179
|
}
|
|
160
180
|
};
|
|
161
181
|
function getThemeInfo(theme) {
|
|
@@ -1107,6 +1127,322 @@ pnpm build
|
|
|
1107
1127
|
Deploy to Vercel, Netlify, or any Node.js hosting platform.
|
|
1108
1128
|
`;
|
|
1109
1129
|
}
|
|
1130
|
+
function nuxtDocsConfigTemplate(cfg) {
|
|
1131
|
+
const t = getThemeInfo(cfg.theme);
|
|
1132
|
+
return `\
|
|
1133
|
+
import { defineDocs } from "@farming-labs/docs";
|
|
1134
|
+
import { ${t.factory} } from "${t.nuxtImport}";
|
|
1135
|
+
|
|
1136
|
+
export default defineDocs({
|
|
1137
|
+
entry: "${cfg.entry}",
|
|
1138
|
+
contentDir: "${cfg.entry}",
|
|
1139
|
+
theme: ${t.factory}({
|
|
1140
|
+
ui: {
|
|
1141
|
+
colors: { primary: "#6366f1" },
|
|
1142
|
+
},
|
|
1143
|
+
}),
|
|
1144
|
+
|
|
1145
|
+
nav: {
|
|
1146
|
+
title: "${cfg.projectName}",
|
|
1147
|
+
url: "/${cfg.entry}",
|
|
1148
|
+
},
|
|
1149
|
+
|
|
1150
|
+
breadcrumb: { enabled: true },
|
|
1151
|
+
|
|
1152
|
+
metadata: {
|
|
1153
|
+
titleTemplate: "%s – ${cfg.projectName}",
|
|
1154
|
+
description: "Documentation for ${cfg.projectName}",
|
|
1155
|
+
},
|
|
1156
|
+
});
|
|
1157
|
+
`;
|
|
1158
|
+
}
|
|
1159
|
+
function nuxtDocsServerTemplate(cfg) {
|
|
1160
|
+
return `\
|
|
1161
|
+
import { createDocsServer } from "@farming-labs/nuxt/server";
|
|
1162
|
+
import config from "../../docs.config";
|
|
1163
|
+
|
|
1164
|
+
const contentFiles = import.meta.glob("/${cfg.entry ?? "docs"}/**/*.{md,mdx}", {
|
|
1165
|
+
query: "?raw",
|
|
1166
|
+
import: "default",
|
|
1167
|
+
eager: true,
|
|
1168
|
+
}) as Record<string, string>;
|
|
1169
|
+
|
|
1170
|
+
export const docsServer = createDocsServer({
|
|
1171
|
+
...config,
|
|
1172
|
+
_preloadedContent: contentFiles,
|
|
1173
|
+
});
|
|
1174
|
+
`;
|
|
1175
|
+
}
|
|
1176
|
+
function nuxtServerApiDocsGetTemplate() {
|
|
1177
|
+
return `\
|
|
1178
|
+
import { getRequestURL } from "h3";
|
|
1179
|
+
import { docsServer } from "../utils/docs-server";
|
|
1180
|
+
|
|
1181
|
+
export default defineEventHandler((event) => {
|
|
1182
|
+
const url = getRequestURL(event);
|
|
1183
|
+
const request = new Request(url.href, {
|
|
1184
|
+
method: event.method,
|
|
1185
|
+
headers: event.headers,
|
|
1186
|
+
});
|
|
1187
|
+
return docsServer.GET({ request });
|
|
1188
|
+
});
|
|
1189
|
+
`;
|
|
1190
|
+
}
|
|
1191
|
+
function nuxtServerApiDocsPostTemplate() {
|
|
1192
|
+
return `\
|
|
1193
|
+
import { getRequestURL, readRawBody } from "h3";
|
|
1194
|
+
import { docsServer } from "../utils/docs-server";
|
|
1195
|
+
|
|
1196
|
+
export default defineEventHandler(async (event) => {
|
|
1197
|
+
const url = getRequestURL(event);
|
|
1198
|
+
const body = await readRawBody(event);
|
|
1199
|
+
const request = new Request(url.href, {
|
|
1200
|
+
method: "POST",
|
|
1201
|
+
headers: event.headers,
|
|
1202
|
+
body: body ?? undefined,
|
|
1203
|
+
});
|
|
1204
|
+
return docsServer.POST({ request });
|
|
1205
|
+
});
|
|
1206
|
+
`;
|
|
1207
|
+
}
|
|
1208
|
+
function nuxtServerApiDocsLoadTemplate() {
|
|
1209
|
+
return `\
|
|
1210
|
+
import { getQuery } from "h3";
|
|
1211
|
+
import { docsServer } from "../../utils/docs-server";
|
|
1212
|
+
|
|
1213
|
+
export default defineEventHandler(async (event) => {
|
|
1214
|
+
const query = getQuery(event);
|
|
1215
|
+
const pathname = (query.pathname as string) ?? "/docs";
|
|
1216
|
+
return docsServer.load(pathname);
|
|
1217
|
+
});
|
|
1218
|
+
`;
|
|
1219
|
+
}
|
|
1220
|
+
function nuxtDocsPageTemplate(cfg) {
|
|
1221
|
+
return `\
|
|
1222
|
+
<script setup lang="ts">
|
|
1223
|
+
import { DocsLayout, DocsContent } from "@farming-labs/nuxt-theme";
|
|
1224
|
+
import config from "${cfg.useAlias ? "~/docs.config" : "../../docs.config"}";
|
|
1225
|
+
|
|
1226
|
+
const route = useRoute();
|
|
1227
|
+
const pathname = computed(() => route.path);
|
|
1228
|
+
|
|
1229
|
+
const { data, error } = await useAsyncData(\`docs-\${pathname.value}\`, () =>
|
|
1230
|
+
$fetch("/api/docs/load", {
|
|
1231
|
+
query: { pathname: pathname.value },
|
|
1232
|
+
})
|
|
1233
|
+
);
|
|
1234
|
+
|
|
1235
|
+
if (error.value) {
|
|
1236
|
+
throw createError({
|
|
1237
|
+
statusCode: 404,
|
|
1238
|
+
statusMessage: "Page not found",
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
<\/script>
|
|
1242
|
+
|
|
1243
|
+
<template>
|
|
1244
|
+
<div v-if="data" class="fd-docs-wrapper">
|
|
1245
|
+
<DocsLayout :tree="data.tree" :config="config">
|
|
1246
|
+
<DocsContent :data="data" :config="config" />
|
|
1247
|
+
</DocsLayout>
|
|
1248
|
+
</div>
|
|
1249
|
+
</template>
|
|
1250
|
+
`;
|
|
1251
|
+
}
|
|
1252
|
+
function nuxtConfigTemplate(cfg) {
|
|
1253
|
+
return `\
|
|
1254
|
+
export default defineNuxtConfig({
|
|
1255
|
+
compatibilityDate: "2024-11-01",
|
|
1256
|
+
|
|
1257
|
+
css: ["@farming-labs/nuxt-theme/${getThemeInfo(cfg.theme).nuxtCssTheme}/css"],
|
|
1258
|
+
|
|
1259
|
+
vite: {
|
|
1260
|
+
optimizeDeps: {
|
|
1261
|
+
include: ["@farming-labs/docs", "@farming-labs/nuxt", "@farming-labs/nuxt-theme"],
|
|
1262
|
+
},
|
|
1263
|
+
},
|
|
1264
|
+
|
|
1265
|
+
nitro: {
|
|
1266
|
+
moduleSideEffects: ["@farming-labs/nuxt/server"],
|
|
1267
|
+
},
|
|
1268
|
+
});
|
|
1269
|
+
`;
|
|
1270
|
+
}
|
|
1271
|
+
function nuxtWelcomePageTemplate(cfg) {
|
|
1272
|
+
return `\
|
|
1273
|
+
---
|
|
1274
|
+
order: 1
|
|
1275
|
+
title: Documentation
|
|
1276
|
+
description: Welcome to ${cfg.projectName} documentation
|
|
1277
|
+
icon: book
|
|
1278
|
+
---
|
|
1279
|
+
|
|
1280
|
+
# Welcome to ${cfg.projectName}
|
|
1281
|
+
|
|
1282
|
+
Get started with our documentation. Browse the pages on the left to learn more.
|
|
1283
|
+
|
|
1284
|
+
## Overview
|
|
1285
|
+
|
|
1286
|
+
This documentation was generated by \`@farming-labs/docs\`. Edit the markdown files in \`${cfg.entry}/\` to customize.
|
|
1287
|
+
|
|
1288
|
+
## Features
|
|
1289
|
+
|
|
1290
|
+
- **Markdown Support** — Write docs with standard Markdown
|
|
1291
|
+
- **Syntax Highlighting** — Code blocks with automatic highlighting
|
|
1292
|
+
- **Dark Mode** — Built-in theme switching
|
|
1293
|
+
- **Search** — Full-text search across all pages (⌘K)
|
|
1294
|
+
- **Responsive** — Works on any screen size
|
|
1295
|
+
|
|
1296
|
+
---
|
|
1297
|
+
|
|
1298
|
+
## Next Steps
|
|
1299
|
+
|
|
1300
|
+
Start by reading the [Installation](/${cfg.entry}/installation) guide, then follow the [Quickstart](/${cfg.entry}/quickstart) to build something.
|
|
1301
|
+
`;
|
|
1302
|
+
}
|
|
1303
|
+
function nuxtInstallationPageTemplate(cfg) {
|
|
1304
|
+
const t = getThemeInfo(cfg.theme);
|
|
1305
|
+
return `\
|
|
1306
|
+
---
|
|
1307
|
+
order: 3
|
|
1308
|
+
title: Installation
|
|
1309
|
+
description: How to install and set up ${cfg.projectName}
|
|
1310
|
+
icon: terminal
|
|
1311
|
+
---
|
|
1312
|
+
|
|
1313
|
+
# Installation
|
|
1314
|
+
|
|
1315
|
+
Follow these steps to install and configure ${cfg.projectName}.
|
|
1316
|
+
|
|
1317
|
+
## Prerequisites
|
|
1318
|
+
|
|
1319
|
+
- Node.js 18+
|
|
1320
|
+
- A package manager (pnpm, npm, or yarn)
|
|
1321
|
+
|
|
1322
|
+
## Install Dependencies
|
|
1323
|
+
|
|
1324
|
+
\`\`\`bash
|
|
1325
|
+
pnpm add @farming-labs/docs @farming-labs/nuxt @farming-labs/nuxt-theme
|
|
1326
|
+
\`\`\`
|
|
1327
|
+
|
|
1328
|
+
## Configuration
|
|
1329
|
+
|
|
1330
|
+
Your project includes a \`docs.config.ts\` at the root:
|
|
1331
|
+
|
|
1332
|
+
\`\`\`ts title="docs.config.ts"
|
|
1333
|
+
import { defineDocs } from "@farming-labs/docs";
|
|
1334
|
+
import { ${t.factory} } from "${t.nuxtImport}";
|
|
1335
|
+
|
|
1336
|
+
export default defineDocs({
|
|
1337
|
+
entry: "${cfg.entry}",
|
|
1338
|
+
contentDir: "${cfg.entry}",
|
|
1339
|
+
theme: ${t.factory}({
|
|
1340
|
+
ui: { colors: { primary: "#6366f1" } },
|
|
1341
|
+
}),
|
|
1342
|
+
});
|
|
1343
|
+
\`\`\`
|
|
1344
|
+
|
|
1345
|
+
## Project Structure
|
|
1346
|
+
|
|
1347
|
+
\`\`\`
|
|
1348
|
+
${cfg.entry}/ # Markdown content
|
|
1349
|
+
page.md
|
|
1350
|
+
installation/page.md
|
|
1351
|
+
quickstart/page.md
|
|
1352
|
+
server/
|
|
1353
|
+
utils/docs-server.ts # createDocsServer + preloaded content
|
|
1354
|
+
api/docs/
|
|
1355
|
+
load.get.ts # Page data API
|
|
1356
|
+
docs.get.ts # Search API
|
|
1357
|
+
docs.post.ts # AI chat API
|
|
1358
|
+
pages/
|
|
1359
|
+
${cfg.entry}/[[...slug]].vue # Docs catch-all page
|
|
1360
|
+
docs.config.ts
|
|
1361
|
+
nuxt.config.ts
|
|
1362
|
+
\`\`\`
|
|
1363
|
+
|
|
1364
|
+
## What's Next?
|
|
1365
|
+
|
|
1366
|
+
Head to the [Quickstart](/${cfg.entry}/quickstart) guide to start writing your first page.
|
|
1367
|
+
`;
|
|
1368
|
+
}
|
|
1369
|
+
function nuxtQuickstartPageTemplate(cfg) {
|
|
1370
|
+
const t = getThemeInfo(cfg.theme);
|
|
1371
|
+
return `\
|
|
1372
|
+
---
|
|
1373
|
+
order: 2
|
|
1374
|
+
title: Quickstart
|
|
1375
|
+
description: Get up and running in minutes
|
|
1376
|
+
icon: rocket
|
|
1377
|
+
---
|
|
1378
|
+
|
|
1379
|
+
# Quickstart
|
|
1380
|
+
|
|
1381
|
+
This guide walks you through creating your first documentation page.
|
|
1382
|
+
|
|
1383
|
+
## Creating a Page
|
|
1384
|
+
|
|
1385
|
+
Create a new folder under \`${cfg.entry}/\` with a \`page.md\` file:
|
|
1386
|
+
|
|
1387
|
+
\`\`\`bash
|
|
1388
|
+
mkdir -p ${cfg.entry}/my-page
|
|
1389
|
+
\`\`\`
|
|
1390
|
+
|
|
1391
|
+
Then create \`${cfg.entry}/my-page/page.md\`:
|
|
1392
|
+
|
|
1393
|
+
\`\`\`md
|
|
1394
|
+
---
|
|
1395
|
+
title: "My Page"
|
|
1396
|
+
description: "A custom documentation page"
|
|
1397
|
+
---
|
|
1398
|
+
|
|
1399
|
+
# My Page
|
|
1400
|
+
|
|
1401
|
+
Write your content here using **Markdown**.
|
|
1402
|
+
\`\`\`
|
|
1403
|
+
|
|
1404
|
+
Your page is now available at \`/${cfg.entry}/my-page\`.
|
|
1405
|
+
|
|
1406
|
+
## Customizing the Theme
|
|
1407
|
+
|
|
1408
|
+
Edit \`docs.config.ts\` to change colors and typography:
|
|
1409
|
+
|
|
1410
|
+
\`\`\`ts
|
|
1411
|
+
theme: ${t.factory}({
|
|
1412
|
+
ui: {
|
|
1413
|
+
colors: { primary: "#22c55e" },
|
|
1414
|
+
},
|
|
1415
|
+
}),
|
|
1416
|
+
\`\`\`
|
|
1417
|
+
|
|
1418
|
+
## Deploying
|
|
1419
|
+
|
|
1420
|
+
Build your docs for production:
|
|
1421
|
+
|
|
1422
|
+
\`\`\`bash
|
|
1423
|
+
pnpm build
|
|
1424
|
+
\`\`\`
|
|
1425
|
+
|
|
1426
|
+
Deploy to Vercel, Netlify, or any Node.js hosting platform.
|
|
1427
|
+
`;
|
|
1428
|
+
}
|
|
1429
|
+
function nuxtGlobalCssTemplate(theme) {
|
|
1430
|
+
return `\
|
|
1431
|
+
@import "@farming-labs/nuxt-theme/${theme}/css";
|
|
1432
|
+
`;
|
|
1433
|
+
}
|
|
1434
|
+
function nuxtCssImportLine(theme) {
|
|
1435
|
+
return `@import "@farming-labs/nuxt-theme/${theme}/css";`;
|
|
1436
|
+
}
|
|
1437
|
+
function injectNuxtCssImport(existingContent, theme) {
|
|
1438
|
+
const importLine = nuxtCssImportLine(theme);
|
|
1439
|
+
if (existingContent.includes(importLine)) return null;
|
|
1440
|
+
const lines = existingContent.split("\n");
|
|
1441
|
+
const lastImportIdx = lines.reduce((acc, l, i) => l.trimStart().startsWith("@import") ? i : acc, -1);
|
|
1442
|
+
if (lastImportIdx >= 0) lines.splice(lastImportIdx + 1, 0, importLine);
|
|
1443
|
+
else lines.unshift(importLine);
|
|
1444
|
+
return lines.join("\n");
|
|
1445
|
+
}
|
|
1110
1446
|
|
|
1111
1447
|
//#endregion
|
|
1112
1448
|
//#region src/cli/init.ts
|
|
@@ -1115,7 +1451,7 @@ async function init() {
|
|
|
1115
1451
|
p.intro(pc.bgCyan(pc.black(" @farming-labs/docs ")));
|
|
1116
1452
|
let framework = detectFramework(cwd);
|
|
1117
1453
|
if (framework) {
|
|
1118
|
-
const frameworkName = framework === "nextjs" ? "Next.js" : framework === "sveltekit" ? "SvelteKit" : "Astro";
|
|
1454
|
+
const frameworkName = framework === "nextjs" ? "Next.js" : framework === "sveltekit" ? "SvelteKit" : framework === "astro" ? "Astro" : "Nuxt";
|
|
1119
1455
|
p.log.success(`Detected framework: ${pc.cyan(frameworkName)}`);
|
|
1120
1456
|
} else {
|
|
1121
1457
|
p.log.warn("Could not auto-detect a framework from " + pc.cyan("package.json") + ".");
|
|
@@ -1136,6 +1472,11 @@ async function init() {
|
|
|
1136
1472
|
value: "astro",
|
|
1137
1473
|
label: "Astro",
|
|
1138
1474
|
hint: "Content-focused framework with island architecture"
|
|
1475
|
+
},
|
|
1476
|
+
{
|
|
1477
|
+
value: "nuxt",
|
|
1478
|
+
label: "Nuxt",
|
|
1479
|
+
hint: "Vue 3 framework with file-based routing and Nitro server"
|
|
1139
1480
|
}
|
|
1140
1481
|
]
|
|
1141
1482
|
});
|
|
@@ -1162,6 +1503,11 @@ async function init() {
|
|
|
1162
1503
|
value: "pixel-border",
|
|
1163
1504
|
label: "Pixel Border",
|
|
1164
1505
|
hint: "Rounded borders, pixel-perfect spacing, refined sidebar"
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
value: "colorful",
|
|
1509
|
+
label: "Colorful",
|
|
1510
|
+
hint: "Fumadocs-style neutral theme with description support"
|
|
1165
1511
|
}
|
|
1166
1512
|
]
|
|
1167
1513
|
});
|
|
@@ -1169,7 +1515,7 @@ async function init() {
|
|
|
1169
1515
|
p.outro(pc.red("Init cancelled."));
|
|
1170
1516
|
process.exit(0);
|
|
1171
1517
|
}
|
|
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)`;
|
|
1518
|
+
const aliasHint = framework === "nextjs" ? `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)` : framework === "sveltekit" ? `Uses ${pc.cyan("$lib/")} prefix (SvelteKit built-in)` : framework === "nuxt" ? `Uses ${pc.cyan("~/")} prefix (Nuxt built-in)` : `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)`;
|
|
1173
1519
|
const useAlias = await p.confirm({
|
|
1174
1520
|
message: `Use path aliases for imports? ${pc.dim(aliasHint)}`,
|
|
1175
1521
|
initialValue: false
|
|
@@ -1226,7 +1572,7 @@ async function init() {
|
|
|
1226
1572
|
const entryPath = entry;
|
|
1227
1573
|
const detectedCssFiles = detectGlobalCssFiles(cwd);
|
|
1228
1574
|
let globalCssRelPath;
|
|
1229
|
-
const defaultCssPath = framework === "sveltekit" ? "src/app.css" : framework === "astro" ? "src/styles/global.css" : "app/globals.css";
|
|
1575
|
+
const defaultCssPath = framework === "sveltekit" ? "src/app.css" : framework === "astro" ? "src/styles/global.css" : framework === "nuxt" ? "assets/css/main.css" : "app/globals.css";
|
|
1230
1576
|
if (detectedCssFiles.length === 1) {
|
|
1231
1577
|
globalCssRelPath = detectedCssFiles[0];
|
|
1232
1578
|
p.log.info(`Found global CSS at ${pc.cyan(globalCssRelPath)}`);
|
|
@@ -1279,6 +1625,7 @@ async function init() {
|
|
|
1279
1625
|
}
|
|
1280
1626
|
if (framework === "sveltekit") scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written);
|
|
1281
1627
|
else if (framework === "astro") scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written);
|
|
1628
|
+
else if (framework === "nuxt") scaffoldNuxt(cwd, cfg, globalCssRelPath, write, skipped, written);
|
|
1282
1629
|
else scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written);
|
|
1283
1630
|
s.stop("Files scaffolded");
|
|
1284
1631
|
if (written.length > 0) p.log.success(`Created ${written.length} file${written.length > 1 ? "s" : ""}:\n` + written.map((f) => ` ${pc.green("+")} ${f}`).join("\n"));
|
|
@@ -1292,7 +1639,8 @@ async function init() {
|
|
|
1292
1639
|
else if (framework === "astro") {
|
|
1293
1640
|
const adapterPkg = getAstroAdapterPkg(cfg.astroAdapter ?? "vercel");
|
|
1294
1641
|
exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme ${adapterPkg}`, cwd);
|
|
1295
|
-
} else {
|
|
1642
|
+
} else if (framework === "nuxt") exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/nuxt @farming-labs/nuxt-theme`, cwd);
|
|
1643
|
+
else {
|
|
1296
1644
|
exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/next @farming-labs/theme`, cwd);
|
|
1297
1645
|
const devDeps = [
|
|
1298
1646
|
"@tailwindcss/postcss",
|
|
@@ -1335,6 +1683,10 @@ async function init() {
|
|
|
1335
1683
|
cmd: "npx",
|
|
1336
1684
|
args: ["astro", "dev"],
|
|
1337
1685
|
waitFor: "ready"
|
|
1686
|
+
} : framework === "nuxt" ? {
|
|
1687
|
+
cmd: "npx",
|
|
1688
|
+
args: ["nuxt", "dev"],
|
|
1689
|
+
waitFor: "Local"
|
|
1338
1690
|
} : {
|
|
1339
1691
|
cmd: "npx",
|
|
1340
1692
|
args: [
|
|
@@ -1344,7 +1696,7 @@ async function init() {
|
|
|
1344
1696
|
],
|
|
1345
1697
|
waitFor: "Ready"
|
|
1346
1698
|
};
|
|
1347
|
-
const defaultPort = framework === "sveltekit" ? "5173" : framework === "astro" ? "4321" : "3000";
|
|
1699
|
+
const defaultPort = framework === "sveltekit" ? "5173" : framework === "astro" ? "4321" : framework === "nuxt" ? "3000" : "3000";
|
|
1348
1700
|
try {
|
|
1349
1701
|
const child = await spawnAndWaitFor(devCommand.cmd, devCommand.args, cwd, devCommand.waitFor, 6e4);
|
|
1350
1702
|
const url = `http://localhost:${defaultPort}/${entryPath}`;
|
|
@@ -1363,7 +1715,7 @@ async function init() {
|
|
|
1363
1715
|
});
|
|
1364
1716
|
});
|
|
1365
1717
|
} catch (err) {
|
|
1366
|
-
const manualCmd = framework === "sveltekit" ? "npx vite dev" : framework === "astro" ? "npx astro dev" : "npx next dev --webpack";
|
|
1718
|
+
const manualCmd = framework === "sveltekit" ? "npx vite dev" : framework === "astro" ? "npx astro dev" : framework === "nuxt" ? "npx nuxt dev" : "npx next dev --webpack";
|
|
1367
1719
|
p.log.error(`Could not start dev server. Try running manually:
|
|
1368
1720
|
${pc.cyan(manualCmd)}`);
|
|
1369
1721
|
p.outro(pc.yellow("Setup complete. Start the server manually."));
|
|
@@ -1411,6 +1763,7 @@ function scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written)
|
|
|
1411
1763
|
fumadocs: "fumadocs",
|
|
1412
1764
|
darksharp: "darksharp",
|
|
1413
1765
|
"pixel-border": "pixel-border",
|
|
1766
|
+
colorful: "colorful",
|
|
1414
1767
|
default: "fumadocs"
|
|
1415
1768
|
}[cfg.theme] || "fumadocs";
|
|
1416
1769
|
if (existingGlobalCss) {
|
|
@@ -1437,6 +1790,7 @@ function scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
1437
1790
|
fumadocs: "fumadocs",
|
|
1438
1791
|
darksharp: "darksharp",
|
|
1439
1792
|
"pixel-border": "pixel-border",
|
|
1793
|
+
colorful: "colorful",
|
|
1440
1794
|
default: "fumadocs"
|
|
1441
1795
|
}[cfg.theme] || "fumadocs";
|
|
1442
1796
|
if (existingGlobalCss) {
|
|
@@ -1450,6 +1804,34 @@ function scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
1450
1804
|
write(`${cfg.entry}/installation/page.md`, astroInstallationPageTemplate(cfg));
|
|
1451
1805
|
write(`${cfg.entry}/quickstart/page.md`, astroQuickstartPageTemplate(cfg));
|
|
1452
1806
|
}
|
|
1807
|
+
function scaffoldNuxt(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
1808
|
+
write("docs.config.ts", nuxtDocsConfigTemplate(cfg));
|
|
1809
|
+
write("server/utils/docs-server.ts", nuxtDocsServerTemplate(cfg));
|
|
1810
|
+
write("server/api/docs.get.ts", nuxtServerApiDocsGetTemplate());
|
|
1811
|
+
write("server/api/docs.post.ts", nuxtServerApiDocsPostTemplate());
|
|
1812
|
+
write("server/api/docs/load.get.ts", nuxtServerApiDocsLoadTemplate());
|
|
1813
|
+
write(`pages/${cfg.entry}/[[...slug]].vue`, nuxtDocsPageTemplate(cfg));
|
|
1814
|
+
path.join(cwd, "nuxt.config.ts");
|
|
1815
|
+
if (!fileExists(path.join(cwd, "nuxt.config.ts")) && !fileExists(path.join(cwd, "nuxt.config.js"))) write("nuxt.config.ts", nuxtConfigTemplate(cfg));
|
|
1816
|
+
const cssTheme = {
|
|
1817
|
+
fumadocs: "fumadocs",
|
|
1818
|
+
darksharp: "darksharp",
|
|
1819
|
+
"pixel-border": "pixel-border",
|
|
1820
|
+
default: "fumadocs"
|
|
1821
|
+
}[cfg.theme] || "fumadocs";
|
|
1822
|
+
const globalCssAbsPath = path.join(cwd, globalCssRelPath);
|
|
1823
|
+
const existingGlobalCss = readFileSafe(globalCssAbsPath);
|
|
1824
|
+
if (existingGlobalCss) {
|
|
1825
|
+
const injected = injectNuxtCssImport(existingGlobalCss, cssTheme);
|
|
1826
|
+
if (injected) {
|
|
1827
|
+
writeFileSafe(globalCssAbsPath, injected, true);
|
|
1828
|
+
written.push(globalCssRelPath + " (updated)");
|
|
1829
|
+
} else skipped.push(globalCssRelPath + " (already configured)");
|
|
1830
|
+
} else write(globalCssRelPath, nuxtGlobalCssTemplate(cssTheme));
|
|
1831
|
+
write(`${cfg.entry}/page.md`, nuxtWelcomePageTemplate(cfg));
|
|
1832
|
+
write(`${cfg.entry}/installation/page.md`, nuxtInstallationPageTemplate(cfg));
|
|
1833
|
+
write(`${cfg.entry}/quickstart/page.md`, nuxtQuickstartPageTemplate(cfg));
|
|
1834
|
+
}
|
|
1453
1835
|
|
|
1454
1836
|
//#endregion
|
|
1455
1837
|
//#region src/cli/index.ts
|
|
@@ -1476,7 +1858,7 @@ ${pc.dim("Commands:")}
|
|
|
1476
1858
|
${pc.cyan("init")} Scaffold docs in your project (default)
|
|
1477
1859
|
|
|
1478
1860
|
${pc.dim("Supported frameworks:")}
|
|
1479
|
-
Next.js, SvelteKit, Astro
|
|
1861
|
+
Next.js, SvelteKit, Astro, Nuxt
|
|
1480
1862
|
|
|
1481
1863
|
${pc.dim("Options:")}
|
|
1482
1864
|
${pc.cyan("-h, --help")} Show this help message
|
package/dist/index.d.mts
CHANGED
|
@@ -137,6 +137,13 @@ interface UIConfig {
|
|
|
137
137
|
toc?: {
|
|
138
138
|
enabled?: boolean;
|
|
139
139
|
depth?: number;
|
|
140
|
+
/**
|
|
141
|
+
* Visual style of the TOC indicator.
|
|
142
|
+
* - `"default"` — highlight active link text color only
|
|
143
|
+
* - `"directional"` — animated thumb bar that tracks active headings (fumadocs style)
|
|
144
|
+
* @default "default"
|
|
145
|
+
*/
|
|
146
|
+
style?: "default" | "directional";
|
|
140
147
|
};
|
|
141
148
|
header?: {
|
|
142
149
|
height?: number;
|
|
@@ -533,19 +540,44 @@ interface AIConfig {
|
|
|
533
540
|
*/
|
|
534
541
|
floatingStyle?: "panel" | "modal" | "popover" | "full-modal";
|
|
535
542
|
/**
|
|
536
|
-
* Custom trigger component for the floating chat button.
|
|
543
|
+
* Custom trigger component for the floating chat button (Next.js only).
|
|
537
544
|
* Only used when `mode` is `"floating"`.
|
|
538
545
|
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
546
|
+
* The click handler is attached automatically by the wrapper.
|
|
547
|
+
*
|
|
548
|
+
* - **Next.js**: Pass a JSX element via this config option.
|
|
549
|
+
* - **SvelteKit**: Use the `aiTrigger` snippet on `<DocsLayout>`.
|
|
550
|
+
* - **Nuxt / Vue**: Use the `ai-trigger` slot on `<DocsLayout>`.
|
|
551
|
+
* - **Astro**: Use `<MyTrigger slot="ai-trigger" />` on `<DocsLayout>`.
|
|
541
552
|
*
|
|
542
553
|
* @example
|
|
543
554
|
* ```tsx
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
555
|
+
* // Next.js — pass JSX directly in config
|
|
556
|
+
* triggerComponent: <button className="my-chat-btn">Ask AI</button>,
|
|
557
|
+
* ```
|
|
558
|
+
*
|
|
559
|
+
* ```svelte
|
|
560
|
+
* <!-- SvelteKit — use snippet in layout -->
|
|
561
|
+
* <DocsLayout {tree} {config}>
|
|
562
|
+
* {#snippet aiTrigger()}<AskAITrigger />{/snippet}
|
|
563
|
+
* {@render children()}
|
|
564
|
+
* </DocsLayout>
|
|
565
|
+
* ```
|
|
566
|
+
*
|
|
567
|
+
* ```vue
|
|
568
|
+
* <!-- Nuxt / Vue — use named slot in layout -->
|
|
569
|
+
* <DocsLayout :tree="tree" :config="config">
|
|
570
|
+
* <template #ai-trigger><AskAITrigger /></template>
|
|
571
|
+
* <DocsContent />
|
|
572
|
+
* </DocsLayout>
|
|
573
|
+
* ```
|
|
574
|
+
*
|
|
575
|
+
* ```astro
|
|
576
|
+
* <!-- Astro — use named slot in layout -->
|
|
577
|
+
* <DocsLayout tree={tree} config={config}>
|
|
578
|
+
* <AskAITrigger slot="ai-trigger" />
|
|
579
|
+
* <DocsContent />
|
|
580
|
+
* </DocsLayout>
|
|
549
581
|
* ```
|
|
550
582
|
*/
|
|
551
583
|
triggerComponent?: unknown;
|