@farming-labs/docs 0.1.59 → 0.1.62

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.
@@ -1,8 +1,4 @@
1
- import { a as devInstallCommand, c as installCommand, d as writeFileSafe, i as detectPackageManagerFromLockfile, l as readFileSafe, n as detectGlobalCssFiles, o as exec, r as detectNextAppDir, s as fileExists, t as detectFramework, u as spawnAndWaitFor } from "./utils-CpTFbAiS.mjs";
2
- import fs from "node:fs";
3
1
  import path from "node:path";
4
- import pc from "picocolors";
5
- import * as p from "@clack/prompts";
6
2
 
7
3
  //#region src/cli/templates.ts
8
4
  const THEME_INFO = {
@@ -350,7 +346,7 @@ function rootLayoutTemplate(cfg, globalCssRelPath = "app/globals.css") {
350
346
  import type { Metadata } from "next";
351
347
  import { RootProvider } from "@farming-labs/theme";
352
348
  import docsConfig from "${nextRootLayoutConfigImport(cfg.useAlias, appDir)}";
353
- import "${cssImport}";
349
+ ${cfg.apiReference ? "import \"@farming-labs/next/api-reference.css\";\n" : ""}import "${cssImport}";
354
350
 
355
351
  export const metadata: Metadata = {
356
352
  title: {
@@ -426,11 +422,11 @@ function docsLayoutTemplate(cfg) {
426
422
  const appDir = cfg.nextAppDir ?? "app";
427
423
  return `\
428
424
  import docsConfig from "${nextDocsLayoutConfigImport(cfg.useAlias, appDir)}";
429
- import { createDocsLayout, createDocsMetadata } from "@farming-labs/theme";
425
+ import { createNextDocsLayout, createNextDocsMetadata } from "@farming-labs/next/layout";
430
426
 
431
- export const metadata = createDocsMetadata(docsConfig);
427
+ export const metadata = createNextDocsMetadata(docsConfig);
432
428
 
433
- const DocsLayout = createDocsLayout(docsConfig);
429
+ const DocsLayout = createNextDocsLayout(docsConfig);
434
430
 
435
431
  export default function Layout({ children }: { children: React.ReactNode }) {
436
432
  return (
@@ -444,7 +440,6 @@ export default function Layout({ children }: { children: React.ReactNode }) {
444
440
  function nextApiReferencePageTemplate(cfg, filePath) {
445
441
  const appDir = cfg.nextAppDir ?? "app";
446
442
  return `
447
- import "@farming-labs/next/api-reference.css";
448
443
  import docsConfig from "${nextApiReferenceConfigImport(cfg.useAlias, appDir, filePath)}";
449
444
  import { createNextApiReferencePage } from "@farming-labs/next/api-reference";
450
445
 
@@ -2357,1158 +2352,4 @@ function injectNuxtCssImport(existingContent, theme, customThemeName, globalCssR
2357
2352
  }
2358
2353
 
2359
2354
  //#endregion
2360
- //#region src/cli/init.ts
2361
- const EXAMPLES_REPO = "farming-labs/docs";
2362
- const VALID_TEMPLATES = [
2363
- "next",
2364
- "nuxt",
2365
- "sveltekit",
2366
- "astro",
2367
- "tanstack-start"
2368
- ];
2369
- const COMMON_LOCALE_OPTIONS = [
2370
- {
2371
- value: "en",
2372
- label: "English",
2373
- hint: "en"
2374
- },
2375
- {
2376
- value: "fr",
2377
- label: "French",
2378
- hint: "fr"
2379
- },
2380
- {
2381
- value: "es",
2382
- label: "Spanish",
2383
- hint: "es"
2384
- },
2385
- {
2386
- value: "de",
2387
- label: "German",
2388
- hint: "de"
2389
- },
2390
- {
2391
- value: "pt",
2392
- label: "Portuguese",
2393
- hint: "pt"
2394
- },
2395
- {
2396
- value: "it",
2397
- label: "Italian",
2398
- hint: "it"
2399
- },
2400
- {
2401
- value: "ja",
2402
- label: "Japanese",
2403
- hint: "ja"
2404
- },
2405
- {
2406
- value: "ko",
2407
- label: "Korean",
2408
- hint: "ko"
2409
- },
2410
- {
2411
- value: "zh",
2412
- label: "Chinese",
2413
- hint: "zh"
2414
- },
2415
- {
2416
- value: "ar",
2417
- label: "Arabic",
2418
- hint: "ar"
2419
- },
2420
- {
2421
- value: "hi",
2422
- label: "Hindi",
2423
- hint: "hi"
2424
- },
2425
- {
2426
- value: "ru",
2427
- label: "Russian",
2428
- hint: "ru"
2429
- }
2430
- ];
2431
- function normalizeLocaleCode(value) {
2432
- const trimmed = value.trim();
2433
- if (!trimmed) return "";
2434
- const [language, ...rest] = trimmed.split("-");
2435
- const normalizedLanguage = language.toLowerCase();
2436
- if (rest.length === 0) return normalizedLanguage;
2437
- return `${normalizedLanguage}-${rest.join("-").toUpperCase()}`;
2438
- }
2439
- function parseLocaleInput(input) {
2440
- return Array.from(new Set(input.split(",").map((value) => normalizeLocaleCode(value)).filter(Boolean)));
2441
- }
2442
- function normalizeEntryPath(entry) {
2443
- return entry.replace(/^\/+|\/+$/g, "");
2444
- }
2445
- function getTanstackDocsRouteDir(entry) {
2446
- return path.posix.join("src/routes", normalizeEntryPath(entry));
2447
- }
2448
- function normalizeApiRouteRoot(routeRoot) {
2449
- return routeRoot.replace(/^\/+|\/+$/g, "");
2450
- }
2451
- function detectApiRouteRoot(cwd, framework, nextAppDir = "app") {
2452
- const defaultRoot = "api";
2453
- const detectFromRecursiveRouteFiles = (baseDir, matcher) => {
2454
- if (!fs.existsSync(baseDir)) return null;
2455
- const candidates = /* @__PURE__ */ new Map();
2456
- const walk = (dir, prefix = "") => {
2457
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
2458
- const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
2459
- const fullPath = path.join(dir, entry.name);
2460
- if (entry.isDirectory()) {
2461
- walk(fullPath, relativePath);
2462
- continue;
2463
- }
2464
- if (!matcher(entry, relativePath)) continue;
2465
- const [topLevel] = relativePath.split("/");
2466
- if (!topLevel) continue;
2467
- candidates.set(topLevel, (candidates.get(topLevel) ?? 0) + 1);
2468
- }
2469
- };
2470
- walk(baseDir);
2471
- return Array.from(candidates.entries()).sort((a, b) => b[1] - a[1])[0]?.[0] ?? null;
2472
- };
2473
- if (framework === "nextjs") {
2474
- const appRoot = path.join(cwd, nextAppDir);
2475
- if (fs.existsSync(path.join(appRoot, defaultRoot))) return defaultRoot;
2476
- return detectFromRecursiveRouteFiles(appRoot, (_entry, relativePath) => /\/?route\.(?:[cm]?[jt]sx?)$/i.test(relativePath)) ?? defaultRoot;
2477
- }
2478
- if (framework === "tanstack-start") {
2479
- const routesRoot = path.join(cwd, "src/routes");
2480
- if (fs.existsSync(path.join(routesRoot, defaultRoot))) return defaultRoot;
2481
- return detectFromRecursiveRouteFiles(routesRoot, (_entry, relativePath) => /(?:^|\/)[^/]+\.(?:[cm]?[jt]sx?)$/i.test(relativePath)) ?? defaultRoot;
2482
- }
2483
- if (framework === "sveltekit") {
2484
- const routesRoot = path.join(cwd, "src/routes");
2485
- if (fs.existsSync(path.join(routesRoot, defaultRoot))) return defaultRoot;
2486
- return detectFromRecursiveRouteFiles(routesRoot, (_entry, relativePath) => /\/?\+server\.(?:[cm]?[jt]s)$/i.test(relativePath)) ?? defaultRoot;
2487
- }
2488
- if (framework === "astro") {
2489
- const pagesRoot = path.join(cwd, "src/pages");
2490
- if (fs.existsSync(path.join(pagesRoot, defaultRoot))) return defaultRoot;
2491
- return detectFromRecursiveRouteFiles(pagesRoot, (entry, relativePath) => /\.(?:[cm]?[jt]s)$/i.test(relativePath) && !relativePath.endsWith(".d.ts") && entry.isFile()) ?? defaultRoot;
2492
- }
2493
- const serverRoot = path.join(cwd, "server");
2494
- if (fs.existsSync(path.join(serverRoot, defaultRoot))) return defaultRoot;
2495
- return detectFromRecursiveRouteFiles(serverRoot, (entry, relativePath) => /\.(?:[cm]?[jt]s)$/i.test(relativePath) && !relativePath.endsWith(".d.ts") && entry.isFile()) ?? defaultRoot;
2496
- }
2497
- async function init(options = {}) {
2498
- const cwd = process.cwd();
2499
- p.intro(pc.bgCyan(pc.black(" @farming-labs/docs ")));
2500
- let projectType = "existing";
2501
- if (!options.template) {
2502
- const projectTypeAnswer = await p.select({
2503
- message: "Are you adding docs to an existing project or starting fresh?",
2504
- options: [{
2505
- value: "existing",
2506
- label: "Existing project",
2507
- hint: "Add docs to the current app in this directory"
2508
- }, {
2509
- value: "fresh",
2510
- label: "Fresh project",
2511
- hint: "Bootstrap a new app from a template (Next, Nuxt, SvelteKit, Astro, TanStack Start)"
2512
- }]
2513
- });
2514
- if (p.isCancel(projectTypeAnswer)) {
2515
- p.outro(pc.red("Init cancelled."));
2516
- process.exit(0);
2517
- }
2518
- projectType = projectTypeAnswer;
2519
- }
2520
- if (projectType === "fresh" || options.template) {
2521
- let template;
2522
- if (options.template) {
2523
- template = options.template.toLowerCase();
2524
- if (!VALID_TEMPLATES.includes(template)) {
2525
- p.log.error(`Invalid ${pc.cyan("--template")}. Use one of: ${VALID_TEMPLATES.map((t) => pc.cyan(t)).join(", ")}`);
2526
- process.exit(1);
2527
- }
2528
- } else {
2529
- const templateAnswer = await p.select({
2530
- message: "Which framework would you like to use?",
2531
- options: [
2532
- {
2533
- value: "next",
2534
- label: "Next.js",
2535
- hint: "React with App Router"
2536
- },
2537
- {
2538
- value: "nuxt",
2539
- label: "Nuxt",
2540
- hint: "Vue 3 with file-based routing"
2541
- },
2542
- {
2543
- value: "sveltekit",
2544
- label: "SvelteKit",
2545
- hint: "Svelte with file-based routing"
2546
- },
2547
- {
2548
- value: "astro",
2549
- label: "Astro",
2550
- hint: "Content-focused with islands"
2551
- },
2552
- {
2553
- value: "tanstack-start",
2554
- label: "TanStack Start",
2555
- hint: "React with TanStack Router and server functions"
2556
- }
2557
- ]
2558
- });
2559
- if (p.isCancel(templateAnswer)) {
2560
- p.outro(pc.red("Init cancelled."));
2561
- process.exit(0);
2562
- }
2563
- template = templateAnswer;
2564
- }
2565
- const defaultProjectName = "my-docs";
2566
- let projectName = options.name?.trim();
2567
- if (!projectName) {
2568
- const nameAnswer = await p.text({
2569
- message: "Project name? (we'll create this folder and bootstrap the app here)",
2570
- placeholder: defaultProjectName,
2571
- defaultValue: defaultProjectName,
2572
- validate: (value) => {
2573
- const v = (value ?? "").trim();
2574
- if (v.includes("/") || v.includes("\\")) return "Project name cannot contain path separators";
2575
- if (v.includes(" ")) return "Project name cannot contain spaces";
2576
- }
2577
- });
2578
- if (p.isCancel(nameAnswer)) {
2579
- p.outro(pc.red("Init cancelled."));
2580
- process.exit(0);
2581
- }
2582
- projectName = nameAnswer.trim() || defaultProjectName;
2583
- }
2584
- const templateLabel = template === "next" ? "Next.js" : template === "nuxt" ? "Nuxt" : template === "sveltekit" ? "SvelteKit" : template === "astro" ? "Astro" : "TanStack Start";
2585
- const targetDir = path.join(cwd, projectName);
2586
- const fs = await import("node:fs");
2587
- if (fs.existsSync(targetDir)) {
2588
- p.log.error(`Directory ${pc.cyan(projectName)} already exists. Choose a different ${pc.cyan("--name")} or remove it.`);
2589
- process.exit(1);
2590
- }
2591
- fs.mkdirSync(targetDir, { recursive: true });
2592
- p.log.step(`Bootstrapping project with ${pc.cyan(`'${projectName}'`)} (${templateLabel})...`);
2593
- try {
2594
- exec(`npx degit ${EXAMPLES_REPO}/examples/${template} . --force`, targetDir);
2595
- } catch {
2596
- p.log.error("Failed to bootstrap. Check your connection and that the repo exists.");
2597
- process.exit(1);
2598
- }
2599
- const pmAnswer = await p.select({
2600
- message: "Which package manager do you want to use in this new project?",
2601
- options: [
2602
- {
2603
- value: "pnpm",
2604
- label: "pnpm",
2605
- hint: "Fast, disk-efficient (recommended)"
2606
- },
2607
- {
2608
- value: "npm",
2609
- label: "npm",
2610
- hint: "Default Node.js package manager"
2611
- },
2612
- {
2613
- value: "yarn",
2614
- label: "yarn",
2615
- hint: "Classic yarn (script: yarn dev)"
2616
- },
2617
- {
2618
- value: "bun",
2619
- label: "bun",
2620
- hint: "Bun runtime + bun install/dev"
2621
- }
2622
- ]
2623
- });
2624
- if (p.isCancel(pmAnswer)) {
2625
- p.outro(pc.red("Init cancelled."));
2626
- process.exit(0);
2627
- }
2628
- const pmFresh = pmAnswer;
2629
- p.log.success(`Bootstrapped ${pc.cyan(`'${projectName}'`)}. Installing dependencies with ${pc.cyan(pmFresh)}...`);
2630
- const installCmd = pmFresh === "yarn" ? "yarn install" : pmFresh === "npm" ? "npm install" : pmFresh === "bun" ? "bun install" : "pnpm install";
2631
- try {
2632
- exec(installCmd, targetDir);
2633
- } catch {
2634
- p.log.warn(`${pmFresh} install failed. Run ${pc.cyan(installCmd)} manually inside the project.`);
2635
- }
2636
- const devCmd = pmFresh === "yarn" ? "yarn dev" : pmFresh === "npm" ? "npm run dev" : pmFresh === "bun" ? "bun dev" : "pnpm dev";
2637
- p.outro(pc.green(`Done! Run ${pc.cyan(`cd ${projectName} && ${devCmd}`)} to start the dev server and navigate to the /docs.`));
2638
- p.outro(pc.green("Happy documenting!"));
2639
- process.exit(0);
2640
- }
2641
- let framework = detectFramework(cwd);
2642
- if (framework) {
2643
- const frameworkName = framework === "nextjs" ? "Next.js" : framework === "tanstack-start" ? "TanStack Start" : framework === "sveltekit" ? "SvelteKit" : framework === "astro" ? "Astro" : "Nuxt";
2644
- p.log.success(`Detected framework: ${pc.cyan(frameworkName)}`);
2645
- } else {
2646
- p.log.warn("Could not auto-detect a framework from " + pc.cyan("package.json") + ".");
2647
- const picked = await p.select({
2648
- message: "Which framework are you using?",
2649
- options: [
2650
- {
2651
- value: "nextjs",
2652
- label: "Next.js",
2653
- hint: "React framework with App Router"
2654
- },
2655
- {
2656
- value: "tanstack-start",
2657
- label: "TanStack Start",
2658
- hint: "React with TanStack Router and server functions"
2659
- },
2660
- {
2661
- value: "sveltekit",
2662
- label: "SvelteKit",
2663
- hint: "Svelte framework with file-based routing"
2664
- },
2665
- {
2666
- value: "astro",
2667
- label: "Astro",
2668
- hint: "Content-focused framework with island architecture"
2669
- },
2670
- {
2671
- value: "nuxt",
2672
- label: "Nuxt",
2673
- hint: "Vue 3 framework with file-based routing and Nitro server"
2674
- }
2675
- ]
2676
- });
2677
- if (p.isCancel(picked)) {
2678
- p.outro(pc.red("Init cancelled."));
2679
- process.exit(0);
2680
- }
2681
- framework = picked;
2682
- }
2683
- let nextAppDir = "app";
2684
- if (framework === "nextjs") {
2685
- const detected = detectNextAppDir(cwd);
2686
- if (detected) {
2687
- nextAppDir = detected;
2688
- p.log.info(`Using App Router at ${pc.cyan(nextAppDir)} (detected ${detected === "src/app" ? "src directory" : "root app"})`);
2689
- } else {
2690
- const useSrcApp = await p.confirm({
2691
- message: "Do you use the src directory for the App Router? (e.g. src/app instead of app)",
2692
- initialValue: false
2693
- });
2694
- if (p.isCancel(useSrcApp)) {
2695
- p.outro(pc.red("Init cancelled."));
2696
- process.exit(0);
2697
- }
2698
- nextAppDir = useSrcApp ? "src/app" : "app";
2699
- }
2700
- }
2701
- const themeOptions = [
2702
- {
2703
- value: "fumadocs",
2704
- label: "Fumadocs (Default)",
2705
- hint: "Clean, modern docs theme with sidebar, search, and dark mode"
2706
- },
2707
- {
2708
- value: "darksharp",
2709
- label: "Darksharp",
2710
- hint: "All-black, sharp edges, zero-radius look"
2711
- },
2712
- {
2713
- value: "pixel-border",
2714
- label: "Pixel Border",
2715
- hint: "Rounded borders, pixel-perfect spacing, refined sidebar"
2716
- },
2717
- {
2718
- value: "colorful",
2719
- label: "Colorful",
2720
- hint: "Fumadocs-style neutral theme with description support"
2721
- },
2722
- {
2723
- value: "darkbold",
2724
- label: "DarkBold",
2725
- hint: "Pure monochrome, Geist typography, clean minimalism"
2726
- },
2727
- {
2728
- value: "shiny",
2729
- label: "Shiny",
2730
- hint: "Glossy, modern look with subtle shimmer effects"
2731
- },
2732
- {
2733
- value: "greentree",
2734
- label: "GreenTree",
2735
- hint: "Emerald green accent, Inter font, Mintlify-inspired"
2736
- },
2737
- {
2738
- value: "concrete",
2739
- label: "Concrete",
2740
- hint: "Brutalist poster-style theme with offset shadows and loud contrast"
2741
- },
2742
- {
2743
- value: "command-grid",
2744
- label: "Command Grid",
2745
- hint: "Paper-grid docs shell inspired by better-cmdk"
2746
- },
2747
- {
2748
- value: "hardline",
2749
- label: "Hardline",
2750
- hint: "Hard-edge theme with square corners and bold borders"
2751
- },
2752
- {
2753
- value: "custom",
2754
- label: "Create your own theme",
2755
- hint: "Scaffold a new theme file + CSS in themes/ (name asked next)"
2756
- }
2757
- ];
2758
- const themeValues = new Set(themeOptions.map((option) => option.value));
2759
- let theme;
2760
- if (options.theme) {
2761
- if (!themeValues.has(options.theme)) {
2762
- p.log.error(`Invalid ${pc.cyan("--theme")}. Use one of: ${themeOptions.map((option) => pc.cyan(option.value)).join(", ")}`);
2763
- process.exit(1);
2764
- }
2765
- theme = options.theme;
2766
- } else {
2767
- const themeAnswer = await p.select({
2768
- message: "Which theme would you like to use?",
2769
- options: themeOptions
2770
- });
2771
- if (p.isCancel(themeAnswer)) {
2772
- p.outro(pc.red("Init cancelled."));
2773
- process.exit(0);
2774
- }
2775
- theme = themeAnswer;
2776
- }
2777
- const defaultThemeName = "my-theme";
2778
- let customThemeName;
2779
- if (theme === "custom") {
2780
- const nameAnswer = await p.text({
2781
- message: "Theme name? (we'll create themes/<name>.ts and themes/<name>.css)",
2782
- placeholder: defaultThemeName,
2783
- defaultValue: defaultThemeName,
2784
- validate: (value) => {
2785
- const v = (value ?? "").trim().replace(/\.(ts|css)$/i, "");
2786
- if (v.includes("/") || v.includes("\\")) return "Theme name cannot contain path separators";
2787
- if (v.includes(" ")) return "Theme name cannot contain spaces";
2788
- if (v && !/^[a-z0-9_-]+$/i.test(v)) return "Use only letters, numbers, hyphens, and underscores";
2789
- }
2790
- });
2791
- if (p.isCancel(nameAnswer)) {
2792
- p.outro(pc.red("Init cancelled."));
2793
- process.exit(0);
2794
- }
2795
- customThemeName = nameAnswer.trim().replace(/\.(ts|css)$/i, "") || defaultThemeName;
2796
- }
2797
- const aliasHint = framework === "nextjs" ? `Uses ${pc.cyan("@/")} prefix (requires tsconfig paths)` : framework === "tanstack-start" ? `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)`;
2798
- const useAlias = await p.confirm({
2799
- message: `Use path aliases for imports? ${pc.dim(aliasHint)}`,
2800
- initialValue: false
2801
- });
2802
- if (p.isCancel(useAlias)) {
2803
- p.outro(pc.red("Init cancelled."));
2804
- process.exit(0);
2805
- }
2806
- let astroAdapter;
2807
- if (framework === "astro") {
2808
- const adapter = await p.select({
2809
- message: "Where will you deploy?",
2810
- options: [
2811
- {
2812
- value: "vercel",
2813
- label: "Vercel",
2814
- hint: "Recommended for most projects"
2815
- },
2816
- {
2817
- value: "netlify",
2818
- label: "Netlify"
2819
- },
2820
- {
2821
- value: "cloudflare",
2822
- label: "Cloudflare Pages"
2823
- },
2824
- {
2825
- value: "node",
2826
- label: "Node.js / Docker",
2827
- hint: "Self-hosted standalone server"
2828
- }
2829
- ]
2830
- });
2831
- if (p.isCancel(adapter)) {
2832
- p.outro(pc.red("Init cancelled."));
2833
- process.exit(0);
2834
- }
2835
- astroAdapter = adapter;
2836
- }
2837
- const defaultEntry = "docs";
2838
- let entryPath;
2839
- if (options.entry) {
2840
- const normalizedEntry = options.entry.trim();
2841
- if (normalizedEntry.startsWith("/")) {
2842
- p.log.error("Use a relative path for --entry (no leading /)");
2843
- process.exit(1);
2844
- }
2845
- if (normalizedEntry.includes(" ")) {
2846
- p.log.error("Path passed to --entry cannot contain spaces");
2847
- process.exit(1);
2848
- }
2849
- entryPath = normalizedEntry || defaultEntry;
2850
- } else {
2851
- const entry = await p.text({
2852
- message: "Where should your docs live?",
2853
- placeholder: defaultEntry,
2854
- defaultValue: defaultEntry,
2855
- validate: (value) => {
2856
- const v = (value ?? "").trim();
2857
- if (v.startsWith("/")) return "Use a relative path (no leading /)";
2858
- if (v.includes(" ")) return "Path cannot contain spaces";
2859
- }
2860
- });
2861
- if (p.isCancel(entry)) {
2862
- p.outro(pc.red("Init cancelled."));
2863
- process.exit(0);
2864
- }
2865
- entryPath = entry.trim() || defaultEntry;
2866
- }
2867
- const defaultApiRouteRoot = normalizeApiRouteRoot(options.apiRouteRoot?.trim() || detectApiRouteRoot(cwd, framework, nextAppDir));
2868
- let apiReferenceConfig;
2869
- let enableApiReference;
2870
- if (typeof options.apiReference === "boolean") enableApiReference = options.apiReference;
2871
- else if (typeof options.apiRouteRoot === "string" && options.apiRouteRoot.trim()) enableApiReference = true;
2872
- else {
2873
- const apiReferenceAnswer = await p.confirm({
2874
- message: "Do you want to scaffold API reference support?",
2875
- initialValue: false
2876
- });
2877
- if (p.isCancel(apiReferenceAnswer)) {
2878
- p.outro(pc.red("Init cancelled."));
2879
- process.exit(0);
2880
- }
2881
- enableApiReference = apiReferenceAnswer;
2882
- }
2883
- if (enableApiReference) {
2884
- let routeRoot = options.apiRouteRoot?.trim();
2885
- if (!routeRoot) {
2886
- const routeRootAnswer = await p.text({
2887
- message: "API route root to scan?",
2888
- placeholder: defaultApiRouteRoot,
2889
- defaultValue: defaultApiRouteRoot,
2890
- validate: (value) => {
2891
- const normalizedValue = normalizeApiRouteRoot((value ?? "").trim());
2892
- if (!normalizedValue) return "Route root cannot be empty";
2893
- if (normalizedValue.includes(" ")) return "Route root cannot contain spaces";
2894
- }
2895
- });
2896
- if (p.isCancel(routeRootAnswer)) {
2897
- p.outro(pc.red("Init cancelled."));
2898
- process.exit(0);
2899
- }
2900
- routeRoot = routeRootAnswer.trim() || defaultApiRouteRoot;
2901
- }
2902
- const normalizedRouteRoot = normalizeApiRouteRoot(routeRoot);
2903
- if (!normalizedRouteRoot) {
2904
- p.log.error("Route root cannot be empty");
2905
- process.exit(1);
2906
- }
2907
- if (normalizedRouteRoot.includes(" ")) {
2908
- p.log.error("Route root cannot contain spaces");
2909
- process.exit(1);
2910
- }
2911
- apiReferenceConfig = {
2912
- path: "api-reference",
2913
- routeRoot: normalizedRouteRoot
2914
- };
2915
- }
2916
- let docsI18n;
2917
- if (framework === "tanstack-start") p.log.info("Skipping i18n scaffold for TanStack Start. Configure localized routes manually if needed.");
2918
- else {
2919
- const enableI18n = await p.confirm({
2920
- message: "Do you want to scaffold internationalized docs ?",
2921
- initialValue: false
2922
- });
2923
- if (p.isCancel(enableI18n)) {
2924
- p.outro(pc.red("Init cancelled."));
2925
- process.exit(0);
2926
- }
2927
- if (!enableI18n) docsI18n = void 0;
2928
- else {
2929
- const selectedLocales = await p.multiselect({
2930
- message: "Which languages should we scaffold?",
2931
- options: COMMON_LOCALE_OPTIONS.map((option) => ({
2932
- value: option.value,
2933
- label: option.label,
2934
- hint: option.hint
2935
- }))
2936
- });
2937
- if (p.isCancel(selectedLocales)) {
2938
- p.outro(pc.red("Init cancelled."));
2939
- process.exit(0);
2940
- }
2941
- const extraLocalesAnswer = await p.text({
2942
- message: "Any additional locale codes? (comma-separated, optional)",
2943
- placeholder: "nl, sv, pt-BR",
2944
- defaultValue: "",
2945
- validate: (value) => {
2946
- return parseLocaleInput(value ?? "").every((locale) => /^[a-z]{2,3}(?:-[A-Z]{2})?$/.test(locale)) ? void 0 : "Use locale codes like en, fr, zh, or pt-BR";
2947
- }
2948
- });
2949
- if (p.isCancel(extraLocalesAnswer)) {
2950
- p.outro(pc.red("Init cancelled."));
2951
- process.exit(0);
2952
- }
2953
- const locales = Array.from(new Set([...(selectedLocales ?? []).map((locale) => normalizeLocaleCode(locale)), ...parseLocaleInput(extraLocalesAnswer ?? "")])).filter(Boolean);
2954
- if (locales.length === 0) {
2955
- p.log.error("Pick at least one locale to scaffold i18n support.");
2956
- p.outro(pc.red("Init cancelled."));
2957
- process.exit(1);
2958
- }
2959
- const defaultLocaleAnswer = await p.select({
2960
- message: "Which locale should be the default?",
2961
- options: locales.map((locale) => ({
2962
- value: locale,
2963
- label: locale,
2964
- hint: locale === "en" ? "Recommended default" : void 0
2965
- })),
2966
- initialValue: locales[0]
2967
- });
2968
- if (p.isCancel(defaultLocaleAnswer)) {
2969
- p.outro(pc.red("Init cancelled."));
2970
- process.exit(0);
2971
- }
2972
- docsI18n = {
2973
- locales,
2974
- defaultLocale: defaultLocaleAnswer
2975
- };
2976
- }
2977
- }
2978
- const detectedCssFiles = detectGlobalCssFiles(cwd);
2979
- let globalCssRelPath;
2980
- const defaultCssPath = framework === "tanstack-start" ? "src/styles/app.css" : 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";
2981
- if (detectedCssFiles.length === 1) {
2982
- globalCssRelPath = detectedCssFiles[0];
2983
- p.log.info(`Found global CSS at ${pc.cyan(globalCssRelPath)}`);
2984
- } else if (detectedCssFiles.length > 1) {
2985
- const picked = await p.select({
2986
- message: "Multiple global CSS files found. Which one should we use?",
2987
- options: detectedCssFiles.map((f) => ({
2988
- value: f,
2989
- label: f
2990
- }))
2991
- });
2992
- if (p.isCancel(picked)) {
2993
- p.outro(pc.red("Init cancelled."));
2994
- process.exit(0);
2995
- }
2996
- globalCssRelPath = picked;
2997
- } else {
2998
- const cssPathAnswer = await p.text({
2999
- message: "Where is your global CSS file?",
3000
- placeholder: defaultCssPath,
3001
- defaultValue: defaultCssPath,
3002
- validate: (value) => {
3003
- const v = (value ?? "").trim();
3004
- if (v && !v.endsWith(".css")) return "Path must end with .css";
3005
- }
3006
- });
3007
- if (p.isCancel(cssPathAnswer)) {
3008
- p.outro(pc.red("Init cancelled."));
3009
- process.exit(0);
3010
- }
3011
- globalCssRelPath = cssPathAnswer.trim() || defaultCssPath;
3012
- }
3013
- const pkgJsonContent = readFileSafe(path.join(cwd, "package.json"));
3014
- const pkgJson = pkgJsonContent ? JSON.parse(pkgJsonContent) : { name: "my-project" };
3015
- const projectName = pkgJson.name || "My Project";
3016
- const cfg = {
3017
- entry: entryPath,
3018
- theme,
3019
- customThemeName,
3020
- projectName,
3021
- framework,
3022
- useAlias,
3023
- astroAdapter,
3024
- i18n: docsI18n,
3025
- apiReference: apiReferenceConfig,
3026
- ...framework === "nextjs" && { nextAppDir }
3027
- };
3028
- const s = p.spinner();
3029
- s.start("Scaffolding docs files");
3030
- const written = [];
3031
- const skipped = [];
3032
- function write(rel, content, overwrite = false) {
3033
- if (writeFileSafe(path.join(cwd, rel), content, overwrite)) written.push(rel);
3034
- else skipped.push(rel);
3035
- }
3036
- if (framework === "tanstack-start") scaffoldTanstackStart(cwd, cfg, globalCssRelPath, write, skipped, written);
3037
- else if (framework === "sveltekit") scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written);
3038
- else if (framework === "astro") scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written);
3039
- else if (framework === "nuxt") scaffoldNuxt(cwd, cfg, globalCssRelPath, write, skipped, written);
3040
- else scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written);
3041
- s.stop("Files scaffolded");
3042
- if (written.length > 0) p.log.success(`Created ${written.length} file${written.length > 1 ? "s" : ""}:\n` + written.map((f) => ` ${pc.green("+")} ${f}`).join("\n"));
3043
- if (skipped.length > 0) p.log.info(`Skipped ${skipped.length} existing file${skipped.length > 1 ? "s" : ""}:\n` + skipped.map((f) => ` ${pc.dim("-")} ${f}`).join("\n"));
3044
- let pm = detectPackageManagerFromLockfile(cwd);
3045
- if (pm) p.log.info(`Detected ${pc.cyan(pm)}`);
3046
- const pmAnswerExisting = await p.select({
3047
- ...pm ? { initialValue: pm } : {},
3048
- message: "Which package manager do you want to use in this project?",
3049
- options: [
3050
- {
3051
- value: "pnpm",
3052
- label: "pnpm",
3053
- hint: "Fast, disk-efficient (recommended)"
3054
- },
3055
- {
3056
- value: "npm",
3057
- label: "npm",
3058
- hint: "Default Node.js package manager"
3059
- },
3060
- {
3061
- value: "yarn",
3062
- label: "yarn",
3063
- hint: "Classic yarn (script: yarn dev)"
3064
- },
3065
- {
3066
- value: "bun",
3067
- label: "bun",
3068
- hint: "Bun runtime + bun install/dev"
3069
- }
3070
- ]
3071
- });
3072
- if (p.isCancel(pmAnswerExisting)) {
3073
- p.outro(pc.red("Init cancelled."));
3074
- process.exit(0);
3075
- }
3076
- pm = pmAnswerExisting;
3077
- p.log.info(`Using ${pc.cyan(pm)} as package manager`);
3078
- const s2 = p.spinner();
3079
- s2.start("Installing dependencies");
3080
- try {
3081
- if (framework === "tanstack-start") {
3082
- exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/theme @farming-labs/tanstack-start`, cwd);
3083
- const devDeps = ["@tailwindcss/vite", "tailwindcss"];
3084
- if (useAlias) devDeps.push("vite-tsconfig-paths");
3085
- const allDeps = {
3086
- ...pkgJson.dependencies,
3087
- ...pkgJson.devDependencies
3088
- };
3089
- const missingDevDeps = devDeps.filter((d) => !allDeps[d]);
3090
- if (missingDevDeps.length > 0) exec(`${devInstallCommand(pm)} ${missingDevDeps.join(" ")}`, cwd);
3091
- } else if (framework === "sveltekit") exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-theme`, cwd);
3092
- else if (framework === "astro") {
3093
- const adapterPkg = getAstroAdapterPkg(cfg.astroAdapter ?? "vercel");
3094
- exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme ${adapterPkg}`, cwd);
3095
- } else if (framework === "nuxt") exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/nuxt @farming-labs/nuxt-theme`, cwd);
3096
- else {
3097
- exec(`${installCommand(pm)} @farming-labs/docs @farming-labs/next @farming-labs/theme`, cwd);
3098
- const devDeps = [
3099
- "@tailwindcss/postcss",
3100
- "postcss",
3101
- "tailwindcss",
3102
- "@types/mdx",
3103
- "@types/node"
3104
- ];
3105
- const allDeps = {
3106
- ...pkgJson.dependencies,
3107
- ...pkgJson.devDependencies
3108
- };
3109
- const missingDevDeps = devDeps.filter((d) => !allDeps[d]);
3110
- if (missingDevDeps.length > 0) exec(`${devInstallCommand(pm)} ${missingDevDeps.join(" ")}`, cwd);
3111
- }
3112
- } catch {
3113
- s2.stop("Failed to install dependencies");
3114
- p.log.error(`Dependency installation failed. Run the install command manually:
3115
- ${pc.cyan(`${installCommand(pm)} @farming-labs/docs`)}`);
3116
- p.outro(pc.yellow("Setup partially complete. Install deps and run dev server manually."));
3117
- process.exit(1);
3118
- }
3119
- s2.stop("Dependencies installed");
3120
- const startDev = await p.confirm({
3121
- message: "Start the dev server now?",
3122
- initialValue: true
3123
- });
3124
- if (p.isCancel(startDev) || !startDev) {
3125
- p.log.info(`You can start the dev server later with:
3126
- ${pc.cyan(`${pm === "yarn" ? "yarn" : pm + " run"} dev`)}`);
3127
- p.outro(pc.green("Done! Happy documenting."));
3128
- process.exit(0);
3129
- }
3130
- p.log.step("Starting dev server...");
3131
- const devCommand = framework === "tanstack-start" ? {
3132
- cmd: "npx",
3133
- args: ["vite", "dev"],
3134
- waitFor: "ready"
3135
- } : framework === "sveltekit" ? {
3136
- cmd: "npx",
3137
- args: ["vite", "dev"],
3138
- waitFor: "ready"
3139
- } : framework === "astro" ? {
3140
- cmd: "npx",
3141
- args: ["astro", "dev"],
3142
- waitFor: "ready"
3143
- } : framework === "nuxt" ? {
3144
- cmd: "npx",
3145
- args: ["nuxt", "dev"],
3146
- waitFor: "Local"
3147
- } : {
3148
- cmd: "npx",
3149
- args: [
3150
- "next",
3151
- "dev",
3152
- "--webpack"
3153
- ],
3154
- waitFor: "Ready"
3155
- };
3156
- const defaultPort = framework === "tanstack-start" ? "5173" : framework === "sveltekit" ? "5173" : framework === "astro" ? "4321" : framework === "nuxt" ? "3000" : "3000";
3157
- try {
3158
- const child = await spawnAndWaitFor(devCommand.cmd, devCommand.args, cwd, devCommand.waitFor, 6e4);
3159
- const url = `http://localhost:${defaultPort}/${entryPath}`;
3160
- console.log();
3161
- p.log.success(`Dev server is running! Your docs are live at:\n\n ${pc.cyan(pc.underline(url))}\n\n Press ${pc.dim("Ctrl+C")} to stop the server.`);
3162
- p.outro(pc.green("Happy documenting!"));
3163
- await new Promise((resolve) => {
3164
- child.on("close", () => resolve());
3165
- process.on("SIGINT", () => {
3166
- child.kill("SIGINT");
3167
- resolve();
3168
- });
3169
- process.on("SIGTERM", () => {
3170
- child.kill("SIGTERM");
3171
- resolve();
3172
- });
3173
- });
3174
- } catch {
3175
- const manualCmd = framework === "tanstack-start" ? "npx vite dev" : framework === "sveltekit" ? "npx vite dev" : framework === "astro" ? "npx astro dev" : framework === "nuxt" ? "npx nuxt dev" : "pnpm dev";
3176
- p.log.error(`Could not start dev server. Try running manually:
3177
- ${pc.cyan(manualCmd)}`);
3178
- p.outro(pc.yellow("Setup complete. Start the server manually."));
3179
- process.exit(1);
3180
- }
3181
- }
3182
- function getScaffoldContentRoots(cfg) {
3183
- return cfg.i18n?.locales?.length ? cfg.i18n.locales.map((locale) => `${cfg.entry}/${locale}`) : [cfg.entry];
3184
- }
3185
- function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
3186
- const appDir = cfg.nextAppDir ?? "app";
3187
- if (cfg.theme === "custom" && cfg.customThemeName) {
3188
- const baseName = cfg.customThemeName.replace(/\.(ts|css)$/i, "");
3189
- write(`themes/${baseName}.ts`, customThemeTsTemplate(baseName));
3190
- write(`themes/${baseName}.css`, customThemeCssTemplate(baseName));
3191
- }
3192
- write("docs.config.ts", docsConfigTemplate(cfg));
3193
- const existingNextConfig = readFileSafe(path.join(cwd, "next.config.ts")) ?? readFileSafe(path.join(cwd, "next.config.mjs")) ?? readFileSafe(path.join(cwd, "next.config.js"));
3194
- if (existingNextConfig) {
3195
- const configFile = fileExists(path.join(cwd, "next.config.ts")) ? "next.config.ts" : fileExists(path.join(cwd, "next.config.mjs")) ? "next.config.mjs" : "next.config.js";
3196
- const merged = nextConfigMergedTemplate(existingNextConfig);
3197
- if (merged !== existingNextConfig) {
3198
- writeFileSafe(path.join(cwd, configFile), merged, true);
3199
- written.push(configFile + " (updated)");
3200
- } else skipped.push(configFile + " (already configured)");
3201
- } else write("next.config.ts", nextConfigTemplate());
3202
- const rootLayoutPath = path.join(cwd, `${appDir}/layout.tsx`);
3203
- const existingRootLayout = readFileSafe(rootLayoutPath);
3204
- if (!existingRootLayout) write(`${appDir}/layout.tsx`, rootLayoutTemplate(cfg, globalCssRelPath), true);
3205
- else if (!existingRootLayout.includes("RootProvider")) {
3206
- const injected = injectRootProviderIntoLayout(existingRootLayout);
3207
- if (injected) {
3208
- writeFileSafe(rootLayoutPath, injected, true);
3209
- written.push(`${appDir}/layout.tsx (injected RootProvider)`);
3210
- } else skipped.push(`${appDir}/layout.tsx (could not inject RootProvider)`);
3211
- } else skipped.push(`${appDir}/layout.tsx (already has RootProvider)`);
3212
- const globalCssAbsPath = path.join(cwd, globalCssRelPath);
3213
- const existingGlobalCss = readFileSafe(globalCssAbsPath);
3214
- if (existingGlobalCss) {
3215
- const injected = injectCssImport(existingGlobalCss, cfg.theme, cfg.customThemeName, globalCssRelPath);
3216
- if (injected) {
3217
- writeFileSafe(globalCssAbsPath, injected, true);
3218
- written.push(globalCssRelPath + " (updated)");
3219
- } else skipped.push(globalCssRelPath + " (already configured)");
3220
- } else write(globalCssRelPath, globalCssTemplate(cfg.theme, cfg.customThemeName, globalCssRelPath));
3221
- write(`${appDir}/${cfg.entry}/layout.tsx`, docsLayoutTemplate(cfg));
3222
- if (cfg.apiReference) {
3223
- const apiReferencePage = `${appDir}/${cfg.apiReference.path}/[[...slug]]/page.tsx`;
3224
- write(apiReferencePage, nextApiReferencePageTemplate(cfg, apiReferencePage));
3225
- }
3226
- write("postcss.config.mjs", postcssConfigTemplate());
3227
- if (!fileExists(path.join(cwd, "tsconfig.json"))) write("tsconfig.json", tsconfigTemplate(cfg.useAlias));
3228
- if (cfg.i18n?.locales.length) {
3229
- write(`${appDir}/components/locale-doc-page.tsx`, nextLocaleDocPageTemplate(cfg.i18n.defaultLocale));
3230
- write(`${appDir}/${cfg.entry}/page.tsx`, nextLocalizedPageTemplate({
3231
- locales: cfg.i18n.locales,
3232
- defaultLocale: cfg.i18n.defaultLocale,
3233
- componentName: "DocsIndexPage",
3234
- helperImport: "../components/locale-doc-page",
3235
- pageImports: cfg.i18n.locales.map((locale) => ({
3236
- locale,
3237
- importPath: `./${locale}/page.mdx`
3238
- }))
3239
- }));
3240
- write(`${appDir}/${cfg.entry}/installation/page.tsx`, nextLocalizedPageTemplate({
3241
- locales: cfg.i18n.locales,
3242
- defaultLocale: cfg.i18n.defaultLocale,
3243
- componentName: "InstallationPage",
3244
- helperImport: "../../components/locale-doc-page",
3245
- pageImports: cfg.i18n.locales.map((locale) => ({
3246
- locale,
3247
- importPath: `../${locale}/installation/page.mdx`
3248
- }))
3249
- }));
3250
- write(`${appDir}/${cfg.entry}/quickstart/page.tsx`, nextLocalizedPageTemplate({
3251
- locales: cfg.i18n.locales,
3252
- defaultLocale: cfg.i18n.defaultLocale,
3253
- componentName: "QuickstartPage",
3254
- helperImport: "../../components/locale-doc-page",
3255
- pageImports: cfg.i18n.locales.map((locale) => ({
3256
- locale,
3257
- importPath: `../${locale}/quickstart/page.mdx`
3258
- }))
3259
- }));
3260
- for (const locale of cfg.i18n.locales) {
3261
- const base = `${appDir}/${cfg.entry}/${locale}`;
3262
- write(`${base}/page.mdx`, welcomePageTemplate(cfg));
3263
- write(`${base}/installation/page.mdx`, installationPageTemplate(cfg));
3264
- write(`${base}/quickstart/page.mdx`, quickstartPageTemplate(cfg));
3265
- }
3266
- return;
3267
- }
3268
- write(`${appDir}/${cfg.entry}/page.mdx`, welcomePageTemplate(cfg));
3269
- write(`${appDir}/${cfg.entry}/installation/page.mdx`, installationPageTemplate(cfg));
3270
- write(`${appDir}/${cfg.entry}/quickstart/page.mdx`, quickstartPageTemplate(cfg));
3271
- }
3272
- function scaffoldTanstackStart(cwd, cfg, globalCssRelPath, write, skipped, written) {
3273
- if (cfg.theme === "custom" && cfg.customThemeName) {
3274
- const baseName = cfg.customThemeName.replace(/\.(ts|css)$/i, "");
3275
- write(`themes/${baseName}.ts`, customThemeTsTemplate(baseName));
3276
- write(`themes/${baseName}.css`, customThemeCssTemplate(baseName));
3277
- }
3278
- write("docs.config.ts", tanstackDocsConfigTemplate(cfg));
3279
- write("src/lib/docs.server.ts", tanstackDocsServerTemplate());
3280
- write("src/lib/docs.functions.ts", tanstackDocsFunctionsTemplate());
3281
- const routeDir = getTanstackDocsRouteDir(cfg.entry);
3282
- const docsIndexRoute = `${routeDir}/index.tsx`;
3283
- const docsCatchAllRoute = `${routeDir}/$.tsx`;
3284
- const apiRoute = "src/routes/api/docs.ts";
3285
- const publicRoute = "src/routes/$.ts";
3286
- write(docsIndexRoute, tanstackDocsIndexRouteTemplate({
3287
- entry: cfg.entry,
3288
- filePath: docsIndexRoute,
3289
- useAlias: cfg.useAlias,
3290
- projectName: cfg.projectName
3291
- }));
3292
- write(docsCatchAllRoute, tanstackDocsCatchAllRouteTemplate({
3293
- entry: cfg.entry,
3294
- filePath: docsCatchAllRoute,
3295
- useAlias: cfg.useAlias,
3296
- projectName: cfg.projectName
3297
- }));
3298
- write(apiRoute, tanstackApiDocsRouteTemplate(cfg.useAlias, apiRoute));
3299
- write(publicRoute, tanstackDocsPublicRouteTemplate(cfg.useAlias, publicRoute, cfg.entry));
3300
- if (cfg.apiReference) {
3301
- const apiReferenceIndexRoute = `src/routes/${cfg.apiReference.path}.index.ts`;
3302
- const apiReferenceCatchAllRoute = `src/routes/${cfg.apiReference.path}.$.ts`;
3303
- write(apiReferenceIndexRoute, tanstackApiReferenceRouteTemplate({
3304
- filePath: apiReferenceIndexRoute,
3305
- useAlias: cfg.useAlias,
3306
- apiReferencePath: cfg.apiReference.path,
3307
- catchAll: false
3308
- }));
3309
- write(apiReferenceCatchAllRoute, tanstackApiReferenceRouteTemplate({
3310
- filePath: apiReferenceCatchAllRoute,
3311
- useAlias: cfg.useAlias,
3312
- apiReferencePath: cfg.apiReference.path,
3313
- catchAll: true
3314
- }));
3315
- }
3316
- const rootRoutePath = path.join(cwd, "src/routes/__root.tsx");
3317
- const existingRootRoute = readFileSafe(rootRoutePath);
3318
- if (!existingRootRoute) write("src/routes/__root.tsx", tanstackRootRouteTemplate(globalCssRelPath), true);
3319
- else if (!existingRootRoute.includes("RootProvider")) {
3320
- const injected = injectTanstackRootProviderIntoRoute(existingRootRoute);
3321
- if (injected) {
3322
- writeFileSafe(rootRoutePath, injected, true);
3323
- written.push("src/routes/__root.tsx (injected RootProvider)");
3324
- } else skipped.push("src/routes/__root.tsx (could not inject RootProvider)");
3325
- } else skipped.push("src/routes/__root.tsx (already has RootProvider)");
3326
- const viteConfigRel = fileExists(path.join(cwd, "vite.config.ts")) ? "vite.config.ts" : fileExists(path.join(cwd, "vite.config.mts")) ? "vite.config.mts" : fileExists(path.join(cwd, "vite.config.js")) ? "vite.config.js" : "vite.config.ts";
3327
- const viteConfigPath = path.join(cwd, viteConfigRel);
3328
- const existingViteConfig = readFileSafe(viteConfigPath);
3329
- if (!existingViteConfig) write(viteConfigRel, tanstackViteConfigTemplate(cfg.useAlias), true);
3330
- else {
3331
- const injected = injectTanstackVitePlugins(existingViteConfig, cfg.useAlias);
3332
- if (injected) {
3333
- writeFileSafe(viteConfigPath, injected, true);
3334
- written.push(`${viteConfigRel} (updated)`);
3335
- } else skipped.push(`${viteConfigRel} (already configured)`);
3336
- }
3337
- const globalCssAbsPath = path.join(cwd, globalCssRelPath);
3338
- const existingGlobalCss = readFileSafe(globalCssAbsPath);
3339
- if (existingGlobalCss) {
3340
- const injected = injectCssImport(existingGlobalCss, cfg.theme, cfg.customThemeName, globalCssRelPath);
3341
- if (injected) {
3342
- writeFileSafe(globalCssAbsPath, injected, true);
3343
- written.push(globalCssRelPath + " (updated)");
3344
- } else skipped.push(globalCssRelPath + " (already configured)");
3345
- } else write(globalCssRelPath, globalCssTemplate(cfg.theme, cfg.customThemeName, globalCssRelPath));
3346
- for (const base of getScaffoldContentRoots(cfg)) {
3347
- write(`${base}/page.mdx`, tanstackWelcomePageTemplate(cfg));
3348
- write(`${base}/installation/page.mdx`, tanstackInstallationPageTemplate(cfg));
3349
- write(`${base}/quickstart/page.mdx`, tanstackQuickstartPageTemplate(cfg));
3350
- }
3351
- }
3352
- function scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written) {
3353
- if (cfg.theme === "custom" && cfg.customThemeName) {
3354
- const baseName = cfg.customThemeName.replace(/\.(ts|css)$/i, "");
3355
- write(`themes/${baseName}.ts`, customThemeTsTemplate(baseName));
3356
- write(`themes/${baseName}.css`, customThemeCssTemplate(baseName));
3357
- }
3358
- write("src/lib/docs.config.ts", svelteDocsConfigTemplate(cfg));
3359
- write("src/lib/docs.server.ts", svelteDocsServerTemplate(cfg));
3360
- write(`src/routes/${cfg.entry}/+layout.svelte`, svelteDocsLayoutTemplate(cfg));
3361
- write(`src/routes/${cfg.entry}/+layout.server.js`, svelteDocsLayoutServerTemplate(cfg));
3362
- write(`src/routes/${cfg.entry}/[...slug]/+page.svelte`, svelteDocsPageTemplate(cfg));
3363
- if (cfg.i18n?.locales.length) write(`src/routes/${cfg.entry}/+page.svelte`, svelteDocsPageTemplate(cfg));
3364
- const apiDocsRoute = "src/routes/api/docs/+server.ts";
3365
- const publicHook = "src/hooks.server.ts";
3366
- write(apiDocsRoute, svelteDocsApiRouteTemplate(apiDocsRoute, cfg.useAlias));
3367
- const publicHookPath = path.join(cwd, publicHook);
3368
- const existingPublicHook = readFileSafe(publicHookPath);
3369
- if (existingPublicHook) {
3370
- const injected = injectSvelteDocsPublicHook(existingPublicHook, publicHook, cfg.useAlias);
3371
- if (injected) {
3372
- writeFileSafe(publicHookPath, injected, true);
3373
- written.push(`${publicHook} (composed docs public hook)`);
3374
- } else skipped.push(`${publicHook} (already configured or could not compose docs public hook)`);
3375
- } else write(publicHook, svelteDocsPublicHookTemplate(publicHook, cfg.useAlias));
3376
- if (cfg.apiReference) {
3377
- const apiReferenceIndexRoute = `src/routes/${cfg.apiReference.path}/+server.ts`;
3378
- const apiReferenceCatchAllRoute = `src/routes/${cfg.apiReference.path}/[...slug]/+server.ts`;
3379
- write(apiReferenceIndexRoute, svelteApiReferenceRouteTemplate(apiReferenceIndexRoute, cfg.useAlias));
3380
- write(apiReferenceCatchAllRoute, svelteApiReferenceRouteTemplate(apiReferenceCatchAllRoute, cfg.useAlias));
3381
- }
3382
- if (!readFileSafe(path.join(cwd, "src/routes/+layout.svelte"))) write("src/routes/+layout.svelte", svelteRootLayoutTemplate(globalCssRelPath));
3383
- const globalCssAbsPath = path.join(cwd, globalCssRelPath);
3384
- const existingGlobalCss = readFileSafe(globalCssAbsPath);
3385
- const cssTheme = {
3386
- fumadocs: "fumadocs",
3387
- darksharp: "darksharp",
3388
- "pixel-border": "pixel-border",
3389
- colorful: "colorful",
3390
- darkbold: "darkbold",
3391
- shiny: "shiny",
3392
- greentree: "greentree",
3393
- concrete: "concrete",
3394
- "command-grid": "command-grid",
3395
- hardline: "hardline",
3396
- default: "fumadocs"
3397
- }[cfg.theme] || "fumadocs";
3398
- if (existingGlobalCss) {
3399
- const injected = cfg.theme === "custom" && cfg.customThemeName ? injectSvelteCssImport(existingGlobalCss, "custom", cfg.customThemeName, globalCssRelPath) : injectSvelteCssImport(existingGlobalCss, cssTheme);
3400
- if (injected) {
3401
- writeFileSafe(globalCssAbsPath, injected, true);
3402
- written.push(globalCssRelPath + " (updated)");
3403
- } else skipped.push(globalCssRelPath + " (already configured)");
3404
- } else write(globalCssRelPath, cfg.theme === "custom" && cfg.customThemeName ? svelteGlobalCssTemplate("custom", cfg.customThemeName, globalCssRelPath) : svelteGlobalCssTemplate(cssTheme));
3405
- for (const base of getScaffoldContentRoots(cfg)) {
3406
- write(`${base}/page.md`, svelteWelcomePageTemplate(cfg));
3407
- write(`${base}/installation/page.md`, svelteInstallationPageTemplate(cfg));
3408
- write(`${base}/quickstart/page.md`, svelteQuickstartPageTemplate(cfg));
3409
- }
3410
- }
3411
- function scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written) {
3412
- if (cfg.theme === "custom" && cfg.customThemeName) {
3413
- const baseName = cfg.customThemeName.replace(/\.(ts|css)$/i, "");
3414
- write(`themes/${baseName}.ts`, customThemeTsTemplate(baseName));
3415
- write(`themes/${baseName}.css`, customThemeCssTemplate(baseName));
3416
- }
3417
- write("src/lib/docs.config.ts", astroDocsConfigTemplate(cfg));
3418
- write("src/lib/docs.server.ts", astroDocsServerTemplate(cfg));
3419
- if (!fileExists(path.join(cwd, "astro.config.mjs")) && !fileExists(path.join(cwd, "astro.config.ts"))) write("astro.config.mjs", astroConfigTemplate(cfg.astroAdapter ?? "vercel"));
3420
- write(`src/pages/${cfg.entry}/index.astro`, astroDocsIndexTemplate(cfg));
3421
- write(`src/pages/${cfg.entry}/[...slug].astro`, astroDocsPageTemplate(cfg));
3422
- write(`src/pages/api/${cfg.entry}.ts`, astroApiRouteTemplate(cfg));
3423
- const middleware = "src/middleware.ts";
3424
- const middlewarePath = path.join(cwd, middleware);
3425
- const existingMiddleware = readFileSafe(middlewarePath);
3426
- if (existingMiddleware) {
3427
- const injected = injectAstroDocsMiddleware(existingMiddleware, middleware, cfg.useAlias);
3428
- if (injected) {
3429
- writeFileSafe(middlewarePath, injected, true);
3430
- written.push(`${middleware} (composed docs public middleware)`);
3431
- } else skipped.push(`${middleware} (already configured or could not compose docs public middleware)`);
3432
- } else write(middleware, astroDocsMiddlewareTemplate(middleware, cfg.useAlias));
3433
- if (cfg.apiReference) {
3434
- const apiReferenceIndexRoute = `src/pages/${cfg.apiReference.path}/index.ts`;
3435
- const apiReferenceCatchAllRoute = `src/pages/${cfg.apiReference.path}/[...slug].ts`;
3436
- write(apiReferenceIndexRoute, astroApiReferenceRouteTemplate(apiReferenceIndexRoute));
3437
- write(apiReferenceCatchAllRoute, astroApiReferenceRouteTemplate(apiReferenceCatchAllRoute));
3438
- }
3439
- const globalCssAbsPath = path.join(cwd, globalCssRelPath);
3440
- const existingGlobalCss = readFileSafe(globalCssAbsPath);
3441
- const cssTheme = {
3442
- fumadocs: "fumadocs",
3443
- darksharp: "darksharp",
3444
- "pixel-border": "pixel-border",
3445
- colorful: "colorful",
3446
- darkbold: "darkbold",
3447
- shiny: "shiny",
3448
- greentree: "greentree",
3449
- concrete: "concrete",
3450
- "command-grid": "command-grid",
3451
- hardline: "hardline",
3452
- default: "fumadocs"
3453
- }[cfg.theme] || "fumadocs";
3454
- if (existingGlobalCss) {
3455
- const injected = cfg.theme === "custom" && cfg.customThemeName ? injectAstroCssImport(existingGlobalCss, "custom", cfg.customThemeName, globalCssRelPath) : injectAstroCssImport(existingGlobalCss, cssTheme);
3456
- if (injected) {
3457
- writeFileSafe(globalCssAbsPath, injected, true);
3458
- written.push(globalCssRelPath + " (updated)");
3459
- } else skipped.push(globalCssRelPath + " (already configured)");
3460
- } else write(globalCssRelPath, cfg.theme === "custom" && cfg.customThemeName ? astroGlobalCssTemplate("custom", cfg.customThemeName, globalCssRelPath) : astroGlobalCssTemplate(cssTheme));
3461
- for (const base of getScaffoldContentRoots(cfg)) {
3462
- write(`${base}/page.md`, astroWelcomePageTemplate(cfg));
3463
- write(`${base}/installation/page.md`, astroInstallationPageTemplate(cfg));
3464
- write(`${base}/quickstart/page.md`, astroQuickstartPageTemplate(cfg));
3465
- }
3466
- }
3467
- function scaffoldNuxt(cwd, cfg, globalCssRelPath, write, skipped, written) {
3468
- if (cfg.theme === "custom" && cfg.customThemeName) {
3469
- const baseName = cfg.customThemeName.replace(/\.(ts|css)$/i, "");
3470
- write(`themes/${baseName}.ts`, customThemeTsTemplate(baseName));
3471
- write(`themes/${baseName}.css`, customThemeCssTemplate(baseName));
3472
- }
3473
- write("docs.config.ts", nuxtDocsConfigTemplate(cfg));
3474
- write("server/api/docs.ts", nuxtServerApiDocsRouteTemplate(cfg));
3475
- write("server/middleware/docs-public.ts", nuxtServerDocsPublicMiddlewareTemplate(cfg));
3476
- write(`pages/${cfg.entry}/[[...slug]].vue`, nuxtDocsPageTemplate(cfg));
3477
- if (cfg.apiReference) {
3478
- const apiReferenceIndexRoute = `server/routes/${cfg.apiReference.path}/index.ts`;
3479
- const apiReferenceCatchAllRoute = `server/routes/${cfg.apiReference.path}/[...slug].ts`;
3480
- write(apiReferenceIndexRoute, nuxtServerApiReferenceRouteTemplate(apiReferenceIndexRoute, cfg.useAlias));
3481
- write(apiReferenceCatchAllRoute, nuxtServerApiReferenceRouteTemplate(apiReferenceCatchAllRoute, cfg.useAlias));
3482
- }
3483
- if (!fileExists(path.join(cwd, "nuxt.config.ts")) && !fileExists(path.join(cwd, "nuxt.config.js"))) write("nuxt.config.ts", nuxtConfigTemplate(cfg));
3484
- const cssTheme = {
3485
- fumadocs: "fumadocs",
3486
- darksharp: "darksharp",
3487
- "pixel-border": "pixel-border",
3488
- colorful: "colorful",
3489
- darkbold: "darkbold",
3490
- shiny: "shiny",
3491
- greentree: "greentree",
3492
- concrete: "concrete",
3493
- "command-grid": "command-grid",
3494
- hardline: "hardline",
3495
- default: "fumadocs"
3496
- }[cfg.theme] || "fumadocs";
3497
- const globalCssAbsPath = path.join(cwd, globalCssRelPath);
3498
- const existingGlobalCss = readFileSafe(globalCssAbsPath);
3499
- if (existingGlobalCss) {
3500
- const injected = cfg.theme === "custom" && cfg.customThemeName ? injectNuxtCssImport(existingGlobalCss, "custom", cfg.customThemeName, globalCssRelPath) : injectNuxtCssImport(existingGlobalCss, cssTheme);
3501
- if (injected) {
3502
- writeFileSafe(globalCssAbsPath, injected, true);
3503
- written.push(globalCssRelPath + " (updated)");
3504
- } else skipped.push(globalCssRelPath + " (already configured)");
3505
- } else write(globalCssRelPath, cfg.theme === "custom" && cfg.customThemeName ? nuxtGlobalCssTemplate("custom", cfg.customThemeName, globalCssRelPath) : nuxtGlobalCssTemplate(cssTheme));
3506
- for (const base of getScaffoldContentRoots(cfg)) {
3507
- write(`${base}/page.md`, nuxtWelcomePageTemplate(cfg));
3508
- write(`${base}/installation/page.md`, nuxtInstallationPageTemplate(cfg));
3509
- write(`${base}/quickstart/page.md`, nuxtQuickstartPageTemplate(cfg));
3510
- }
3511
- }
3512
-
3513
- //#endregion
3514
- export { init };
2355
+ export { svelteDocsPublicHookTemplate as $, nextConfigMergedTemplate as A, nuxtServerApiDocsRouteTemplate as B, injectRootProviderIntoLayout as C, injectTanstackVitePlugins as D, injectTanstackRootProviderIntoRoute as E, nuxtDocsConfigTemplate as F, quickstartPageTemplate as G, nuxtServerDocsPublicMiddlewareTemplate as H, nuxtDocsPageTemplate as I, svelteDocsApiRouteTemplate as J, rootLayoutTemplate as K, nuxtGlobalCssTemplate as L, nextLocaleDocPageTemplate as M, nextLocalizedPageTemplate as N, installationPageTemplate as O, nuxtConfigTemplate as P, svelteDocsPageTemplate as Q, nuxtInstallationPageTemplate as R, injectNuxtCssImport as S, injectSvelteDocsPublicHook as T, nuxtWelcomePageTemplate as U, nuxtServerApiReferenceRouteTemplate as V, postcssConfigTemplate as W, svelteDocsLayoutServerTemplate as X, svelteDocsConfigTemplate as Y, svelteDocsLayoutTemplate as Z, getAstroAdapterPkg as _, tanstackViteConfigTemplate as _t, astroDocsIndexTemplate as a, svelteWelcomePageTemplate as at, injectAstroDocsMiddleware as b, welcomePageTemplate as bt, astroDocsServerTemplate as c, tanstackDocsCatchAllRouteTemplate as ct, astroQuickstartPageTemplate as d, tanstackDocsIndexRouteTemplate as dt, svelteDocsServerTemplate as et, astroWelcomePageTemplate as f, tanstackDocsPublicRouteTemplate as ft, docsLayoutTemplate as g, tanstackRootRouteTemplate as gt, docsConfigTemplate as h, tanstackQuickstartPageTemplate as ht, astroDocsConfigTemplate as i, svelteRootLayoutTemplate as it, nextConfigTemplate as j, nextApiReferencePageTemplate as k, astroGlobalCssTemplate as l, tanstackDocsConfigTemplate as lt, customThemeTsTemplate as m, tanstackInstallationPageTemplate as mt, astroApiRouteTemplate as n, svelteInstallationPageTemplate as nt, astroDocsMiddlewareTemplate as o, tanstackApiDocsRouteTemplate as ot, customThemeCssTemplate as p, tanstackDocsServerTemplate as pt, svelteApiReferenceRouteTemplate as q, astroConfigTemplate as r, svelteQuickstartPageTemplate as rt, astroDocsPageTemplate as s, tanstackApiReferenceRouteTemplate as st, astroApiReferenceRouteTemplate as t, svelteGlobalCssTemplate as tt, astroInstallationPageTemplate as u, tanstackDocsFunctionsTemplate as ut, globalCssTemplate as v, tanstackWelcomePageTemplate as vt, injectSvelteCssImport as w, injectCssImport as x, injectAstroCssImport as y, tsconfigTemplate as yt, nuxtQuickstartPageTemplate as z };