@aigne/doc-smith 0.9.8-alpha.7 → 0.9.8-alpha.9
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 +71 -17
- package/agents/bash-executor/bash-executor.mjs +280 -0
- package/agents/preload-i18n.mjs +73 -0
- package/agents/publish/check-docs.mjs +44 -0
- package/agents/publish/index.yaml +12 -0
- package/agents/publish/init-config.mjs +133 -0
- package/agents/publish/publish-docs.mjs +377 -0
- package/aigne.yaml +7 -0
- package/doc-smith/SKILL.md +77 -26
- package/doc-smith/references/changeset-guide.md +170 -0
- package/doc-smith/references/document-content-guide.md +15 -74
- package/doc-smith/references/document-structure-schema.md +2 -2
- package/doc-smith/references/patch-guide.md +96 -0
- package/doc-smith/references/structure-planning-guide.md +8 -5
- package/doc-smith/references/update-workflow.md +108 -0
- package/doc-smith/references/user-intent-guide.md +3 -0
- package/doc-smith/references/workspace-initialization.md +326 -0
- package/doc-smith.yaml +4 -0
- package/feature-design/workspace.md +697 -0
- package/package.json +15 -2
- package/prompt/doc-smith.md +57 -0
- package/utils/auth.mjs +275 -0
- package/utils/branding.mjs +83 -0
- package/utils/config.mjs +262 -0
- package/utils/constants.mjs +38 -0
- package/utils/deploy.mjs +86 -0
- package/utils/docs.mjs +247 -0
- package/utils/files.mjs +76 -0
- package/utils/git.mjs +54 -0
- package/utils/http.mjs +122 -0
- package/utils/project.mjs +76 -0
- package/utils/store/index.mjs +45 -0
- package/utils/upload.mjs +231 -0
- package/doc-smith/references/changeset-schema.md +0 -79
- package/doc-smith/references/document-update-guide.md +0 -192
package/README.md
CHANGED
|
@@ -71,28 +71,74 @@ doc-smith-skill/
|
|
|
71
71
|
|
|
72
72
|
### 2. 使用 Skill
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
#### Workspace 模式 (推荐)
|
|
75
|
+
|
|
76
|
+
DocSmith 现在使用独立 workspace 目录,不会污染源仓库。
|
|
77
|
+
|
|
78
|
+
**创建并使用 workspace:**
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# 1. 创建空目录作为 workspace
|
|
82
|
+
mkdir my-docs-workspace
|
|
83
|
+
cd my-docs-workspace
|
|
84
|
+
|
|
85
|
+
# 2. 打开 Claude Code 并执行 doc-smith
|
|
86
|
+
# 输入: 使用 doc-smith 生成文档
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**初始化流程:**
|
|
90
|
+
DocSmith 会引导你完成初始化:
|
|
91
|
+
1. 询问输出语言(如:zh、en)
|
|
92
|
+
2. 询问源仓库 Git URL(可选,如果源代码在本地可不提供)
|
|
93
|
+
3. 自动创建目录结构
|
|
94
|
+
4. 自动添加源仓库为 git submodule(如果提供了 URL)
|
|
95
|
+
5. 生成 config.yaml 配置文件
|
|
96
|
+
6. 初始化 git 仓库并提交
|
|
97
|
+
|
|
98
|
+
**后续操作:**
|
|
99
|
+
DocSmith 会:
|
|
100
|
+
1. 分析源仓库内容
|
|
101
|
+
2. 推断用户意图
|
|
102
|
+
3. 规划文档结构
|
|
103
|
+
4. 生成结构化的 Markdown 文档
|
|
104
|
+
5. 询问是否提交到 Git
|
|
105
|
+
|
|
106
|
+
### 3. Workspace 目录结构
|
|
75
107
|
|
|
76
108
|
```
|
|
77
|
-
|
|
109
|
+
my-docs-workspace/ # 独立 workspace 目录
|
|
110
|
+
├── config.yaml # workspace 配置文件
|
|
111
|
+
├── sources/ # 源仓库 (git submodule)
|
|
112
|
+
│ └── my-project/
|
|
113
|
+
├── intent/
|
|
114
|
+
│ └── user-intent.md # 用户意图描述
|
|
115
|
+
├── planning/
|
|
116
|
+
│ └── document-structure.yaml # 文档结构计划
|
|
117
|
+
├── docs/ # 生成的文档
|
|
118
|
+
│ ├── overview.md
|
|
119
|
+
│ ├── getting-started.md
|
|
120
|
+
│ └── api/
|
|
121
|
+
│ └── authentication.md
|
|
122
|
+
└── cache/ # 临时数据 (不纳入 git)
|
|
78
123
|
```
|
|
79
124
|
|
|
80
|
-
|
|
81
|
-
1. 分析你的工作区
|
|
82
|
-
2. 规划文档结构
|
|
83
|
-
3. 生成 `document-structure.yaml`
|
|
84
|
-
4. 创建结构化的 Markdown 文档
|
|
125
|
+
### 4. 版本管理
|
|
85
126
|
|
|
86
|
-
|
|
127
|
+
Workspace 是一个独立的 Git 仓库,支持完整的版本管理:
|
|
87
128
|
|
|
88
|
-
|
|
129
|
+
```bash
|
|
130
|
+
# 查看历史
|
|
131
|
+
git log
|
|
89
132
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
133
|
+
# 查看变更
|
|
134
|
+
git diff
|
|
135
|
+
|
|
136
|
+
# 回滚版本
|
|
137
|
+
git revert <commit-hash>
|
|
138
|
+
|
|
139
|
+
# 推送到远程仓库(可选)
|
|
140
|
+
git remote add origin <your-repo-url>
|
|
141
|
+
git push -u origin main
|
|
96
142
|
```
|
|
97
143
|
|
|
98
144
|
## 文档说明
|
|
@@ -134,8 +180,16 @@ cp -r doc-smith ~/.claude/skills/
|
|
|
134
180
|
## 注意事项
|
|
135
181
|
|
|
136
182
|
- 确保 Claude Code 已正确安装
|
|
137
|
-
-
|
|
138
|
-
-
|
|
183
|
+
- 确保 Git 已安装(用于 submodule 和版本管理)
|
|
184
|
+
- Workspace 需要在空目录中初始化
|
|
185
|
+
- 生成的文档在独立的 workspace 目录中,不会污染源仓库
|
|
186
|
+
|
|
187
|
+
## 迁移说明
|
|
188
|
+
|
|
189
|
+
如果你之前使用过旧版本(`.aigne/doc-smith/` 目录结构),建议:
|
|
190
|
+
1. 创建新的 workspace 目录
|
|
191
|
+
2. 重新生成文档
|
|
192
|
+
3. 旧版本数据可以手动迁移到新的 workspace 目录结构中
|
|
139
193
|
|
|
140
194
|
## 支持
|
|
141
195
|
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 虚拟 Bash 执行器 - Git 专用
|
|
6
|
+
* 支持的命令类型:
|
|
7
|
+
* - Git 操作: init, clone, config, status, log, diff, branch, show, add, commit, fetch, pull, submodule
|
|
8
|
+
*
|
|
9
|
+
* 安全限制:
|
|
10
|
+
* - 仅支持 git 命令,不支持其他 shell 命令
|
|
11
|
+
* - 所有命令必须来自预定义的安全枚举
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// 支持的命令枚举
|
|
15
|
+
const ALLOWED_COMMANDS = {
|
|
16
|
+
// Git 命令
|
|
17
|
+
git: {
|
|
18
|
+
// 初始化和克隆
|
|
19
|
+
init: true,
|
|
20
|
+
clone: true,
|
|
21
|
+
|
|
22
|
+
// 配置命令
|
|
23
|
+
config: true,
|
|
24
|
+
|
|
25
|
+
// 查询命令
|
|
26
|
+
status: true,
|
|
27
|
+
log: true,
|
|
28
|
+
diff: true,
|
|
29
|
+
branch: true,
|
|
30
|
+
show: true,
|
|
31
|
+
|
|
32
|
+
// 提交命令
|
|
33
|
+
add: true,
|
|
34
|
+
commit: true,
|
|
35
|
+
|
|
36
|
+
// 远程命令
|
|
37
|
+
fetch: true,
|
|
38
|
+
pull: true,
|
|
39
|
+
|
|
40
|
+
// 子模块命令
|
|
41
|
+
submodule: true,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 验证命令是否在允许列表中
|
|
47
|
+
*/
|
|
48
|
+
function validateCommand(command, args = []) {
|
|
49
|
+
const cmd = command.toLowerCase();
|
|
50
|
+
|
|
51
|
+
// 只支持 git 命令
|
|
52
|
+
if (cmd !== "git") {
|
|
53
|
+
throw new Error(`不支持的命令: ${cmd},仅支持 git 命令`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (args.length === 0) {
|
|
57
|
+
throw new Error("Git 命令需要指定子命令");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const subCommand = args[0].toLowerCase();
|
|
61
|
+
if (!ALLOWED_COMMANDS.git[subCommand]) {
|
|
62
|
+
throw new Error(`不支持的 git 子命令: ${subCommand}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 执行单个命令
|
|
70
|
+
*/
|
|
71
|
+
function executeCommand(command, args = []) {
|
|
72
|
+
try {
|
|
73
|
+
// 验证命令
|
|
74
|
+
validateCommand(command, args);
|
|
75
|
+
|
|
76
|
+
// 构建完整命令用于显示和日志
|
|
77
|
+
const fullCommand = [command, ...args].join(" ");
|
|
78
|
+
|
|
79
|
+
// 使用 spawnSync 可以同时捕获 stdout 和 stderr
|
|
80
|
+
const result = spawnSync(command, args, {
|
|
81
|
+
encoding: "utf-8",
|
|
82
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
83
|
+
timeout: 60000, // 60秒超时
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// 检查是否执行成功
|
|
87
|
+
if (result.status === 0 && !result.error) {
|
|
88
|
+
return {
|
|
89
|
+
success: true,
|
|
90
|
+
command: fullCommand,
|
|
91
|
+
output: result.stdout?.trim() || "",
|
|
92
|
+
error: result.stderr?.trim() || "", // 即使成功也返回 stderr,可能包含警告信息
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 命令执行失败
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
command: fullCommand,
|
|
100
|
+
output: result.stdout?.trim() || "",
|
|
101
|
+
error: result.stderr?.trim() || result.error?.message || "命令执行失败",
|
|
102
|
+
};
|
|
103
|
+
} catch (error) {
|
|
104
|
+
// 验证失败或其他异常
|
|
105
|
+
const fullCommand = [command, ...args].join(" ");
|
|
106
|
+
console.log(`[bash-executor] 异常: ${error.message}`);
|
|
107
|
+
return {
|
|
108
|
+
success: false,
|
|
109
|
+
command: fullCommand,
|
|
110
|
+
output: "",
|
|
111
|
+
error: error.message,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 按顺序执行多个命令
|
|
118
|
+
* 如果某个命令失败,立即停止执行后续命令
|
|
119
|
+
*/
|
|
120
|
+
function executeBatch(commands) {
|
|
121
|
+
const results = [];
|
|
122
|
+
|
|
123
|
+
for (const item of commands) {
|
|
124
|
+
const { command, args = [] } = item;
|
|
125
|
+
|
|
126
|
+
if (!command) {
|
|
127
|
+
const errorResult = {
|
|
128
|
+
success: false,
|
|
129
|
+
command: "",
|
|
130
|
+
output: "",
|
|
131
|
+
error: "命令不能为空",
|
|
132
|
+
};
|
|
133
|
+
results.push(errorResult);
|
|
134
|
+
// 命令为空视为失败,停止执行
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const result = executeCommand(command, args);
|
|
139
|
+
results.push(result);
|
|
140
|
+
|
|
141
|
+
// 如果命令失败,立即停止执行后续命令
|
|
142
|
+
if (!result.success) {
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return results;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 安全执行预定义的 Shell 命令
|
|
152
|
+
* @param {Object} params - 输入参数
|
|
153
|
+
* @param {Array} params.commands - 命令列表
|
|
154
|
+
* @returns {Object} - 执行结果
|
|
155
|
+
*/
|
|
156
|
+
export default function executeSafeShellCommands({ commands }) {
|
|
157
|
+
// 验证输入
|
|
158
|
+
if (!Array.isArray(commands)) {
|
|
159
|
+
return {
|
|
160
|
+
success: false,
|
|
161
|
+
error: "参数 commands 必须是一个数组",
|
|
162
|
+
results: [],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (commands.length === 0) {
|
|
167
|
+
return {
|
|
168
|
+
success: false,
|
|
169
|
+
error: "命令列表不能为空",
|
|
170
|
+
results: [],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 执行命令批次
|
|
175
|
+
const results = executeBatch(commands);
|
|
176
|
+
|
|
177
|
+
// 统计执行结果
|
|
178
|
+
const successCount = results.filter((r) => r.success).length;
|
|
179
|
+
const failureCount = results.length - successCount;
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
success: successCount > 0,
|
|
183
|
+
total: results.length,
|
|
184
|
+
succeeded: successCount,
|
|
185
|
+
failed: failureCount,
|
|
186
|
+
results,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// 添加描述信息,帮助 LLM 理解何时调用此 agent
|
|
191
|
+
executeSafeShellCommands.description =
|
|
192
|
+
"安全执行 Git 命令,支持的子命令包括: init/clone/config/status/log/diff/branch/show/add/commit/fetch/pull/submodule。" +
|
|
193
|
+
"适用于需要批量执行多个有顺序依赖的 git 操作,如果某个命令失败会立即停止执行后续命令。";
|
|
194
|
+
|
|
195
|
+
// 定义输入 schema
|
|
196
|
+
executeSafeShellCommands.input_schema = {
|
|
197
|
+
type: "object",
|
|
198
|
+
required: ["commands"],
|
|
199
|
+
properties: {
|
|
200
|
+
commands: {
|
|
201
|
+
type: "array",
|
|
202
|
+
description: "要执行的 Git 命令列表,按顺序执行",
|
|
203
|
+
items: {
|
|
204
|
+
type: "object",
|
|
205
|
+
required: ["command"],
|
|
206
|
+
properties: {
|
|
207
|
+
command: {
|
|
208
|
+
type: "string",
|
|
209
|
+
description: "命令名称,必须是 git",
|
|
210
|
+
enum: ["git"],
|
|
211
|
+
},
|
|
212
|
+
args: {
|
|
213
|
+
type: "array",
|
|
214
|
+
description:
|
|
215
|
+
"Git 子命令和参数列表,第一个参数必须是支持的子命令(init/clone/config/status/log/diff/branch/show/add/commit/fetch/pull/submodule)",
|
|
216
|
+
items: {
|
|
217
|
+
type: "string",
|
|
218
|
+
},
|
|
219
|
+
minItems: 1,
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
minItems: 1,
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// 定义输出 schema
|
|
229
|
+
executeSafeShellCommands.output_schema = {
|
|
230
|
+
type: "object",
|
|
231
|
+
required: ["success", "results"],
|
|
232
|
+
properties: {
|
|
233
|
+
success: {
|
|
234
|
+
type: "boolean",
|
|
235
|
+
description: "是否至少有一个命令执行成功",
|
|
236
|
+
},
|
|
237
|
+
total: {
|
|
238
|
+
type: "integer",
|
|
239
|
+
description: "总命令数(执行命令时存在)",
|
|
240
|
+
},
|
|
241
|
+
succeeded: {
|
|
242
|
+
type: "integer",
|
|
243
|
+
description: "成功执行的命令数(执行命令时存在)",
|
|
244
|
+
},
|
|
245
|
+
failed: {
|
|
246
|
+
type: "integer",
|
|
247
|
+
description: "失败的命令数(执行命令时存在)",
|
|
248
|
+
},
|
|
249
|
+
error: {
|
|
250
|
+
type: "string",
|
|
251
|
+
description: "全局错误信息(验证失败时存在)",
|
|
252
|
+
},
|
|
253
|
+
results: {
|
|
254
|
+
type: "array",
|
|
255
|
+
description: "每个命令的执行结果",
|
|
256
|
+
items: {
|
|
257
|
+
type: "object",
|
|
258
|
+
required: ["success", "command", "output", "error"],
|
|
259
|
+
properties: {
|
|
260
|
+
success: {
|
|
261
|
+
type: "boolean",
|
|
262
|
+
description: "该命令是否执行成功",
|
|
263
|
+
},
|
|
264
|
+
command: {
|
|
265
|
+
type: "string",
|
|
266
|
+
description: "执行的完整命令",
|
|
267
|
+
},
|
|
268
|
+
output: {
|
|
269
|
+
type: "string",
|
|
270
|
+
description: "命令的标准输出",
|
|
271
|
+
},
|
|
272
|
+
error: {
|
|
273
|
+
type: "string",
|
|
274
|
+
description: "错误信息,成功时为空字符串,失败时包含错误详情",
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export default async function preloadI18n(_, options) {
|
|
2
|
+
const content = `
|
|
3
|
+
## 系统架构
|
|
4
|
+
|
|
5
|
+
<!-- afs:image id="architecture-overview" key="snap-kit-architecture" desc="Snap Kit system architecture showing React frontend, Express API, and Crawler Engine components with their interactions" -->
|
|
6
|
+
|
|
7
|
+
Snap Kit 采用清晰的三层架构设计:
|
|
8
|
+
|
|
9
|
+
- **前端层**: React 19.1 + TypeScript + Vite,提供现代化的用户界面和实时仪表板
|
|
10
|
+
- **API 层**: Express 4.21 + TypeScript,提供 RESTful 接口、DID 认证和速率限制
|
|
11
|
+
- **引擎层**: Puppeteer + 队列系统 + SQLite,负责核心自动化和数据存储
|
|
12
|
+
`;
|
|
13
|
+
const resultWriter = await this.afs.write(
|
|
14
|
+
"/modules/doc-smith/docs/getting-started-image.md",
|
|
15
|
+
{
|
|
16
|
+
content,
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const image = await this.afs.getImageBySlot(
|
|
21
|
+
"/modules/doc-smith/docs/getting-started-image.md",
|
|
22
|
+
"architecture-overview",
|
|
23
|
+
{
|
|
24
|
+
view: {
|
|
25
|
+
format: "jpg",
|
|
26
|
+
},
|
|
27
|
+
context: options.context,
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const result = await this.afs.read(
|
|
32
|
+
"/modules/doc-smith/docs/getting-started.md",
|
|
33
|
+
{
|
|
34
|
+
view: {
|
|
35
|
+
language: "en",
|
|
36
|
+
},
|
|
37
|
+
context: options.context,
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
i18n: {
|
|
43
|
+
result,
|
|
44
|
+
image,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
preloadI18n.afs = {
|
|
50
|
+
modules: [
|
|
51
|
+
{
|
|
52
|
+
module: "local-fs",
|
|
53
|
+
options: {
|
|
54
|
+
name: "doc-smith",
|
|
55
|
+
localPath: "${CWD}/.aigne/doc-smith",
|
|
56
|
+
description:
|
|
57
|
+
"The Doc Smith workspace for storing intermediate and output files",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
drivers: [
|
|
62
|
+
{
|
|
63
|
+
driver: "i18n",
|
|
64
|
+
options: {
|
|
65
|
+
defaultSourceLanguage: "zh",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
driver: "image-generate",
|
|
70
|
+
options: {},
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { getMainLanguageFiles } from "../../utils/docs.mjs";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Check if documents exist in the docs directory
|
|
6
|
+
* @param {Object} params
|
|
7
|
+
* @param {string} params.docsDir - Documentation directory
|
|
8
|
+
* @param {string} params.locale - Main language locale
|
|
9
|
+
* @param {Array} params.documentStructure - Document structure
|
|
10
|
+
* @returns {Promise<Object>} - Result object
|
|
11
|
+
*/
|
|
12
|
+
export default async function checkDocs({ docsDir = "./docs" }) {
|
|
13
|
+
const mainLanguageFiles = await getMainLanguageFiles(docsDir);
|
|
14
|
+
|
|
15
|
+
if (mainLanguageFiles.length === 0) {
|
|
16
|
+
console.log(`⚠️ No documents found in the docs directory.`);
|
|
17
|
+
console.log(`💡 Please generate documentation first before publishing.`);
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
message: `Found ${mainLanguageFiles.length} document(s) in the docs directory`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
checkDocs.description = "Check if documents exist before publishing";
|
|
27
|
+
|
|
28
|
+
checkDocs.input_schema = {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
docsDir: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Documentation directory",
|
|
34
|
+
},
|
|
35
|
+
locale: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "Main language locale",
|
|
38
|
+
},
|
|
39
|
+
documentStructure: {
|
|
40
|
+
type: "array",
|
|
41
|
+
description: "Document structure",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type: team
|
|
2
|
+
name: publish
|
|
3
|
+
alias:
|
|
4
|
+
- pub
|
|
5
|
+
- p
|
|
6
|
+
description: Publish DocSmith generated documentation to the online platform
|
|
7
|
+
skills:
|
|
8
|
+
- url: ./init-config.mjs
|
|
9
|
+
default_input:
|
|
10
|
+
skipIfExists: true
|
|
11
|
+
- url: ./check-docs.mjs
|
|
12
|
+
- url: ./publish-docs.mjs
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { loadConfigFromFile, generateConfigYAML } from "../../utils/config.mjs";
|
|
6
|
+
import { getProjectInfo, detectSystemLanguage } from "../../utils/project.mjs";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Initialize configuration for publishing
|
|
10
|
+
* @param {Object} params
|
|
11
|
+
* @param {string} params.outputPath - Output path for config file
|
|
12
|
+
* @param {string} params.fileName - Config file name
|
|
13
|
+
* @param {boolean} params.skipIfExists - Skip if config file exists
|
|
14
|
+
* @param {boolean} params.checkOnly - Only check if config exists
|
|
15
|
+
* @param {string} params.appUrl - Optional app URL
|
|
16
|
+
* @returns {Promise<Object>} - Configuration object
|
|
17
|
+
*/
|
|
18
|
+
export default async function initConfig(
|
|
19
|
+
{
|
|
20
|
+
fileName = "config.yaml",
|
|
21
|
+
skipIfExists = false,
|
|
22
|
+
appUrl,
|
|
23
|
+
checkOnly = false,
|
|
24
|
+
} = {},
|
|
25
|
+
options
|
|
26
|
+
) {
|
|
27
|
+
// Detect workspace mode (new structure with config.yaml in root)
|
|
28
|
+
const configPath = "./";
|
|
29
|
+
|
|
30
|
+
// Check only mode
|
|
31
|
+
if (checkOnly) {
|
|
32
|
+
const filePath = join(configPath, fileName);
|
|
33
|
+
const configContent = await readFile(filePath, "utf8").catch(() => null);
|
|
34
|
+
|
|
35
|
+
if (!configContent || configContent.trim() === "") {
|
|
36
|
+
console.log("⚠️ No configuration file found.");
|
|
37
|
+
console.log(
|
|
38
|
+
`🚀 Configuration will be created automatically when you run the publish command.`
|
|
39
|
+
);
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const config = await loadConfigFromFile();
|
|
44
|
+
return { ...config, appUrl };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Skip if exists mode
|
|
48
|
+
if (skipIfExists) {
|
|
49
|
+
const filePath = join(configPath, fileName);
|
|
50
|
+
const configContent = await readFile(filePath, "utf8").catch(() => null);
|
|
51
|
+
|
|
52
|
+
if (configContent && configContent.trim() !== "") {
|
|
53
|
+
const config = await loadConfigFromFile();
|
|
54
|
+
return { ...config, appUrl };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Create new config with default values
|
|
59
|
+
const input = {};
|
|
60
|
+
|
|
61
|
+
// Detect system language
|
|
62
|
+
input.locale = detectSystemLanguage();
|
|
63
|
+
|
|
64
|
+
// Get project info
|
|
65
|
+
const projectInfo = await getProjectInfo();
|
|
66
|
+
input.projectName = projectInfo.name.trim();
|
|
67
|
+
input.projectDesc = projectInfo.description.trim();
|
|
68
|
+
input.projectLogo = projectInfo.icon;
|
|
69
|
+
|
|
70
|
+
input.docsDir = "./docs";
|
|
71
|
+
input.sourcesPath = ["sources/"];
|
|
72
|
+
input.translateLanguages = [];
|
|
73
|
+
|
|
74
|
+
// Generate YAML content
|
|
75
|
+
const yamlContent = generateConfigYAML(input);
|
|
76
|
+
|
|
77
|
+
// Save file
|
|
78
|
+
try {
|
|
79
|
+
const filePath = join(configPath, fileName);
|
|
80
|
+
const dirPath = dirname(filePath);
|
|
81
|
+
|
|
82
|
+
await mkdir(dirPath, { recursive: true });
|
|
83
|
+
await writeFile(filePath, yamlContent, "utf8");
|
|
84
|
+
|
|
85
|
+
console.log(
|
|
86
|
+
`\n✅ Configuration created successfully: ${chalk.cyan(filePath)}`
|
|
87
|
+
);
|
|
88
|
+
console.log(
|
|
89
|
+
"💡 You can edit this file to customize your publishing settings.\n"
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
if (skipIfExists) {
|
|
93
|
+
const config = await loadConfigFromFile();
|
|
94
|
+
return { ...config, appUrl };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {};
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error(`❌ Failed to create configuration file: ${error.message}`);
|
|
100
|
+
return {
|
|
101
|
+
inputGeneratorStatus: false,
|
|
102
|
+
inputGeneratorError: error.message,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
initConfig.description = "Initialize configuration for document publishing";
|
|
108
|
+
|
|
109
|
+
initConfig.input_schema = {
|
|
110
|
+
type: "object",
|
|
111
|
+
properties: {
|
|
112
|
+
outputPath: {
|
|
113
|
+
type: "string",
|
|
114
|
+
description: "Output path for config file",
|
|
115
|
+
},
|
|
116
|
+
fileName: {
|
|
117
|
+
type: "string",
|
|
118
|
+
description: "Config file name",
|
|
119
|
+
},
|
|
120
|
+
skipIfExists: {
|
|
121
|
+
type: "boolean",
|
|
122
|
+
description: "Skip if config file exists",
|
|
123
|
+
},
|
|
124
|
+
checkOnly: {
|
|
125
|
+
type: "boolean",
|
|
126
|
+
description: "Only check if config exists",
|
|
127
|
+
},
|
|
128
|
+
appUrl: {
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "App URL for publishing",
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
};
|