@aigne/doc-smith 0.9.8-alpha.2 → 0.9.8-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +43 -0
- package/README.md +94 -250
- package/aigne.yaml +2 -149
- package/doc-smith/SKILL.md +117 -0
- package/doc-smith/references/changeset_schema.md +118 -0
- package/doc-smith/references/document_structure_schema.md +139 -0
- package/doc-smith/references/document_update_guide.md +193 -0
- package/doc-smith/references/structure_confirmation_guide.md +133 -0
- package/doc-smith/references/structure_planning_guide.md +146 -0
- package/doc-smith/references/user_intent_guide.md +172 -0
- package/doc-smith.yaml +114 -0
- package/main-system-prompt.md +56 -0
- package/package.json +3 -69
- package/scripts/README.md +90 -0
- package/scripts/install.sh +86 -0
- package/scripts/uninstall.sh +52 -0
- package/CHANGELOG.md +0 -994
- package/LICENSE +0 -93
- package/agentic-agents/common/base-info.md +0 -53
- package/agentic-agents/common/planner.md +0 -168
- package/agentic-agents/common/worker.md +0 -93
- package/agentic-agents/create/index.yaml +0 -118
- package/agentic-agents/create/objective.md +0 -44
- package/agentic-agents/create/set-custom-prompt.mjs +0 -27
- package/agentic-agents/detail/index.yaml +0 -95
- package/agentic-agents/detail/objective.md +0 -9
- package/agentic-agents/detail/set-custom-prompt.mjs +0 -88
- package/agentic-agents/predict-resources/index.yaml +0 -44
- package/agentic-agents/predict-resources/instructions.md +0 -61
- package/agentic-agents/structure/design-rules.md +0 -39
- package/agentic-agents/structure/index.yaml +0 -86
- package/agentic-agents/structure/objective.md +0 -14
- package/agentic-agents/structure/review-criteria.md +0 -55
- package/agentic-agents/structure/set-custom-prompt.mjs +0 -78
- package/agentic-agents/utils/init-workspace-cache.mjs +0 -171
- package/agentic-agents/utils/load-base-sources.mjs +0 -20
- package/agentic-agents/workspace-cache-sharing-design.md +0 -671
- package/agents/chat/chat-system.md +0 -38
- package/agents/chat/index.mjs +0 -59
- package/agents/chat/skills/generate-document.yaml +0 -15
- package/agents/chat/skills/list-documents.mjs +0 -15
- package/agents/chat/skills/update-document.yaml +0 -24
- package/agents/clear/choose-contents.mjs +0 -192
- package/agents/clear/clear-auth-tokens.mjs +0 -88
- package/agents/clear/clear-deployment-config.mjs +0 -49
- package/agents/clear/clear-document-config.mjs +0 -36
- package/agents/clear/clear-document-structure.mjs +0 -102
- package/agents/clear/clear-generated-docs.mjs +0 -142
- package/agents/clear/clear-media-description.mjs +0 -129
- package/agents/clear/index.yaml +0 -26
- package/agents/create/analyze-diagram-type-llm.yaml +0 -160
- package/agents/create/analyze-diagram-type.mjs +0 -297
- package/agents/create/check-document-structure.yaml +0 -30
- package/agents/create/check-need-generate-structure.mjs +0 -105
- package/agents/create/document-structure-tools/add-document.mjs +0 -85
- package/agents/create/document-structure-tools/delete-document.mjs +0 -116
- package/agents/create/document-structure-tools/move-document.mjs +0 -109
- package/agents/create/document-structure-tools/update-document.mjs +0 -84
- package/agents/create/generate-diagram-image.yaml +0 -60
- package/agents/create/generate-structure.yaml +0 -117
- package/agents/create/index.yaml +0 -49
- package/agents/create/refine-document-structure.yaml +0 -12
- package/agents/create/replace-d2-with-image.mjs +0 -625
- package/agents/create/update-document-structure.yaml +0 -54
- package/agents/create/user-add-document/add-documents-to-structure.mjs +0 -90
- package/agents/create/user-add-document/find-documents-to-add-links.yaml +0 -47
- package/agents/create/user-add-document/index.yaml +0 -46
- package/agents/create/user-add-document/prepare-documents-to-translate.mjs +0 -22
- package/agents/create/user-add-document/print-add-document-summary.mjs +0 -63
- package/agents/create/user-add-document/review-documents-with-new-links.mjs +0 -110
- package/agents/create/user-remove-document/find-documents-with-invalid-links.mjs +0 -78
- package/agents/create/user-remove-document/index.yaml +0 -40
- package/agents/create/user-remove-document/prepare-documents-to-translate.mjs +0 -22
- package/agents/create/user-remove-document/print-remove-document-summary.mjs +0 -53
- package/agents/create/user-remove-document/remove-documents-from-structure.mjs +0 -99
- package/agents/create/user-remove-document/review-documents-with-invalid-links.mjs +0 -115
- package/agents/create/user-review-document-structure.mjs +0 -140
- package/agents/create/utils/init-current-content.mjs +0 -34
- package/agents/create/utils/merge-document-structures.mjs +0 -30
- package/agents/evaluate/code-snippet.mjs +0 -97
- package/agents/evaluate/document-structure.yaml +0 -67
- package/agents/evaluate/document.yaml +0 -82
- package/agents/evaluate/generate-report.mjs +0 -85
- package/agents/evaluate/index.yaml +0 -46
- package/agents/history/index.yaml +0 -6
- package/agents/history/view.mjs +0 -78
- package/agents/init/check.mjs +0 -16
- package/agents/init/index.mjs +0 -275
- package/agents/init/validate.mjs +0 -16
- package/agents/localize/choose-language.mjs +0 -107
- package/agents/localize/index.yaml +0 -58
- package/agents/localize/record-translation-history.mjs +0 -23
- package/agents/localize/translate-document.yaml +0 -24
- package/agents/localize/translate-multilingual.yaml +0 -51
- package/agents/media/batch-generate-media-description.yaml +0 -46
- package/agents/media/generate-media-description.yaml +0 -50
- package/agents/media/load-media-description.mjs +0 -256
- package/agents/prefs/index.mjs +0 -203
- package/agents/publish/index.yaml +0 -26
- package/agents/publish/publish-docs.mjs +0 -356
- package/agents/publish/translate-meta.mjs +0 -103
- package/agents/schema/document-structure-item.yaml +0 -26
- package/agents/schema/document-structure-refine-item.yaml +0 -23
- package/agents/schema/document-structure.yaml +0 -29
- package/agents/update/batch-generate-document.yaml +0 -27
- package/agents/update/batch-update-document.yaml +0 -7
- package/agents/update/check-diagram-flag.mjs +0 -116
- package/agents/update/check-document.mjs +0 -162
- package/agents/update/check-generate-diagram.mjs +0 -106
- package/agents/update/check-sync-image-flag.mjs +0 -55
- package/agents/update/check-update-is-single.mjs +0 -53
- package/agents/update/document-tools/update-document-content.mjs +0 -303
- package/agents/update/generate-diagram.yaml +0 -63
- package/agents/update/generate-document.yaml +0 -70
- package/agents/update/handle-document-update.yaml +0 -103
- package/agents/update/index.yaml +0 -79
- package/agents/update/pre-check-generate-diagram.yaml +0 -44
- package/agents/update/save-and-translate-document.mjs +0 -76
- package/agents/update/sync-images-and-exit.mjs +0 -148
- package/agents/update/update-document-detail.yaml +0 -71
- package/agents/update/update-single/update-single-document-detail.mjs +0 -280
- package/agents/update/update-single-document.yaml +0 -7
- package/agents/update/user-review-document.mjs +0 -272
- package/agents/utils/action-success.mjs +0 -16
- package/agents/utils/analyze-document-feedback-intent.yaml +0 -32
- package/agents/utils/analyze-feedback-intent.mjs +0 -136
- package/agents/utils/analyze-structure-feedback-intent.yaml +0 -29
- package/agents/utils/check-detail-result.mjs +0 -38
- package/agents/utils/check-feedback-refiner.mjs +0 -81
- package/agents/utils/choose-docs.mjs +0 -293
- package/agents/utils/document-icon-generate.yaml +0 -52
- package/agents/utils/document-title-streamline.yaml +0 -48
- package/agents/utils/ensure-document-icons.mjs +0 -129
- package/agents/utils/exit.mjs +0 -6
- package/agents/utils/feedback-refiner.yaml +0 -50
- package/agents/utils/find-item-by-path.mjs +0 -114
- package/agents/utils/find-user-preferences-by-path.mjs +0 -37
- package/agents/utils/format-document-structure.mjs +0 -35
- package/agents/utils/generate-document-or-skip.mjs +0 -41
- package/agents/utils/handle-diagram-operations.mjs +0 -263
- package/agents/utils/load-all-document-content.mjs +0 -30
- package/agents/utils/load-document-all-content.mjs +0 -84
- package/agents/utils/load-sources.mjs +0 -405
- package/agents/utils/map-reasoning-effort-level.mjs +0 -15
- package/agents/utils/post-generate.mjs +0 -144
- package/agents/utils/read-current-document-content.mjs +0 -46
- package/agents/utils/save-doc-translation.mjs +0 -61
- package/agents/utils/save-doc.mjs +0 -88
- package/agents/utils/save-output.mjs +0 -26
- package/agents/utils/save-sidebar.mjs +0 -51
- package/agents/utils/skip-if-content-exists.mjs +0 -27
- package/agents/utils/streamline-document-titles-if-needed.mjs +0 -88
- package/agents/utils/transform-detail-data-sources.mjs +0 -45
- package/agents/utils/update-branding.mjs +0 -84
- package/assets/report-template/report.html +0 -198
- package/docs-mcp/analyze-content-relevance.yaml +0 -50
- package/docs-mcp/analyze-docs-relevance.yaml +0 -59
- package/docs-mcp/docs-search.yaml +0 -42
- package/docs-mcp/get-docs-detail.mjs +0 -41
- package/docs-mcp/get-docs-structure.mjs +0 -16
- package/docs-mcp/read-doc-content.mjs +0 -119
- package/prompts/common/document/content-rules-core.md +0 -20
- package/prompts/common/document/markdown-syntax-rules.md +0 -65
- package/prompts/common/document/media-file-list-usage-rules.md +0 -18
- package/prompts/common/document/openapi-usage-rules.md +0 -189
- package/prompts/common/document/role-and-personality.md +0 -16
- package/prompts/common/document/user-preferences.md +0 -9
- package/prompts/common/document-structure/conflict-resolution-guidance.md +0 -16
- package/prompts/common/document-structure/document-icon-generate.md +0 -116
- package/prompts/common/document-structure/document-structure-rules.md +0 -43
- package/prompts/common/document-structure/document-title-streamline.md +0 -86
- package/prompts/common/document-structure/glossary.md +0 -7
- package/prompts/common/document-structure/intj-traits.md +0 -5
- package/prompts/common/document-structure/openapi-usage-rules.md +0 -28
- package/prompts/common/document-structure/output-constraints.md +0 -18
- package/prompts/common/document-structure/user-locale-rules.md +0 -10
- package/prompts/common/document-structure/user-preferences.md +0 -9
- package/prompts/detail/custom/admonition-usage-rules.md +0 -94
- package/prompts/detail/custom/code-block-usage-rules.md +0 -163
- package/prompts/detail/custom/custom-components/x-card-usage-rules.md +0 -63
- package/prompts/detail/custom/custom-components/x-cards-usage-rules.md +0 -83
- package/prompts/detail/custom/custom-components/x-field-desc-usage-rules.md +0 -120
- package/prompts/detail/custom/custom-components/x-field-group-usage-rules.md +0 -80
- package/prompts/detail/custom/custom-components/x-field-usage-rules.md +0 -189
- package/prompts/detail/custom/custom-components-usage-rules.md +0 -18
- package/prompts/detail/diagram/generate-image-system.md +0 -135
- package/prompts/detail/diagram/generate-image-user.md +0 -32
- package/prompts/detail/diagram/guide.md +0 -29
- package/prompts/detail/diagram/official-examples.md +0 -712
- package/prompts/detail/diagram/pre-check.md +0 -23
- package/prompts/detail/diagram/role-and-personality.md +0 -2
- package/prompts/detail/diagram/rules.md +0 -46
- package/prompts/detail/diagram/system-prompt.md +0 -1139
- package/prompts/detail/diagram/user-prompt.md +0 -43
- package/prompts/detail/generate/detail-example.md +0 -457
- package/prompts/detail/generate/document-rules.md +0 -45
- package/prompts/detail/generate/system-prompt.md +0 -61
- package/prompts/detail/generate/user-prompt.md +0 -99
- package/prompts/detail/jsx/rules.md +0 -6
- package/prompts/detail/update/system-prompt.md +0 -121
- package/prompts/detail/update/user-prompt.md +0 -41
- package/prompts/evaluate/document-structure.md +0 -93
- package/prompts/evaluate/document.md +0 -149
- package/prompts/media/media-description/system-prompt.md +0 -43
- package/prompts/media/media-description/user-prompt.md +0 -17
- package/prompts/structure/check-document-structure.md +0 -93
- package/prompts/structure/document-rules.md +0 -21
- package/prompts/structure/find-documents-to-add-links.md +0 -52
- package/prompts/structure/generate/system-prompt.md +0 -13
- package/prompts/structure/generate/user-prompt.md +0 -137
- package/prompts/structure/review/structure-review-system.md +0 -81
- package/prompts/structure/structure-example.md +0 -89
- package/prompts/structure/structure-getting-started.md +0 -10
- package/prompts/structure/update/system-prompt.md +0 -93
- package/prompts/structure/update/user-prompt.md +0 -43
- package/prompts/translate/admonition.md +0 -20
- package/prompts/translate/code-block.md +0 -33
- package/prompts/translate/glossary.md +0 -6
- package/prompts/translate/translate-document.md +0 -305
- package/prompts/utils/analyze-document-feedback-intent.md +0 -54
- package/prompts/utils/analyze-structure-feedback-intent.md +0 -43
- package/prompts/utils/feedback-refiner.md +0 -105
- package/types/document-schema.mjs +0 -55
- package/types/document-structure-schema.mjs +0 -261
- package/utils/auth-utils.mjs +0 -275
- package/utils/blocklet.mjs +0 -104
- package/utils/check-document-has-diagram.mjs +0 -95
- package/utils/conflict-detector.mjs +0 -149
- package/utils/constants/index.mjs +0 -620
- package/utils/constants/linter.mjs +0 -102
- package/utils/d2-utils.mjs +0 -198
- package/utils/debug.mjs +0 -3
- package/utils/delete-diagram-images.mjs +0 -99
- package/utils/deploy.mjs +0 -86
- package/utils/docs-finder-utils.mjs +0 -623
- package/utils/evaluate/report-utils.mjs +0 -132
- package/utils/extract-api.mjs +0 -32
- package/utils/file-utils.mjs +0 -960
- package/utils/history-utils.mjs +0 -203
- package/utils/icon-map.mjs +0 -26
- package/utils/image-compress.mjs +0 -75
- package/utils/kroki-utils.mjs +0 -173
- package/utils/linter/index.mjs +0 -50
- package/utils/load-config.mjs +0 -107
- package/utils/markdown/index.mjs +0 -26
- package/utils/markdown-checker.mjs +0 -694
- package/utils/mermaid-validator.mjs +0 -140
- package/utils/mermaid-worker-pool.mjs +0 -250
- package/utils/mermaid-worker.mjs +0 -233
- package/utils/openapi/index.mjs +0 -28
- package/utils/preferences-utils.mjs +0 -175
- package/utils/request.mjs +0 -10
- package/utils/store/index.mjs +0 -45
- package/utils/sync-diagram-to-translations.mjs +0 -262
- package/utils/upload-files.mjs +0 -231
- package/utils/utils.mjs +0 -1354
|
@@ -1,623 +0,0 @@
|
|
|
1
|
-
import { access, readdir, readFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import pLimit from "p-limit";
|
|
5
|
-
import yaml from "yaml";
|
|
6
|
-
import { pathExists } from "./file-utils.mjs";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Get action-specific text based on isTranslate flag
|
|
10
|
-
* @param {string} baseText - Base text template with {action} placeholder
|
|
11
|
-
* @param {string} action - doc action type
|
|
12
|
-
* @returns {string} Text with action replaced
|
|
13
|
-
*/
|
|
14
|
-
export function getActionText(baseText, action) {
|
|
15
|
-
return baseText.replace("{action}", action);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Convert path to flattened name format
|
|
20
|
-
* @param {string} path - Document path (e.g., "/api/users")
|
|
21
|
-
* @returns {string} Flattened name (e.g., "api-users")
|
|
22
|
-
*/
|
|
23
|
-
export function pathToFlatName(path) {
|
|
24
|
-
return path.replace(/^\//, "").replace(/\//g, "-");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Generate filename based on flattened path and locale
|
|
29
|
-
* @param {string} flatName - Flattened path name
|
|
30
|
-
* @param {string} locale - Main language locale (e.g., 'en', 'zh', 'fr')
|
|
31
|
-
* @returns {string} Generated filename
|
|
32
|
-
*/
|
|
33
|
-
export function generateFileName(flatName, locale) {
|
|
34
|
-
const isEnglish = locale === "en";
|
|
35
|
-
return isEnglish ? `${flatName}.md` : `${flatName}.${locale}.md`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Find a single item by path in documentation structure result and read its content
|
|
40
|
-
* @param {Array} documentStructure - Array of documentation structure items
|
|
41
|
-
* @param {string} docPath - Document path to find (supports .md filenames)
|
|
42
|
-
* @param {string} boardId - Board ID for fallback matching
|
|
43
|
-
* @param {string} docsDir - Docs directory path for reading content
|
|
44
|
-
* @param {string} locale - Main language locale (e.g., 'en', 'zh', 'fr')
|
|
45
|
-
* @returns {Promise<Object|null>} Found item with content or null
|
|
46
|
-
*/
|
|
47
|
-
export async function findItemByPath(documentStructure, docPath, boardId, docsDir, locale = "en") {
|
|
48
|
-
let foundItem = null;
|
|
49
|
-
let fileName = null;
|
|
50
|
-
|
|
51
|
-
// Check if docPath is a .md filename
|
|
52
|
-
if (docPath.endsWith(".md")) {
|
|
53
|
-
fileName = docPath;
|
|
54
|
-
const flatName = fileNameToFlatPath(docPath);
|
|
55
|
-
foundItem = findItemByFlatName(documentStructure, flatName);
|
|
56
|
-
} else {
|
|
57
|
-
// First try direct path matching
|
|
58
|
-
foundItem = documentStructure.find((item) => item.path === docPath);
|
|
59
|
-
|
|
60
|
-
// If not found and boardId is provided, try boardId-flattenedPath format matching
|
|
61
|
-
if (!foundItem && boardId) {
|
|
62
|
-
// Check if path starts with boardId followed by a dash
|
|
63
|
-
if (docPath.startsWith(`${boardId}-`)) {
|
|
64
|
-
// Extract the flattened path part after boardId-
|
|
65
|
-
const flattenedPath = docPath.substring(boardId.length + 1);
|
|
66
|
-
|
|
67
|
-
// Find item by comparing flattened paths
|
|
68
|
-
foundItem = documentStructure.find((item) => {
|
|
69
|
-
// Convert item.path to flattened format (replace / with -)
|
|
70
|
-
const itemFlattenedPath = item.path.replace(/^\//, "").replace(/\//g, "-");
|
|
71
|
-
return itemFlattenedPath === flattenedPath;
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Generate filename from found item path
|
|
77
|
-
if (foundItem) {
|
|
78
|
-
const itemFlattenedPath = foundItem.path.replace(/^\//, "").replace(/\//g, "-");
|
|
79
|
-
fileName = generateFileName(itemFlattenedPath, locale);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (!foundItem) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Read file content if docsDir is provided
|
|
88
|
-
let content = null;
|
|
89
|
-
if (docsDir && fileName) {
|
|
90
|
-
content = await readFileContent(docsDir, fileName);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Return item with content
|
|
94
|
-
const result = {
|
|
95
|
-
...foundItem,
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
if (content !== null) {
|
|
99
|
-
result.content = content;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return result;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Read file content from docs directory
|
|
107
|
-
* @param {string} docsDir - Docs directory path
|
|
108
|
-
* @param {string} fileName - File name to read
|
|
109
|
-
* @returns {Promise<string|null>} File content or null if failed
|
|
110
|
-
*/
|
|
111
|
-
/**
|
|
112
|
-
* Remove base64 encoded images from markdown content
|
|
113
|
-
* This prevents large binary data from being included in document content
|
|
114
|
-
* Base64 images are completely removed (not replaced with placeholders) because:
|
|
115
|
-
* 1. They significantly increase token usage without providing useful information to LLM
|
|
116
|
-
* 2. Normal image references (file paths) are preserved and should be used instead
|
|
117
|
-
* 3. Base64 images are typically temporary or erroneous entries
|
|
118
|
-
* @param {string} content - Markdown content that may contain base64 images
|
|
119
|
-
* @returns {string} - Content with base64 images completely removed
|
|
120
|
-
*/
|
|
121
|
-
function removeBase64Images(content) {
|
|
122
|
-
if (!content || typeof content !== "string") {
|
|
123
|
-
return content;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Match markdown image syntax with data URLs: 
|
|
127
|
-
// This regex matches:
|
|
128
|
-
// - 
|
|
129
|
-
// - 
|
|
130
|
-
// - [](link)
|
|
131
|
-
const base64ImageRegex = /!\[([^\]]*)\]\(data:image\/[^)]+\)/g;
|
|
132
|
-
|
|
133
|
-
// Completely remove base64 images (including the entire markdown image syntax)
|
|
134
|
-
// This maximizes token reduction while preserving normal image references
|
|
135
|
-
const cleanedContent = content.replace(base64ImageRegex, "");
|
|
136
|
-
|
|
137
|
-
return cleanedContent;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export async function readFileContent(docsDir, fileName) {
|
|
141
|
-
try {
|
|
142
|
-
const filePath = join(docsDir, fileName);
|
|
143
|
-
const content = await readFile(filePath, "utf-8");
|
|
144
|
-
|
|
145
|
-
// Remove base64 encoded images to reduce token usage
|
|
146
|
-
// Base64 image data is not useful for LLM processing and significantly increases token count
|
|
147
|
-
return removeBase64Images(content);
|
|
148
|
-
} catch (readError) {
|
|
149
|
-
console.warn(`⚠️ Could not read content from ${fileName}:`, readError.message);
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get main language markdown files from docs directory
|
|
156
|
-
* @param {string} docsDir - Docs directory path
|
|
157
|
-
* @param {string} locale - Main language locale (e.g., 'en', 'zh', 'fr')
|
|
158
|
-
* @param {Array} documentStructure - Array of documentation structure items to determine file order
|
|
159
|
-
* @returns {Promise<string[]>} Array of main language .md files ordered by documentStructure
|
|
160
|
-
*/
|
|
161
|
-
export async function getMainLanguageFiles(docsDir, locale, documentStructure = null) {
|
|
162
|
-
// Check if docsDir exists
|
|
163
|
-
try {
|
|
164
|
-
await access(docsDir);
|
|
165
|
-
} catch (error) {
|
|
166
|
-
if (error.code === "ENOENT") {
|
|
167
|
-
return [];
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
throw error;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const files = await readdir(docsDir);
|
|
174
|
-
|
|
175
|
-
// Filter for main language .md files (exclude _sidebar.md)
|
|
176
|
-
const filteredFiles = files.filter((file) => {
|
|
177
|
-
// Skip non-markdown files and _sidebar.md
|
|
178
|
-
if (!file.endsWith(".md") || file === "_sidebar.md") {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// If main language is English, return files without language suffix
|
|
183
|
-
// FIXME: 临时修改为 zh,后续需要优化
|
|
184
|
-
if (locale === "zh") {
|
|
185
|
-
// Return files that don't have language suffixes (e.g., overview.md, not overview.zh.md)
|
|
186
|
-
return !file.match(/\.\w+(-\w+)?\.md$/);
|
|
187
|
-
} else {
|
|
188
|
-
// For non-English main language, return files with the exact locale suffix
|
|
189
|
-
const localePattern = new RegExp(`\\.${locale}\\.md$`);
|
|
190
|
-
return localePattern.test(file);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// If documentStructure is provided, sort files according to the order in documentStructure
|
|
195
|
-
if (documentStructure && Array.isArray(documentStructure)) {
|
|
196
|
-
// Create a map from flat file name to documentation structure order
|
|
197
|
-
const orderMap = new Map();
|
|
198
|
-
documentStructure.forEach((item, index) => {
|
|
199
|
-
const itemFlattenedPath = item.path.replace(/^\//, "").replace(/\//g, "-");
|
|
200
|
-
const expectedFileName = generateFileName(itemFlattenedPath, locale);
|
|
201
|
-
orderMap.set(expectedFileName, index);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// Sort filtered files based on their order in documentStructure
|
|
205
|
-
return filteredFiles.sort((a, b) => {
|
|
206
|
-
const orderA = orderMap.get(a);
|
|
207
|
-
const orderB = orderMap.get(b);
|
|
208
|
-
|
|
209
|
-
// If both files are in the documentation structure, sort by order
|
|
210
|
-
if (orderA !== undefined && orderB !== undefined) {
|
|
211
|
-
return orderA - orderB;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// If only one file is in the documentation structure, it comes first
|
|
215
|
-
if (orderA !== undefined) return -1;
|
|
216
|
-
if (orderB !== undefined) return 1;
|
|
217
|
-
|
|
218
|
-
// If neither file is in the documentation structure, maintain alphabetical order
|
|
219
|
-
return a.localeCompare(b);
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// If no documentStructure provided, return files in alphabetical order
|
|
224
|
-
return filteredFiles.sort();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Convert filename to flattened path format
|
|
229
|
-
* @param {string} fileName - File name to convert
|
|
230
|
-
* @returns {string} Flattened path without .md extension and language suffix
|
|
231
|
-
*/
|
|
232
|
-
export function fileNameToFlatPath(fileName) {
|
|
233
|
-
// Remove .md extension first
|
|
234
|
-
let flatName = fileName.replace(/\.md$/, "");
|
|
235
|
-
|
|
236
|
-
// Remove language suffix if present (e.g., .zh, .zh-CN, .fr, etc.)
|
|
237
|
-
flatName = flatName.replace(/\.\w+(-\w+)?$/, "");
|
|
238
|
-
|
|
239
|
-
return flatName;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Find documentation structure item by flattened file name
|
|
244
|
-
* @param {Array} documentStructure - Array of documentation structure items
|
|
245
|
-
* @param {string} flatName - Flattened file name
|
|
246
|
-
* @returns {Object|null} Found item or null
|
|
247
|
-
*/
|
|
248
|
-
export function findItemByFlatName(documentStructure, flatName) {
|
|
249
|
-
return documentStructure.find((item) => {
|
|
250
|
-
const itemFlattenedPath = item.path.replace(/^\//, "").replace(/\//g, "-");
|
|
251
|
-
return itemFlattenedPath === flatName;
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Process selected files and convert to found items with content
|
|
257
|
-
* @param {string[]} selectedFiles - Array of selected file names
|
|
258
|
-
* @param {Array} documentStructure - Array of documentation structure items
|
|
259
|
-
* @param {string} docsDir - Docs directory path
|
|
260
|
-
* @returns {Promise<Object[]>} Array of found items with content
|
|
261
|
-
*/
|
|
262
|
-
export async function processSelectedFiles(selectedFiles, documentStructure, docsDir) {
|
|
263
|
-
const foundItems = [];
|
|
264
|
-
|
|
265
|
-
for (const selectedFile of selectedFiles) {
|
|
266
|
-
// Read the selected .md file content
|
|
267
|
-
const selectedFileContent = await readFileContent(docsDir, selectedFile);
|
|
268
|
-
|
|
269
|
-
// Convert filename back to path
|
|
270
|
-
const flatName = fileNameToFlatPath(selectedFile);
|
|
271
|
-
|
|
272
|
-
// Try to find matching item by comparing flattened paths
|
|
273
|
-
const foundItemByFile = findItemByFlatName(documentStructure, flatName);
|
|
274
|
-
|
|
275
|
-
if (foundItemByFile) {
|
|
276
|
-
const result = {
|
|
277
|
-
...foundItemByFile,
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
// Add content if we read it from user selection
|
|
281
|
-
if (selectedFileContent !== null) {
|
|
282
|
-
result.content = selectedFileContent;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
foundItems.push(result);
|
|
286
|
-
} else {
|
|
287
|
-
console.warn(`⚠️ No documentation structure item found for file: ${selectedFile}`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return foundItems;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Add feedback to all items in the array
|
|
296
|
-
* @param {Object[]} items - Array of items to add feedback to
|
|
297
|
-
* @param {string} feedback - Feedback text to add
|
|
298
|
-
* @returns {Object[]} Items with feedback added
|
|
299
|
-
*/
|
|
300
|
-
export function addFeedbackToItems(items, feedback) {
|
|
301
|
-
if (!feedback?.trim()) {
|
|
302
|
-
return items;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
return items.map((item) => ({
|
|
306
|
-
...item,
|
|
307
|
-
feedback: feedback.trim(),
|
|
308
|
-
}));
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Convert YAML document structure to flat array format
|
|
313
|
-
* @param {Object} yamlData - Parsed YAML data with documents array
|
|
314
|
-
* @returns {Array} Flat array of document structure items
|
|
315
|
-
*/
|
|
316
|
-
function convertYamlToStructure(yamlData) {
|
|
317
|
-
const result = [];
|
|
318
|
-
|
|
319
|
-
function flattenDocuments(documents, parentId = null) {
|
|
320
|
-
if (!Array.isArray(documents)) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
for (const doc of documents) {
|
|
325
|
-
if (!doc.path || !doc.title) {
|
|
326
|
-
continue;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Create structure item
|
|
330
|
-
const item = {
|
|
331
|
-
title: doc.title,
|
|
332
|
-
description: doc.description || "",
|
|
333
|
-
path: doc.path,
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
if (parentId) {
|
|
337
|
-
item.parentId = parentId;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (doc.icon) {
|
|
341
|
-
item.icon = doc.icon;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if (doc.sourcePaths) {
|
|
345
|
-
item.sourcePaths = doc.sourcePaths;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
result.push(item);
|
|
349
|
-
|
|
350
|
-
// Recursively process children
|
|
351
|
-
if (doc.children && Array.isArray(doc.children)) {
|
|
352
|
-
flattenDocuments(doc.children, doc.path);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
flattenDocuments(yamlData.documents);
|
|
358
|
-
return result;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Load document execution structure from structure-plan.json or document_structure.yaml
|
|
363
|
-
* @param {string} outputDir - Output directory containing structure files
|
|
364
|
-
* @returns {Promise<Array|null>} Document execution structure array or null if not found/failed
|
|
365
|
-
*/
|
|
366
|
-
export async function loadDocumentStructure(outputDir) {
|
|
367
|
-
if (!outputDir) {
|
|
368
|
-
return null;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Try loading structure-plan.json first
|
|
372
|
-
try {
|
|
373
|
-
const structurePlanPath = join(outputDir, "structure-plan.json");
|
|
374
|
-
const structureExists = await pathExists(structurePlanPath);
|
|
375
|
-
|
|
376
|
-
if (structureExists) {
|
|
377
|
-
const structureContent = await readFile(structurePlanPath, "utf8");
|
|
378
|
-
if (structureContent?.trim()) {
|
|
379
|
-
try {
|
|
380
|
-
// Validate that the content looks like JSON before parsing
|
|
381
|
-
const trimmedContent = structureContent.trim();
|
|
382
|
-
if (trimmedContent.startsWith("[") || trimmedContent.startsWith("{")) {
|
|
383
|
-
const parsed = JSON.parse(structureContent);
|
|
384
|
-
// Return array if it's an array, otherwise return null
|
|
385
|
-
if (Array.isArray(parsed)) {
|
|
386
|
-
return parsed;
|
|
387
|
-
}
|
|
388
|
-
} else {
|
|
389
|
-
console.warn("structure-plan.json contains non-JSON content, skipping parse");
|
|
390
|
-
}
|
|
391
|
-
} catch (parseError) {
|
|
392
|
-
console.error(`Failed to parse structure-plan.json: ${parseError.message}`);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
} catch (readError) {
|
|
397
|
-
// Only warn if it's not a "file not found" error
|
|
398
|
-
if (readError.code !== "ENOENT") {
|
|
399
|
-
console.warn(`Error reading structure-plan.json: ${readError.message}`);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Try loading document_structure.yaml as fallback
|
|
404
|
-
try {
|
|
405
|
-
const yamlPath = join(outputDir, "document_structure.yaml");
|
|
406
|
-
const yamlExists = await pathExists(yamlPath);
|
|
407
|
-
|
|
408
|
-
if (yamlExists) {
|
|
409
|
-
const yamlContent = await readFile(yamlPath, "utf8");
|
|
410
|
-
if (yamlContent?.trim()) {
|
|
411
|
-
try {
|
|
412
|
-
const parsed = yaml.parse(yamlContent);
|
|
413
|
-
if (parsed && parsed.documents) {
|
|
414
|
-
return convertYamlToStructure(parsed);
|
|
415
|
-
}
|
|
416
|
-
} catch (parseError) {
|
|
417
|
-
console.error(`Failed to parse document_structure.yaml: ${parseError.message}`);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
} catch (readError) {
|
|
422
|
-
// Only warn if it's not a "file not found" error
|
|
423
|
-
if (readError.code !== "ENOENT") {
|
|
424
|
-
console.warn(`Error reading document_structure.yaml: ${readError.message}`);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
return null;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Build allowed links set from document structure
|
|
433
|
-
* Includes both original paths and processed .md paths for link validation
|
|
434
|
-
* @param {Array} documentStructure - Array of documentation structure items with path property
|
|
435
|
-
* @returns {Set<string>} Set of allowed link paths
|
|
436
|
-
*/
|
|
437
|
-
export function buildAllowedLinksFromStructure(documentStructure) {
|
|
438
|
-
const allowedLinks = new Set();
|
|
439
|
-
|
|
440
|
-
if (!Array.isArray(documentStructure)) {
|
|
441
|
-
return allowedLinks;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
documentStructure.forEach((item) => {
|
|
445
|
-
if (!item?.path) {
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// Add original path
|
|
450
|
-
allowedLinks.add(item.path);
|
|
451
|
-
|
|
452
|
-
// Add processed .md path (same logic as processContent in utils.mjs)
|
|
453
|
-
let processedPath = item.path;
|
|
454
|
-
if (processedPath.startsWith(".")) {
|
|
455
|
-
processedPath = processedPath.replace(/^\./, "");
|
|
456
|
-
}
|
|
457
|
-
let flatPath = processedPath.replace(/^\//, "").replace(/\//g, "-");
|
|
458
|
-
flatPath = `./${flatPath}.md`;
|
|
459
|
-
allowedLinks.add(flatPath);
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
return allowedLinks;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
/**
|
|
466
|
-
* Build a tree structure from a flat document structure array using parentId
|
|
467
|
-
* @param {Array} documentStructure - Flat array of document structure items with path and parentId
|
|
468
|
-
* @returns {Object} Object containing rootNodes (array of root nodes) and nodeMap (Map for lookups)
|
|
469
|
-
*/
|
|
470
|
-
export function buildDocumentTree(documentStructure) {
|
|
471
|
-
// Create a map of nodes for easy lookup
|
|
472
|
-
const nodeMap = new Map();
|
|
473
|
-
const rootNodes = [];
|
|
474
|
-
|
|
475
|
-
// First pass: create node map
|
|
476
|
-
documentStructure.forEach((node) => {
|
|
477
|
-
nodeMap.set(node.path, {
|
|
478
|
-
...node,
|
|
479
|
-
children: [],
|
|
480
|
-
});
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
// Build the tree structure using parentId
|
|
484
|
-
documentStructure.forEach((node) => {
|
|
485
|
-
if (node.parentId) {
|
|
486
|
-
const parent = nodeMap.get(node.parentId);
|
|
487
|
-
if (parent) {
|
|
488
|
-
parent.children.push(nodeMap.get(node.path));
|
|
489
|
-
} else {
|
|
490
|
-
rootNodes.push(nodeMap.get(node.path));
|
|
491
|
-
}
|
|
492
|
-
} else {
|
|
493
|
-
rootNodes.push(nodeMap.get(node.path));
|
|
494
|
-
}
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
return { rootNodes, nodeMap };
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* Build checkbox choices from tree structure with visual hierarchy
|
|
502
|
-
* @param {Array} nodes - Array of tree nodes
|
|
503
|
-
* @param {string} prefix - Current prefix for indentation
|
|
504
|
-
* @param {number} depth - Current depth level (0 for root)
|
|
505
|
-
* @param {Object} context - Context object containing locale, docsDir, etc.
|
|
506
|
-
* @param {string} context.locale - Main language locale (e.g., 'en', 'zh', 'fr')
|
|
507
|
-
* @param {string} [context.docsDir] - Docs directory path for file existence check
|
|
508
|
-
* @returns {Promise<Array>} Array of choice objects
|
|
509
|
-
*/
|
|
510
|
-
export async function buildChoicesFromTree(nodes, prefix = "", depth = 0, context = {}) {
|
|
511
|
-
const { locale = "en", docsDir } = context;
|
|
512
|
-
const choices = [];
|
|
513
|
-
|
|
514
|
-
// Limit concurrent file checks to 50 per level to avoid overwhelming the file system
|
|
515
|
-
const limit = pLimit(50);
|
|
516
|
-
|
|
517
|
-
// Process nodes with controlled concurrency while maintaining order
|
|
518
|
-
const nodePromises = nodes.map((node, i) =>
|
|
519
|
-
limit(async () => {
|
|
520
|
-
const isLastSibling = i === nodes.length - 1;
|
|
521
|
-
const hasChildren = node.children && node.children.length > 0;
|
|
522
|
-
|
|
523
|
-
// Build the tree prefix - top level nodes don't have ├─ or └─
|
|
524
|
-
const treePrefix = depth === 0 ? "" : prefix + (isLastSibling ? "└─ " : "├─ ");
|
|
525
|
-
const flatName = pathToFlatName(node.path);
|
|
526
|
-
const filename = generateFileName(flatName, locale);
|
|
527
|
-
|
|
528
|
-
// Check file existence if docsDir is provided
|
|
529
|
-
let fileExists = true;
|
|
530
|
-
let missingFileText = "";
|
|
531
|
-
if (docsDir) {
|
|
532
|
-
const filePath = join(docsDir, filename);
|
|
533
|
-
fileExists = await pathExists(filePath);
|
|
534
|
-
if (!fileExists) {
|
|
535
|
-
missingFileText = chalk.red(" - file not found");
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
// warningText only shows when file exists, missingFileText has higher priority
|
|
540
|
-
const warningText =
|
|
541
|
-
fileExists && hasChildren ? chalk.yellow(" - will cascade delete all child documents") : "";
|
|
542
|
-
|
|
543
|
-
const displayName = `${treePrefix}${node.title} (${filename})${warningText}${missingFileText}`;
|
|
544
|
-
|
|
545
|
-
const choice = {
|
|
546
|
-
name: displayName,
|
|
547
|
-
value: node.path,
|
|
548
|
-
short: node.title,
|
|
549
|
-
disabled: !fileExists,
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
// Recursively process children
|
|
553
|
-
let childChoices = [];
|
|
554
|
-
if (hasChildren) {
|
|
555
|
-
const childPrefix = depth === 0 ? "" : prefix + (isLastSibling ? " " : "│ ");
|
|
556
|
-
childChoices = await buildChoicesFromTree(node.children, childPrefix, depth + 1, context);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
return { choice, childChoices };
|
|
560
|
-
}),
|
|
561
|
-
);
|
|
562
|
-
|
|
563
|
-
// Wait for all nodes at this level to complete, maintaining order
|
|
564
|
-
const results = await Promise.all(nodePromises);
|
|
565
|
-
|
|
566
|
-
// Build choices array in order
|
|
567
|
-
for (const { choice, childChoices } of results) {
|
|
568
|
-
choices.push(choice);
|
|
569
|
-
if (childChoices.length > 0) {
|
|
570
|
-
choices.push(...childChoices);
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
return choices;
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
/**
|
|
578
|
-
* Format document structure for printing
|
|
579
|
-
* @param {Array} structure - Document structure array
|
|
580
|
-
* @returns {Object} Object containing rootNodes and printNode function
|
|
581
|
-
*/
|
|
582
|
-
function formatDocumentStructure(structure) {
|
|
583
|
-
const { rootNodes } = buildDocumentTree(structure);
|
|
584
|
-
|
|
585
|
-
function printNode(node, depth = 0) {
|
|
586
|
-
const INDENT_SPACES = " ";
|
|
587
|
-
const FOLDER_ICON = " 📁";
|
|
588
|
-
const FILE_ICON = " 📄";
|
|
589
|
-
const indent = INDENT_SPACES.repeat(depth);
|
|
590
|
-
const prefix = depth === 0 ? FOLDER_ICON : FILE_ICON;
|
|
591
|
-
|
|
592
|
-
console.log(`${indent}${prefix} ${node.title}`);
|
|
593
|
-
|
|
594
|
-
if (node.children && node.children.length > 0) {
|
|
595
|
-
node.children.forEach((child) => {
|
|
596
|
-
printNode(child, depth + 1);
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
return { rootNodes, printNode };
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
/**
|
|
605
|
-
* Print document structure in a user-friendly format
|
|
606
|
-
* @param {Array} structure - Document structure array
|
|
607
|
-
*/
|
|
608
|
-
export function printDocumentStructure(structure) {
|
|
609
|
-
console.log(`\n ${"-".repeat(50)}`);
|
|
610
|
-
console.log(" Current Documentation Structure");
|
|
611
|
-
console.log(` ${"-".repeat(50)}`);
|
|
612
|
-
|
|
613
|
-
const { rootNodes, printNode } = formatDocumentStructure(structure);
|
|
614
|
-
|
|
615
|
-
if (rootNodes.length === 0) {
|
|
616
|
-
console.log(" No documentation structure found.");
|
|
617
|
-
} else {
|
|
618
|
-
rootNodes.forEach((node) => {
|
|
619
|
-
printNode(node);
|
|
620
|
-
});
|
|
621
|
-
}
|
|
622
|
-
console.log();
|
|
623
|
-
}
|