scaffold-doc-cli 1.0.0
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/.docs/architecture.md +9 -0
- package/.docs/getting-started.md +13 -0
- package/.docs/index.md +15 -0
- package/.docs/reference/components.md +12 -0
- package/.docs/reference/composables.md +12 -0
- package/.docs/reference/server-routes.md +12 -0
- package/.github/scripts/doc-sync.mjs +82 -0
- package/.github/workflows/ai-doc-sync.yml +37 -0
- package/README.md +54 -0
- package/index.js +382 -0
- package/mkdocs.yml +12 -0
- package/package.json +26 -0
package/.docs/index.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
AI_DOC_START
|
|
3
|
+
CONTEXT: This is the entry point for the project documentation.
|
|
4
|
+
INSTRUCTION: Analyze the project structure and update the "Overview" section.
|
|
5
|
+
-->
|
|
6
|
+
# test Documentation
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
<!-- AI_CONTENT_START -->
|
|
10
|
+
Documentation initialized.
|
|
11
|
+
<!-- AI_CONTENT_END -->
|
|
12
|
+
|
|
13
|
+
## Quick Links
|
|
14
|
+
- [Getting Started](./getting-started.md)
|
|
15
|
+
- [Architecture](./architecture.md)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { GoogleGenAI } from "@google/genai";
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
|
|
6
|
+
const genAI = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
console.log("Starting AI Doc Sync...");
|
|
10
|
+
|
|
11
|
+
// 1. Detect Changed Files
|
|
12
|
+
let changedFiles = [];
|
|
13
|
+
try {
|
|
14
|
+
const output = execSync('git diff --name-only HEAD~1 HEAD').toString();
|
|
15
|
+
changedFiles = output.split('\n').filter(f => f && !f.startsWith('.docs') && !f.startsWith('.github'));
|
|
16
|
+
} catch (e) {
|
|
17
|
+
console.error("Failed to detect changes:", e.message);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (changedFiles.length === 0) {
|
|
22
|
+
console.log("No relevant code changes detected.");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log("Processing changed files:", changedFiles);
|
|
27
|
+
|
|
28
|
+
// 2. Prepare Context for Gemini
|
|
29
|
+
let context = "";
|
|
30
|
+
for (const file of changedFiles) {
|
|
31
|
+
if (fs.existsSync(file)) {
|
|
32
|
+
context += `\n--- File: ${file} ---\n`;
|
|
33
|
+
context += fs.readFileSync(file, 'utf-8').slice(0, 10000); // Limit size
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 3. Prompt Gemini
|
|
38
|
+
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
|
|
39
|
+
|
|
40
|
+
const prompt = `
|
|
41
|
+
You are a technical documentation assistant.
|
|
42
|
+
Analyze the following code changes and update the documentation in the .docs/ directory.
|
|
43
|
+
|
|
44
|
+
Rules:
|
|
45
|
+
1. Output MUST be a valid JSON object where keys are file paths (relative to .docs/, e.g., "reference/controllers.md") and values are the NEW content of that file.
|
|
46
|
+
2. You can create new files if necessary.
|
|
47
|
+
3. You can update existing files (e.g., getting-started.md, architecture.md).
|
|
48
|
+
4. Focus on accuracy and clarity.
|
|
49
|
+
5. Do not include markdown code fence blocks in your response, just the raw JSON string.
|
|
50
|
+
|
|
51
|
+
Code Context:
|
|
52
|
+
${context}
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const result = await model.generateContent(prompt);
|
|
57
|
+
const text = result.response.text();
|
|
58
|
+
|
|
59
|
+
// Simple cleanup if model adds code blocks
|
|
60
|
+
const jsonStr = text.replace(/\`\`\`json/g, '').replace(/\`\`\`/g, '').trim();
|
|
61
|
+
const updates = JSON.parse(jsonStr);
|
|
62
|
+
|
|
63
|
+
// 4. Write Updates
|
|
64
|
+
for (const [relativePath, content] of Object.entries(updates)) {
|
|
65
|
+
const fullPath = path.join(process.cwd(), '.docs', relativePath);
|
|
66
|
+
const dir = path.dirname(fullPath);
|
|
67
|
+
|
|
68
|
+
if (!fs.existsSync(dir)) {
|
|
69
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
fs.writeFileSync(fullPath, content);
|
|
73
|
+
console.log(`Updated: .docs/${relativePath}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error("AI Generation failed:", error);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
main();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: AI Doc Sync
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
paths-ignore:
|
|
6
|
+
- '.docs/**'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
doc-completion:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v3
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 2
|
|
19
|
+
|
|
20
|
+
- name: Setup Node.js
|
|
21
|
+
uses: actions/setup-node@v3
|
|
22
|
+
with:
|
|
23
|
+
node-version: '18'
|
|
24
|
+
|
|
25
|
+
- name: Install Dependencies
|
|
26
|
+
run: npm install @google/genai
|
|
27
|
+
|
|
28
|
+
- name: Run AI Doc Sync
|
|
29
|
+
env:
|
|
30
|
+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
31
|
+
run: node .github/scripts/doc-sync.mjs
|
|
32
|
+
|
|
33
|
+
- name: Commit Changes
|
|
34
|
+
uses: stefanzweifel/git-auto-commit-action@v5
|
|
35
|
+
with:
|
|
36
|
+
commit_message: "docs: auto-generated documentation updates"
|
|
37
|
+
file_pattern: .docs/** mkdocs.yml
|
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Motin Doc CLI
|
|
2
|
+
|
|
3
|
+
A CLI tool to scaffold standardized documentation structure for Motin projects, ready for AI completion.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 Initializes `.docs/` directory with standardized structure.
|
|
8
|
+
- 🔧 Supports multiple stacks (Nuxt, Node, Python, etc.).
|
|
9
|
+
- 🤖 Embeds AI-friendly context and instructions in Markdown comments.
|
|
10
|
+
- 📦 Optional GitHub Workflow for automated AI documentation updates.
|
|
11
|
+
|
|
12
|
+
## Installation & Usage (Local Development)
|
|
13
|
+
|
|
14
|
+
1. Clone the repository.
|
|
15
|
+
2. Install dependencies:
|
|
16
|
+
```bash
|
|
17
|
+
npm install
|
|
18
|
+
```
|
|
19
|
+
3. Link the package globally:
|
|
20
|
+
```bash
|
|
21
|
+
npm link
|
|
22
|
+
```
|
|
23
|
+
4. Navigate to your target project folder:
|
|
24
|
+
```bash
|
|
25
|
+
cd ../my-project
|
|
26
|
+
```
|
|
27
|
+
5. Run the initialization command:
|
|
28
|
+
```bash
|
|
29
|
+
init-doc
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Publishing to NPM
|
|
33
|
+
|
|
34
|
+
1. Login to NPM:
|
|
35
|
+
```bash
|
|
36
|
+
npm login
|
|
37
|
+
```
|
|
38
|
+
2. Publish the package:
|
|
39
|
+
```bash
|
|
40
|
+
npm publish
|
|
41
|
+
```
|
|
42
|
+
*Note: Ensure the `name` in `package.json` is unique on NPM or scoped (e.g., `@motin/doc-cli`).*
|
|
43
|
+
|
|
44
|
+
## Generated Structure
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
my-project/
|
|
48
|
+
├── .docs/
|
|
49
|
+
│ ├── index.md # Entry point with AI context
|
|
50
|
+
│ └── components.md # Stack-specific (e.g., for Nuxt)
|
|
51
|
+
└── .github/
|
|
52
|
+
└── workflows/
|
|
53
|
+
└── ai-doc-sync.yml # (Optional) Workflow file
|
|
54
|
+
```
|
package/index.js
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
async function init() {
|
|
12
|
+
console.log(chalk.green.bold('Welcome to the Motin Documentation Initializer! 🚀'));
|
|
13
|
+
|
|
14
|
+
const answers = await inquirer.prompt([
|
|
15
|
+
{
|
|
16
|
+
type: 'input',
|
|
17
|
+
name: 'projectName',
|
|
18
|
+
message: 'What is the name of your project?',
|
|
19
|
+
default: path.basename(process.cwd()),
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: 'list',
|
|
23
|
+
name: 'stack',
|
|
24
|
+
message: 'Which technical stack are you using?',
|
|
25
|
+
choices: [
|
|
26
|
+
new inquirer.Separator('--- JavaScript/TypeScript ---'),
|
|
27
|
+
'Nuxt', 'Next.js', 'Vue', 'React', 'Angular', 'Svelte', 'Node (Express/NestJS)',
|
|
28
|
+
new inquirer.Separator('--- PHP ---'),
|
|
29
|
+
'Laravel', 'Symfony', 'Generic PHP',
|
|
30
|
+
new inquirer.Separator('--- Python ---'),
|
|
31
|
+
'Django', 'FastAPI', 'Flask', 'Generic Python',
|
|
32
|
+
new inquirer.Separator('--- Other ---'),
|
|
33
|
+
'Java (Spring)', 'Ruby (Rails)', 'Go', 'Rust', 'Other'
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'confirm',
|
|
38
|
+
name: 'includeWorkflow',
|
|
39
|
+
message: 'Do you want to include a GitHub Workflow for AI doc completion?',
|
|
40
|
+
default: true,
|
|
41
|
+
},
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
const docsDir = path.join(process.cwd(), '.docs');
|
|
45
|
+
const referenceDir = path.join(docsDir, 'reference');
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const relativeDocsDir = path.relative(process.cwd(), docsDir);
|
|
49
|
+
console.log(chalk.blue(`\nCreating documentation directory at ./${relativeDocsDir}...`));
|
|
50
|
+
await fs.ensureDir(docsDir);
|
|
51
|
+
await fs.ensureDir(referenceDir);
|
|
52
|
+
|
|
53
|
+
// 1. Create Standard Files
|
|
54
|
+
// ------------------------
|
|
55
|
+
|
|
56
|
+
// index.md
|
|
57
|
+
const indexContent = `<!--
|
|
58
|
+
AI_DOC_START
|
|
59
|
+
CONTEXT: This is the entry point for the project documentation.
|
|
60
|
+
INSTRUCTION: Analyze the project structure and update the "Overview" section.
|
|
61
|
+
-->
|
|
62
|
+
# ${answers.projectName} Documentation
|
|
63
|
+
|
|
64
|
+
## Overview
|
|
65
|
+
<!-- AI_CONTENT_START -->
|
|
66
|
+
Documentation initialized.
|
|
67
|
+
<!-- AI_CONTENT_END -->
|
|
68
|
+
|
|
69
|
+
## Quick Links
|
|
70
|
+
- [Getting Started](./getting-started.md)
|
|
71
|
+
- [Architecture](./architecture.md)
|
|
72
|
+
`;
|
|
73
|
+
await fs.writeFile(path.join(docsDir, 'index.md'), indexContent);
|
|
74
|
+
|
|
75
|
+
// getting-started.md
|
|
76
|
+
const gettingStartedContent = `# Getting Started
|
|
77
|
+
|
|
78
|
+
<!--
|
|
79
|
+
INSTRUCTION: Document the installation and setup steps.
|
|
80
|
+
-->
|
|
81
|
+
|
|
82
|
+
## Prerequisites
|
|
83
|
+
<!-- AI_CONTENT_START -->
|
|
84
|
+
<!-- AI_CONTENT_END -->
|
|
85
|
+
|
|
86
|
+
## Installation
|
|
87
|
+
<!-- AI_CONTENT_START -->
|
|
88
|
+
<!-- AI_CONTENT_END -->
|
|
89
|
+
`;
|
|
90
|
+
await fs.writeFile(path.join(docsDir, 'getting-started.md'), gettingStartedContent);
|
|
91
|
+
|
|
92
|
+
// architecture.md
|
|
93
|
+
const architectureContent = `# Architecture
|
|
94
|
+
|
|
95
|
+
<!--
|
|
96
|
+
INSTRUCTION: Document the high-level system architecture, data flow, and key design decisions.
|
|
97
|
+
-->
|
|
98
|
+
|
|
99
|
+
## specificities
|
|
100
|
+
<!-- AI_CONTENT_START -->
|
|
101
|
+
<!-- AI_CONTENT_END -->
|
|
102
|
+
`;
|
|
103
|
+
await fs.writeFile(path.join(docsDir, 'architecture.md'), architectureContent);
|
|
104
|
+
|
|
105
|
+
// 2. Create Stack Specific Files (Granular)
|
|
106
|
+
// ----------------------------------------
|
|
107
|
+
const stackConfig = getStackConfig(answers.stack);
|
|
108
|
+
|
|
109
|
+
// Generate each reference file defined in the config
|
|
110
|
+
for (const [filename, contentGenerator] of Object.entries(stackConfig.files)) {
|
|
111
|
+
await fs.writeFile(path.join(referenceDir, filename), contentGenerator());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log(chalk.green('✔ Standard documentation files created'));
|
|
115
|
+
console.log(chalk.green(`✔ ${Object.keys(stackConfig.files).length} reference doc(s) created`));
|
|
116
|
+
|
|
117
|
+
// 3. Create MkDocs Config
|
|
118
|
+
// -----------------------
|
|
119
|
+
|
|
120
|
+
// Construct navigation for Reference section
|
|
121
|
+
const referenceNav = Object.keys(stackConfig.files).map(filename => {
|
|
122
|
+
// Convert 'controllers.md' -> 'Controllers'
|
|
123
|
+
const title = filename.replace('.md', '').charAt(0).toUpperCase() + filename.replace('.md', '').slice(1);
|
|
124
|
+
return ` - ${title}: reference/${filename}`;
|
|
125
|
+
}).join('\n');
|
|
126
|
+
|
|
127
|
+
const mkdocsContent = `site_name: ${answers.projectName} Documentation
|
|
128
|
+
docs_dir: .docs
|
|
129
|
+
theme: readthedocs
|
|
130
|
+
|
|
131
|
+
nav:
|
|
132
|
+
- Home: index.md
|
|
133
|
+
- Getting Started: getting-started.md
|
|
134
|
+
- Architecture: architecture.md
|
|
135
|
+
- Reference:
|
|
136
|
+
${referenceNav}
|
|
137
|
+
`;
|
|
138
|
+
await fs.writeFile(path.join(process.cwd(), 'mkdocs.yml'), mkdocsContent);
|
|
139
|
+
console.log(chalk.green('✔ mkdocs.yml created'));
|
|
140
|
+
|
|
141
|
+
// 4. Create GitHub Workflow & AI Script
|
|
142
|
+
// -------------------------
|
|
143
|
+
if (answers.includeWorkflow) {
|
|
144
|
+
const workflowDir = path.join(process.cwd(), '.github', 'workflows');
|
|
145
|
+
const scriptsDir = path.join(process.cwd(), '.github', 'scripts');
|
|
146
|
+
await fs.ensureDir(workflowDir);
|
|
147
|
+
await fs.ensureDir(scriptsDir);
|
|
148
|
+
|
|
149
|
+
// Workflow File
|
|
150
|
+
const workflowContent = `name: AI Doc Sync
|
|
151
|
+
|
|
152
|
+
on:
|
|
153
|
+
push:
|
|
154
|
+
paths-ignore:
|
|
155
|
+
- '.docs/**'
|
|
156
|
+
workflow_dispatch:
|
|
157
|
+
|
|
158
|
+
permissions:
|
|
159
|
+
contents: write
|
|
160
|
+
|
|
161
|
+
jobs:
|
|
162
|
+
doc-completion:
|
|
163
|
+
runs-on: ubuntu-latest
|
|
164
|
+
steps:
|
|
165
|
+
- uses: actions/checkout@v3
|
|
166
|
+
with:
|
|
167
|
+
fetch-depth: 2
|
|
168
|
+
|
|
169
|
+
- name: Setup Node.js
|
|
170
|
+
uses: actions/setup-node@v3
|
|
171
|
+
with:
|
|
172
|
+
node-version: '18'
|
|
173
|
+
|
|
174
|
+
- name: Install Dependencies
|
|
175
|
+
run: npm install @google/genai
|
|
176
|
+
|
|
177
|
+
- name: Run AI Doc Sync
|
|
178
|
+
env:
|
|
179
|
+
GEMINI_API_KEY: \${{ secrets.GEMINI_API_KEY }}
|
|
180
|
+
run: node .github/scripts/doc-sync.mjs
|
|
181
|
+
|
|
182
|
+
- name: Commit Changes
|
|
183
|
+
uses: stefanzweifel/git-auto-commit-action@v5
|
|
184
|
+
with:
|
|
185
|
+
commit_message: "docs: auto-generated documentation updates"
|
|
186
|
+
file_pattern: .docs/** mkdocs.yml
|
|
187
|
+
`;
|
|
188
|
+
await fs.writeFile(path.join(workflowDir, 'ai-doc-sync.yml'), workflowContent);
|
|
189
|
+
console.log(chalk.green('✔ .github/workflows/ai-doc-sync.yml created'));
|
|
190
|
+
|
|
191
|
+
// AI Sync Script
|
|
192
|
+
const scriptContent = `import { GoogleGenAI } from "@google/genai";
|
|
193
|
+
import fs from 'fs';
|
|
194
|
+
import path from 'path';
|
|
195
|
+
import { execSync } from 'child_process';
|
|
196
|
+
|
|
197
|
+
const genAI = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
|
|
198
|
+
|
|
199
|
+
async function main() {
|
|
200
|
+
console.log("Starting AI Doc Sync...");
|
|
201
|
+
|
|
202
|
+
// 1. Detect Changed Files
|
|
203
|
+
let changedFiles = [];
|
|
204
|
+
try {
|
|
205
|
+
const output = execSync('git diff --name-only HEAD~1 HEAD').toString();
|
|
206
|
+
changedFiles = output.split('\\n').filter(f => f && !f.startsWith('.docs') && !f.startsWith('.github'));
|
|
207
|
+
} catch (e) {
|
|
208
|
+
console.error("Failed to detect changes:", e.message);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (changedFiles.length === 0) {
|
|
213
|
+
console.log("No relevant code changes detected.");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
console.log("Processing changed files:", changedFiles);
|
|
218
|
+
|
|
219
|
+
// 2. Prepare Context for Gemini
|
|
220
|
+
let context = "";
|
|
221
|
+
for (const file of changedFiles) {
|
|
222
|
+
if (fs.existsSync(file)) {
|
|
223
|
+
context += \`\\n--- File: \${file} ---\\n\`;
|
|
224
|
+
context += fs.readFileSync(file, 'utf-8').slice(0, 10000); // Limit size
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 3. Prompt Gemini
|
|
229
|
+
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
|
|
230
|
+
|
|
231
|
+
const prompt = \`
|
|
232
|
+
You are a technical documentation assistant.
|
|
233
|
+
Analyze the following code changes and update the documentation in the .docs/ directory.
|
|
234
|
+
|
|
235
|
+
Rules:
|
|
236
|
+
1. Output MUST be a valid JSON object where keys are file paths (relative to .docs/, e.g., "reference/controllers.md") and values are the NEW content of that file.
|
|
237
|
+
2. You can create new files if necessary.
|
|
238
|
+
3. You can update existing files (e.g., getting-started.md, architecture.md).
|
|
239
|
+
4. Focus on accuracy and clarity.
|
|
240
|
+
5. Do not include markdown code fence blocks in your response, just the raw JSON string.
|
|
241
|
+
|
|
242
|
+
Code Context:
|
|
243
|
+
\${context}
|
|
244
|
+
\`;
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
const result = await model.generateContent(prompt);
|
|
248
|
+
const text = result.response.text();
|
|
249
|
+
|
|
250
|
+
// Simple cleanup if model adds code blocks
|
|
251
|
+
const jsonStr = text.replace(/\\\`\\\`\\\`json/g, '').replace(/\\\`\\\`\\\`/g, '').trim();
|
|
252
|
+
const updates = JSON.parse(jsonStr);
|
|
253
|
+
|
|
254
|
+
// 4. Write Updates
|
|
255
|
+
for (const [relativePath, content] of Object.entries(updates)) {
|
|
256
|
+
const fullPath = path.join(process.cwd(), '.docs', relativePath);
|
|
257
|
+
const dir = path.dirname(fullPath);
|
|
258
|
+
|
|
259
|
+
if (!fs.existsSync(dir)) {
|
|
260
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
fs.writeFileSync(fullPath, content);
|
|
264
|
+
console.log(\`Updated: .docs/\${relativePath}\`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.error("AI Generation failed:", error);
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
main();`;
|
|
274
|
+
await fs.writeFile(path.join(scriptsDir, 'doc-sync.mjs'), scriptContent);
|
|
275
|
+
console.log(chalk.green('✔ .github/scripts/doc-sync.mjs created'));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
console.log(chalk.green.bold('\nDocumentation scaffolding complete! 🎉'));
|
|
279
|
+
console.log(chalk.yellow('Next steps:'));
|
|
280
|
+
console.log(`1. Review the generated files in ./${relativeDocsDir}`);
|
|
281
|
+
console.log('2. Run "mkdocs serve" to preview your documentation');
|
|
282
|
+
console.log('3. Commit the changes');
|
|
283
|
+
|
|
284
|
+
} catch (err) {
|
|
285
|
+
console.error(chalk.red('Error creating documentation files:'), err);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Config Factory
|
|
290
|
+
function getStackConfig(stack) {
|
|
291
|
+
const commonHeader = (type) => `<!--
|
|
292
|
+
AI_DOC_START
|
|
293
|
+
STACK: ${stack}
|
|
294
|
+
TYPE: ${type}
|
|
295
|
+
-->\n`;
|
|
296
|
+
|
|
297
|
+
// --- PHP: Symfony ---
|
|
298
|
+
if (stack.includes('Symfony')) {
|
|
299
|
+
return {
|
|
300
|
+
files: {
|
|
301
|
+
'controllers.md': () => `${commonHeader('Controllers')}# Controllers\n\n<!-- INSTRUCTION: Document all Symfony Controllers found in /src/Controller -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
302
|
+
'entities.md': () => `${commonHeader('Entities')}# Entities\n\n<!-- INSTRUCTION: Document all Doctrine Entities found in /src/Entity -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
303
|
+
'services.md': () => `${commonHeader('Services')}# Services\n\n<!-- INSTRUCTION: Document core application services found in /src/Service -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// --- PHP: Laravel ---
|
|
309
|
+
if (stack.includes('Laravel')) {
|
|
310
|
+
return {
|
|
311
|
+
files: {
|
|
312
|
+
'controllers.md': () => `${commonHeader('Controllers')}# Controllers\n\n<!-- INSTRUCTION: Document Http Controllers found in /app/Http/Controllers -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
313
|
+
'models.md': () => `${commonHeader('Models')}# Models\n\n<!-- INSTRUCTION: Document Eloquent Models found in /app/Models -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
314
|
+
'routes.md': () => `${commonHeader('Routes')}# Routes\n\n<!-- INSTRUCTION: Document application routes found in /routes -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// --- JS: Nuxt ---
|
|
320
|
+
if (stack.includes('Nuxt')) {
|
|
321
|
+
return {
|
|
322
|
+
files: {
|
|
323
|
+
'components.md': () => `${commonHeader('Components')}# Components\n\n<!-- INSTRUCTION: Document Vue components in /components -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
324
|
+
'composables.md': () => `${commonHeader('Composables')}# Composables\n\n<!-- INSTRUCTION: Document auto-imported composables in /composables -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
325
|
+
'server-routes.md': () => `${commonHeader('Server Routes')}# Server Routes\n\n<!-- INSTRUCTION: Document Nitro server routes in /server/api -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// --- JS: General (React, Next, Vue) ---
|
|
331
|
+
if (stack.includes('React') || stack.includes('Next') || stack.includes('Vue') || stack.includes('Angular') || stack.includes('Svelte')) {
|
|
332
|
+
return {
|
|
333
|
+
files: {
|
|
334
|
+
'components.md': () => `${commonHeader('Components')}# Components\n\n<!-- INSTRUCTION: Document UI components -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
335
|
+
'hooks.md': () => `${commonHeader('Hooks')}# Hooks\n\n<!-- INSTRUCTION: Document custom hooks/composables -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
336
|
+
'api.md': () => `${commonHeader('API')}# API Integration\n\n<!-- INSTRUCTION: Document API clients or fetch wrappers -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// --- Python: Django ---
|
|
342
|
+
if (stack.includes('Django')) {
|
|
343
|
+
return {
|
|
344
|
+
files: {
|
|
345
|
+
'models.md': () => `${commonHeader('Models')}# Models\n\n<!-- INSTRUCTION: Document Django Models -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
346
|
+
'views.md': () => `${commonHeader('Views')}# Views\n\n<!-- INSTRUCTION: Document Django Views/ViewSets -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
347
|
+
'admin.md': () => `${commonHeader('Admin')}# Admin Customization\n\n<!-- INSTRUCTION: Document Admin classes -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// --- Python: FastAPI ---
|
|
353
|
+
if (stack.includes('FastAPI')) {
|
|
354
|
+
return {
|
|
355
|
+
files: {
|
|
356
|
+
'endpoints.md': () => `${commonHeader('Endpoints')}# Endpoints\n\n<!-- INSTRUCTION: Document FastAPI routes and decorators -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
357
|
+
'models.md': () => `${commonHeader('Models')}# Pydantic Models\n\n<!-- INSTRUCTION: Document Pydantic models -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// --- Java/Spring ---
|
|
363
|
+
if (stack.includes('Spring') || stack.includes('Java')) {
|
|
364
|
+
return {
|
|
365
|
+
files: {
|
|
366
|
+
'controllers.md': () => `${commonHeader('Controllers')}# Controllers\n\n<!-- INSTRUCTION: Document REST Controllers -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
367
|
+
'services.md': () => `${commonHeader('Services')}# Services\n\n<!-- INSTRUCTION: Document Service beans -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
368
|
+
'domain.md': () => `${commonHeader('Domain')}# Domain Models\n\n<!-- INSTRUCTION: Document Entity classes -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// --- Default Fallback ---
|
|
374
|
+
return {
|
|
375
|
+
files: {
|
|
376
|
+
'api.md': () => `${commonHeader('API')}# API Reference\n\n<!-- INSTRUCTION: Document public API endpoints -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
377
|
+
'modules.md': () => `${commonHeader('Modules')}# Core Modules\n\n<!-- INSTRUCTION: Document core logical modules -->\n\n## List\n<!-- AI_CONTENT_START -->\n<!-- AI_CONTENT_END -->`,
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
init();
|
package/mkdocs.yml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
site_name: test Documentation
|
|
2
|
+
docs_dir: .docs
|
|
3
|
+
theme: readthedocs
|
|
4
|
+
|
|
5
|
+
nav:
|
|
6
|
+
- Home: index.md
|
|
7
|
+
- Getting Started: getting-started.md
|
|
8
|
+
- Architecture: architecture.md
|
|
9
|
+
- Reference:
|
|
10
|
+
- Components: reference/components.md
|
|
11
|
+
- Composables: reference/composables.md
|
|
12
|
+
- Server-routes: reference/server-routes.md
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "scaffold-doc-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to scaffold standardized documentation structure for projects.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"init-doc": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"cli",
|
|
15
|
+
"documentation",
|
|
16
|
+
"scaffolding",
|
|
17
|
+
"ai"
|
|
18
|
+
],
|
|
19
|
+
"author": "mael50",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"chalk": "^5.3.0",
|
|
23
|
+
"fs-extra": "^11.2.0",
|
|
24
|
+
"inquirer": "^9.2.12"
|
|
25
|
+
}
|
|
26
|
+
}
|