@farming-labs/docs 0.0.2-beta.1 → 0.0.2-beta.3

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.
@@ -53,6 +53,24 @@ function readFileSafe(filePath) {
53
53
  if (!fs.existsSync(filePath)) return null;
54
54
  return fs.readFileSync(filePath, "utf-8");
55
55
  }
56
+ /** Common locations where global CSS files live in Next.js projects. */
57
+ const GLOBAL_CSS_CANDIDATES = [
58
+ "app/globals.css",
59
+ "app/global.css",
60
+ "src/app/globals.css",
61
+ "src/app/global.css",
62
+ "styles/globals.css",
63
+ "styles/global.css",
64
+ "src/styles/globals.css",
65
+ "src/styles/global.css"
66
+ ];
67
+ /**
68
+ * Find existing global CSS files in the project.
69
+ * Returns relative paths that exist.
70
+ */
71
+ function detectGlobalCssFiles(cwd) {
72
+ return GLOBAL_CSS_CANDIDATES.filter((rel) => fs.existsSync(path.join(cwd, rel)));
73
+ }
56
74
  /**
57
75
  * Run a shell command synchronously, inheriting stdio.
58
76
  */
@@ -151,12 +169,16 @@ function nextConfigMergedTemplate(existingContent) {
151
169
  }
152
170
  return lines.join("\n");
153
171
  }
154
- function rootLayoutTemplate() {
172
+ function rootLayoutTemplate(globalCssRelPath = "app/globals.css") {
173
+ let cssImport;
174
+ if (globalCssRelPath.startsWith("app/")) cssImport = "./" + globalCssRelPath.slice(4);
175
+ else if (globalCssRelPath.startsWith("src/app/")) cssImport = "./" + globalCssRelPath.slice(8);
176
+ else cssImport = "../" + globalCssRelPath;
155
177
  return `\
156
178
  import type { Metadata } from "next";
157
179
  import { RootProvider } from "@farming-labs/fumadocs";
158
180
  import docsConfig from "@/docs.config";
159
- import "./global.css";
181
+ import "${cssImport}";
160
182
 
161
183
  export const metadata: Metadata = {
162
184
  title: {
@@ -458,6 +480,40 @@ async function init() {
458
480
  process.exit(0);
459
481
  }
460
482
  const entryPath = entry;
483
+ const detectedCssFiles = detectGlobalCssFiles(cwd);
484
+ let globalCssRelPath;
485
+ if (detectedCssFiles.length === 1) {
486
+ globalCssRelPath = detectedCssFiles[0];
487
+ p.log.info(`Found global CSS at ${pc.cyan(globalCssRelPath)}`);
488
+ } else if (detectedCssFiles.length > 1) {
489
+ const picked = await p.select({
490
+ message: "Multiple global CSS files found. Which one should we use?",
491
+ options: detectedCssFiles.map((f) => ({
492
+ value: f,
493
+ label: f
494
+ }))
495
+ });
496
+ if (p.isCancel(picked)) {
497
+ p.outro(pc.red("Init cancelled."));
498
+ process.exit(0);
499
+ }
500
+ globalCssRelPath = picked;
501
+ } else {
502
+ const cssPath = await p.text({
503
+ message: "Where is your global CSS file?",
504
+ placeholder: "app/globals.css",
505
+ defaultValue: "app/globals.css",
506
+ validate: (value) => {
507
+ if (!value) return "CSS file path is required";
508
+ if (!value.endsWith(".css")) return "Path must end with .css";
509
+ }
510
+ });
511
+ if (p.isCancel(cssPath)) {
512
+ p.outro(pc.red("Init cancelled."));
513
+ process.exit(0);
514
+ }
515
+ globalCssRelPath = cssPath;
516
+ }
461
517
  const pkgJson = JSON.parse(readFileSafe(path.join(cwd, "package.json")));
462
518
  const cfg = {
463
519
  entry: entryPath,
@@ -482,16 +538,16 @@ async function init() {
482
538
  written.push(configFile + " (updated)");
483
539
  } else skipped.push(configFile + " (already configured)");
484
540
  } else write("next.config.ts", nextConfigTemplate());
485
- write("app/layout.tsx", rootLayoutTemplate());
486
- const globalCssPath = path.join(cwd, "app/global.css");
487
- const existingGlobalCss = readFileSafe(globalCssPath);
541
+ write("app/layout.tsx", rootLayoutTemplate(globalCssRelPath));
542
+ const globalCssAbsPath = path.join(cwd, globalCssRelPath);
543
+ const existingGlobalCss = readFileSafe(globalCssAbsPath);
488
544
  if (existingGlobalCss) {
489
545
  const injected = injectCssImport(existingGlobalCss, theme);
490
546
  if (injected) {
491
- writeFileSafe(globalCssPath, injected, true);
492
- written.push("app/global.css (updated)");
493
- } else skipped.push("app/global.css (already configured)");
494
- } else write("app/global.css", globalCssTemplate(theme));
547
+ writeFileSafe(globalCssAbsPath, injected, true);
548
+ written.push(globalCssRelPath + " (updated)");
549
+ } else skipped.push(globalCssRelPath + " (already configured)");
550
+ } else write(globalCssRelPath, globalCssTemplate(theme));
495
551
  write(`app/${entryPath}/layout.tsx`, docsLayoutTemplate());
496
552
  write("postcss.config.mjs", postcssConfigTemplate());
497
553
  if (!fileExists(path.join(cwd, "tsconfig.json"))) write("tsconfig.json", tsconfigTemplate());
@@ -587,7 +643,7 @@ function printHelp() {
587
643
  ${pc.bold("@farming-labs/docs")} — Documentation framework CLI
588
644
 
589
645
  ${pc.dim("Usage:")}
590
- farming-docs ${pc.cyan("<command>")}
646
+ npx @farming-labs/docs ${pc.cyan("<command>")}
591
647
 
592
648
  ${pc.dim("Commands:")}
593
649
  ${pc.cyan("init")} Scaffold docs in your project (default)
package/dist/index.d.mts CHANGED
@@ -405,11 +405,71 @@ interface PageActionsConfig {
405
405
  */
406
406
  position?: "above-title" | "below-title";
407
407
  }
408
+ /**
409
+ * GitHub repository configuration for "Edit on GitHub" links
410
+ * and source file references.
411
+ *
412
+ * @example
413
+ * ```ts
414
+ * // Simple repo (not a monorepo)
415
+ * github: {
416
+ * url: "https://github.com/Kinfe123/my-docs",
417
+ * }
418
+ *
419
+ * // Monorepo — docs site lives in "website/" subdirectory
420
+ * github: {
421
+ * url: "https://github.com/farming-labs/docs",
422
+ * directory: "website",
423
+ * branch: "main",
424
+ * }
425
+ * ```
426
+ *
427
+ * Or as a simple string (branch defaults to "main", no directory prefix):
428
+ * ```ts
429
+ * github: "https://github.com/Kinfe123/my-docs"
430
+ * ```
431
+ */
432
+ interface GithubConfig {
433
+ /** Repository URL (e.g. "https://github.com/farming-labs/docs") */
434
+ url: string;
435
+ /** Branch name. @default "main" */
436
+ branch?: string;
437
+ /**
438
+ * Subdirectory inside the repo where the docs site lives.
439
+ * Use this for monorepos where the docs app is not at the repo root.
440
+ *
441
+ * @example "website" → links point to `website/app/docs/…/page.mdx`
442
+ */
443
+ directory?: string;
444
+ }
408
445
  interface DocsConfig {
409
446
  /** Entry folder for docs (e.g. "docs" → /docs) */
410
447
  entry: string;
411
448
  /** Theme configuration - single source of truth for UI */
412
449
  theme?: DocsTheme;
450
+ /**
451
+ * GitHub repository URL or config. Enables "Edit on GitHub" links
452
+ * on each docs page footer, pointing to the source `.mdx` file.
453
+ *
454
+ * @example
455
+ * ```ts
456
+ * // Simple — branch defaults to "main"
457
+ * github: "https://github.com/Kinfe123/my-docs"
458
+ *
459
+ * // Monorepo — docs site lives in "website/" subdirectory
460
+ * github: {
461
+ * url: "https://github.com/farming-labs/docs",
462
+ * directory: "website",
463
+ * }
464
+ *
465
+ * // Custom branch
466
+ * github: {
467
+ * url: "https://github.com/Kinfe123/my-docs",
468
+ * branch: "develop",
469
+ * }
470
+ * ```
471
+ */
472
+ github?: string | GithubConfig;
413
473
  /**
414
474
  * Sidebar navigation header.
415
475
  * Customise the title shown at the top of the sidebar.
@@ -594,4 +654,4 @@ declare function resolveTitle(pageTitle: string, metadata?: DocsMetadata): strin
594
654
  */
595
655
  declare function resolveOGImage(page: PageFrontmatter, ogConfig?: OGConfig, baseUrl?: string): string | undefined;
596
656
  //#endregion
597
- export { type BreadcrumbConfig, type CopyMarkdownConfig, type DocsConfig, type DocsMetadata, type DocsNav, type DocsTheme, type FontStyle, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type PageActionsConfig, type PageFrontmatter, type SidebarConfig, type ThemeToggleConfig, type TypographyConfig, type UIConfig, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
657
+ export { 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 };
package/dist/index.mjs CHANGED
@@ -7,6 +7,7 @@ function defineDocs(config) {
7
7
  entry: config.entry ?? "docs",
8
8
  theme: config.theme,
9
9
  nav: config.nav,
10
+ github: config.github,
10
11
  themeToggle: config.themeToggle,
11
12
  breadcrumb: config.breadcrumb,
12
13
  sidebar: config.sidebar,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/docs",
3
- "version": "0.0.2-beta.1",
3
+ "version": "0.0.2-beta.3",
4
4
  "description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -14,7 +14,7 @@
14
14
  }
15
15
  },
16
16
  "bin": {
17
- "farming-docs": "./dist/cli/index.mjs"
17
+ "docs": "./dist/cli/index.mjs"
18
18
  },
19
19
  "files": [
20
20
  "dist"