@aigne/doc-smith 0.8.12-beta.8 → 0.8.12-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/agents/publish/index.yaml +4 -0
  3. package/agents/publish/publish-docs.mjs +77 -5
  4. package/agents/publish/translate-meta.mjs +103 -0
  5. package/agents/update/generate-document.yaml +30 -28
  6. package/agents/update/update-document-detail.yaml +3 -1
  7. package/agents/utils/update-branding.mjs +69 -0
  8. package/package.json +16 -2
  9. package/prompts/common/document/role-and-personality.md +3 -1
  10. package/prompts/detail/d2-diagram/guide.md +7 -1
  11. package/prompts/detail/d2-diagram/user-prompt.md +3 -0
  12. package/prompts/detail/generate/system-prompt.md +6 -7
  13. package/prompts/detail/generate/user-prompt.md +12 -3
  14. package/prompts/detail/update/user-prompt.md +0 -2
  15. package/prompts/structure/update/user-prompt.md +0 -4
  16. package/utils/file-utils.mjs +69 -24
  17. package/utils/markdown-checker.mjs +0 -20
  18. package/utils/request.mjs +7 -0
  19. package/utils/upload-files.mjs +231 -0
  20. package/utils/utils.mjs +11 -1
  21. package/.aigne/doc-smith/config.yaml +0 -77
  22. package/.aigne/doc-smith/history.yaml +0 -37
  23. package/.aigne/doc-smith/media-description.yaml +0 -91
  24. package/.aigne/doc-smith/output/structure-plan.json +0 -162
  25. package/.aigne/doc-smith/preferences.yml +0 -97
  26. package/.aigne/doc-smith/upload-cache.yaml +0 -1830
  27. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  28. package/.github/workflows/ci.yml +0 -54
  29. package/.github/workflows/create-release-pr.yaml +0 -21
  30. package/.github/workflows/publish-docs.yml +0 -65
  31. package/.github/workflows/release.yml +0 -49
  32. package/.github/workflows/reviewer.yml +0 -54
  33. package/.release-please-manifest.json +0 -3
  34. package/RELEASE.md +0 -9
  35. package/assets/screenshots/doc-complete-setup.png +0 -0
  36. package/assets/screenshots/doc-generate-docs.png +0 -0
  37. package/assets/screenshots/doc-generate.png +0 -0
  38. package/assets/screenshots/doc-generated-successfully.png +0 -0
  39. package/assets/screenshots/doc-publish.png +0 -0
  40. package/assets/screenshots/doc-regenerate.png +0 -0
  41. package/assets/screenshots/doc-translate-langs.png +0 -0
  42. package/assets/screenshots/doc-translate.png +0 -0
  43. package/assets/screenshots/doc-update.png +0 -0
  44. package/biome.json +0 -73
  45. package/codecov.yml +0 -15
  46. package/docs/_sidebar.md +0 -15
  47. package/docs/configuration-initial-setup.ja.md +0 -179
  48. package/docs/configuration-initial-setup.md +0 -198
  49. package/docs/configuration-initial-setup.zh-TW.md +0 -179
  50. package/docs/configuration-initial-setup.zh.md +0 -179
  51. package/docs/configuration-managing-preferences.ja.md +0 -100
  52. package/docs/configuration-managing-preferences.md +0 -100
  53. package/docs/configuration-managing-preferences.zh-TW.md +0 -100
  54. package/docs/configuration-managing-preferences.zh.md +0 -100
  55. package/docs/configuration.ja.md +0 -69
  56. package/docs/configuration.md +0 -69
  57. package/docs/configuration.zh-TW.md +0 -69
  58. package/docs/configuration.zh.md +0 -69
  59. package/docs/getting-started.ja.md +0 -107
  60. package/docs/getting-started.md +0 -107
  61. package/docs/getting-started.zh-TW.md +0 -107
  62. package/docs/getting-started.zh.md +0 -107
  63. package/docs/guides-cleaning-up.ja.md +0 -51
  64. package/docs/guides-cleaning-up.md +0 -52
  65. package/docs/guides-cleaning-up.zh-TW.md +0 -51
  66. package/docs/guides-cleaning-up.zh.md +0 -51
  67. package/docs/guides-evaluating-documents.ja.md +0 -66
  68. package/docs/guides-evaluating-documents.md +0 -107
  69. package/docs/guides-evaluating-documents.zh-TW.md +0 -66
  70. package/docs/guides-evaluating-documents.zh.md +0 -66
  71. package/docs/guides-generating-documentation.ja.md +0 -151
  72. package/docs/guides-generating-documentation.md +0 -89
  73. package/docs/guides-generating-documentation.zh-TW.md +0 -151
  74. package/docs/guides-generating-documentation.zh.md +0 -151
  75. package/docs/guides-interactive-chat.ja.md +0 -85
  76. package/docs/guides-interactive-chat.md +0 -93
  77. package/docs/guides-interactive-chat.zh-TW.md +0 -85
  78. package/docs/guides-interactive-chat.zh.md +0 -85
  79. package/docs/guides-managing-history.ja.md +0 -48
  80. package/docs/guides-managing-history.md +0 -53
  81. package/docs/guides-managing-history.zh-TW.md +0 -48
  82. package/docs/guides-managing-history.zh.md +0 -48
  83. package/docs/guides-publishing-your-docs.ja.md +0 -78
  84. package/docs/guides-publishing-your-docs.md +0 -83
  85. package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
  86. package/docs/guides-publishing-your-docs.zh.md +0 -78
  87. package/docs/guides-translating-documentation.ja.md +0 -95
  88. package/docs/guides-translating-documentation.md +0 -100
  89. package/docs/guides-translating-documentation.zh-TW.md +0 -95
  90. package/docs/guides-translating-documentation.zh.md +0 -95
  91. package/docs/guides-updating-documentation.ja.md +0 -77
  92. package/docs/guides-updating-documentation.md +0 -79
  93. package/docs/guides-updating-documentation.zh-TW.md +0 -77
  94. package/docs/guides-updating-documentation.zh.md +0 -77
  95. package/docs/guides.ja.md +0 -32
  96. package/docs/guides.md +0 -32
  97. package/docs/guides.zh-TW.md +0 -32
  98. package/docs/guides.zh.md +0 -32
  99. package/docs/overview.ja.md +0 -61
  100. package/docs/overview.md +0 -61
  101. package/docs/overview.zh-TW.md +0 -61
  102. package/docs/overview.zh.md +0 -61
  103. package/docs/release-notes.ja.md +0 -255
  104. package/docs/release-notes.md +0 -288
  105. package/docs/release-notes.zh-TW.md +0 -255
  106. package/docs/release-notes.zh.md +0 -255
  107. package/prompts/common/afs/afs-tools-usage.md +0 -5
  108. package/prompts/common/afs/use-afs-instruction.md +0 -1
  109. package/release-please-config.json +0 -14
  110. package/tests/agents/chat/chat.test.mjs +0 -46
  111. package/tests/agents/clear/choose-contents.test.mjs +0 -284
  112. package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
  113. package/tests/agents/clear/clear-document-config.test.mjs +0 -167
  114. package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
  115. package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
  116. package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
  117. package/tests/agents/evaluate/fixtures/api-services.md +0 -87
  118. package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
  119. package/tests/agents/evaluate/generate-report.test.mjs +0 -312
  120. package/tests/agents/generate/check-document-structure.test.mjs +0 -45
  121. package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
  122. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
  123. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
  124. package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
  125. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
  126. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
  127. package/tests/agents/generate/generate-structure.test.mjs +0 -45
  128. package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
  129. package/tests/agents/history/view.test.mjs +0 -97
  130. package/tests/agents/init/init.test.mjs +0 -1657
  131. package/tests/agents/prefs/prefs.test.mjs +0 -431
  132. package/tests/agents/publish/publish-docs.test.mjs +0 -787
  133. package/tests/agents/translate/choose-language.test.mjs +0 -311
  134. package/tests/agents/translate/translate-document.test.mjs +0 -51
  135. package/tests/agents/update/check-document.test.mjs +0 -463
  136. package/tests/agents/update/check-update-is-single.test.mjs +0 -300
  137. package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
  138. package/tests/agents/update/generate-document.test.mjs +0 -51
  139. package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
  140. package/tests/agents/update/user-review-document.test.mjs +0 -582
  141. package/tests/agents/utils/action-success.test.mjs +0 -54
  142. package/tests/agents/utils/check-detail-result.test.mjs +0 -743
  143. package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
  144. package/tests/agents/utils/choose-docs.test.mjs +0 -406
  145. package/tests/agents/utils/exit.test.mjs +0 -70
  146. package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
  147. package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
  148. package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
  149. package/tests/agents/utils/format-document-structure.test.mjs +0 -364
  150. package/tests/agents/utils/fs.test.mjs +0 -267
  151. package/tests/agents/utils/load-sources.test.mjs +0 -1470
  152. package/tests/agents/utils/save-docs.test.mjs +0 -109
  153. package/tests/agents/utils/save-output.test.mjs +0 -315
  154. package/tests/agents/utils/save-single-doc.test.mjs +0 -364
  155. package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
  156. package/tests/utils/auth-utils.test.mjs +0 -596
  157. package/tests/utils/blocklet.test.mjs +0 -336
  158. package/tests/utils/conflict-detector.test.mjs +0 -355
  159. package/tests/utils/constants.test.mjs +0 -295
  160. package/tests/utils/d2-utils.test.mjs +0 -437
  161. package/tests/utils/deploy.test.mjs +0 -399
  162. package/tests/utils/docs-finder-utils.test.mjs +0 -650
  163. package/tests/utils/file-utils.test.mjs +0 -521
  164. package/tests/utils/history-utils.test.mjs +0 -206
  165. package/tests/utils/kroki-utils.test.mjs +0 -646
  166. package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
  167. package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
  168. package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
  169. package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
  170. package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
  171. package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
  172. package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
  173. package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
  174. package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
  175. package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
  176. package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
  177. package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
  178. package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
  179. package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
  180. package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
  181. package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
  182. package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
  183. package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
  184. package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
  185. package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
  186. package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
  187. package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
  188. package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
  189. package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
  190. package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
  191. package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
  192. package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
  193. package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
  194. package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
  195. package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
  196. package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
  197. package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
  198. package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
  199. package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
  200. package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
  201. package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
  202. package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
  203. package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
  204. package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
  205. package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
  206. package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
  207. package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
  208. package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
  209. package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
  210. package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
  211. package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
  212. package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
  213. package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
  214. package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
  215. package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
  216. package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
  217. package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
  218. package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
  219. package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
  220. package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
  221. package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
  222. package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
  223. package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
  224. package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
  225. package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
  226. package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
  227. package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
  228. package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
  229. package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
  230. package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
  231. package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
  232. package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
  233. package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
  234. package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
  235. package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
  236. package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
  237. package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
  238. package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
  239. package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
  240. package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
  241. package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
  242. package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
  243. package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
  244. package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
  245. package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
  246. package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
  247. package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
  248. package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
  249. package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
  250. package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
  251. package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
  252. package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
  253. package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
  254. package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
  255. package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
  256. package/tests/utils/linter/index.test.mjs +0 -440
  257. package/tests/utils/linter/scan-results.mjs +0 -42
  258. package/tests/utils/load-config.test.mjs +0 -141
  259. package/tests/utils/markdown/index.test.mjs +0 -478
  260. package/tests/utils/mermaid-validator.test.mjs +0 -541
  261. package/tests/utils/mock-chat-model.mjs +0 -12
  262. package/tests/utils/preferences-utils.test.mjs +0 -465
  263. package/tests/utils/save-value-to-config.test.mjs +0 -483
  264. package/tests/utils/utils.test.mjs +0 -941
@@ -1,483 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
2
- import * as fs from "node:fs";
3
- import { existsSync } from "node:fs";
4
- import fsPromisesDefault, * as fsPromises from "node:fs/promises";
5
- import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
6
- import { dirname, join } from "node:path";
7
- import { fileURLToPath } from "node:url";
8
-
9
- import { DOC_SMITH_DIR } from "../../utils/constants/index.mjs";
10
- import { saveValueToConfig } from "../../utils/utils.mjs";
11
-
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
-
15
- // Test directory for isolated testing
16
- const TEST_DIR = join(__dirname, "temp-config-test");
17
- const TEST_CONFIG_DIR = join(TEST_DIR, DOC_SMITH_DIR);
18
- const TEST_CONFIG_PATH = join(TEST_CONFIG_DIR, "config.yaml");
19
-
20
- // Store original working directory
21
- let originalCwd;
22
-
23
- // Setup and teardown helpers
24
- async function setupTestDir() {
25
- // Save original working directory
26
- originalCwd = process.cwd();
27
-
28
- if (existsSync(TEST_DIR)) {
29
- await rm(TEST_DIR, { recursive: true, force: true });
30
- }
31
- await mkdir(TEST_DIR, { recursive: true });
32
-
33
- // Change to test directory for the duration of tests
34
- process.chdir(TEST_DIR);
35
- }
36
-
37
- async function teardownTestDir() {
38
- // Change back to original directory
39
- process.chdir(originalCwd);
40
-
41
- if (existsSync(TEST_DIR)) {
42
- await rm(TEST_DIR, { recursive: true, force: true });
43
- }
44
- }
45
-
46
- async function readConfigFile() {
47
- if (!existsSync(TEST_CONFIG_PATH)) {
48
- return "";
49
- }
50
- return await readFile(TEST_CONFIG_PATH, "utf8");
51
- }
52
-
53
- async function createInitialConfig(content) {
54
- await mkdir(TEST_CONFIG_DIR, { recursive: true });
55
- await writeFile(TEST_CONFIG_PATH, content, "utf8");
56
- }
57
-
58
- // Test suite
59
- describe("save-value-to-config", () => {
60
- let restoreFunctions = [];
61
-
62
- beforeEach(async () => {
63
- await setupTestDir();
64
-
65
- // Restore any existing mocks that might interfere with our file operations
66
- // This is crucial when running alongside other test files like utils.test.mjs
67
- restoreFunctions = [];
68
-
69
- // Restore fs sync mocks if they exist
70
- if (typeof fs.existsSync.mockRestore === "function") {
71
- fs.existsSync.mockRestore();
72
- restoreFunctions.push(() => spyOn(fs, "existsSync").mockReturnValue(true));
73
- }
74
- if (typeof fs.mkdirSync.mockRestore === "function") {
75
- fs.mkdirSync.mockRestore();
76
- restoreFunctions.push(() => spyOn(fs, "mkdirSync").mockImplementation(() => {}));
77
- }
78
-
79
- // Restore fs async mocks if they exist
80
- if (typeof fsPromises.writeFile.mockRestore === "function") {
81
- fsPromises.writeFile.mockRestore();
82
- restoreFunctions.push(() => spyOn(fsPromises, "writeFile").mockResolvedValue());
83
- }
84
- if (typeof fsPromises.mkdir.mockRestore === "function") {
85
- fsPromises.mkdir.mockRestore();
86
- restoreFunctions.push(() => spyOn(fsPromises, "mkdir").mockResolvedValue());
87
- }
88
- if (typeof fsPromises.readFile.mockRestore === "function") {
89
- fsPromises.readFile.mockRestore();
90
- restoreFunctions.push(() => spyOn(fsPromises, "readFile").mockResolvedValue("test content"));
91
- }
92
-
93
- // Restore default import mocks if they exist
94
- if (typeof fsPromisesDefault.writeFile.mockRestore === "function") {
95
- fsPromisesDefault.writeFile.mockRestore();
96
- restoreFunctions.push(() => spyOn(fsPromisesDefault, "writeFile").mockResolvedValue());
97
- }
98
- if (typeof fsPromisesDefault.mkdir.mockRestore === "function") {
99
- fsPromisesDefault.mkdir.mockRestore();
100
- restoreFunctions.push(() => spyOn(fsPromisesDefault, "mkdir").mockResolvedValue());
101
- }
102
- });
103
-
104
- afterEach(async () => {
105
- await teardownTestDir();
106
-
107
- // Restore the original mocks that other tests might depend on
108
- restoreFunctions.forEach((restoreFn) => {
109
- try {
110
- restoreFn();
111
- } catch {
112
- // Ignore errors when restoring mocks
113
- }
114
- });
115
- });
116
-
117
- test("Save string value to empty file", async () => {
118
- await saveValueToConfig("projectName", "test-project");
119
- const content = await readConfigFile();
120
-
121
- expect(content).toContain("projectName: test-project");
122
- });
123
-
124
- test("Save string value with comment to empty file", async () => {
125
- await saveValueToConfig("projectDesc", "A test project", "Project description");
126
- const content = await readConfigFile();
127
-
128
- expect(content).toContain("# Project description");
129
- expect(content).toContain("projectDesc: A test project");
130
- });
131
-
132
- test("Save array value to empty file", async () => {
133
- await saveValueToConfig("translateLanguages", ["zh", "ja", "ko"]);
134
- const content = await readConfigFile();
135
-
136
- expect(content).toContain("translateLanguages:");
137
- expect(content).toContain(" - zh");
138
- expect(content).toContain(" - ja");
139
- expect(content).toContain(" - ko");
140
- });
141
-
142
- test("Save empty array", async () => {
143
- await saveValueToConfig("emptyArray", []);
144
- const content = await readConfigFile();
145
-
146
- expect(content).toContain("emptyArray: []");
147
- });
148
-
149
- test("Save array with comment", async () => {
150
- await saveValueToConfig("sourcePaths", ["./src", "./lib"], "Source code paths");
151
- const content = await readConfigFile();
152
-
153
- expect(content).toContain("# Source code paths");
154
- expect(content).toContain("sourcePaths:");
155
- expect(content).toContain(" - ./src");
156
- expect(content).toContain(" - ./lib");
157
- });
158
-
159
- test("Update existing string value", async () => {
160
- await createInitialConfig('projectName: "old-project"\nversion: "1.0.0"');
161
-
162
- await saveValueToConfig("projectName", "new-project");
163
- const content = await readConfigFile();
164
-
165
- expect(content).toContain("projectName: new-project");
166
- expect(content).toContain('version: "1.0.0"');
167
- expect(content).not.toContain("old-project");
168
- });
169
-
170
- test("Update existing array value", async () => {
171
- await createInitialConfig(`translateLanguages:
172
- - en
173
- - fr
174
- version: "1.0.0"`);
175
-
176
- await saveValueToConfig("translateLanguages", ["zh", "ja"]);
177
- const content = await readConfigFile();
178
-
179
- expect(content).toContain("translateLanguages:");
180
- expect(content).toContain(" - zh");
181
- expect(content).toContain(" - ja");
182
- expect(content).not.toContain(" - en");
183
- expect(content).not.toContain(" - fr");
184
- expect(content).toContain('version: "1.0.0"');
185
- });
186
-
187
- test("Update array to empty array", async () => {
188
- await createInitialConfig(`translateLanguages:
189
- - en
190
- - fr
191
- version: "1.0.0"`);
192
-
193
- await saveValueToConfig("translateLanguages", []);
194
- const content = await readConfigFile();
195
-
196
- expect(content).toContain("translateLanguages: []");
197
- expect(content).not.toContain(" - en");
198
- expect(content).toContain('version: "1.0.0"');
199
- });
200
-
201
- test("Update empty array to populated array", async () => {
202
- await createInitialConfig(`translateLanguages: []
203
- version: "1.0.0"`);
204
-
205
- await saveValueToConfig("translateLanguages", ["zh", "ja"]);
206
- const content = await readConfigFile();
207
-
208
- expect(content).toContain("translateLanguages:");
209
- expect(content).toContain(" - zh");
210
- expect(content).toContain(" - ja");
211
- expect(content).not.toContain("translateLanguages: []");
212
- expect(content).toContain('version: "1.0.0"');
213
- });
214
-
215
- test("Add comment to existing value without comment", async () => {
216
- await createInitialConfig('projectName: "test-project"\nversion: "1.0.0"');
217
-
218
- await saveValueToConfig("projectName", "updated-project", "Updated project name");
219
- const content = await readConfigFile();
220
-
221
- expect(content).toContain("# Updated project name");
222
- expect(content).toContain("projectName: updated-project");
223
- });
224
-
225
- test("Update value that already has comment", async () => {
226
- await createInitialConfig(`# Project information
227
- projectName: "old-project"
228
- version: "1.0.0"`);
229
-
230
- await saveValueToConfig("projectName", "new-project", "Updated project info");
231
- const content = await readConfigFile();
232
-
233
- expect(content).toContain("# Project information");
234
- expect(content).toContain("projectName: new-project");
235
- expect(content).not.toContain("# Updated project info");
236
- });
237
-
238
- test("Complex array with various items", async () => {
239
- const complexArray = ["./src/components", "./lib/utils", "./modules/auth"];
240
- await saveValueToConfig("sourcePaths", complexArray, "All source paths");
241
- const content = await readConfigFile();
242
-
243
- expect(content).toContain("# All source paths");
244
- expect(content).toContain("sourcePaths:");
245
- expect(content).toContain(" - ./src/components");
246
- expect(content).toContain(" - ./lib/utils");
247
- expect(content).toContain(" - ./modules/auth");
248
- });
249
-
250
- test("Mixed content preservation", async () => {
251
- await createInitialConfig(`# Project configuration
252
- projectName: "original-project"
253
- translateLanguages:
254
- - en
255
- - fr
256
- # Other settings
257
- version: "1.0.0"
258
- locale: en`);
259
-
260
- await saveValueToConfig("translateLanguages", ["zh", "ja", "ko"], "Updated languages");
261
- const content = await readConfigFile();
262
-
263
- expect(content).toContain("# Project configuration");
264
- expect(content).toContain('projectName: "original-project"');
265
- expect(content).toContain("# Updated languages");
266
- expect(content).toContain("translateLanguages:");
267
- expect(content).toContain(" - zh");
268
- expect(content).toContain(" - ja");
269
- expect(content).toContain(" - ko");
270
- expect(content).toContain("# Other settings");
271
- expect(content).toContain('version: "1.0.0"');
272
- expect(content).toContain("locale: en");
273
- expect(content).not.toContain(" - en");
274
- expect(content).not.toContain(" - fr");
275
- });
276
-
277
- test("Array in middle of file", async () => {
278
- await createInitialConfig(`projectName: "test-project"
279
- translateLanguages:
280
- - en
281
- - fr
282
- locale: en
283
- version: "1.0.0"`);
284
-
285
- await saveValueToConfig("translateLanguages", ["zh"]);
286
- const content = await readConfigFile();
287
-
288
- expect(content).toContain('projectName: "test-project"');
289
- expect(content).toContain("translateLanguages:");
290
- expect(content).toContain(" - zh");
291
- expect(content).toContain("locale: en");
292
- expect(content).toContain('version: "1.0.0"');
293
- expect(content).not.toContain(" - en");
294
- expect(content).not.toContain(" - fr");
295
- });
296
-
297
- test("Handle undefined values", async () => {
298
- const initialContent = 'projectName: "test-project"';
299
- await createInitialConfig(initialContent);
300
-
301
- await saveValueToConfig("undefinedKey", undefined);
302
- const content = await readConfigFile();
303
-
304
- expect(content).toBe(initialContent);
305
- });
306
-
307
- // Edge cases and special character tests
308
- describe("Special characters and edge cases", () => {
309
- test("Save string with double quotes", async () => {
310
- await saveValueToConfig("projectDesc", 'My "awesome" project with quotes');
311
- const content = await readConfigFile();
312
-
313
- // Should be properly escaped
314
- expect(content).toContain('My "awesome" project with quotes');
315
- // Verify YAML is valid by checking structure
316
- expect(content).toContain("projectDesc:");
317
- });
318
-
319
- test("Save string with single quotes", async () => {
320
- await saveValueToConfig("projectName", "It's a 'great' project");
321
- const content = await readConfigFile();
322
-
323
- expect(content).toContain("It's a 'great' project");
324
- expect(content).toContain("projectName:");
325
- });
326
-
327
- test("Save string with colons and special YAML characters", async () => {
328
- await saveValueToConfig(
329
- "rule",
330
- "Use proper formatting: semicolons; colons: and pipes | symbols",
331
- );
332
- const content = await readConfigFile();
333
-
334
- expect(content).toContain("Use proper formatting: semicolons; colons: and pipes | symbols");
335
- expect(content).toContain("rule:");
336
- });
337
-
338
- test("Save multiline string with newlines", async () => {
339
- const multilineValue =
340
- "Line 1: First line\nLine 2: Second line\nLine 3: Third line with: special characters";
341
- await saveValueToConfig("multilineRule", multilineValue);
342
- const content = await readConfigFile();
343
-
344
- expect(content).toContain("Line 1: First line");
345
- expect(content).toContain("Line 2: Second line");
346
- expect(content).toContain("Line 3: Third line with: special characters");
347
- });
348
-
349
- test("Save string with Chinese characters and symbols", async () => {
350
- await saveValueToConfig(
351
- "chineseProject",
352
- '中文项目:包含特殊符号!@#¥%…()—— quotes"and" colons:',
353
- );
354
- const content = await readConfigFile();
355
-
356
- expect(content).toContain('中文项目:包含特殊符号!@#¥%…()—— quotes"and" colons:');
357
- expect(content).toContain("chineseProject:");
358
- });
359
-
360
- test("Save string with emoji and Unicode", async () => {
361
- await saveValueToConfig(
362
- "emojiProject",
363
- "🚀 Project with emoji: 🔥 hot features 💯 and symbols ⭐ ✨ 🎉",
364
- );
365
- const content = await readConfigFile();
366
-
367
- expect(content).toContain("🚀 Project with emoji: 🔥 hot features 💯 and symbols ⭐ ✨ 🎉");
368
- expect(content).toContain("emojiProject:");
369
- });
370
-
371
- test("Save array with special character items", async () => {
372
- const specialPaths = [
373
- "./src: main source",
374
- "./lib/utils: helper functions",
375
- "./docs-中文/guide",
376
- "./path with spaces/file",
377
- "./symbols@#$%/directory",
378
- './quotes"and"colons:/path',
379
- ];
380
- await saveValueToConfig("specialPaths", specialPaths);
381
- const content = await readConfigFile();
382
-
383
- expect(content).toContain("specialPaths:");
384
- specialPaths.forEach((path) => {
385
- expect(content).toContain(path);
386
- });
387
- });
388
-
389
- test("Save array with multiline items", async () => {
390
- const multilineArray = [
391
- "Item 1:\nWith newline content",
392
- "Item 2: Simple item",
393
- "Item 3:\nMultiple\nLines\nWith: colons and | pipes",
394
- ];
395
- await saveValueToConfig("multilineArray", multilineArray);
396
- const content = await readConfigFile();
397
-
398
- expect(content).toContain("multilineArray:");
399
- expect(content).toContain("Item 1:");
400
- expect(content).toContain("With newline content");
401
- expect(content).toContain("Item 3:");
402
- expect(content).toContain("With: colons and | pipes");
403
- });
404
-
405
- test("Update existing value containing special characters", async () => {
406
- await createInitialConfig('projectName: "old: project with | pipes"\nversion: "1.0.0"');
407
-
408
- await saveValueToConfig("projectName", 'new: project with "quotes" and | pipes: updated');
409
- const content = await readConfigFile();
410
-
411
- expect(content).toContain('new: project with "quotes" and | pipes: updated');
412
- expect(content).toContain('version: "1.0.0"');
413
- expect(content).not.toContain("old: project");
414
- });
415
-
416
- test("Save very long string with special characters", async () => {
417
- const longString =
418
- "A very long project description that contains many special characters: colons, semicolons; quotes \"like this\", single quotes 'like this', pipes | symbols, Chinese characters 中文内容:包含各种符号!@#¥%…()——, emojis 🚀🔥💯⭐✨🎉, and newlines\nSecond line with more content\nThird line: even more special content with all sorts of symbols @#$%^&*()_+-=[]{}|\\;':./?,<>~`";
419
- await saveValueToConfig("veryLongDesc", longString);
420
- const content = await readConfigFile();
421
-
422
- expect(content).toContain("veryLongDesc:");
423
- expect(content).toContain("A very long project description");
424
- expect(content).toContain("中文内容:包含各种符号");
425
- expect(content).toContain("🚀🔥💯⭐✨🎉");
426
- expect(content).toContain("Second line with more content");
427
- });
428
-
429
- test("Save empty string", async () => {
430
- await saveValueToConfig("emptyString", "");
431
- const content = await readConfigFile();
432
-
433
- expect(content).toContain('emptyString: ""');
434
- });
435
-
436
- test("Save string that looks like YAML syntax", async () => {
437
- await saveValueToConfig("yamlLikeString", "key: value\nother: - item1\n- item2: subvalue");
438
- const content = await readConfigFile();
439
-
440
- expect(content).toContain("yamlLikeString:");
441
- expect(content).toContain("key: value");
442
- expect(content).toContain("other: - item1");
443
- expect(content).toContain("- item2: subvalue");
444
- });
445
-
446
- test("Complex mixed scenario with multiple special character values", async () => {
447
- // Create initial config with some special content
448
- await createInitialConfig(`# Project configuration
449
- # with special comments: and symbols
450
- projectName: "original: project"
451
- locale: zh`);
452
-
453
- // Update with various special character content
454
- await saveValueToConfig("projectDesc", 'Updated description: with "quotes" and | pipes');
455
- await saveValueToConfig("specialArray", [
456
- "path: with colons",
457
- "中文路径/文件",
458
- "emoji 🔥 path",
459
- ]);
460
- await saveValueToConfig(
461
- "multilineContent",
462
- "Line 1: content\nLine 2: more content\nLine 3: final content",
463
- );
464
-
465
- const content = await readConfigFile();
466
-
467
- // Check all content is preserved
468
- expect(content).toContain("# Project configuration");
469
- expect(content).toContain("# with special comments: and symbols");
470
- expect(content).toContain('projectName: "original: project"');
471
- expect(content).toContain("locale: zh");
472
- expect(content).toContain('Updated description: with "quotes" and | pipes');
473
- expect(content).toContain("specialArray:");
474
- expect(content).toContain("path: with colons");
475
- expect(content).toContain("中文路径/文件");
476
- expect(content).toContain("emoji 🔥 path");
477
- expect(content).toContain("multilineContent:");
478
- expect(content).toContain("Line 1: content");
479
- expect(content).toContain("Line 2: more content");
480
- expect(content).toContain("Line 3: final content");
481
- });
482
- });
483
- });