doccupine 0.0.2 → 0.0.4
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/README.md +8 -31
- package/dist/index.js +189 -144
- package/dist/templates/commands.mdx.d.ts +1 -0
- package/dist/templates/commands.mdx.js +48 -0
- package/dist/templates/home.mdx.d.ts +1 -0
- package/dist/templates/home.mdx.js +44 -0
- package/dist/templates/homemdx.d.ts +1 -0
- package/dist/templates/homemdx.js +59 -0
- package/dist/templates/next.config.d.ts +1 -0
- package/dist/templates/next.config.js +11 -0
- package/dist/templates/package.d.ts +1 -0
- package/dist/templates/package.js +34 -0
- package/dist/templates/tsconfig.d.ts +1 -0
- package/dist/templates/tsconfig.js +24 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,6 +6,13 @@ Doccupine is a free and open-source document management system that allows you t
|
|
|
6
6
|
|
|
7
7
|
Doccupine is built on open standards, enabling customization and extensibility for different documentation needs. You stay in control of your content, with the option to host docs yourself and tailor the website’s look and features to match your organization’s requirements.
|
|
8
8
|
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 📝 Markdown-based content
|
|
12
|
+
- 📦 Built-in file structure
|
|
13
|
+
- ⚡ Live Preview & Auto-Update
|
|
14
|
+
- 🚀 Easy Deployment
|
|
15
|
+
|
|
9
16
|
## Getting Started
|
|
10
17
|
|
|
11
18
|
To get started with Doccupine, make sure you have [Node.js](https://nodejs.org) and npm installed on your machine. Then, follow these steps:
|
|
@@ -23,38 +30,8 @@ After selecting the directory, Doccupine will ask you to enter the name of the d
|
|
|
23
30
|
|
|
24
31
|
This will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.
|
|
25
32
|
|
|
26
|
-
- **Generate the website:**
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
npx doccupine build
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
This will generate the build files for your documentation website without starting the development server. You can then deploy the generated files to a hosting service of your choice.
|
|
33
|
-
|
|
34
|
-
## Features
|
|
35
|
-
|
|
36
|
-
- 📝 Markdown-based content
|
|
37
|
-
- 📦 Built-in file structure
|
|
38
|
-
- ⚡ Live Preview & Auto-Update
|
|
39
|
-
- 🚀 Easy Deployment
|
|
40
|
-
|
|
41
33
|
## Start documenting
|
|
42
34
|
|
|
43
|
-
Start documenting your project by
|
|
44
|
-
|
|
45
|
-
```text
|
|
46
|
-
---
|
|
47
|
-
title: "Home"
|
|
48
|
-
description: "This is my first Doccupine project"
|
|
49
|
-
date: "2025-01-15"
|
|
50
|
-
category: "General"
|
|
51
|
-
categoryOrder: 0
|
|
52
|
-
order: 0
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
# Home
|
|
56
|
-
|
|
57
|
-
This is some **markdown** content with MDX support.
|
|
58
|
-
```
|
|
35
|
+
Start documenting your project by editing the **index.mdx** file in the choosen MDX directory.
|
|
59
36
|
|
|
60
37
|
In your MDX directory, you can structure your content using folders and files. Doccupine will automatically generate a navigation menu based on the configured categories and order.
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,9 @@ import matter from "gray-matter";
|
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
import prompts from "prompts";
|
|
9
9
|
import { gitignoreTemplate } from "./templates/gitignore.js";
|
|
10
|
-
import {
|
|
10
|
+
import { packageJsonTemplate } from "./templates/package.js";
|
|
11
|
+
import { nextConfigTemplate } from "./templates/next.config.js";
|
|
12
|
+
import { tsconfigTemplate } from "./templates/tsconfig.js";
|
|
11
13
|
import { notFoundTemplate } from "./templates/not-found.js";
|
|
12
14
|
import { layoutTemplate } from "./templates/layout.js";
|
|
13
15
|
import { themeTemplate } from "./templates/theme.js";
|
|
@@ -24,6 +26,75 @@ import { clickOutsideTemplate } from "./templates/components/ClickOutside.js";
|
|
|
24
26
|
import { docsTemplate } from "./templates/components/Docs.js";
|
|
25
27
|
import { orderNavItemsTemplate } from "./templates/utils/orderNavItems.js";
|
|
26
28
|
import { sideBarTemplate } from "./templates/components/SideBar.js";
|
|
29
|
+
import { homeMdxTemplate } from "./templates/home.mdx.js";
|
|
30
|
+
import { commandsMdxTemplate } from "./templates/commands.mdx.js";
|
|
31
|
+
class ConfigManager {
|
|
32
|
+
configPath;
|
|
33
|
+
constructor(configPath = "doccupine.json") {
|
|
34
|
+
this.configPath = path.resolve(process.cwd(), configPath);
|
|
35
|
+
}
|
|
36
|
+
async loadConfig() {
|
|
37
|
+
try {
|
|
38
|
+
if (await fs.pathExists(this.configPath)) {
|
|
39
|
+
const configContent = await fs.readFile(this.configPath, "utf8");
|
|
40
|
+
const config = JSON.parse(configContent);
|
|
41
|
+
console.log(chalk.blue("📄 Using existing configuration from doccupine.json"));
|
|
42
|
+
return config;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.warn(chalk.yellow("⚠️ Error reading config file, will create new one"));
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
async saveConfig(config) {
|
|
51
|
+
try {
|
|
52
|
+
await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), "utf8");
|
|
53
|
+
console.log(chalk.green("💾 Configuration saved to doccupine.json"));
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error(chalk.red("❌ Error saving config file:"), error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async promptForConfig(existingConfig) {
|
|
60
|
+
const questions = [
|
|
61
|
+
{
|
|
62
|
+
type: "text",
|
|
63
|
+
name: "watchDir",
|
|
64
|
+
message: "Enter directory to watch for MDX files:",
|
|
65
|
+
initial: existingConfig?.watchDir || "docs",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: "text",
|
|
69
|
+
name: "outputDir",
|
|
70
|
+
message: "Enter output directory for Next.js app:",
|
|
71
|
+
initial: existingConfig?.outputDir || "nextjs-app",
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
const { watchDir, outputDir } = (await prompts(questions));
|
|
75
|
+
return {
|
|
76
|
+
watchDir: path.resolve(process.cwd(), watchDir),
|
|
77
|
+
outputDir: path.resolve(process.cwd(), outputDir),
|
|
78
|
+
port: existingConfig?.port || "3000",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async getConfig(options = {}) {
|
|
82
|
+
let config = null;
|
|
83
|
+
if (!options.reset) {
|
|
84
|
+
config = await this.loadConfig();
|
|
85
|
+
}
|
|
86
|
+
if (!config || options.reset) {
|
|
87
|
+
console.log(chalk.blue("🔧 Setting up Doccupine configuration..."));
|
|
88
|
+
config = await this.promptForConfig(config || {});
|
|
89
|
+
await this.saveConfig(config);
|
|
90
|
+
}
|
|
91
|
+
if (options.port) {
|
|
92
|
+
config.port = options.port;
|
|
93
|
+
await this.saveConfig(config);
|
|
94
|
+
}
|
|
95
|
+
return config;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
27
98
|
class MDXToNextJSGenerator {
|
|
28
99
|
watchDir;
|
|
29
100
|
outputDir;
|
|
@@ -34,12 +105,10 @@ class MDXToNextJSGenerator {
|
|
|
34
105
|
}
|
|
35
106
|
async init() {
|
|
36
107
|
console.log(chalk.blue("🚀 Initializing MDX to Next.js generator..."));
|
|
37
|
-
// Ensure directories exist
|
|
38
108
|
await fs.ensureDir(this.watchDir);
|
|
39
109
|
await fs.ensureDir(this.outputDir);
|
|
40
|
-
// Create initial Next.js structure
|
|
41
110
|
await this.createNextJSStructure();
|
|
42
|
-
|
|
111
|
+
await this.createStartingDocs();
|
|
43
112
|
await this.processAllMDXFiles();
|
|
44
113
|
console.log(chalk.green("✅ Initial setup complete!"));
|
|
45
114
|
console.log(chalk.cyan("💡 To start the Next.js dev server:"));
|
|
@@ -53,7 +122,6 @@ class MDXToNextJSGenerator {
|
|
|
53
122
|
"next.config.ts": this.generateNextConfig(),
|
|
54
123
|
"tsconfig.json": this.generateTSConfig(),
|
|
55
124
|
"app/layout.tsx": await this.generateRootLayout(),
|
|
56
|
-
"app/page.tsx": this.generateHomePage(),
|
|
57
125
|
"app/not-found.tsx": this.generateNotFoundPage(),
|
|
58
126
|
"app/theme.ts": this.generateTheme(),
|
|
59
127
|
"components/layout/Icon.tsx": this.generateIcon(),
|
|
@@ -76,17 +144,52 @@ class MDXToNextJSGenerator {
|
|
|
76
144
|
await fs.writeFile(fullPath, String(content), "utf8");
|
|
77
145
|
}
|
|
78
146
|
}
|
|
147
|
+
async createStartingDocs() {
|
|
148
|
+
const structure = {
|
|
149
|
+
"index.mdx": this.generateHomeMdx(),
|
|
150
|
+
"commands.mdx": this.generateCommandsMdx(),
|
|
151
|
+
};
|
|
152
|
+
const indexMdxExists = await fs.pathExists(path.join(this.watchDir, "index.mdx"));
|
|
153
|
+
if (!indexMdxExists) {
|
|
154
|
+
for (const [filePath, content] of Object.entries(structure)) {
|
|
155
|
+
const fullPath = path.join(this.watchDir, filePath);
|
|
156
|
+
await fs.ensureDir(path.dirname(fullPath));
|
|
157
|
+
await fs.writeFile(fullPath, String(content), "utf8");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
79
161
|
async startWatching() {
|
|
80
162
|
console.log(chalk.yellow(`👀 Watching for changes in: ${this.watchDir}`));
|
|
81
|
-
this.watcher = chokidar.watch(
|
|
82
|
-
cwd: this.watchDir,
|
|
163
|
+
this.watcher = chokidar.watch(this.watchDir, {
|
|
83
164
|
persistent: true,
|
|
84
|
-
ignoreInitial:
|
|
165
|
+
ignoreInitial: true,
|
|
166
|
+
ignored: (filePath, stats) => {
|
|
167
|
+
const isFile = stats?.isFile() ?? path.extname(filePath) !== "";
|
|
168
|
+
if (isFile && !filePath.endsWith(".mdx")) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
},
|
|
85
173
|
});
|
|
86
174
|
this.watcher
|
|
87
|
-
.on("add", (filePath) =>
|
|
88
|
-
|
|
89
|
-
.
|
|
175
|
+
.on("add", (filePath) => {
|
|
176
|
+
const relativePath = path.relative(this.watchDir, filePath);
|
|
177
|
+
this.handleFileChange("added", relativePath);
|
|
178
|
+
})
|
|
179
|
+
.on("change", (filePath) => {
|
|
180
|
+
const relativePath = path.relative(this.watchDir, filePath);
|
|
181
|
+
this.handleFileChange("changed", relativePath);
|
|
182
|
+
})
|
|
183
|
+
.on("unlink", (filePath) => {
|
|
184
|
+
const relativePath = path.relative(this.watchDir, filePath);
|
|
185
|
+
this.handleFileDelete(relativePath);
|
|
186
|
+
})
|
|
187
|
+
.on("ready", () => {
|
|
188
|
+
console.log(chalk.green("📁 Initial scan complete. Ready for changes..."));
|
|
189
|
+
})
|
|
190
|
+
.on("error", (error) => {
|
|
191
|
+
console.error(chalk.red("❌ Watcher error:"), error);
|
|
192
|
+
});
|
|
90
193
|
}
|
|
91
194
|
async handleFileChange(action, filePath) {
|
|
92
195
|
console.log(chalk.cyan(`📝 File ${action}: ${filePath}`));
|
|
@@ -197,6 +300,12 @@ const content = \`${mdxFile.content.replace(/`/g, "\\`")}\`;
|
|
|
197
300
|
export const metadata: Metadata = {
|
|
198
301
|
title: '${mdxFile.frontmatter.title || "Generated with Doccupine"}',
|
|
199
302
|
description: '${mdxFile.frontmatter.description || "Automatically generated from MDX files using Doccupine"}',
|
|
303
|
+
icons: '${mdxFile.frontmatter.icon || ""}',
|
|
304
|
+
openGraph: {
|
|
305
|
+
title: '${mdxFile.frontmatter.title || "Generated with Doccupine"}',
|
|
306
|
+
description: '${mdxFile.frontmatter.description || "Automatically generated from MDX files using Doccupine"}',
|
|
307
|
+
images: '${mdxFile.frontmatter.image || ""}',
|
|
308
|
+
}
|
|
200
309
|
};
|
|
201
310
|
|
|
202
311
|
export default function Page() {
|
|
@@ -224,6 +333,8 @@ export default function Page() {
|
|
|
224
333
|
description: frontmatter.description || "",
|
|
225
334
|
categoryOrder: frontmatter.categoryOrder || 0,
|
|
226
335
|
order: frontmatter.order || 0,
|
|
336
|
+
icon: frontmatter.icon || "",
|
|
337
|
+
image: frontmatter.image || "",
|
|
227
338
|
};
|
|
228
339
|
}
|
|
229
340
|
}
|
|
@@ -236,6 +347,12 @@ ${indexMDX
|
|
|
236
347
|
? `export const metadata: Metadata = {
|
|
237
348
|
title: '${indexMDX.title}',
|
|
238
349
|
description: '${indexMDX.description}',
|
|
350
|
+
icons: '${indexMDX.icon}',
|
|
351
|
+
openGraph: {
|
|
352
|
+
title: '${indexMDX.title}',
|
|
353
|
+
description: '${indexMDX.description}',
|
|
354
|
+
images: '${indexMDX.image}',
|
|
355
|
+
}
|
|
239
356
|
};`
|
|
240
357
|
: `export const metadata: Metadata = {
|
|
241
358
|
title: 'Generated with Doccupine',
|
|
@@ -252,86 +369,14 @@ export default function Home() {
|
|
|
252
369
|
generateGitIgnore() {
|
|
253
370
|
return gitignoreTemplate;
|
|
254
371
|
}
|
|
255
|
-
// Configuration file generators
|
|
256
372
|
generatePackageJson() {
|
|
257
|
-
return
|
|
258
|
-
name: "doccupine",
|
|
259
|
-
version: "0.1.0",
|
|
260
|
-
private: true,
|
|
261
|
-
scripts: {
|
|
262
|
-
dev: "next dev",
|
|
263
|
-
build: "next build",
|
|
264
|
-
start: "next start",
|
|
265
|
-
lint: "next lint",
|
|
266
|
-
},
|
|
267
|
-
dependencies: {
|
|
268
|
-
next: "15.5.2",
|
|
269
|
-
react: "19.1.1",
|
|
270
|
-
"react-dom": "19.1.1",
|
|
271
|
-
},
|
|
272
|
-
devDependencies: {
|
|
273
|
-
"@types/node": "^24",
|
|
274
|
-
"@types/react": "^19",
|
|
275
|
-
"@types/react-dom": "^19",
|
|
276
|
-
"cherry-styled-components": "^0.1.0-43",
|
|
277
|
-
eslint: "^9",
|
|
278
|
-
"eslint-config-next": "15.5.2",
|
|
279
|
-
"lucide-react": "^0.542.0",
|
|
280
|
-
polished: "^4.3.1",
|
|
281
|
-
prettier: "^3.6.2",
|
|
282
|
-
"react-markdown": "^10.1.0",
|
|
283
|
-
"rehype-highlight": "^7.0.2",
|
|
284
|
-
"rehype-parse": "^9.0.1",
|
|
285
|
-
"rehype-stringify": "^10.0.1",
|
|
286
|
-
"remark-gfm": "^4.0.1",
|
|
287
|
-
"styled-components": "^6.1.19",
|
|
288
|
-
typescript: "^5",
|
|
289
|
-
},
|
|
290
|
-
}, null, 2);
|
|
373
|
+
return packageJsonTemplate;
|
|
291
374
|
}
|
|
292
375
|
generateNextConfig() {
|
|
293
|
-
return
|
|
294
|
-
|
|
295
|
-
const nextConfig: NextConfig = {
|
|
296
|
-
compiler: {
|
|
297
|
-
styledComponents: true,
|
|
298
|
-
},
|
|
299
|
-
transpilePackages: ["lucide-react"],
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
export default nextConfig;
|
|
303
|
-
`;
|
|
376
|
+
return nextConfigTemplate;
|
|
304
377
|
}
|
|
305
378
|
generateTSConfig() {
|
|
306
|
-
return
|
|
307
|
-
compilerOptions: {
|
|
308
|
-
target: "es5",
|
|
309
|
-
lib: ["dom", "dom.iterable", "es6"],
|
|
310
|
-
allowJs: true,
|
|
311
|
-
skipLibCheck: true,
|
|
312
|
-
strict: true,
|
|
313
|
-
noEmit: true,
|
|
314
|
-
esModuleInterop: true,
|
|
315
|
-
module: "esnext",
|
|
316
|
-
moduleResolution: "bundler",
|
|
317
|
-
resolveJsonModule: true,
|
|
318
|
-
isolatedModules: true,
|
|
319
|
-
jsx: "preserve",
|
|
320
|
-
incremental: true,
|
|
321
|
-
plugins: [{ name: "next" }],
|
|
322
|
-
baseUrl: ".",
|
|
323
|
-
paths: {
|
|
324
|
-
"@/*": ["./*"],
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
|
-
include: [
|
|
328
|
-
"next-env.d.ts",
|
|
329
|
-
"**/*.ts",
|
|
330
|
-
"**/*.tsx",
|
|
331
|
-
".next/types/**/*.ts",
|
|
332
|
-
],
|
|
333
|
-
exclude: ["node_modules"],
|
|
334
|
-
}, null, 2);
|
|
379
|
+
return tsconfigTemplate;
|
|
335
380
|
}
|
|
336
381
|
async generateRootLayout() {
|
|
337
382
|
const files = await this.getAllMDXFiles();
|
|
@@ -357,8 +402,11 @@ export default nextConfig;
|
|
|
357
402
|
const layoutContent = await this.generateRootLayout();
|
|
358
403
|
await fs.writeFile(path.join(this.outputDir, "app", "layout.tsx"), layoutContent, "utf8");
|
|
359
404
|
}
|
|
360
|
-
|
|
361
|
-
return
|
|
405
|
+
generateHomeMdx() {
|
|
406
|
+
return homeMdxTemplate;
|
|
407
|
+
}
|
|
408
|
+
generateCommandsMdx() {
|
|
409
|
+
return commandsMdxTemplate;
|
|
362
410
|
}
|
|
363
411
|
generateNotFoundPage() {
|
|
364
412
|
return notFoundTemplate;
|
|
@@ -405,49 +453,36 @@ export default nextConfig;
|
|
|
405
453
|
generateOrderNavItems() {
|
|
406
454
|
return orderNavItemsTemplate;
|
|
407
455
|
}
|
|
408
|
-
stop() {
|
|
456
|
+
async stop() {
|
|
409
457
|
if (this.watcher) {
|
|
410
|
-
this.watcher.close();
|
|
458
|
+
await this.watcher.close();
|
|
411
459
|
console.log(chalk.yellow("👋 Stopped watching for changes"));
|
|
412
460
|
}
|
|
413
461
|
}
|
|
414
462
|
}
|
|
415
|
-
// CLI Commands
|
|
416
463
|
program
|
|
417
464
|
.name("doccupine")
|
|
418
465
|
.description("Watch MDX files and generate Next.js documentation pages automatically")
|
|
419
|
-
.version("0.0.
|
|
466
|
+
.version("0.0.4");
|
|
420
467
|
program
|
|
421
468
|
.command("watch", { isDefault: true })
|
|
422
469
|
.description("Watch a directory for MDX changes and generate Next.js app")
|
|
423
470
|
.option("--port <port>", "Port for Next.js dev server", "3000")
|
|
424
471
|
.option("--verbose", "Show verbose output")
|
|
472
|
+
.option("--reset", "Reset configuration and prompt for new directories")
|
|
425
473
|
.action(async (options) => {
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
type: "text",
|
|
435
|
-
name: "outputDir",
|
|
436
|
-
message: "Enter output directory for Next.js app:",
|
|
437
|
-
initial: "nextjs-app",
|
|
438
|
-
},
|
|
439
|
-
];
|
|
440
|
-
const { watchDir: watchDirInput, outputDir: outputDirInput } = (await prompts(questions));
|
|
441
|
-
const watchDir = path.resolve(process.cwd(), watchDirInput);
|
|
442
|
-
const outputDir = path.resolve(process.cwd(), outputDirInput);
|
|
443
|
-
const generator = new MDXToNextJSGenerator(watchDir, outputDir);
|
|
474
|
+
const configManager = new ConfigManager();
|
|
475
|
+
const config = await configManager.getConfig({
|
|
476
|
+
reset: options.reset,
|
|
477
|
+
port: options.port,
|
|
478
|
+
});
|
|
479
|
+
const generator = new MDXToNextJSGenerator(config.watchDir, config.outputDir);
|
|
444
480
|
await generator.init();
|
|
445
481
|
let devServer = null;
|
|
446
482
|
console.log(chalk.blue("📦 Installing dependencies..."));
|
|
447
483
|
const { spawn } = await import("child_process");
|
|
448
|
-
// Install dependencies first
|
|
449
484
|
const install = spawn("npm", ["install"], {
|
|
450
|
-
cwd: outputDir,
|
|
485
|
+
cwd: config.outputDir,
|
|
451
486
|
stdio: "pipe",
|
|
452
487
|
});
|
|
453
488
|
await new Promise((resolve, reject) => {
|
|
@@ -462,18 +497,16 @@ program
|
|
|
462
497
|
});
|
|
463
498
|
install.on("error", reject);
|
|
464
499
|
});
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
cwd: outputDir,
|
|
500
|
+
console.log(chalk.blue(`🚀 Starting Next.js dev server on port ${config.port}...`));
|
|
501
|
+
devServer = spawn("npm", ["run", "dev", "--", "--port", config.port], {
|
|
502
|
+
cwd: config.outputDir,
|
|
469
503
|
stdio: ["ignore", "pipe", "pipe"],
|
|
470
504
|
});
|
|
471
505
|
devServer.stdout.on("data", (data) => {
|
|
472
506
|
const output = data.toString();
|
|
473
507
|
if (output.includes("Ready") || output.includes("started")) {
|
|
474
|
-
console.log(chalk.green(`🌐 Next.js ready at http://localhost:${
|
|
508
|
+
console.log(chalk.green(`🌐 Next.js ready at http://localhost:${config.port}`));
|
|
475
509
|
}
|
|
476
|
-
// Filter out noisy Next.js logs, show important ones
|
|
477
510
|
if (output.includes("compiled") ||
|
|
478
511
|
output.includes("error") ||
|
|
479
512
|
output.includes("Ready")) {
|
|
@@ -489,44 +522,56 @@ program
|
|
|
489
522
|
console.error(chalk.red("❌ Error starting dev server:"), error);
|
|
490
523
|
});
|
|
491
524
|
await generator.startWatching();
|
|
492
|
-
|
|
493
|
-
process.on("SIGINT", () => {
|
|
525
|
+
process.on("SIGINT", async () => {
|
|
494
526
|
console.log(chalk.yellow("\n🛑 Shutting down..."));
|
|
495
|
-
generator.stop();
|
|
527
|
+
await generator.stop();
|
|
496
528
|
if (devServer) {
|
|
497
529
|
devServer.kill();
|
|
498
530
|
}
|
|
499
531
|
process.exit(0);
|
|
500
532
|
});
|
|
501
533
|
console.log(chalk.green("🎉 Generator is running! Press Ctrl+C to stop."));
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
console.log(chalk.cyan(`🌐 View changes at: http://localhost:${options.port}`));
|
|
505
|
-
}
|
|
534
|
+
console.log(chalk.cyan(`📝 Edit your MDX files in: ${config.watchDir}`));
|
|
535
|
+
console.log(chalk.cyan(`🌐 View changes at: http://localhost:${config.port}`));
|
|
506
536
|
});
|
|
507
537
|
program
|
|
508
538
|
.command("build")
|
|
509
539
|
.description("One-time build of Next.js app from MDX files")
|
|
510
|
-
.
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
},
|
|
518
|
-
{
|
|
519
|
-
type: "text",
|
|
520
|
-
name: "outputDir",
|
|
521
|
-
message: "Enter output directory for Next.js app:",
|
|
522
|
-
initial: "nextjs-app",
|
|
523
|
-
},
|
|
524
|
-
];
|
|
525
|
-
const { watchDir: watchDirInput, outputDir: outputDirInput } = (await prompts(questions));
|
|
526
|
-
const watchDir = path.resolve(process.cwd(), watchDirInput);
|
|
527
|
-
const outputDir = path.resolve(process.cwd(), outputDirInput);
|
|
528
|
-
const generator = new MDXToNextJSGenerator(watchDir, outputDir);
|
|
540
|
+
.option("--reset", "Reset configuration and prompt for new directories")
|
|
541
|
+
.action(async (options) => {
|
|
542
|
+
const configManager = new ConfigManager();
|
|
543
|
+
const config = await configManager.getConfig({
|
|
544
|
+
reset: options.reset,
|
|
545
|
+
});
|
|
546
|
+
const generator = new MDXToNextJSGenerator(config.watchDir, config.outputDir);
|
|
529
547
|
await generator.init();
|
|
530
548
|
console.log(chalk.green("🎉 Build complete!"));
|
|
531
549
|
});
|
|
550
|
+
program
|
|
551
|
+
.command("config")
|
|
552
|
+
.description("Show or reset configuration")
|
|
553
|
+
.option("--show", "Show current configuration")
|
|
554
|
+
.option("--reset", "Reset configuration")
|
|
555
|
+
.action(async (options) => {
|
|
556
|
+
const configManager = new ConfigManager();
|
|
557
|
+
if (options.show) {
|
|
558
|
+
const config = await configManager.loadConfig();
|
|
559
|
+
if (config) {
|
|
560
|
+
console.log(chalk.blue("📄 Current configuration:"));
|
|
561
|
+
console.log(chalk.white("Watch Directory:"), chalk.cyan(path.relative(process.cwd(), config.watchDir)));
|
|
562
|
+
console.log(chalk.white("Output Directory:"), chalk.cyan(path.relative(process.cwd(), config.outputDir)));
|
|
563
|
+
console.log(chalk.white("Port:"), chalk.cyan(config.port || "3000"));
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
console.log(chalk.yellow("⚠️ No configuration file found"));
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
else if (options.reset) {
|
|
570
|
+
await configManager.getConfig({ reset: true });
|
|
571
|
+
console.log(chalk.green("✅ Configuration reset"));
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
console.log(chalk.blue("Use --show to display configuration or --reset to reset it"));
|
|
575
|
+
}
|
|
576
|
+
});
|
|
532
577
|
program.parse();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const commandsMdxTemplate = "---\ntitle: \"Commands\"\ndescription: \"Doccupine CLI commands\"\ndate: \"2025-01-15\"\ncategory: \"General\"\ncategoryOrder: 0\norder: 1\n---\n# Commands\n\nIn this page, you can find all the commands available in Doccupine CLI.\n\n- **Run Doccupine CLI:**\n\nCreate a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:\n\n~~~bash\nnpx doccupine\n~~~\n\nOnce you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.\nAfter selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.\n\nThis will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.\n\n- **Generate the website:**\n\n~~~bash\nnpx doccupine build\n~~~\n\nThis will generate the build files for your documentation website without starting the development server. You can then deploy the generated files to a hosting service of your choice.\n\n- **Show current configuration:**\n\n~~~bash\nnpx doccupine config --show\n~~~\n\nThis will show the current configuration for Doccupine.\n\n- **Reset configuration:**\n\n~~~bash\nnpx doccupine config --reset\n~~~\n \nThis will reset the current configuration for Doccupine.";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const commandsMdxTemplate = `---
|
|
2
|
+
title: "Commands"
|
|
3
|
+
description: "Doccupine CLI commands"
|
|
4
|
+
date: "2025-01-15"
|
|
5
|
+
category: "General"
|
|
6
|
+
categoryOrder: 0
|
|
7
|
+
order: 1
|
|
8
|
+
---
|
|
9
|
+
# Commands
|
|
10
|
+
|
|
11
|
+
In this page, you can find all the commands available in Doccupine CLI.
|
|
12
|
+
|
|
13
|
+
- **Run Doccupine CLI:**
|
|
14
|
+
|
|
15
|
+
Create a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:
|
|
16
|
+
|
|
17
|
+
~~~bash
|
|
18
|
+
npx doccupine
|
|
19
|
+
~~~
|
|
20
|
+
|
|
21
|
+
Once you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.
|
|
22
|
+
After selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.
|
|
23
|
+
|
|
24
|
+
This will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.
|
|
25
|
+
|
|
26
|
+
- **Generate the website:**
|
|
27
|
+
|
|
28
|
+
~~~bash
|
|
29
|
+
npx doccupine build
|
|
30
|
+
~~~
|
|
31
|
+
|
|
32
|
+
This will generate the build files for your documentation website without starting the development server. You can then deploy the generated files to a hosting service of your choice.
|
|
33
|
+
|
|
34
|
+
- **Show current configuration:**
|
|
35
|
+
|
|
36
|
+
~~~bash
|
|
37
|
+
npx doccupine config --show
|
|
38
|
+
~~~
|
|
39
|
+
|
|
40
|
+
This will show the current configuration for Doccupine.
|
|
41
|
+
|
|
42
|
+
- **Reset configuration:**
|
|
43
|
+
|
|
44
|
+
~~~bash
|
|
45
|
+
npx doccupine config --reset
|
|
46
|
+
~~~
|
|
47
|
+
|
|
48
|
+
This will reset the current configuration for Doccupine.`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const homeMdxTemplate = "---\ntitle: \"Getting Started\"\ndescription: \"This is my first Doccupine project\"\ndate: \"2025-01-15\"\ncategory: \"General\"\ncategoryOrder: 0\norder: 0\n---\n# Welcome to Doccupine\n\nDoccupine is a free and open-source document management system that allows you to store, organize, and share your documentation with ease. Using Doccupine, you simply create your documentation in MDX files with traditional Markdown syntax, Doccupine monitors your changes automatically generating a beautiful, modern documentation website.\n\n## Open Source and Extensible\nDoccupine is built on open standards, enabling customization and extensibility for different documentation needs. You stay in control of your content, with the option to host docs yourself and tailor the website\u2019s look and features to match your organization\u2019s requirements.\n\n## Features\n\n- \uD83D\uDCDD Markdown-based content\n- \uD83D\uDCE6 Built-in file structure\n- \u26A1 Live Preview & Auto-Update\n- \uD83D\uDE80 Easy Deployment\n\n## Getting Started\n\nTo get started with Doccupine, make sure you have [Node.js](https://nodejs.org) and npm installed on your machine. Then, follow these steps:\n\n- **Run Doccupine CLI:**\n\nCreate a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:\n\n~~~bash\nnpx doccupine\n~~~\n\nOnce you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.\nAfter selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.\n\nThis will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.\n\n## Start documenting\nStart documenting your project by editing the **index.mdx** file in the choosen MDX directory.\n\nIn your MDX directory, you can structure your content using folders and files. Doccupine will automatically generate a navigation menu based on the configured categories and order.\n";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const homeMdxTemplate = `---
|
|
2
|
+
title: "Getting Started"
|
|
3
|
+
description: "This is my first Doccupine project"
|
|
4
|
+
date: "2025-01-15"
|
|
5
|
+
category: "General"
|
|
6
|
+
categoryOrder: 0
|
|
7
|
+
order: 0
|
|
8
|
+
---
|
|
9
|
+
# Welcome to Doccupine
|
|
10
|
+
|
|
11
|
+
Doccupine is a free and open-source document management system that allows you to store, organize, and share your documentation with ease. Using Doccupine, you simply create your documentation in MDX files with traditional Markdown syntax, Doccupine monitors your changes automatically generating a beautiful, modern documentation website.
|
|
12
|
+
|
|
13
|
+
## Open Source and Extensible
|
|
14
|
+
Doccupine is built on open standards, enabling customization and extensibility for different documentation needs. You stay in control of your content, with the option to host docs yourself and tailor the website’s look and features to match your organization’s requirements.
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- 📝 Markdown-based content
|
|
19
|
+
- 📦 Built-in file structure
|
|
20
|
+
- ⚡ Live Preview & Auto-Update
|
|
21
|
+
- 🚀 Easy Deployment
|
|
22
|
+
|
|
23
|
+
## Getting Started
|
|
24
|
+
|
|
25
|
+
To get started with Doccupine, make sure you have [Node.js](https://nodejs.org) and npm installed on your machine. Then, follow these steps:
|
|
26
|
+
|
|
27
|
+
- **Run Doccupine CLI:**
|
|
28
|
+
|
|
29
|
+
Create a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:
|
|
30
|
+
|
|
31
|
+
~~~bash
|
|
32
|
+
npx doccupine
|
|
33
|
+
~~~
|
|
34
|
+
|
|
35
|
+
Once you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.
|
|
36
|
+
After selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.
|
|
37
|
+
|
|
38
|
+
This will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.
|
|
39
|
+
|
|
40
|
+
## Start documenting
|
|
41
|
+
Start documenting your project by editing the **index.mdx** file in the choosen MDX directory.
|
|
42
|
+
|
|
43
|
+
In your MDX directory, you can structure your content using folders and files. Doccupine will automatically generate a navigation menu based on the configured categories and order.
|
|
44
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const homeMdxTemplate = "---\ntitle: \"Home\"\ndescription: \"This is my first Doccupine project\"\ndate: \"2025-01-15\"\ncategory: \"General\"\ncategoryOrder: 0\norder: 0\n---\n# Welcome to Doccupine\n\nDoccupine is a free and open-source document management system that allows you to store, organize, and share your documentation with ease. Using Doccupine, you simply create your documentation in MDX files with traditional Markdown syntax, Doccupine monitors your changes automatically generating a beautiful, modern documentation website.\n\n## Open Source and Extensible\nDoccupine is built on open standards, enabling customization and extensibility for different documentation needs. You stay in control of your content, with the option to host docs yourself and tailor the website\u2019s look and features to match your organization\u2019s requirements.\n\n## Getting Started\n\nTo get started with Doccupine, make sure you have [Node.js](https://nodejs.org) and npm installed on your machine. Then, follow these steps:\n\n- **Run Doccupine CLI:**\n\nCreate a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:\n\n~~~bash\nnpx doccupine\n~~~\n\nOnce you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.\nAfter selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.\n\nThis will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.\n\n- **Generate the website:**\n\n~~~bash\nnpx doccupine build\n~~~\n\nThis will generate the build files for your documentation website without starting the development server. You can then deploy the generated files to a hosting service of your choice.\n\n## Features\n\n- \uD83D\uDCDD Markdown-based content\n- \uD83D\uDCE6 Built-in file structure\n- \u26A1 Live Preview & Auto-Update\n- \uD83D\uDE80 Easy Deployment\n\n## Start documenting\nStart documenting your project by creating a new **index.mdx** file in the choosen MDX directory. You can use the following template as a starting point:\n\n~~~text\n\n# Home\n\nThis is some **markdown** content with MDX support.\n~~~\n\nIn your MDX directory, you can structure your content using folders and files. Doccupine will automatically generate a navigation menu based on the configured categories and order.\n";
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export const homeMdxTemplate = `---
|
|
2
|
+
title: "Home"
|
|
3
|
+
description: "This is my first Doccupine project"
|
|
4
|
+
date: "2025-01-15"
|
|
5
|
+
category: "General"
|
|
6
|
+
categoryOrder: 0
|
|
7
|
+
order: 0
|
|
8
|
+
---
|
|
9
|
+
# Welcome to Doccupine
|
|
10
|
+
|
|
11
|
+
Doccupine is a free and open-source document management system that allows you to store, organize, and share your documentation with ease. Using Doccupine, you simply create your documentation in MDX files with traditional Markdown syntax, Doccupine monitors your changes automatically generating a beautiful, modern documentation website.
|
|
12
|
+
|
|
13
|
+
## Open Source and Extensible
|
|
14
|
+
Doccupine is built on open standards, enabling customization and extensibility for different documentation needs. You stay in control of your content, with the option to host docs yourself and tailor the website’s look and features to match your organization’s requirements.
|
|
15
|
+
|
|
16
|
+
## Getting Started
|
|
17
|
+
|
|
18
|
+
To get started with Doccupine, make sure you have [Node.js](https://nodejs.org) and npm installed on your machine. Then, follow these steps:
|
|
19
|
+
|
|
20
|
+
- **Run Doccupine CLI:**
|
|
21
|
+
|
|
22
|
+
Create a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:
|
|
23
|
+
|
|
24
|
+
~~~bash
|
|
25
|
+
npx doccupine
|
|
26
|
+
~~~
|
|
27
|
+
|
|
28
|
+
Once you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.
|
|
29
|
+
After selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.
|
|
30
|
+
|
|
31
|
+
This will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.
|
|
32
|
+
|
|
33
|
+
- **Generate the website:**
|
|
34
|
+
|
|
35
|
+
~~~bash
|
|
36
|
+
npx doccupine build
|
|
37
|
+
~~~
|
|
38
|
+
|
|
39
|
+
This will generate the build files for your documentation website without starting the development server. You can then deploy the generated files to a hosting service of your choice.
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
- 📝 Markdown-based content
|
|
44
|
+
- 📦 Built-in file structure
|
|
45
|
+
- ⚡ Live Preview & Auto-Update
|
|
46
|
+
- 🚀 Easy Deployment
|
|
47
|
+
|
|
48
|
+
## Start documenting
|
|
49
|
+
Start documenting your project by creating a new **index.mdx** file in the choosen MDX directory. You can use the following template as a starting point:
|
|
50
|
+
|
|
51
|
+
~~~text
|
|
52
|
+
|
|
53
|
+
# Home
|
|
54
|
+
|
|
55
|
+
This is some **markdown** content with MDX support.
|
|
56
|
+
~~~
|
|
57
|
+
|
|
58
|
+
In your MDX directory, you can structure your content using folders and files. Doccupine will automatically generate a navigation menu based on the configured categories and order.
|
|
59
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const nextConfigTemplate = "import type { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n compiler: {\n styledComponents: true,\n },\n transpilePackages: [\"lucide-react\"],\n};\n\nexport default nextConfig;\n";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const packageJsonTemplate: string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const packageJsonTemplate = JSON.stringify({
|
|
2
|
+
name: "doccupine",
|
|
3
|
+
version: "0.1.0",
|
|
4
|
+
private: true,
|
|
5
|
+
scripts: {
|
|
6
|
+
dev: "next dev",
|
|
7
|
+
build: "next build",
|
|
8
|
+
start: "next start",
|
|
9
|
+
lint: "next lint",
|
|
10
|
+
},
|
|
11
|
+
dependencies: {
|
|
12
|
+
next: "15.5.2",
|
|
13
|
+
react: "19.1.1",
|
|
14
|
+
"react-dom": "19.1.1",
|
|
15
|
+
},
|
|
16
|
+
devDependencies: {
|
|
17
|
+
"@types/node": "^24",
|
|
18
|
+
"@types/react": "^19",
|
|
19
|
+
"@types/react-dom": "^19",
|
|
20
|
+
"cherry-styled-components": "^0.1.0-43",
|
|
21
|
+
eslint: "^9",
|
|
22
|
+
"eslint-config-next": "15.5.2",
|
|
23
|
+
"lucide-react": "^0.542.0",
|
|
24
|
+
polished: "^4.3.1",
|
|
25
|
+
prettier: "^3.6.2",
|
|
26
|
+
"react-markdown": "^10.1.0",
|
|
27
|
+
"rehype-highlight": "^7.0.2",
|
|
28
|
+
"rehype-parse": "^9.0.1",
|
|
29
|
+
"rehype-stringify": "^10.0.1",
|
|
30
|
+
"remark-gfm": "^4.0.1",
|
|
31
|
+
"styled-components": "^6.1.19",
|
|
32
|
+
typescript: "^5",
|
|
33
|
+
},
|
|
34
|
+
}, null, 2);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const tsconfigTemplate: string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const tsconfigTemplate = JSON.stringify({
|
|
2
|
+
compilerOptions: {
|
|
3
|
+
target: "es5",
|
|
4
|
+
lib: ["dom", "dom.iterable", "es6"],
|
|
5
|
+
allowJs: true,
|
|
6
|
+
skipLibCheck: true,
|
|
7
|
+
strict: true,
|
|
8
|
+
noEmit: true,
|
|
9
|
+
esModuleInterop: true,
|
|
10
|
+
module: "esnext",
|
|
11
|
+
moduleResolution: "bundler",
|
|
12
|
+
resolveJsonModule: true,
|
|
13
|
+
isolatedModules: true,
|
|
14
|
+
jsx: "preserve",
|
|
15
|
+
incremental: true,
|
|
16
|
+
plugins: [{ name: "next" }],
|
|
17
|
+
baseUrl: ".",
|
|
18
|
+
paths: {
|
|
19
|
+
"@/*": ["./*"],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
23
|
+
exclude: ["node_modules"],
|
|
24
|
+
}, null, 2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doccupine",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "CLI tool to watch MDX files and generate Next.js beautiful documentation pages automatically",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/chokidar": "^2.1.7",
|
|
37
37
|
"@types/fs-extra": "^11.0.4",
|
|
38
|
-
"@types/node": "^24.3.
|
|
38
|
+
"@types/node": "^24.3.1",
|
|
39
39
|
"@types/prompts": "^2.4.9",
|
|
40
40
|
"typescript": "^5.9.2"
|
|
41
41
|
},
|