@aigne/doc-smith 0.9.10 → 0.9.11-beta

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.
Files changed (308) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +189 -219
  3. package/README.zh.md +270 -0
  4. package/agents/bash-executor/index.mjs +347 -0
  5. package/agents/clear/ai/intent.md +142 -0
  6. package/agents/clear/choose-contents.mjs +13 -65
  7. package/agents/clear/clear-auth-tokens.mjs +17 -21
  8. package/agents/clear/clear-deployment-config.mjs +33 -24
  9. package/agents/clear/index.yaml +1 -9
  10. package/agents/content-checker/ai/intent.md +209 -0
  11. package/agents/content-checker/clean-invalid-docs.mjs +254 -0
  12. package/agents/content-checker/index.mjs +191 -0
  13. package/agents/content-checker/validate-content.mjs +983 -0
  14. package/agents/generate-images/generate-image.yaml +75 -0
  15. package/agents/generate-images/generate-summary.mjs +213 -0
  16. package/agents/generate-images/index.yaml +39 -0
  17. package/agents/generate-images/prepare-generation.mjs +286 -0
  18. package/agents/generate-images/prepare-image-generation.mjs +130 -0
  19. package/{prompts/detail/diagram/generate-image-system.md → agents/generate-images/prompts/system.md} +22 -56
  20. package/agents/generate-images/prompts/user.md +85 -0
  21. package/agents/generate-images/save-image-result.mjs +247 -0
  22. package/agents/generate-images/scan-image-slots.mjs +247 -0
  23. package/agents/localize/index.yaml +19 -42
  24. package/{prompts/translate → agents/localize/prompts}/translate-document.md +0 -139
  25. package/agents/localize/translate-documents/generate-summary.mjs +163 -0
  26. package/agents/localize/translate-documents/load-glossary.mjs +52 -0
  27. package/agents/localize/translate-documents/prepare-translation.mjs +249 -0
  28. package/agents/localize/translate-documents/save-translation.mjs +171 -0
  29. package/agents/localize/translate-documents/translate-document-to-language.mjs +209 -0
  30. package/agents/localize/translate-documents/translate-document.yaml +23 -0
  31. package/agents/localize/translate-documents/translate-to-languages.yaml +10 -0
  32. package/agents/localize/translate-images/check-image-translation.mjs +225 -0
  33. package/agents/localize/translate-images/detect-text/detect-and-update-shared.mjs +148 -0
  34. package/agents/localize/translate-images/detect-text/detect-image-text.yaml +44 -0
  35. package/agents/localize/translate-images/detect-text/detect-images-text.yaml +21 -0
  36. package/agents/localize/translate-images/detect-text/prompts/detect-image-text-system.md +43 -0
  37. package/agents/localize/translate-images/detect-text/prompts/detect-image-text-user.md +14 -0
  38. package/agents/localize/translate-images/detect-text/save-text-detection.mjs +105 -0
  39. package/agents/localize/translate-images/prepare-image-input.mjs +124 -0
  40. package/agents/localize/translate-images/save-image-translation.mjs +172 -0
  41. package/agents/localize/translate-images/scan-doc-images.mjs +165 -0
  42. package/agents/localize/translate-images/translate-doc-images.yaml +24 -0
  43. package/agents/localize/{translate-diagram.yaml → translate-images/translate-image.yaml} +25 -14
  44. package/agents/publish/ai/intent.md +182 -0
  45. package/agents/publish/check.mjs +107 -0
  46. package/agents/publish/index.yaml +9 -14
  47. package/agents/publish/publish-docs.mjs +81 -61
  48. package/agents/publish/translate-meta.mjs +79 -58
  49. package/agents/save-document/index.mjs +260 -0
  50. package/agents/structure-checker/index.mjs +307 -0
  51. package/agents/structure-checker/validate-structure.mjs +477 -0
  52. package/agents/update-image/analyze-feedback.yaml +37 -0
  53. package/agents/update-image/index.yaml +78 -0
  54. package/agents/update-image/load-existing-image.mjs +211 -0
  55. package/agents/update-image/prompts/analyze-feedback-system.md +43 -0
  56. package/agents/update-image/prompts/analyze-feedback-user.md +15 -0
  57. package/aigne.yaml +26 -139
  58. package/package.json +16 -48
  59. package/scripts/README.md +90 -0
  60. package/scripts/install.sh +86 -0
  61. package/scripts/uninstall.sh +52 -0
  62. package/skills/doc-smith/SKILL.md +285 -0
  63. package/skills/doc-smith/ai/intent/sources-improve.md +290 -0
  64. package/skills/doc-smith/references/changeset-guide.md +171 -0
  65. package/skills/doc-smith/references/document-content-guide.md +214 -0
  66. package/skills/doc-smith/references/document-structure-schema.md +138 -0
  67. package/skills/doc-smith/references/patch-guide.md +96 -0
  68. package/skills/doc-smith/references/structure-confirmation-guide.md +133 -0
  69. package/skills/doc-smith/references/structure-planning-guide.md +149 -0
  70. package/skills/doc-smith/references/update-workflow.md +108 -0
  71. package/skills/doc-smith/references/user-intent-guide.md +175 -0
  72. package/skills/doc-smith/references/workspace-initialization.md +376 -0
  73. package/skills/doc-smith-docs-detail/SKILL.md +356 -0
  74. package/skills/doc-smith-docs-detail/ai/intent.md +271 -0
  75. package/skills-entry/doc-smith/ai/intent.md +260 -0
  76. package/skills-entry/doc-smith/index.mjs +66 -0
  77. package/skills-entry/doc-smith/prompt.md +57 -0
  78. package/skills-entry/doc-smith/utils.mjs +27 -0
  79. package/skills-entry/doc-smith-docs-detail/batch.yaml +56 -0
  80. package/skills-entry/doc-smith-docs-detail/index.mjs +95 -0
  81. package/skills-entry/doc-smith-docs-detail/prompt.md +64 -0
  82. package/utils/afs-factory.mjs +183 -0
  83. package/utils/agent-constants.mjs +97 -0
  84. package/utils/{auth-utils.mjs → auth.mjs} +6 -9
  85. package/{agents/utils/update-branding.mjs → utils/branding.mjs} +3 -4
  86. package/utils/config.mjs +261 -0
  87. package/utils/constants.mjs +32 -0
  88. package/utils/deploy.mjs +3 -3
  89. package/utils/docs-converter.mjs +454 -0
  90. package/utils/docs.mjs +212 -0
  91. package/utils/document-paths.mjs +172 -0
  92. package/utils/files.mjs +74 -0
  93. package/utils/git.mjs +65 -0
  94. package/utils/{blocklet.mjs → http.mjs} +18 -0
  95. package/utils/image-slots.mjs +57 -0
  96. package/utils/image-utils.mjs +114 -0
  97. package/utils/project.mjs +95 -0
  98. package/utils/sources-path-resolver.mjs +76 -0
  99. package/utils/{upload-files.mjs → upload.mjs} +3 -3
  100. package/utils/workspace.mjs +371 -0
  101. package/agents/chat/chat-system.md +0 -38
  102. package/agents/chat/index.mjs +0 -59
  103. package/agents/chat/skills/generate-document.yaml +0 -15
  104. package/agents/chat/skills/list-documents.mjs +0 -15
  105. package/agents/chat/skills/update-document.yaml +0 -24
  106. package/agents/clear/clear-document-config.mjs +0 -36
  107. package/agents/clear/clear-document-structure.mjs +0 -102
  108. package/agents/clear/clear-generated-docs.mjs +0 -142
  109. package/agents/clear/clear-media-description.mjs +0 -129
  110. package/agents/create/aggregate-document-structure.mjs +0 -21
  111. package/agents/create/analyze-diagram-type-llm.yaml +0 -159
  112. package/agents/create/analyze-diagram-type.mjs +0 -455
  113. package/agents/create/check-document-structure.yaml +0 -30
  114. package/agents/create/check-need-generate-structure.mjs +0 -138
  115. package/agents/create/document-structure-tools/add-document.mjs +0 -85
  116. package/agents/create/document-structure-tools/delete-document.mjs +0 -116
  117. package/agents/create/document-structure-tools/move-document.mjs +0 -109
  118. package/agents/create/document-structure-tools/update-document.mjs +0 -84
  119. package/agents/create/generate-diagram-image.yaml +0 -91
  120. package/agents/create/generate-structure.yaml +0 -106
  121. package/agents/create/index.yaml +0 -45
  122. package/agents/create/refine-document-structure.yaml +0 -12
  123. package/agents/create/replace-d2-with-image.mjs +0 -610
  124. package/agents/create/update-document-structure.yaml +0 -54
  125. package/agents/create/user-add-document/add-documents-to-structure.mjs +0 -90
  126. package/agents/create/user-add-document/find-documents-to-add-links.yaml +0 -47
  127. package/agents/create/user-add-document/index.yaml +0 -46
  128. package/agents/create/user-add-document/prepare-documents-to-translate.mjs +0 -22
  129. package/agents/create/user-add-document/print-add-document-summary.mjs +0 -63
  130. package/agents/create/user-add-document/review-documents-with-new-links.mjs +0 -110
  131. package/agents/create/user-remove-document/find-documents-with-invalid-links.mjs +0 -78
  132. package/agents/create/user-remove-document/index.yaml +0 -40
  133. package/agents/create/user-remove-document/prepare-documents-to-translate.mjs +0 -22
  134. package/agents/create/user-remove-document/print-remove-document-summary.mjs +0 -53
  135. package/agents/create/user-remove-document/remove-documents-from-structure.mjs +0 -99
  136. package/agents/create/user-remove-document/review-documents-with-invalid-links.mjs +0 -115
  137. package/agents/create/user-review-document-structure.mjs +0 -139
  138. package/agents/create/utils/init-current-content.mjs +0 -34
  139. package/agents/create/utils/merge-document-structures.mjs +0 -36
  140. package/agents/evaluate/code-snippet.mjs +0 -97
  141. package/agents/evaluate/document-structure.yaml +0 -67
  142. package/agents/evaluate/document.yaml +0 -82
  143. package/agents/evaluate/generate-report.mjs +0 -85
  144. package/agents/evaluate/index.yaml +0 -46
  145. package/agents/history/index.yaml +0 -6
  146. package/agents/history/view.mjs +0 -78
  147. package/agents/init/check.mjs +0 -16
  148. package/agents/init/index.mjs +0 -643
  149. package/agents/init/validate.mjs +0 -16
  150. package/agents/localize/choose-language.mjs +0 -107
  151. package/agents/localize/record-translation-history.mjs +0 -23
  152. package/agents/localize/save-doc-translation-or-skip.mjs +0 -18
  153. package/agents/localize/set-review-content.mjs +0 -58
  154. package/agents/localize/translate-document-wrapper.mjs +0 -34
  155. package/agents/localize/translate-document.yaml +0 -24
  156. package/agents/localize/translate-multilingual.yaml +0 -57
  157. package/agents/localize/translate-or-skip-diagram.mjs +0 -52
  158. package/agents/media/batch-generate-media-description.yaml +0 -46
  159. package/agents/media/generate-media-description.yaml +0 -50
  160. package/agents/media/load-media-description.mjs +0 -454
  161. package/agents/prefs/index.mjs +0 -203
  162. package/agents/schema/document-structure-item.yaml +0 -26
  163. package/agents/schema/document-structure-refine-item.yaml +0 -23
  164. package/agents/schema/document-structure.yaml +0 -29
  165. package/agents/update/batch-generate-document.yaml +0 -27
  166. package/agents/update/batch-update-document.yaml +0 -7
  167. package/agents/update/check-diagram-flag.mjs +0 -116
  168. package/agents/update/check-document.mjs +0 -162
  169. package/agents/update/check-generate-diagram.mjs +0 -106
  170. package/agents/update/check-update-is-single.mjs +0 -53
  171. package/agents/update/document-tools/update-document-content.mjs +0 -303
  172. package/agents/update/generate-diagram.yaml +0 -80
  173. package/agents/update/generate-document.yaml +0 -70
  174. package/agents/update/handle-document-update.yaml +0 -103
  175. package/agents/update/index.yaml +0 -69
  176. package/agents/update/pre-check-generate-diagram.yaml +0 -44
  177. package/agents/update/save-and-translate-document.mjs +0 -80
  178. package/agents/update/update-document-detail.yaml +0 -71
  179. package/agents/update/update-single/update-single-document-detail.mjs +0 -322
  180. package/agents/update/update-single-document.yaml +0 -7
  181. package/agents/update/user-review-document.mjs +0 -272
  182. package/agents/utils/action-success.mjs +0 -16
  183. package/agents/utils/analyze-document-feedback-intent.yaml +0 -32
  184. package/agents/utils/analyze-feedback-intent.mjs +0 -253
  185. package/agents/utils/analyze-structure-feedback-intent.yaml +0 -29
  186. package/agents/utils/check-detail-result.mjs +0 -51
  187. package/agents/utils/check-feedback-refiner.mjs +0 -81
  188. package/agents/utils/choose-docs.mjs +0 -251
  189. package/agents/utils/document-icon-generate.yaml +0 -52
  190. package/agents/utils/document-title-streamline.yaml +0 -48
  191. package/agents/utils/ensure-document-icons.mjs +0 -129
  192. package/agents/utils/exit.mjs +0 -6
  193. package/agents/utils/feedback-refiner.yaml +0 -50
  194. package/agents/utils/find-item-by-path.mjs +0 -114
  195. package/agents/utils/find-user-preferences-by-path.mjs +0 -37
  196. package/agents/utils/format-document-structure.mjs +0 -35
  197. package/agents/utils/generate-document-or-skip.mjs +0 -41
  198. package/agents/utils/handle-diagram-operations.mjs +0 -263
  199. package/agents/utils/load-all-document-content.mjs +0 -30
  200. package/agents/utils/load-document-all-content.mjs +0 -96
  201. package/agents/utils/load-sources.mjs +0 -405
  202. package/agents/utils/map-reasoning-effort-level.mjs +0 -15
  203. package/agents/utils/post-generate.mjs +0 -133
  204. package/agents/utils/read-current-document-content.mjs +0 -46
  205. package/agents/utils/save-doc-translation.mjs +0 -30
  206. package/agents/utils/save-doc.mjs +0 -54
  207. package/agents/utils/save-output.mjs +0 -26
  208. package/agents/utils/save-sidebar.mjs +0 -38
  209. package/agents/utils/skip-if-content-exists.mjs +0 -27
  210. package/agents/utils/streamline-document-titles-if-needed.mjs +0 -88
  211. package/agents/utils/transform-detail-data-sources.mjs +0 -45
  212. package/assets/report-template/report.html +0 -198
  213. package/docs-mcp/analyze-content-relevance.yaml +0 -50
  214. package/docs-mcp/analyze-docs-relevance.yaml +0 -59
  215. package/docs-mcp/docs-search.yaml +0 -42
  216. package/docs-mcp/get-docs-detail.mjs +0 -41
  217. package/docs-mcp/get-docs-structure.mjs +0 -16
  218. package/docs-mcp/read-doc-content.mjs +0 -119
  219. package/prompts/common/document/content-rules-core.md +0 -20
  220. package/prompts/common/document/markdown-syntax-rules.md +0 -65
  221. package/prompts/common/document/media-file-list-usage-rules.md +0 -18
  222. package/prompts/common/document/openapi-usage-rules.md +0 -189
  223. package/prompts/common/document/role-and-personality.md +0 -16
  224. package/prompts/common/document/user-preferences.md +0 -9
  225. package/prompts/common/document-structure/conflict-resolution-guidance.md +0 -16
  226. package/prompts/common/document-structure/document-icon-generate.md +0 -116
  227. package/prompts/common/document-structure/document-structure-rules.md +0 -43
  228. package/prompts/common/document-structure/document-title-streamline.md +0 -86
  229. package/prompts/common/document-structure/glossary.md +0 -7
  230. package/prompts/common/document-structure/intj-traits.md +0 -5
  231. package/prompts/common/document-structure/openapi-usage-rules.md +0 -28
  232. package/prompts/common/document-structure/output-constraints.md +0 -18
  233. package/prompts/common/document-structure/user-locale-rules.md +0 -10
  234. package/prompts/common/document-structure/user-preferences.md +0 -9
  235. package/prompts/detail/custom/admonition-usage-rules.md +0 -94
  236. package/prompts/detail/custom/code-block-usage-rules.md +0 -163
  237. package/prompts/detail/custom/custom-components/x-card-usage-rules.md +0 -63
  238. package/prompts/detail/custom/custom-components/x-cards-usage-rules.md +0 -83
  239. package/prompts/detail/custom/custom-components/x-field-desc-usage-rules.md +0 -120
  240. package/prompts/detail/custom/custom-components/x-field-group-usage-rules.md +0 -80
  241. package/prompts/detail/custom/custom-components/x-field-usage-rules.md +0 -189
  242. package/prompts/detail/custom/custom-components-usage-rules.md +0 -18
  243. package/prompts/detail/diagram/generate-image-user.md +0 -81
  244. package/prompts/detail/diagram/guide.md +0 -29
  245. package/prompts/detail/diagram/official-examples.md +0 -712
  246. package/prompts/detail/diagram/pre-check.md +0 -23
  247. package/prompts/detail/diagram/role-and-personality.md +0 -2
  248. package/prompts/detail/diagram/rules.md +0 -46
  249. package/prompts/detail/diagram/system-prompt.md +0 -1139
  250. package/prompts/detail/diagram/user-prompt.md +0 -43
  251. package/prompts/detail/generate/detail-example.md +0 -457
  252. package/prompts/detail/generate/document-rules.md +0 -45
  253. package/prompts/detail/generate/system-prompt.md +0 -61
  254. package/prompts/detail/generate/user-prompt.md +0 -99
  255. package/prompts/detail/jsx/rules.md +0 -6
  256. package/prompts/detail/update/system-prompt.md +0 -121
  257. package/prompts/detail/update/user-prompt.md +0 -41
  258. package/prompts/evaluate/document-structure.md +0 -93
  259. package/prompts/evaluate/document.md +0 -149
  260. package/prompts/media/media-description/system-prompt.md +0 -43
  261. package/prompts/media/media-description/user-prompt.md +0 -17
  262. package/prompts/structure/check-document-structure.md +0 -93
  263. package/prompts/structure/document-rules.md +0 -21
  264. package/prompts/structure/find-documents-to-add-links.md +0 -52
  265. package/prompts/structure/generate/system-prompt.md +0 -13
  266. package/prompts/structure/generate/user-prompt.md +0 -137
  267. package/prompts/structure/review/structure-review-system.md +0 -81
  268. package/prompts/structure/structure-example.md +0 -89
  269. package/prompts/structure/structure-getting-started.md +0 -10
  270. package/prompts/structure/update/system-prompt.md +0 -93
  271. package/prompts/structure/update/user-prompt.md +0 -43
  272. package/prompts/translate/admonition.md +0 -20
  273. package/prompts/translate/code-block.md +0 -33
  274. package/prompts/utils/analyze-document-feedback-intent.md +0 -54
  275. package/prompts/utils/analyze-structure-feedback-intent.md +0 -43
  276. package/prompts/utils/feedback-refiner.md +0 -105
  277. package/types/document-schema.mjs +0 -55
  278. package/types/document-structure-schema.mjs +0 -261
  279. package/utils/check-document-has-diagram.mjs +0 -95
  280. package/utils/conflict-detector.mjs +0 -149
  281. package/utils/constants/index.mjs +0 -620
  282. package/utils/constants/linter.mjs +0 -102
  283. package/utils/d2-utils.mjs +0 -205
  284. package/utils/debug.mjs +0 -3
  285. package/utils/delete-diagram-images.mjs +0 -99
  286. package/utils/diagram-version-utils.mjs +0 -14
  287. package/utils/docs-finder-utils.mjs +0 -548
  288. package/utils/evaluate/report-utils.mjs +0 -132
  289. package/utils/extract-api.mjs +0 -32
  290. package/utils/file-utils.mjs +0 -960
  291. package/utils/history-utils.mjs +0 -203
  292. package/utils/icon-map.mjs +0 -26
  293. package/utils/image-compress.mjs +0 -154
  294. package/utils/kroki-utils.mjs +0 -173
  295. package/utils/linter/index.mjs +0 -50
  296. package/utils/load-config.mjs +0 -78
  297. package/utils/markdown/index.mjs +0 -26
  298. package/utils/markdown-checker.mjs +0 -694
  299. package/utils/mermaid-validator.mjs +0 -140
  300. package/utils/mermaid-worker-pool.mjs +0 -250
  301. package/utils/mermaid-worker.mjs +0 -233
  302. package/utils/openapi/index.mjs +0 -28
  303. package/utils/preferences-utils.mjs +0 -175
  304. package/utils/request.mjs +0 -10
  305. package/utils/sync-diagram-to-translations.mjs +0 -272
  306. package/utils/translate-diagram-images.mjs +0 -807
  307. package/utils/utils.mjs +0 -1354
  308. /package/{prompts/translate → agents/localize/prompts}/glossary.md +0 -0
@@ -1,548 +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 { pathExists } from "./file-utils.mjs";
6
-
7
- /**
8
- * Get action-specific text based on isTranslate flag
9
- * @param {string} baseText - Base text template with {action} placeholder
10
- * @param {string} action - doc action type
11
- * @returns {string} Text with action replaced
12
- */
13
- export function getActionText(baseText, action) {
14
- return baseText.replace("{action}", action);
15
- }
16
-
17
- /**
18
- * Convert path to flattened name format
19
- * @param {string} path - Document path (e.g., "/api/users")
20
- * @returns {string} Flattened name (e.g., "api-users")
21
- */
22
- export function pathToFlatName(path) {
23
- return path.replace(/^\//, "").replace(/\//g, "-");
24
- }
25
-
26
- /**
27
- * Generate filename based on flattened path and locale
28
- * @param {string} flatName - Flattened path name
29
- * @param {string} locale - Main language locale (e.g., 'en', 'zh', 'fr')
30
- * @returns {string} Generated filename
31
- */
32
- export function generateFileName(flatName, locale) {
33
- const isEnglish = locale === "en";
34
- return isEnglish ? `${flatName}.md` : `${flatName}.${locale}.md`;
35
- }
36
-
37
- /**
38
- * Find a single item by path in documentation structure result and read its content
39
- * @param {Array} documentStructure - Array of documentation structure items
40
- * @param {string} docPath - Document path to find (supports .md filenames)
41
- * @param {string} boardId - Board ID for fallback matching
42
- * @param {string} docsDir - Docs directory path for reading content
43
- * @param {string} locale - Main language locale (e.g., 'en', 'zh', 'fr')
44
- * @returns {Promise<Object|null>} Found item with content or null
45
- */
46
- export async function findItemByPath(documentStructure, docPath, boardId, docsDir, locale = "en") {
47
- let foundItem = null;
48
- let fileName = null;
49
-
50
- // Check if docPath is a .md filename
51
- if (docPath.endsWith(".md")) {
52
- fileName = docPath;
53
- const flatName = fileNameToFlatPath(docPath);
54
- foundItem = findItemByFlatName(documentStructure, flatName);
55
- } else {
56
- // First try direct path matching
57
- foundItem = documentStructure.find((item) => item.path === docPath);
58
-
59
- // If not found and boardId is provided, try boardId-flattenedPath format matching
60
- if (!foundItem && boardId) {
61
- // Check if path starts with boardId followed by a dash
62
- if (docPath.startsWith(`${boardId}-`)) {
63
- // Extract the flattened path part after boardId-
64
- const flattenedPath = docPath.substring(boardId.length + 1);
65
-
66
- // Find item by comparing flattened paths
67
- foundItem = documentStructure.find((item) => {
68
- // Convert item.path to flattened format (replace / with -)
69
- const itemFlattenedPath = item.path.replace(/^\//, "").replace(/\//g, "-");
70
- return itemFlattenedPath === flattenedPath;
71
- });
72
- }
73
- }
74
-
75
- // Generate filename from found item path
76
- if (foundItem) {
77
- const itemFlattenedPath = foundItem.path.replace(/^\//, "").replace(/\//g, "-");
78
- fileName = generateFileName(itemFlattenedPath, locale);
79
- }
80
- }
81
-
82
- if (!foundItem) {
83
- return null;
84
- }
85
-
86
- // Read file content if docsDir is provided
87
- let content = null;
88
- if (docsDir && fileName) {
89
- content = await readFileContent(docsDir, fileName);
90
- }
91
-
92
- // Return item with content
93
- const result = {
94
- ...foundItem,
95
- };
96
-
97
- if (content !== null) {
98
- result.content = content;
99
- }
100
-
101
- return result;
102
- }
103
-
104
- /**
105
- * Read file content from docs directory
106
- * @param {string} docsDir - Docs directory path
107
- * @param {string} fileName - File name to read
108
- * @returns {Promise<string|null>} File content or null if failed
109
- */
110
- /**
111
- * Remove base64 encoded images from markdown content
112
- * This prevents large binary data from being included in document content
113
- * Base64 images are completely removed (not replaced with placeholders) because:
114
- * 1. They significantly increase token usage without providing useful information to LLM
115
- * 2. Normal image references (file paths) are preserved and should be used instead
116
- * 3. Base64 images are typically temporary or erroneous entries
117
- * @param {string} content - Markdown content that may contain base64 images
118
- * @returns {string} - Content with base64 images completely removed
119
- */
120
- function removeBase64Images(content) {
121
- if (!content || typeof content !== "string") {
122
- return content;
123
- }
124
-
125
- // Match markdown image syntax with data URLs: ![alt](data:image/...;base64,...)
126
- // This regex matches:
127
- // - ![alt text](data:image/type;base64,base64data...)
128
- // - ![alt](data:image/type;base64,base64data...)
129
- // - [![alt](data:image/type;base64,base64data...)](link)
130
- const base64ImageRegex = /!\[([^\]]*)\]\(data:image\/[^)]+\)/g;
131
-
132
- // Completely remove base64 images (including the entire markdown image syntax)
133
- // This maximizes token reduction while preserving normal image references
134
- const cleanedContent = content.replace(base64ImageRegex, "");
135
-
136
- return cleanedContent;
137
- }
138
-
139
- export async function readFileContent(docsDir, fileName) {
140
- try {
141
- const filePath = join(docsDir, fileName);
142
- const content = await readFile(filePath, "utf-8");
143
-
144
- // Remove base64 encoded images to reduce token usage
145
- // Base64 image data is not useful for LLM processing and significantly increases token count
146
- return removeBase64Images(content);
147
- } catch (readError) {
148
- console.warn(`⚠️ Could not read content from ${fileName}:`, readError.message);
149
- return null;
150
- }
151
- }
152
-
153
- /**
154
- * Get main language markdown files from docs directory
155
- * @param {string} docsDir - Docs directory path
156
- * @param {string} locale - Main language locale (e.g., 'en', 'zh', 'fr')
157
- * @param {Array} documentStructure - Array of documentation structure items to determine file order
158
- * @returns {Promise<string[]>} Array of main language .md files ordered by documentStructure
159
- */
160
- export async function getMainLanguageFiles(docsDir, locale, documentStructure = null) {
161
- // Check if docsDir exists
162
- try {
163
- await access(docsDir);
164
- } catch (error) {
165
- if (error.code === "ENOENT") {
166
- return [];
167
- }
168
-
169
- throw error;
170
- }
171
-
172
- const files = await readdir(docsDir);
173
-
174
- // Filter for main language .md files (exclude _sidebar.md)
175
- const filteredFiles = files.filter((file) => {
176
- // Skip non-markdown files and _sidebar.md
177
- if (!file.endsWith(".md") || file === "_sidebar.md") {
178
- return false;
179
- }
180
-
181
- // If main language is English, return files without language suffix
182
- if (locale === "en") {
183
- // Return files that don't have language suffixes (e.g., overview.md, not overview.zh.md)
184
- return !file.match(/\.\w+(-\w+)?\.md$/);
185
- } else {
186
- // For non-English main language, return files with the exact locale suffix
187
- const localePattern = new RegExp(`\\.${locale}\\.md$`);
188
- return localePattern.test(file);
189
- }
190
- });
191
-
192
- // If documentStructure is provided, sort files according to the order in documentStructure
193
- if (documentStructure && Array.isArray(documentStructure)) {
194
- // Create a map from flat file name to documentation structure order
195
- const orderMap = new Map();
196
- documentStructure.forEach((item, index) => {
197
- const itemFlattenedPath = item.path.replace(/^\//, "").replace(/\//g, "-");
198
- const expectedFileName = generateFileName(itemFlattenedPath, locale);
199
- orderMap.set(expectedFileName, index);
200
- });
201
-
202
- // Sort filtered files based on their order in documentStructure
203
- return filteredFiles.sort((a, b) => {
204
- const orderA = orderMap.get(a);
205
- const orderB = orderMap.get(b);
206
-
207
- // If both files are in the documentation structure, sort by order
208
- if (orderA !== undefined && orderB !== undefined) {
209
- return orderA - orderB;
210
- }
211
-
212
- // If only one file is in the documentation structure, it comes first
213
- if (orderA !== undefined) return -1;
214
- if (orderB !== undefined) return 1;
215
-
216
- // If neither file is in the documentation structure, maintain alphabetical order
217
- return a.localeCompare(b);
218
- });
219
- }
220
-
221
- // If no documentStructure provided, return files in alphabetical order
222
- return filteredFiles.sort();
223
- }
224
-
225
- /**
226
- * Convert filename to flattened path format
227
- * @param {string} fileName - File name to convert
228
- * @returns {string} Flattened path without .md extension and language suffix
229
- */
230
- export function fileNameToFlatPath(fileName) {
231
- // Remove .md extension first
232
- let flatName = fileName.replace(/\.md$/, "");
233
-
234
- // Remove language suffix if present (e.g., .zh, .zh-CN, .fr, etc.)
235
- flatName = flatName.replace(/\.\w+(-\w+)?$/, "");
236
-
237
- return flatName;
238
- }
239
-
240
- /**
241
- * Find documentation structure item by flattened file name
242
- * @param {Array} documentStructure - Array of documentation structure items
243
- * @param {string} flatName - Flattened file name
244
- * @returns {Object|null} Found item or null
245
- */
246
- export function findItemByFlatName(documentStructure, flatName) {
247
- return documentStructure.find((item) => {
248
- const itemFlattenedPath = item.path.replace(/^\//, "").replace(/\//g, "-");
249
- return itemFlattenedPath === flatName;
250
- });
251
- }
252
-
253
- /**
254
- * Process selected files and convert to found items with content
255
- * @param {string[]} selectedFiles - Array of selected file names
256
- * @param {Array} documentStructure - Array of documentation structure items
257
- * @param {string} docsDir - Docs directory path
258
- * @returns {Promise<Object[]>} Array of found items with content
259
- */
260
- export async function processSelectedFiles(selectedFiles, documentStructure, docsDir) {
261
- const foundItems = [];
262
-
263
- for (const selectedFile of selectedFiles) {
264
- // Read the selected .md file content
265
- const selectedFileContent = await readFileContent(docsDir, selectedFile);
266
-
267
- // Convert filename back to path
268
- const flatName = fileNameToFlatPath(selectedFile);
269
-
270
- // Try to find matching item by comparing flattened paths
271
- const foundItemByFile = findItemByFlatName(documentStructure, flatName);
272
-
273
- if (foundItemByFile) {
274
- const result = {
275
- ...foundItemByFile,
276
- };
277
-
278
- // Add content if we read it from user selection
279
- if (selectedFileContent !== null) {
280
- result.content = selectedFileContent;
281
- }
282
-
283
- foundItems.push(result);
284
- } else {
285
- console.warn(`⚠️ No documentation structure item found for file: ${selectedFile}`);
286
- }
287
- }
288
-
289
- return foundItems;
290
- }
291
-
292
- /**
293
- * Add feedback to all items in the array
294
- * @param {Object[]} items - Array of items to add feedback to
295
- * @param {string} feedback - Feedback text to add
296
- * @returns {Object[]} Items with feedback added
297
- */
298
- export function addFeedbackToItems(items, feedback) {
299
- if (!feedback?.trim()) {
300
- return items;
301
- }
302
-
303
- return items.map((item) => ({
304
- ...item,
305
- feedback: feedback.trim(),
306
- }));
307
- }
308
-
309
- /**
310
- * Load document execution structure from structure-plan.json
311
- * @param {string} outputDir - Output directory containing structure-plan.json
312
- * @returns {Promise<Array|null>} Document execution structure array or null if not found/failed
313
- */
314
- export async function loadDocumentStructure(outputDir) {
315
- if (!outputDir) {
316
- return null;
317
- }
318
-
319
- try {
320
- const structurePlanPath = join(outputDir, "structure-plan.json");
321
- const structureExists = await pathExists(structurePlanPath);
322
-
323
- if (!structureExists) {
324
- return null;
325
- }
326
-
327
- const structureContent = await readFile(structurePlanPath, "utf8");
328
- if (!structureContent?.trim()) {
329
- return null;
330
- }
331
-
332
- try {
333
- // Validate that the content looks like JSON before parsing
334
- const trimmedContent = structureContent.trim();
335
- if (!trimmedContent.startsWith("[") && !trimmedContent.startsWith("{")) {
336
- console.warn("structure-plan.json contains non-JSON content, skipping parse");
337
- return null;
338
- }
339
-
340
- const parsed = JSON.parse(structureContent);
341
- // Return array if it's an array, otherwise return null
342
- return Array.isArray(parsed) ? parsed : null;
343
- } catch (parseError) {
344
- console.error(`Failed to parse structure-plan.json: ${parseError.message}`);
345
- return null;
346
- }
347
- } catch (readError) {
348
- // Only warn if it's not a "file not found" error
349
- if (readError.code !== "ENOENT") {
350
- console.warn(`Error reading structure-plan.json: ${readError.message}`);
351
- }
352
- return null;
353
- }
354
- }
355
-
356
- /**
357
- * Build allowed links set from document structure
358
- * Includes both original paths and processed .md paths for link validation
359
- * @param {Array} documentStructure - Array of documentation structure items with path property
360
- * @returns {Set<string>} Set of allowed link paths
361
- */
362
- export function buildAllowedLinksFromStructure(documentStructure) {
363
- const allowedLinks = new Set();
364
-
365
- if (!Array.isArray(documentStructure)) {
366
- return allowedLinks;
367
- }
368
-
369
- documentStructure.forEach((item) => {
370
- if (!item?.path) {
371
- return;
372
- }
373
-
374
- // Add original path
375
- allowedLinks.add(item.path);
376
-
377
- // Add processed .md path (same logic as processContent in utils.mjs)
378
- let processedPath = item.path;
379
- if (processedPath.startsWith(".")) {
380
- processedPath = processedPath.replace(/^\./, "");
381
- }
382
- let flatPath = processedPath.replace(/^\//, "").replace(/\//g, "-");
383
- flatPath = `./${flatPath}.md`;
384
- allowedLinks.add(flatPath);
385
- });
386
-
387
- return allowedLinks;
388
- }
389
-
390
- /**
391
- * Build a tree structure from a flat document structure array using parentId
392
- * @param {Array} documentStructure - Flat array of document structure items with path and parentId
393
- * @returns {Object} Object containing rootNodes (array of root nodes) and nodeMap (Map for lookups)
394
- */
395
- export function buildDocumentTree(documentStructure) {
396
- // Create a map of nodes for easy lookup
397
- const nodeMap = new Map();
398
- const rootNodes = [];
399
-
400
- // First pass: create node map
401
- documentStructure.forEach((node) => {
402
- nodeMap.set(node.path, {
403
- ...node,
404
- children: [],
405
- });
406
- });
407
-
408
- // Build the tree structure using parentId
409
- documentStructure.forEach((node) => {
410
- if (node.parentId) {
411
- const parent = nodeMap.get(node.parentId);
412
- if (parent) {
413
- parent.children.push(nodeMap.get(node.path));
414
- } else {
415
- rootNodes.push(nodeMap.get(node.path));
416
- }
417
- } else {
418
- rootNodes.push(nodeMap.get(node.path));
419
- }
420
- });
421
-
422
- return { rootNodes, nodeMap };
423
- }
424
-
425
- /**
426
- * Build checkbox choices from tree structure with visual hierarchy
427
- * @param {Array} nodes - Array of tree nodes
428
- * @param {string} prefix - Current prefix for indentation
429
- * @param {number} depth - Current depth level (0 for root)
430
- * @param {Object} context - Context object containing locale, docsDir, etc.
431
- * @param {string} context.locale - Main language locale (e.g., 'en', 'zh', 'fr')
432
- * @param {string} [context.docsDir] - Docs directory path for file existence check
433
- * @returns {Promise<Array>} Array of choice objects
434
- */
435
- export async function buildChoicesFromTree(nodes, prefix = "", depth = 0, context = {}) {
436
- const { locale = "en", docsDir } = context;
437
- const choices = [];
438
-
439
- // Limit concurrent file checks to 50 per level to avoid overwhelming the file system
440
- const limit = pLimit(50);
441
-
442
- // Process nodes with controlled concurrency while maintaining order
443
- const nodePromises = nodes.map((node, i) =>
444
- limit(async () => {
445
- const isLastSibling = i === nodes.length - 1;
446
- const hasChildren = node.children && node.children.length > 0;
447
-
448
- // Build the tree prefix - top level nodes don't have ├─ or └─
449
- const treePrefix = depth === 0 ? "" : prefix + (isLastSibling ? "└─ " : "├─ ");
450
- const flatName = pathToFlatName(node.path);
451
- const filename = generateFileName(flatName, locale);
452
-
453
- // Check file existence if docsDir is provided
454
- let fileExists = true;
455
- let missingFileText = "";
456
- if (docsDir) {
457
- const filePath = join(docsDir, filename);
458
- fileExists = await pathExists(filePath);
459
- if (!fileExists) {
460
- missingFileText = chalk.red(" - file not found");
461
- }
462
- }
463
-
464
- // warningText only shows when file exists, missingFileText has higher priority
465
- const warningText =
466
- fileExists && hasChildren ? chalk.yellow(" - will cascade delete all child documents") : "";
467
-
468
- const displayName = `${treePrefix}${node.title} (${filename})${warningText}${missingFileText}`;
469
-
470
- const choice = {
471
- name: displayName,
472
- value: node.path,
473
- short: node.title,
474
- disabled: !fileExists,
475
- };
476
-
477
- // Recursively process children
478
- let childChoices = [];
479
- if (hasChildren) {
480
- const childPrefix = depth === 0 ? "" : prefix + (isLastSibling ? " " : "│ ");
481
- childChoices = await buildChoicesFromTree(node.children, childPrefix, depth + 1, context);
482
- }
483
-
484
- return { choice, childChoices };
485
- }),
486
- );
487
-
488
- // Wait for all nodes at this level to complete, maintaining order
489
- const results = await Promise.all(nodePromises);
490
-
491
- // Build choices array in order
492
- for (const { choice, childChoices } of results) {
493
- choices.push(choice);
494
- if (childChoices.length > 0) {
495
- choices.push(...childChoices);
496
- }
497
- }
498
-
499
- return choices;
500
- }
501
-
502
- /**
503
- * Format document structure for printing
504
- * @param {Array} structure - Document structure array
505
- * @returns {Object} Object containing rootNodes and printNode function
506
- */
507
- function formatDocumentStructure(structure) {
508
- const { rootNodes } = buildDocumentTree(structure);
509
-
510
- function printNode(node, depth = 0) {
511
- const INDENT_SPACES = " ";
512
- const FOLDER_ICON = " 📁";
513
- const FILE_ICON = " 📄";
514
- const indent = INDENT_SPACES.repeat(depth);
515
- const prefix = depth === 0 ? FOLDER_ICON : FILE_ICON;
516
-
517
- console.log(`${indent}${prefix} ${node.title}`);
518
-
519
- if (node.children && node.children.length > 0) {
520
- node.children.forEach((child) => {
521
- printNode(child, depth + 1);
522
- });
523
- }
524
- }
525
-
526
- return { rootNodes, printNode };
527
- }
528
-
529
- /**
530
- * Print document structure in a user-friendly format
531
- * @param {Array} structure - Document structure array
532
- */
533
- export function printDocumentStructure(structure) {
534
- console.log(`\n ${"-".repeat(50)}`);
535
- console.log(" Current Documentation Structure");
536
- console.log(` ${"-".repeat(50)}`);
537
-
538
- const { rootNodes, printNode } = formatDocumentStructure(structure);
539
-
540
- if (rootNodes.length === 0) {
541
- console.log(" No documentation structure found.");
542
- } else {
543
- rootNodes.forEach((node) => {
544
- printNode(node);
545
- });
546
- }
547
- console.log();
548
- }
@@ -1,132 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { mkdir, readFile, writeFile } from "node:fs/promises";
3
- import { dirname, join } from "node:path";
4
- import { fileURLToPath } from "node:url";
5
-
6
- import { toRelativePath } from "../utils.mjs";
7
-
8
- /**
9
- * Create report structure with evaluation data
10
- * @param {Object} params - Parameters for creating the report
11
- * @param {string} params.timestamp - Report generation timestamp
12
- * @param {Object} params.metadata - Additional metadata for the report
13
- * @param {Object} params.structureEvaluation - Structure evaluation results
14
- * @param {Array} params.documentEvaluations - Individual document evaluations
15
- * @param {string} params.projectName - Name of the project
16
- * @param {string} params.projectDesc - Project description
17
- * @param {string} params.projectLogo - Project logo URL
18
- * @param {string} params.documentPurpose - Purpose of the documentation
19
- * @param {Array} params.targetAudienceTypes - Types of target audience
20
- * @param {string} params.readerKnowledgeLevel - Expected reader knowledge level
21
- * @param {string} params.documentationDepth - Depth of documentation
22
- * @param {string} params.targetAudience - Target audience description
23
- * @returns {Object} Complete report structure
24
- */
25
- export function createReportStructure({
26
- timestamp,
27
- metadata,
28
- structureEvaluation,
29
- documentEvaluations,
30
- projectName,
31
- projectDesc,
32
- projectLogo,
33
- documentPurpose,
34
- targetAudienceTypes,
35
- readerKnowledgeLevel,
36
- documentationDepth,
37
- targetAudience,
38
- }) {
39
- return {
40
- documentInfo: {
41
- projectName,
42
- projectDesc,
43
- projectLogo,
44
- documentPurpose,
45
- targetAudienceTypes,
46
- readerKnowledgeLevel,
47
- documentationDepth,
48
- targetAudience,
49
- },
50
- metadata: {
51
- version: "0.1.0",
52
- generatedBy: "AIGNE Doc Smith",
53
- generatedAt: timestamp,
54
- documentCount: documentEvaluations.length,
55
- ...metadata,
56
- },
57
- structureEvaluation: {
58
- type: "document-structure",
59
- results: structureEvaluation,
60
- },
61
- documentEvaluations: {
62
- type: "document-content",
63
- results: documentEvaluations,
64
- },
65
- };
66
- }
67
-
68
- /**
69
- * Ensure directory exists, create if it doesn't
70
- * @param {string} dirPath - Directory path to ensure exists
71
- */
72
- export async function ensureDirectoryExists(dirPath) {
73
- if (!existsSync(dirPath)) {
74
- await mkdir(dirPath, { recursive: true });
75
- }
76
- }
77
-
78
- /**
79
- * Generate timestamp formatted for folder names
80
- * @param {Date} [date] - Date object, defaults to current date
81
- * @returns {string} Formatted timestamp string
82
- */
83
- export function generateTimestampForFolder(date = new Date()) {
84
- const year = date.getFullYear();
85
- const month = String(date.getMonth() + 1).padStart(2, "0");
86
- const day = String(date.getDate()).padStart(2, "0");
87
- const hours = String(date.getHours()).padStart(2, "0");
88
- const minutes = String(date.getMinutes()).padStart(2, "0");
89
-
90
- return `${year}-${month}-${day}_${hours}-${minutes}`;
91
- }
92
-
93
- /**
94
- * Copy HTML report template to the report directory
95
- * @param {string} targetDir - Target directory for the HTML report
96
- * @returns {Promise<string>} Path to the copied HTML file
97
- */
98
- export async function copyHtmlReportTemplate(targetDir, data) {
99
- const __filename = fileURLToPath(import.meta.url);
100
- const __dirname = dirname(__filename);
101
-
102
- // Path to the HTML template
103
- const templatePath = join(__dirname, "../../", "assets", "report-template", "report.html");
104
- const targetPath = join(targetDir, "integrity-report.html");
105
-
106
- const templateReport = await readFile(templatePath, "utf-8");
107
- const templateData = templateReport.replace("window.__REPORT_DATA__", JSON.stringify(data));
108
- await writeFile(targetPath, templateData);
109
- return toRelativePath(targetPath);
110
- }
111
-
112
- /**
113
- * Generate success message with report links
114
- * @param {string} jsonReportPath - Path to the JSON report
115
- * @param {string} htmlReportPath - Path to the HTML report
116
- * @returns {string} Success message with links
117
- */
118
- export function generateReportSuccessMessage(jsonReportPath, htmlReportPath) {
119
- return `# ✅ Documentation Evaluation Report Generated Successfully!
120
-
121
- Generated evaluation report and saved to:
122
-
123
- \`${jsonReportPath}\`
124
-
125
- ## 📊 View HTML Report
126
-
127
- Open in your browser to view detailed analysis:
128
-
129
- \`Run in terminal: open ${htmlReportPath}\`
130
-
131
- `;
132
- }
@@ -1,32 +0,0 @@
1
- import { readFile } from "node:fs/promises";
2
- import { transpileDeclaration } from "typescript";
3
-
4
- export async function extractApi(path) {
5
- const content = await readFile(path, "utf8");
6
-
7
- const lang = languages.find((lang) => lang.match(path, content));
8
- if (lang) {
9
- return lang.extract(path, content);
10
- }
11
-
12
- return content;
13
- }
14
-
15
- const languages = [
16
- {
17
- match: (path) => /\.m?(js|ts)x?$/.test(path),
18
- extract: extractJsApi,
19
- },
20
- ];
21
-
22
- async function extractJsApi(_path, content) {
23
- const res = transpileDeclaration(content, {
24
- compilerOptions: {
25
- declaration: true,
26
- emitDeclarationOnly: true,
27
- allowJs: true,
28
- },
29
- });
30
-
31
- return res.outputText.trim();
32
- }