@aigne/doc-smith 0.2.4 ā 0.2.6
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/CHANGELOG.md +14 -0
- package/README.md +1 -0
- package/agents/check-detail-result.mjs +15 -120
- package/agents/check-structure-plan.mjs +56 -7
- package/agents/detail-generator-and-translate.yaml +7 -1
- package/agents/detail-regenerator.yaml +6 -57
- package/agents/docs-generator.yaml +5 -61
- package/agents/find-item-by-path.mjs +63 -14
- package/agents/input-generator.mjs +31 -21
- package/agents/language-selector.mjs +101 -0
- package/agents/load-config.mjs +3 -3
- package/agents/load-sources.mjs +55 -40
- package/agents/publish-docs.mjs +44 -153
- package/agents/retranslate.yaml +74 -0
- package/agents/save-docs.mjs +12 -2
- package/agents/save-output.mjs +9 -3
- package/agents/save-single-doc.mjs +19 -0
- package/agents/structure-planning.yaml +6 -0
- package/agents/team-publish-docs.yaml +7 -7
- package/agents/translate.yaml +3 -0
- package/aigne.yaml +5 -1
- package/docs-mcp/docs-search.yaml +1 -1
- package/docs-mcp/get-docs-detail.mjs +1 -1
- package/docs-mcp/get-docs-structure.mjs +1 -1
- package/docs-mcp/read-doc-content.mjs +1 -1
- package/package.json +16 -7
- package/prompts/check-structure-planning-result.md +4 -7
- package/prompts/content-detail-generator.md +1 -2
- package/prompts/structure-planning.md +7 -2
- package/prompts/translator.md +4 -0
- package/tests/test-all-validation-cases.mjs +707 -0
- package/utils/constants.mjs +3 -2
- package/utils/markdown-checker.mjs +386 -0
- package/utils/mermaid-validator.mjs +158 -0
- package/utils/mermaid-worker-pool.mjs +254 -0
- package/utils/mermaid-worker.mjs +242 -0
- package/utils/utils.mjs +155 -44
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { writeFile, mkdir, readFile } from "node:fs/promises";
|
|
2
2
|
import { join, dirname } from "node:path";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
validatePath,
|
|
6
|
+
getAvailablePaths,
|
|
7
|
+
getProjectInfo,
|
|
8
|
+
} from "../utils/utils.mjs";
|
|
5
9
|
import {
|
|
6
10
|
SUPPORTED_LANGUAGES,
|
|
7
11
|
DOCUMENT_STYLES,
|
|
8
12
|
TARGET_AUDIENCES,
|
|
9
13
|
} from "../utils/constants.mjs";
|
|
10
|
-
|
|
11
14
|
// UI constants
|
|
12
15
|
const PRESS_ENTER_TO_FINISH = "Press Enter to finish";
|
|
13
16
|
|
|
@@ -20,7 +23,7 @@ const PRESS_ENTER_TO_FINISH = "Press Enter to finish";
|
|
|
20
23
|
*/
|
|
21
24
|
export default async function init(
|
|
22
25
|
{
|
|
23
|
-
outputPath = "
|
|
26
|
+
outputPath = ".aigne/doc-smith",
|
|
24
27
|
fileName = "config.yaml",
|
|
25
28
|
skipIfExists = false,
|
|
26
29
|
},
|
|
@@ -40,11 +43,9 @@ export default async function init(
|
|
|
40
43
|
const input = {};
|
|
41
44
|
|
|
42
45
|
// 1. Document generation rules with style selection
|
|
43
|
-
console.log("š Step 1/6: Document Generation Rules");
|
|
44
|
-
|
|
45
46
|
// Let user select a document style
|
|
46
47
|
const styleChoice = await options.prompts.select({
|
|
47
|
-
message: "Choose your documentation style:",
|
|
48
|
+
message: "š Step 1/6: Choose your documentation style:",
|
|
48
49
|
choices: Object.entries(DOCUMENT_STYLES).map(([key, style]) => ({
|
|
49
50
|
name: `${style.name} - ${style.rules}`,
|
|
50
51
|
value: key,
|
|
@@ -65,11 +66,9 @@ export default async function init(
|
|
|
65
66
|
input.rules = rules.trim();
|
|
66
67
|
|
|
67
68
|
// 2. Target audience selection
|
|
68
|
-
console.log("\nš„ Step 2/6: Target Audience");
|
|
69
|
-
|
|
70
69
|
// Let user select target audience
|
|
71
70
|
const audienceChoice = await options.prompts.select({
|
|
72
|
-
message: "Who is your target audience?",
|
|
71
|
+
message: "š„ Step 2/6: Who is your target audience?",
|
|
73
72
|
choices: Object.entries(TARGET_AUDIENCES).map(([key, audience]) => ({
|
|
74
73
|
name: audience,
|
|
75
74
|
value: key,
|
|
@@ -90,11 +89,9 @@ export default async function init(
|
|
|
90
89
|
input.targetAudience = targetAudience.trim();
|
|
91
90
|
|
|
92
91
|
// 3. Language settings
|
|
93
|
-
console.log("\nš Step 3/6: Primary Language");
|
|
94
|
-
|
|
95
92
|
// Let user select primary language from supported list
|
|
96
93
|
const primaryLanguageChoice = await options.prompts.select({
|
|
97
|
-
message: "Choose primary documentation language:",
|
|
94
|
+
message: "š Step 3/6: Choose primary documentation language:",
|
|
98
95
|
choices: SUPPORTED_LANGUAGES.map((lang) => ({
|
|
99
96
|
name: `${lang.label} - ${lang.sample}`,
|
|
100
97
|
value: lang.code,
|
|
@@ -104,15 +101,13 @@ export default async function init(
|
|
|
104
101
|
input.locale = primaryLanguageChoice;
|
|
105
102
|
|
|
106
103
|
// 4. Translation languages
|
|
107
|
-
console.log("\nš Step 4/6: Translation Languages");
|
|
108
|
-
|
|
109
104
|
// Filter out the primary language from available choices
|
|
110
105
|
const availableTranslationLanguages = SUPPORTED_LANGUAGES.filter(
|
|
111
106
|
(lang) => lang.code !== primaryLanguageChoice
|
|
112
107
|
);
|
|
113
108
|
|
|
114
109
|
const translateLanguageChoices = await options.prompts.checkbox({
|
|
115
|
-
message: "Select translation languages:",
|
|
110
|
+
message: "š Step 4/6: Select translation languages:",
|
|
116
111
|
choices: availableTranslationLanguages.map((lang) => ({
|
|
117
112
|
name: `${lang.label} - ${lang.sample}`,
|
|
118
113
|
value: lang.code,
|
|
@@ -122,9 +117,8 @@ export default async function init(
|
|
|
122
117
|
input.translateLanguages = translateLanguageChoices;
|
|
123
118
|
|
|
124
119
|
// 5. Documentation directory
|
|
125
|
-
console.log("\nš Step 5/6: Output Directory");
|
|
126
120
|
const docsDirInput = await options.prompts.input({
|
|
127
|
-
message:
|
|
121
|
+
message: `š Step 5/6: Where to save generated docs:`,
|
|
128
122
|
default: `${outputPath}/docs`,
|
|
129
123
|
});
|
|
130
124
|
input.docsDir = docsDirInput.trim() || `${outputPath}/docs`;
|
|
@@ -189,6 +183,12 @@ export default async function init(
|
|
|
189
183
|
// If no paths entered, use default
|
|
190
184
|
input.sourcesPath = sourcePaths.length > 0 ? sourcePaths : ["./"];
|
|
191
185
|
|
|
186
|
+
// Save project info to config
|
|
187
|
+
const projectInfo = await getProjectInfo();
|
|
188
|
+
input.projectName = projectInfo.name;
|
|
189
|
+
input.projectDesc = projectInfo.description;
|
|
190
|
+
input.projectLogo = projectInfo.icon;
|
|
191
|
+
|
|
192
192
|
// Generate YAML content
|
|
193
193
|
const yamlContent = generateYAML(input, outputPath);
|
|
194
194
|
|
|
@@ -202,13 +202,17 @@ export default async function init(
|
|
|
202
202
|
|
|
203
203
|
await writeFile(filePath, yamlContent, "utf8");
|
|
204
204
|
console.log(`\nš Configuration saved to: ${chalk.cyan(filePath)}`);
|
|
205
|
+
// Print YAML content for user review
|
|
206
|
+
console.log(chalk.cyan("---"));
|
|
207
|
+
console.log(chalk.cyan(yamlContent));
|
|
208
|
+
console.log(chalk.cyan("---"));
|
|
205
209
|
console.log(
|
|
206
|
-
"š” You can edit the configuration file anytime to modify settings
|
|
210
|
+
"š” You can edit the configuration file anytime to modify settings.\n"
|
|
207
211
|
);
|
|
208
212
|
console.log(
|
|
209
213
|
`š Run ${chalk.cyan(
|
|
210
214
|
"'aigne doc generate'"
|
|
211
|
-
)} to start documentation generation
|
|
215
|
+
)} to start documentation generation!\n`
|
|
212
216
|
);
|
|
213
217
|
|
|
214
218
|
return {};
|
|
@@ -224,12 +228,18 @@ export default async function init(
|
|
|
224
228
|
/**
|
|
225
229
|
* Generate YAML configuration content
|
|
226
230
|
* @param {Object} input - Input object
|
|
227
|
-
* @param {string} outputPath - Output path for directory configuration
|
|
228
231
|
* @returns {string} YAML string
|
|
229
232
|
*/
|
|
230
|
-
function generateYAML(input
|
|
233
|
+
function generateYAML(input) {
|
|
231
234
|
let yaml = "";
|
|
232
235
|
|
|
236
|
+
// Add project information at the beginning
|
|
237
|
+
yaml += `# Project information for documentation publishing\n`;
|
|
238
|
+
yaml += `projectName: ${input.projectName || ""}\n`;
|
|
239
|
+
yaml += `projectDesc: ${input.projectDesc || ""}\n`;
|
|
240
|
+
yaml += `projectLogo: ${input.projectLogo || ""}\n`;
|
|
241
|
+
yaml += `\n`;
|
|
242
|
+
|
|
233
243
|
// Add rules (required field)
|
|
234
244
|
yaml += `rules: |\n`;
|
|
235
245
|
if (input.rules && input.rules.trim()) {
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { SUPPORTED_LANGUAGES } from "../utils/constants.mjs";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Interactive language selector for translation from configured languages
|
|
5
|
+
* @param {Object} params
|
|
6
|
+
* @param {Array<string>} [params.languages] - Pre-selected languages
|
|
7
|
+
* @param {Array<string>} params.translateLanguages - Available languages from config
|
|
8
|
+
* @param {Object} options - Options object with prompts
|
|
9
|
+
* @returns {Promise<Object>} Selected languages
|
|
10
|
+
*/
|
|
11
|
+
export default async function languageSelector(
|
|
12
|
+
{ languages, translateLanguages },
|
|
13
|
+
options
|
|
14
|
+
) {
|
|
15
|
+
let selectedLanguages = [];
|
|
16
|
+
|
|
17
|
+
// Check if translateLanguages is available from config
|
|
18
|
+
if (
|
|
19
|
+
!translateLanguages ||
|
|
20
|
+
!Array.isArray(translateLanguages) ||
|
|
21
|
+
translateLanguages.length === 0
|
|
22
|
+
) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
"No translation languages configured in config.yaml. Please add translateLanguages to your configuration."
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// If languages are provided as parameter, validate against configured languages
|
|
29
|
+
if (languages && Array.isArray(languages) && languages.length > 0) {
|
|
30
|
+
const validLanguages = languages.filter((lang) =>
|
|
31
|
+
translateLanguages.includes(lang)
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (validLanguages.length > 0) {
|
|
35
|
+
selectedLanguages = validLanguages;
|
|
36
|
+
} else {
|
|
37
|
+
console.log(`ā ļø Invalid languages provided: ${languages.join(", ")}`);
|
|
38
|
+
console.log(
|
|
39
|
+
"Available configured languages:",
|
|
40
|
+
translateLanguages.join(", ")
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// If no valid languages were provided, let user select from configured languages
|
|
46
|
+
if (selectedLanguages.length === 0) {
|
|
47
|
+
// Create choices from configured languages with labels
|
|
48
|
+
const choices = translateLanguages.map((langCode) => {
|
|
49
|
+
const supportedLang = SUPPORTED_LANGUAGES.find(
|
|
50
|
+
(l) => l.code === langCode
|
|
51
|
+
);
|
|
52
|
+
return {
|
|
53
|
+
name: supportedLang
|
|
54
|
+
? `${supportedLang.label} (${supportedLang.sample})`
|
|
55
|
+
: langCode,
|
|
56
|
+
value: langCode,
|
|
57
|
+
short: langCode,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
selectedLanguages = await options.prompts.checkbox({
|
|
62
|
+
message: "Select languages to translate:",
|
|
63
|
+
choices: choices,
|
|
64
|
+
validate: (answer) => {
|
|
65
|
+
if (answer.length === 0) {
|
|
66
|
+
return "Please select at least one language";
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (selectedLanguages.length === 0) {
|
|
74
|
+
throw new Error("No languages selected for re-translation");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
selectedLanguages,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
languageSelector.input_schema = {
|
|
83
|
+
type: "object",
|
|
84
|
+
properties: {
|
|
85
|
+
languages: {
|
|
86
|
+
type: "array",
|
|
87
|
+
items: {
|
|
88
|
+
type: "string",
|
|
89
|
+
},
|
|
90
|
+
description: "Pre-selected languages for translation",
|
|
91
|
+
},
|
|
92
|
+
translateLanguages: {
|
|
93
|
+
type: "array",
|
|
94
|
+
items: {
|
|
95
|
+
type: "string",
|
|
96
|
+
},
|
|
97
|
+
description: "Available translation languages from config",
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
required: ["translateLanguages"],
|
|
101
|
+
};
|
package/agents/load-config.mjs
CHANGED
|
@@ -22,8 +22,8 @@ export default async function loadConfig({ config }) {
|
|
|
22
22
|
nodeName: "Section",
|
|
23
23
|
locale: "en",
|
|
24
24
|
sourcesPath: ["./"],
|
|
25
|
-
|
|
26
|
-
outputDir: "
|
|
25
|
+
docsDir: "./.aigne/doc-smith/docs",
|
|
26
|
+
outputDir: "./.aigne/doc-smith/output",
|
|
27
27
|
lastGitHead: parsedConfig.lastGitHead || "",
|
|
28
28
|
...parsedConfig,
|
|
29
29
|
};
|
|
@@ -38,7 +38,7 @@ loadConfig.input_schema = {
|
|
|
38
38
|
properties: {
|
|
39
39
|
config: {
|
|
40
40
|
type: "string",
|
|
41
|
-
default: "
|
|
41
|
+
default: "./.aigne/doc-smith/config.yaml",
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
};
|
package/agents/load-sources.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { access, readFile } from "node:fs/promises";
|
|
1
|
+
import { access, readFile, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { glob } from "glob";
|
|
4
4
|
import {
|
|
@@ -115,50 +115,65 @@ export default async function loadSources({
|
|
|
115
115
|
|
|
116
116
|
for (const dir of paths) {
|
|
117
117
|
try {
|
|
118
|
-
//
|
|
119
|
-
const
|
|
118
|
+
// Check if the path is a file or directory
|
|
119
|
+
const stats = await stat(dir);
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
if (stats.isFile()) {
|
|
122
|
+
// If it's a file, add it directly without filtering
|
|
123
|
+
allFiles.push(dir);
|
|
124
|
+
} else if (stats.isDirectory()) {
|
|
125
|
+
// If it's a directory, use the existing glob logic
|
|
126
|
+
// Load .gitignore for this directory
|
|
127
|
+
const gitignorePatterns = await loadGitignore(dir);
|
|
124
128
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
? Array.isArray(includePatterns)
|
|
129
|
-
? includePatterns
|
|
130
|
-
: [includePatterns]
|
|
131
|
-
: [];
|
|
132
|
-
const userExclude = excludePatterns
|
|
133
|
-
? Array.isArray(excludePatterns)
|
|
134
|
-
? excludePatterns
|
|
135
|
-
: [excludePatterns]
|
|
136
|
-
: [];
|
|
129
|
+
// Prepare patterns
|
|
130
|
+
let finalIncludePatterns = null;
|
|
131
|
+
let finalExcludePatterns = null;
|
|
137
132
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
133
|
+
if (useDefaultPatterns) {
|
|
134
|
+
// Merge with default patterns
|
|
135
|
+
const userInclude = includePatterns
|
|
136
|
+
? Array.isArray(includePatterns)
|
|
137
|
+
? includePatterns
|
|
138
|
+
: [includePatterns]
|
|
139
|
+
: [];
|
|
140
|
+
const userExclude = excludePatterns
|
|
141
|
+
? Array.isArray(excludePatterns)
|
|
142
|
+
? excludePatterns
|
|
143
|
+
: [excludePatterns]
|
|
144
|
+
: [];
|
|
145
|
+
|
|
146
|
+
finalIncludePatterns = [
|
|
147
|
+
...DEFAULT_INCLUDE_PATTERNS,
|
|
148
|
+
...userInclude,
|
|
149
|
+
];
|
|
150
|
+
finalExcludePatterns = [
|
|
151
|
+
...DEFAULT_EXCLUDE_PATTERNS,
|
|
152
|
+
...userExclude,
|
|
153
|
+
];
|
|
154
|
+
} else {
|
|
155
|
+
// Use only user patterns
|
|
156
|
+
if (includePatterns) {
|
|
157
|
+
finalIncludePatterns = Array.isArray(includePatterns)
|
|
158
|
+
? includePatterns
|
|
159
|
+
: [includePatterns];
|
|
160
|
+
}
|
|
161
|
+
if (excludePatterns) {
|
|
162
|
+
finalExcludePatterns = Array.isArray(excludePatterns)
|
|
163
|
+
? excludePatterns
|
|
164
|
+
: [excludePatterns];
|
|
165
|
+
}
|
|
151
166
|
}
|
|
152
|
-
}
|
|
153
167
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
// Get files using glob
|
|
169
|
+
const filesInDir = await getFilesWithGlob(
|
|
170
|
+
dir,
|
|
171
|
+
finalIncludePatterns,
|
|
172
|
+
finalExcludePatterns,
|
|
173
|
+
gitignorePatterns
|
|
174
|
+
);
|
|
175
|
+
allFiles = allFiles.concat(filesInDir);
|
|
176
|
+
}
|
|
162
177
|
} catch (err) {
|
|
163
178
|
if (err.code !== "ENOENT") throw err;
|
|
164
179
|
}
|
package/agents/publish-docs.mjs
CHANGED
|
@@ -7,119 +7,12 @@ import { existsSync, mkdirSync } from "node:fs";
|
|
|
7
7
|
import { readFile, writeFile } from "node:fs/promises";
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
9
|
import { parse, stringify } from "yaml";
|
|
10
|
-
import { execSync } from "node:child_process";
|
|
11
10
|
import { basename } from "node:path";
|
|
12
11
|
import { loadConfigFromFile, saveValueToConfig } from "../utils/utils.mjs";
|
|
13
12
|
|
|
14
13
|
const WELLKNOWN_SERVICE_PATH_PREFIX = "/.well-known/service";
|
|
15
14
|
const DEFAULT_APP_URL = "https://docsmith.aigne.io";
|
|
16
15
|
|
|
17
|
-
/**
|
|
18
|
-
* Get GitHub repository information
|
|
19
|
-
* @param {string} repoUrl - The repository URL
|
|
20
|
-
* @returns {Promise<Object>} - Repository information
|
|
21
|
-
*/
|
|
22
|
-
async function getGitHubRepoInfo(repoUrl) {
|
|
23
|
-
try {
|
|
24
|
-
// Extract owner and repo from GitHub URL
|
|
25
|
-
const match = repoUrl.match(
|
|
26
|
-
/github\.com[\/:]([^\/]+)\/([^\/]+?)(?:\.git)?$/
|
|
27
|
-
);
|
|
28
|
-
if (!match) return null;
|
|
29
|
-
|
|
30
|
-
const [, owner, repo] = match;
|
|
31
|
-
const apiUrl = `https://api.github.com/repos/${owner}/${repo}`;
|
|
32
|
-
|
|
33
|
-
const response = await fetch(apiUrl);
|
|
34
|
-
if (!response.ok) return null;
|
|
35
|
-
|
|
36
|
-
const data = await response.json();
|
|
37
|
-
return {
|
|
38
|
-
name: data.name,
|
|
39
|
-
description: data.description || "",
|
|
40
|
-
icon: data.owner?.avatar_url || "",
|
|
41
|
-
};
|
|
42
|
-
} catch (error) {
|
|
43
|
-
console.warn("Failed to fetch GitHub repository info:", error.message);
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get project information with user confirmation
|
|
50
|
-
* @param {Object} options - Options object containing prompts
|
|
51
|
-
* @returns {Promise<Object>} - Project information including name, description, and icon
|
|
52
|
-
*/
|
|
53
|
-
async function getProjectInfo(options) {
|
|
54
|
-
let repoInfo = null;
|
|
55
|
-
let defaultName = basename(process.cwd());
|
|
56
|
-
let defaultDescription = "";
|
|
57
|
-
let defaultIcon = "";
|
|
58
|
-
|
|
59
|
-
// Check if we're in a git repository
|
|
60
|
-
try {
|
|
61
|
-
const gitRemote = execSync("git remote get-url origin", {
|
|
62
|
-
encoding: "utf8",
|
|
63
|
-
stdio: ["pipe", "pipe", "ignore"],
|
|
64
|
-
}).trim();
|
|
65
|
-
|
|
66
|
-
// Extract repository name from git remote URL
|
|
67
|
-
const repoName = gitRemote.split("/").pop().replace(".git", "");
|
|
68
|
-
defaultName = repoName;
|
|
69
|
-
|
|
70
|
-
// If it's a GitHub repository, try to get additional info
|
|
71
|
-
if (gitRemote.includes("github.com")) {
|
|
72
|
-
repoInfo = await getGitHubRepoInfo(gitRemote);
|
|
73
|
-
if (repoInfo) {
|
|
74
|
-
defaultDescription = repoInfo.description;
|
|
75
|
-
defaultIcon = repoInfo.icon;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
} catch (error) {
|
|
79
|
-
// Not in git repository or no origin remote, use current directory name
|
|
80
|
-
console.warn("No git repository found, using current directory name");
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Prompt user for project information
|
|
84
|
-
console.log("\nš Project Information for Documentation Platform");
|
|
85
|
-
|
|
86
|
-
const projectName = await options.prompts.input({
|
|
87
|
-
message: "Project name:",
|
|
88
|
-
default: defaultName,
|
|
89
|
-
validate: (input) => {
|
|
90
|
-
if (!input || input.trim() === "") {
|
|
91
|
-
return "Project name cannot be empty";
|
|
92
|
-
}
|
|
93
|
-
return true;
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const projectDescription = await options.prompts.input({
|
|
98
|
-
message: "Project description (optional):",
|
|
99
|
-
default: defaultDescription,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
const projectIcon = await options.prompts.input({
|
|
103
|
-
message: "Project icon URL (optional):",
|
|
104
|
-
default: defaultIcon,
|
|
105
|
-
validate: (input) => {
|
|
106
|
-
if (!input || input.trim() === "") return true;
|
|
107
|
-
try {
|
|
108
|
-
new URL(input);
|
|
109
|
-
return true;
|
|
110
|
-
} catch {
|
|
111
|
-
return "Please enter a valid URL";
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
name: projectName.trim(),
|
|
118
|
-
description: projectDescription.trim(),
|
|
119
|
-
icon: projectIcon.trim(),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
16
|
/**
|
|
124
17
|
* Get access token from environment, config file, or prompt user for authorization
|
|
125
18
|
* @param {string} appUrl - The application URL
|
|
@@ -207,7 +100,7 @@ async function getAccessToken(appUrl) {
|
|
|
207
100
|
}
|
|
208
101
|
|
|
209
102
|
export default async function publishDocs(
|
|
210
|
-
{ docsDir, appUrl, boardId,
|
|
103
|
+
{ docsDir, appUrl, boardId, projectName, projectDesc, projectLogo },
|
|
211
104
|
options
|
|
212
105
|
) {
|
|
213
106
|
// Check if DOC_DISCUSS_KIT_URL is set in environment variables
|
|
@@ -260,58 +153,56 @@ export default async function publishDocs(
|
|
|
260
153
|
|
|
261
154
|
const sidebarPath = join(docsDir, "_sidebar.md");
|
|
262
155
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
156
|
+
// Get project info from config
|
|
157
|
+
const projectInfo = {
|
|
158
|
+
name: projectName || config?.projectName || basename(process.cwd()),
|
|
159
|
+
description: projectDesc || config?.projectDesc || "",
|
|
160
|
+
icon: projectLogo || config?.projectLogo || "",
|
|
267
161
|
};
|
|
268
162
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
await
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
163
|
+
try {
|
|
164
|
+
const {
|
|
165
|
+
success,
|
|
166
|
+
boardId: newBoardId,
|
|
167
|
+
docsUrl,
|
|
168
|
+
} = await publishDocsFn({
|
|
169
|
+
sidebarPath,
|
|
170
|
+
accessToken,
|
|
171
|
+
appUrl,
|
|
172
|
+
boardId,
|
|
173
|
+
autoCreateBoard: true,
|
|
174
|
+
// Pass additional project information if available
|
|
175
|
+
boardName: projectInfo.name,
|
|
176
|
+
boardDesc: projectInfo.description,
|
|
177
|
+
boardCover: projectInfo.icon,
|
|
178
|
+
});
|
|
278
179
|
|
|
279
|
-
|
|
280
|
-
success
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
accessToken,
|
|
286
|
-
appUrl,
|
|
287
|
-
boardId,
|
|
288
|
-
autoCreateBoard: true,
|
|
289
|
-
// Pass additional project information if available
|
|
290
|
-
boardName: projectInfo.name,
|
|
291
|
-
boardDesc: projectInfo.description,
|
|
292
|
-
boardCover: projectInfo.icon,
|
|
293
|
-
});
|
|
180
|
+
// Save values to config.yaml if publish was successful
|
|
181
|
+
if (success) {
|
|
182
|
+
// Save appUrl to config only when not using environment variable
|
|
183
|
+
if (!useEnvAppUrl) {
|
|
184
|
+
await saveValueToConfig("appUrl", appUrl);
|
|
185
|
+
}
|
|
294
186
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
187
|
+
// Save boardId to config if it was auto-created
|
|
188
|
+
if (boardId !== newBoardId) {
|
|
189
|
+
await saveValueToConfig(
|
|
190
|
+
"boardId",
|
|
191
|
+
newBoardId,
|
|
192
|
+
"ā ļø Warning: boardId is auto-generated by system, please do not edit manually"
|
|
193
|
+
);
|
|
194
|
+
}
|
|
300
195
|
}
|
|
301
196
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
197
|
+
const message = `ā
Documentation Published Successfully!`;
|
|
198
|
+
return {
|
|
199
|
+
message,
|
|
200
|
+
};
|
|
201
|
+
} catch (error) {
|
|
202
|
+
return {
|
|
203
|
+
message: `ā Failed to publish docs: ${error.message}`,
|
|
204
|
+
};
|
|
306
205
|
}
|
|
307
|
-
|
|
308
|
-
// const message = `## ā
Documentation Published Successfully!
|
|
309
|
-
|
|
310
|
-
// Documentation is now available at: \`${docsUrl}\`
|
|
311
|
-
// `;
|
|
312
|
-
return {
|
|
313
|
-
// message,
|
|
314
|
-
};
|
|
315
206
|
}
|
|
316
207
|
|
|
317
208
|
publishDocs.input_schema = {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
type: team
|
|
2
|
+
name: retranslate
|
|
3
|
+
alias:
|
|
4
|
+
- rt
|
|
5
|
+
- translate-again
|
|
6
|
+
description: Re-translate individual document content to selected languages
|
|
7
|
+
skills:
|
|
8
|
+
- url: ./input-generator.mjs
|
|
9
|
+
default_input:
|
|
10
|
+
skipIfExists: true
|
|
11
|
+
- ./load-config.mjs
|
|
12
|
+
- ./load-sources.mjs
|
|
13
|
+
- type: transform
|
|
14
|
+
jsonata: |
|
|
15
|
+
$merge([
|
|
16
|
+
$,
|
|
17
|
+
{
|
|
18
|
+
'structurePlan': originalStructurePlan,
|
|
19
|
+
'structurePlanResult': $map(originalStructurePlan, function($item) {
|
|
20
|
+
$merge([
|
|
21
|
+
$item,
|
|
22
|
+
{
|
|
23
|
+
'translates': [$map(translateLanguages, function($lang) { {"language": $lang} })]
|
|
24
|
+
}
|
|
25
|
+
])
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
])
|
|
29
|
+
- url: ./find-item-by-path.mjs
|
|
30
|
+
default_input:
|
|
31
|
+
isTranslate: true
|
|
32
|
+
- ./language-selector.mjs
|
|
33
|
+
- type: transform
|
|
34
|
+
jsonata: |
|
|
35
|
+
$merge([
|
|
36
|
+
$,
|
|
37
|
+
{
|
|
38
|
+
'translates': [$map(selectedLanguages, function($lang) { {"language": $lang} })]
|
|
39
|
+
}
|
|
40
|
+
])
|
|
41
|
+
- ./batch-translate.yaml
|
|
42
|
+
- url: ./save-single-doc.mjs
|
|
43
|
+
default_input:
|
|
44
|
+
isTranslate: true
|
|
45
|
+
isShowMessage: true
|
|
46
|
+
input_schema:
|
|
47
|
+
type: object
|
|
48
|
+
properties:
|
|
49
|
+
glossary:
|
|
50
|
+
type: string
|
|
51
|
+
description: Glossary of terms for consistent terminology
|
|
52
|
+
doc-path:
|
|
53
|
+
type: string
|
|
54
|
+
description: Document path to retranslate
|
|
55
|
+
# languages:
|
|
56
|
+
# type: array
|
|
57
|
+
# items:
|
|
58
|
+
# type: string
|
|
59
|
+
# description: Languages to translate to
|
|
60
|
+
feedback:
|
|
61
|
+
type: string
|
|
62
|
+
description: Feedback for translation improvement
|
|
63
|
+
output_schema:
|
|
64
|
+
type: object
|
|
65
|
+
properties:
|
|
66
|
+
title:
|
|
67
|
+
type: string
|
|
68
|
+
description:
|
|
69
|
+
type: string
|
|
70
|
+
path:
|
|
71
|
+
type: string
|
|
72
|
+
content:
|
|
73
|
+
type: string
|
|
74
|
+
mode: sequential
|