@aigne/doc-smith 0.2.5 → 0.2.8
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 +26 -0
- package/README.md +1 -0
- package/agents/check-detail-result.mjs +13 -139
- package/agents/check-detail.mjs +4 -6
- package/agents/check-structure-plan.mjs +56 -12
- package/agents/detail-generator-and-translate.yaml +7 -1
- package/agents/detail-regenerator.yaml +3 -1
- package/agents/docs-generator.yaml +2 -1
- package/agents/find-item-by-path.mjs +64 -15
- package/agents/input-generator.mjs +31 -11
- package/agents/language-selector.mjs +89 -0
- package/agents/load-config.mjs +2 -2
- package/agents/load-sources.mjs +13 -40
- package/agents/publish-docs.mjs +47 -161
- package/agents/retranslate.yaml +74 -0
- package/agents/save-docs.mjs +19 -21
- package/agents/save-output.mjs +2 -9
- package/agents/save-single-doc.mjs +20 -1
- package/agents/schema/structure-plan.yaml +1 -1
- package/agents/structure-planning.yaml +6 -0
- package/agents/transform-detail-datasources.mjs +2 -5
- package/agents/translate.yaml +3 -0
- package/aigne.yaml +5 -1
- package/biome.json +13 -3
- package/docs-mcp/get-docs-structure.mjs +1 -1
- package/docs-mcp/read-doc-content.mjs +1 -4
- package/package.json +20 -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/check-detail-result.test.mjs +8 -19
- package/tests/load-sources.test.mjs +65 -161
- package/tests/test-all-validation-cases.mjs +741 -0
- package/tests/test-save-docs.mjs +6 -17
- package/utils/constants.mjs +1 -2
- package/utils/markdown-checker.mjs +453 -0
- package/utils/mermaid-validator.mjs +153 -0
- package/utils/mermaid-worker-pool.mjs +250 -0
- package/utils/mermaid-worker.mjs +233 -0
- package/utils/utils.mjs +162 -114
package/utils/utils.mjs
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { accessSync, constants, existsSync, mkdirSync, readdirSync, statSync } from "node:fs";
|
|
1
3
|
import fs from "node:fs/promises";
|
|
2
4
|
import path from "node:path";
|
|
3
|
-
import { execSync } from "node:child_process";
|
|
4
|
-
import {
|
|
5
|
-
existsSync,
|
|
6
|
-
mkdirSync,
|
|
7
|
-
readdirSync,
|
|
8
|
-
accessSync,
|
|
9
|
-
constants,
|
|
10
|
-
statSync,
|
|
11
|
-
} from "node:fs";
|
|
12
|
-
import { parse } from "yaml";
|
|
13
5
|
import chalk from "chalk";
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
DEFAULT_EXCLUDE_PATTERNS,
|
|
17
|
-
} from "./constants.mjs";
|
|
6
|
+
import { parse } from "yaml";
|
|
7
|
+
import { DEFAULT_EXCLUDE_PATTERNS, DEFAULT_INCLUDE_PATTERNS } from "./constants.mjs";
|
|
18
8
|
|
|
19
9
|
/**
|
|
20
10
|
* Normalize path to absolute path for consistent comparison
|
|
@@ -22,9 +12,7 @@ import {
|
|
|
22
12
|
* @returns {string} - Absolute path
|
|
23
13
|
*/
|
|
24
14
|
export function normalizePath(filePath) {
|
|
25
|
-
return path.isAbsolute(filePath)
|
|
26
|
-
? filePath
|
|
27
|
-
: path.resolve(process.cwd(), filePath);
|
|
15
|
+
return path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
|
|
28
16
|
}
|
|
29
17
|
|
|
30
18
|
/**
|
|
@@ -33,36 +21,31 @@ export function normalizePath(filePath) {
|
|
|
33
21
|
* @returns {string} - Relative path
|
|
34
22
|
*/
|
|
35
23
|
export function toRelativePath(filePath) {
|
|
36
|
-
return path.isAbsolute(filePath)
|
|
37
|
-
? path.relative(process.cwd(), filePath)
|
|
38
|
-
: filePath;
|
|
24
|
+
return path.isAbsolute(filePath) ? path.relative(process.cwd(), filePath) : filePath;
|
|
39
25
|
}
|
|
40
26
|
|
|
41
27
|
export function processContent({ content }) {
|
|
42
28
|
// Match markdown regular links [text](link), exclude images 
|
|
43
|
-
return content.replace(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (path.startsWith(".")) {
|
|
58
|
-
finalPath = path.replace(/^\./, "");
|
|
59
|
-
}
|
|
60
|
-
let flatPath = finalPath.replace(/^\//, "").replace(/\//g, "-");
|
|
61
|
-
flatPath = `./${flatPath}.md`;
|
|
62
|
-
const newLink = hash ? `${flatPath}#${hash}` : flatPath;
|
|
63
|
-
return `[${text}](${newLink})`;
|
|
29
|
+
return content.replace(/(?<!!)\[([^\]]+)\]\(([^)]+)\)/g, (match, text, link) => {
|
|
30
|
+
const trimLink = link.trim();
|
|
31
|
+
// Exclude external links and mailto
|
|
32
|
+
if (/^(https?:\/\/|mailto:)/.test(trimLink)) return match;
|
|
33
|
+
// Preserve anchors
|
|
34
|
+
const [path, hash] = trimLink.split("#");
|
|
35
|
+
// Skip if already has extension
|
|
36
|
+
if (/\.[a-zA-Z0-9]+$/.test(path)) return match;
|
|
37
|
+
// Only process relative paths or paths starting with /
|
|
38
|
+
if (!path) return match;
|
|
39
|
+
// Flatten to ./xxx-yyy.md
|
|
40
|
+
let finalPath = path;
|
|
41
|
+
if (path.startsWith(".")) {
|
|
42
|
+
finalPath = path.replace(/^\./, "");
|
|
64
43
|
}
|
|
65
|
-
|
|
44
|
+
let flatPath = finalPath.replace(/^\//, "").replace(/\//g, "-");
|
|
45
|
+
flatPath = `./${flatPath}.md`;
|
|
46
|
+
const newLink = hash ? `${flatPath}#${hash}` : flatPath;
|
|
47
|
+
return `[${text}](${newLink})`;
|
|
48
|
+
});
|
|
66
49
|
}
|
|
67
50
|
|
|
68
51
|
/**
|
|
@@ -83,6 +66,7 @@ export async function saveDocWithTranslations({
|
|
|
83
66
|
locale,
|
|
84
67
|
translates = [],
|
|
85
68
|
labels,
|
|
69
|
+
isTranslate = false,
|
|
86
70
|
}) {
|
|
87
71
|
const results = [];
|
|
88
72
|
try {
|
|
@@ -96,20 +80,22 @@ export async function saveDocWithTranslations({
|
|
|
96
80
|
return isEnglish ? `${flatName}.md` : `${flatName}.${language}.md`;
|
|
97
81
|
};
|
|
98
82
|
|
|
99
|
-
// Save main content with appropriate filename based on locale
|
|
100
|
-
|
|
101
|
-
|
|
83
|
+
// Save main content with appropriate filename based on locale (skip if isTranslate is true)
|
|
84
|
+
if (!isTranslate) {
|
|
85
|
+
const mainFileName = getFileName(locale);
|
|
86
|
+
const mainFilePath = path.join(docsDir, mainFileName);
|
|
102
87
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
88
|
+
// Add labels front matter if labels are provided
|
|
89
|
+
let finalContent = processContent({ content });
|
|
90
|
+
if (labels && labels.length > 0) {
|
|
91
|
+
const frontMatter = `---\nlabels: ${JSON.stringify(labels)}\n---\n\n`;
|
|
92
|
+
finalContent = frontMatter + finalContent;
|
|
93
|
+
}
|
|
109
94
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
95
|
+
await fs.writeFile(mainFilePath, finalContent, "utf8");
|
|
96
|
+
results.push({ path: mainFilePath, success: true });
|
|
97
|
+
console.log(chalk.green(`Saved: ${chalk.cyan(mainFilePath)}`));
|
|
98
|
+
}
|
|
113
99
|
|
|
114
100
|
// Process all translations
|
|
115
101
|
for (const translate of translates) {
|
|
@@ -187,7 +173,7 @@ export async function saveGitHeadToConfig(gitHead) {
|
|
|
187
173
|
if (fileContent && !fileContent.endsWith("\n")) {
|
|
188
174
|
fileContent += "\n";
|
|
189
175
|
}
|
|
190
|
-
fileContent += newLastGitHeadLine
|
|
176
|
+
fileContent += `${newLastGitHeadLine}\n`;
|
|
191
177
|
}
|
|
192
178
|
|
|
193
179
|
await fs.writeFile(inputFilePath, fileContent);
|
|
@@ -203,20 +189,13 @@ export async function saveGitHeadToConfig(gitHead) {
|
|
|
203
189
|
* @param {Array<string>} filePaths - Array of file paths to check
|
|
204
190
|
* @returns {Array<string>} - Array of modified file paths
|
|
205
191
|
*/
|
|
206
|
-
export function getModifiedFilesBetweenCommits(
|
|
207
|
-
fromCommit,
|
|
208
|
-
toCommit = "HEAD",
|
|
209
|
-
filePaths = []
|
|
210
|
-
) {
|
|
192
|
+
export function getModifiedFilesBetweenCommits(fromCommit, toCommit = "HEAD", filePaths = []) {
|
|
211
193
|
try {
|
|
212
194
|
// Get all modified files between commits
|
|
213
|
-
const modifiedFiles = execSync(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
stdio: ["pipe", "pipe", "ignore"],
|
|
218
|
-
}
|
|
219
|
-
)
|
|
195
|
+
const modifiedFiles = execSync(`git diff --name-only ${fromCommit}..${toCommit}`, {
|
|
196
|
+
encoding: "utf8",
|
|
197
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
198
|
+
})
|
|
220
199
|
.trim()
|
|
221
200
|
.split("\n")
|
|
222
201
|
.filter(Boolean);
|
|
@@ -231,12 +210,12 @@ export function getModifiedFilesBetweenCommits(
|
|
|
231
210
|
const absoluteFile = normalizePath(file);
|
|
232
211
|
const absoluteTarget = normalizePath(targetPath);
|
|
233
212
|
return absoluteFile === absoluteTarget;
|
|
234
|
-
})
|
|
213
|
+
}),
|
|
235
214
|
);
|
|
236
215
|
} catch (error) {
|
|
237
216
|
console.warn(
|
|
238
217
|
`Failed to get modified files between ${fromCommit} and ${toCommit}:`,
|
|
239
|
-
error.message
|
|
218
|
+
error.message,
|
|
240
219
|
);
|
|
241
220
|
return [];
|
|
242
221
|
}
|
|
@@ -258,7 +237,7 @@ export function hasSourceFilesChanged(sourceIds, modifiedFiles) {
|
|
|
258
237
|
const absoluteModifiedFile = normalizePath(modifiedFile);
|
|
259
238
|
const absoluteSourceId = normalizePath(sourceId);
|
|
260
239
|
return absoluteModifiedFile === absoluteSourceId;
|
|
261
|
-
})
|
|
240
|
+
}),
|
|
262
241
|
);
|
|
263
242
|
}
|
|
264
243
|
|
|
@@ -274,17 +253,14 @@ export function hasFileChangesBetweenCommits(
|
|
|
274
253
|
fromCommit,
|
|
275
254
|
toCommit = "HEAD",
|
|
276
255
|
includePatterns = DEFAULT_INCLUDE_PATTERNS,
|
|
277
|
-
excludePatterns = DEFAULT_EXCLUDE_PATTERNS
|
|
256
|
+
excludePatterns = DEFAULT_EXCLUDE_PATTERNS,
|
|
278
257
|
) {
|
|
279
258
|
try {
|
|
280
259
|
// Get file changes with status (A=added, D=deleted, M=modified)
|
|
281
|
-
const changes = execSync(
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
stdio: ["pipe", "pipe", "ignore"],
|
|
286
|
-
}
|
|
287
|
-
)
|
|
260
|
+
const changes = execSync(`git diff --name-status ${fromCommit}..${toCommit}`, {
|
|
261
|
+
encoding: "utf8",
|
|
262
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
263
|
+
})
|
|
288
264
|
.trim()
|
|
289
265
|
.split("\n")
|
|
290
266
|
.filter(Boolean);
|
|
@@ -306,10 +282,7 @@ export function hasFileChangesBetweenCommits(
|
|
|
306
282
|
// Check if file matches any include pattern
|
|
307
283
|
const matchesInclude = includePatterns.some((pattern) => {
|
|
308
284
|
// Convert glob pattern to regex for matching
|
|
309
|
-
const regexPattern = pattern
|
|
310
|
-
.replace(/\./g, "\\.")
|
|
311
|
-
.replace(/\*/g, ".*")
|
|
312
|
-
.replace(/\?/g, ".");
|
|
285
|
+
const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
313
286
|
const regex = new RegExp(regexPattern);
|
|
314
287
|
return regex.test(filePath);
|
|
315
288
|
});
|
|
@@ -321,10 +294,7 @@ export function hasFileChangesBetweenCommits(
|
|
|
321
294
|
// Check if file matches any exclude pattern
|
|
322
295
|
const matchesExclude = excludePatterns.some((pattern) => {
|
|
323
296
|
// Convert glob pattern to regex for matching
|
|
324
|
-
const regexPattern = pattern
|
|
325
|
-
.replace(/\./g, "\\.")
|
|
326
|
-
.replace(/\*/g, ".*")
|
|
327
|
-
.replace(/\?/g, ".");
|
|
297
|
+
const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
328
298
|
const regex = new RegExp(regexPattern);
|
|
329
299
|
return regex.test(filePath);
|
|
330
300
|
});
|
|
@@ -334,7 +304,7 @@ export function hasFileChangesBetweenCommits(
|
|
|
334
304
|
} catch (error) {
|
|
335
305
|
console.warn(
|
|
336
306
|
`Failed to check file changes between ${fromCommit} and ${toCommit}:`,
|
|
337
|
-
error.message
|
|
307
|
+
error.message,
|
|
338
308
|
);
|
|
339
309
|
return false;
|
|
340
310
|
}
|
|
@@ -345,11 +315,7 @@ export function hasFileChangesBetweenCommits(
|
|
|
345
315
|
* @returns {Promise<Object|null>} - The config object or null if file doesn't exist
|
|
346
316
|
*/
|
|
347
317
|
export async function loadConfigFromFile() {
|
|
348
|
-
const configPath = path.join(
|
|
349
|
-
process.cwd(),
|
|
350
|
-
"./.aigne/doc-smith",
|
|
351
|
-
"config.yaml"
|
|
352
|
-
);
|
|
318
|
+
const configPath = path.join(process.cwd(), "./.aigne/doc-smith", "config.yaml");
|
|
353
319
|
|
|
354
320
|
try {
|
|
355
321
|
if (!existsSync(configPath)) {
|
|
@@ -368,10 +334,11 @@ export async function loadConfigFromFile() {
|
|
|
368
334
|
* Save value to config.yaml file
|
|
369
335
|
* @param {string} key - The config key to save
|
|
370
336
|
* @param {string} value - The value to save
|
|
337
|
+
* @param {string} [comment] - Optional comment to add above the key
|
|
371
338
|
*/
|
|
372
|
-
export async function saveValueToConfig(key, value) {
|
|
373
|
-
if (
|
|
374
|
-
return; // Skip if
|
|
339
|
+
export async function saveValueToConfig(key, value, comment) {
|
|
340
|
+
if (value === undefined) {
|
|
341
|
+
return; // Skip if value is undefined
|
|
375
342
|
}
|
|
376
343
|
|
|
377
344
|
try {
|
|
@@ -389,18 +356,35 @@ export async function saveValueToConfig(key, value) {
|
|
|
389
356
|
}
|
|
390
357
|
|
|
391
358
|
// Check if key already exists in the file
|
|
392
|
-
const
|
|
393
|
-
const
|
|
359
|
+
const lines = fileContent.split("\n");
|
|
360
|
+
const keyRegex = new RegExp(`^${key}:\\s*.*$`);
|
|
361
|
+
const newKeyLine = `${key}: "${value}"`;
|
|
394
362
|
|
|
395
|
-
|
|
363
|
+
const keyIndex = lines.findIndex((line) => keyRegex.test(line));
|
|
364
|
+
|
|
365
|
+
if (keyIndex !== -1) {
|
|
396
366
|
// Replace existing key line
|
|
397
|
-
|
|
367
|
+
lines[keyIndex] = newKeyLine;
|
|
368
|
+
fileContent = lines.join("\n");
|
|
369
|
+
|
|
370
|
+
// Add comment if provided and not already present
|
|
371
|
+
if (comment && keyIndex > 0 && !lines[keyIndex - 1].trim().startsWith("# ")) {
|
|
372
|
+
// Add comment above the key if it doesn't already have one
|
|
373
|
+
lines.splice(keyIndex, 0, `# ${comment}`);
|
|
374
|
+
fileContent = lines.join("\n");
|
|
375
|
+
}
|
|
398
376
|
} else {
|
|
399
377
|
// Add key to the end of file
|
|
400
378
|
if (fileContent && !fileContent.endsWith("\n")) {
|
|
401
379
|
fileContent += "\n";
|
|
402
380
|
}
|
|
403
|
-
|
|
381
|
+
|
|
382
|
+
// Add comment if provided
|
|
383
|
+
if (comment) {
|
|
384
|
+
fileContent += `# ${comment}\n`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
fileContent += `${newKeyLine}\n`;
|
|
404
388
|
}
|
|
405
389
|
|
|
406
390
|
await fs.writeFile(configPath, fileContent);
|
|
@@ -429,7 +413,7 @@ export function validatePath(filePath) {
|
|
|
429
413
|
// Check if path is accessible (readable)
|
|
430
414
|
try {
|
|
431
415
|
accessSync(absolutePath, constants.R_OK);
|
|
432
|
-
} catch (
|
|
416
|
+
} catch (_accessError) {
|
|
433
417
|
return {
|
|
434
418
|
isValid: false,
|
|
435
419
|
error: `Path is not accessible: ${filePath}`,
|
|
@@ -440,7 +424,7 @@ export function validatePath(filePath) {
|
|
|
440
424
|
isValid: true,
|
|
441
425
|
error: null,
|
|
442
426
|
};
|
|
443
|
-
} catch (
|
|
427
|
+
} catch (_error) {
|
|
444
428
|
return {
|
|
445
429
|
isValid: false,
|
|
446
430
|
error: `Invalid path format: ${filePath}`,
|
|
@@ -563,10 +547,7 @@ export function getAvailablePaths(userInput = "") {
|
|
|
563
547
|
|
|
564
548
|
return uniqueResults;
|
|
565
549
|
} catch (error) {
|
|
566
|
-
console.warn(
|
|
567
|
-
`Failed to get available paths for "${userInput}":`,
|
|
568
|
-
error.message
|
|
569
|
-
);
|
|
550
|
+
console.warn(`Failed to get available paths for "${userInput}":`, error.message);
|
|
570
551
|
return [];
|
|
571
552
|
}
|
|
572
553
|
}
|
|
@@ -607,10 +588,7 @@ function getDirectoryContents(dirPath, searchTerm = "") {
|
|
|
607
588
|
}
|
|
608
589
|
|
|
609
590
|
// Filter by search term if provided
|
|
610
|
-
if (
|
|
611
|
-
searchTerm &&
|
|
612
|
-
!entryName.toLowerCase().includes(searchTerm.toLowerCase())
|
|
613
|
-
) {
|
|
591
|
+
if (searchTerm && !entryName.toLowerCase().includes(searchTerm.toLowerCase())) {
|
|
614
592
|
continue;
|
|
615
593
|
}
|
|
616
594
|
|
|
@@ -648,10 +626,80 @@ function getDirectoryContents(dirPath, searchTerm = "") {
|
|
|
648
626
|
|
|
649
627
|
return items;
|
|
650
628
|
} catch (error) {
|
|
651
|
-
console.warn(
|
|
652
|
-
`Failed to get directory contents from ${dirPath}:`,
|
|
653
|
-
error.message
|
|
654
|
-
);
|
|
629
|
+
console.warn(`Failed to get directory contents from ${dirPath}:`, error.message);
|
|
655
630
|
return [];
|
|
656
631
|
}
|
|
657
632
|
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Get GitHub repository information
|
|
636
|
+
* @param {string} repoUrl - The repository URL
|
|
637
|
+
* @returns {Promise<Object>} - Repository information
|
|
638
|
+
*/
|
|
639
|
+
export async function getGitHubRepoInfo(repoUrl) {
|
|
640
|
+
try {
|
|
641
|
+
// Extract owner and repo from GitHub URL
|
|
642
|
+
const match = repoUrl.match(/github\.com[/:]([^/]+)\/([^/]+?)(?:\.git)?$/);
|
|
643
|
+
if (!match) return null;
|
|
644
|
+
|
|
645
|
+
const [, owner, repo] = match;
|
|
646
|
+
const apiUrl = `https://api.github.com/repos/${owner}/${repo}`;
|
|
647
|
+
|
|
648
|
+
const response = await fetch(apiUrl);
|
|
649
|
+
if (!response.ok) return null;
|
|
650
|
+
|
|
651
|
+
const data = await response.json();
|
|
652
|
+
return {
|
|
653
|
+
name: data.name,
|
|
654
|
+
description: data.description || "",
|
|
655
|
+
icon: data.owner?.avatar_url || "",
|
|
656
|
+
};
|
|
657
|
+
} catch (error) {
|
|
658
|
+
console.warn("Failed to fetch GitHub repository info:", error.message);
|
|
659
|
+
return null;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Get project information automatically without user confirmation
|
|
665
|
+
* @returns {Promise<Object>} - Project information including name, description, icon, and fromGitHub flag
|
|
666
|
+
*/
|
|
667
|
+
export async function getProjectInfo() {
|
|
668
|
+
let repoInfo = null;
|
|
669
|
+
let defaultName = path.basename(process.cwd());
|
|
670
|
+
let defaultDescription = "";
|
|
671
|
+
let defaultIcon = "";
|
|
672
|
+
let fromGitHub = false;
|
|
673
|
+
|
|
674
|
+
// Check if we're in a git repository
|
|
675
|
+
try {
|
|
676
|
+
const gitRemote = execSync("git remote get-url origin", {
|
|
677
|
+
encoding: "utf8",
|
|
678
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
679
|
+
}).trim();
|
|
680
|
+
|
|
681
|
+
// Extract repository name from git remote URL
|
|
682
|
+
const repoName = gitRemote.split("/").pop().replace(".git", "");
|
|
683
|
+
defaultName = repoName;
|
|
684
|
+
|
|
685
|
+
// If it's a GitHub repository, try to get additional info
|
|
686
|
+
if (gitRemote.includes("github.com")) {
|
|
687
|
+
repoInfo = await getGitHubRepoInfo(gitRemote);
|
|
688
|
+
if (repoInfo) {
|
|
689
|
+
defaultDescription = repoInfo.description;
|
|
690
|
+
defaultIcon = repoInfo.icon;
|
|
691
|
+
fromGitHub = true;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
} catch (_error) {
|
|
695
|
+
// Not in git repository or no origin remote, use current directory name
|
|
696
|
+
console.warn("No git repository found, using current directory name");
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
return {
|
|
700
|
+
name: defaultName,
|
|
701
|
+
description: defaultDescription,
|
|
702
|
+
icon: defaultIcon,
|
|
703
|
+
fromGitHub,
|
|
704
|
+
};
|
|
705
|
+
}
|