@aigne/doc-smith 0.8.12-beta.7 → 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 (284) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/agents/clear/choose-contents.mjs +14 -1
  3. package/agents/clear/clear-media-description.mjs +129 -0
  4. package/agents/clear/index.yaml +3 -1
  5. package/agents/evaluate/code-snippet.mjs +28 -24
  6. package/agents/evaluate/document-structure.yaml +0 -4
  7. package/agents/evaluate/document.yaml +1 -5
  8. package/agents/generate/index.yaml +1 -0
  9. package/agents/init/index.mjs +10 -0
  10. package/agents/media/batch-generate-media-description.yaml +44 -0
  11. package/agents/media/generate-media-description.yaml +47 -0
  12. package/agents/media/load-media-description.mjs +238 -0
  13. package/agents/publish/index.yaml +4 -0
  14. package/agents/publish/publish-docs.mjs +77 -5
  15. package/agents/publish/translate-meta.mjs +103 -0
  16. package/agents/update/generate-document.yaml +30 -28
  17. package/agents/update/index.yaml +1 -0
  18. package/agents/update/update-document-detail.yaml +3 -1
  19. package/agents/utils/load-sources.mjs +103 -53
  20. package/agents/utils/update-branding.mjs +69 -0
  21. package/aigne.yaml +6 -0
  22. package/assets/report-template/report.html +34 -34
  23. package/package.json +17 -2
  24. package/prompts/common/document/role-and-personality.md +3 -1
  25. package/prompts/detail/d2-diagram/guide.md +7 -1
  26. package/prompts/detail/d2-diagram/user-prompt.md +3 -0
  27. package/prompts/detail/generate/system-prompt.md +6 -7
  28. package/prompts/detail/generate/user-prompt.md +12 -3
  29. package/prompts/detail/update/user-prompt.md +0 -2
  30. package/prompts/evaluate/document-structure.md +6 -7
  31. package/prompts/evaluate/document.md +16 -25
  32. package/prompts/media/media-description/system-prompt.md +35 -0
  33. package/prompts/media/media-description/user-prompt.md +8 -0
  34. package/prompts/structure/update/user-prompt.md +0 -4
  35. package/utils/constants/index.mjs +0 -107
  36. package/utils/file-utils.mjs +86 -0
  37. package/utils/markdown-checker.mjs +0 -20
  38. package/utils/request.mjs +7 -0
  39. package/utils/upload-files.mjs +231 -0
  40. package/utils/utils.mjs +11 -1
  41. package/.aigne/doc-smith/config.yaml +0 -77
  42. package/.aigne/doc-smith/history.yaml +0 -37
  43. package/.aigne/doc-smith/output/structure-plan.json +0 -162
  44. package/.aigne/doc-smith/preferences.yml +0 -97
  45. package/.aigne/doc-smith/upload-cache.yaml +0 -1893
  46. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  47. package/.github/workflows/ci.yml +0 -54
  48. package/.github/workflows/create-release-pr.yaml +0 -21
  49. package/.github/workflows/publish-docs.yml +0 -65
  50. package/.github/workflows/release.yml +0 -49
  51. package/.github/workflows/reviewer.yml +0 -54
  52. package/.release-please-manifest.json +0 -3
  53. package/RELEASE.md +0 -9
  54. package/assets/screenshots/doc-complete-setup.png +0 -0
  55. package/assets/screenshots/doc-generate-docs.png +0 -0
  56. package/assets/screenshots/doc-generate.png +0 -0
  57. package/assets/screenshots/doc-generated-successfully.png +0 -0
  58. package/assets/screenshots/doc-publish.png +0 -0
  59. package/assets/screenshots/doc-regenerate.png +0 -0
  60. package/assets/screenshots/doc-translate-langs.png +0 -0
  61. package/assets/screenshots/doc-translate.png +0 -0
  62. package/assets/screenshots/doc-update.png +0 -0
  63. package/biome.json +0 -73
  64. package/codecov.yml +0 -15
  65. package/docs/_sidebar.md +0 -15
  66. package/docs/configuration-initial-setup.ja.md +0 -179
  67. package/docs/configuration-initial-setup.md +0 -179
  68. package/docs/configuration-initial-setup.zh-TW.md +0 -179
  69. package/docs/configuration-initial-setup.zh.md +0 -179
  70. package/docs/configuration-managing-preferences.ja.md +0 -100
  71. package/docs/configuration-managing-preferences.md +0 -100
  72. package/docs/configuration-managing-preferences.zh-TW.md +0 -100
  73. package/docs/configuration-managing-preferences.zh.md +0 -100
  74. package/docs/configuration.ja.md +0 -96
  75. package/docs/configuration.md +0 -96
  76. package/docs/configuration.zh-TW.md +0 -96
  77. package/docs/configuration.zh.md +0 -96
  78. package/docs/getting-started.ja.md +0 -88
  79. package/docs/getting-started.md +0 -88
  80. package/docs/getting-started.zh-TW.md +0 -88
  81. package/docs/getting-started.zh.md +0 -88
  82. package/docs/guides-cleaning-up.ja.md +0 -51
  83. package/docs/guides-cleaning-up.md +0 -51
  84. package/docs/guides-cleaning-up.zh-TW.md +0 -51
  85. package/docs/guides-cleaning-up.zh.md +0 -51
  86. package/docs/guides-evaluating-documents.ja.md +0 -66
  87. package/docs/guides-evaluating-documents.md +0 -66
  88. package/docs/guides-evaluating-documents.zh-TW.md +0 -66
  89. package/docs/guides-evaluating-documents.zh.md +0 -66
  90. package/docs/guides-generating-documentation.ja.md +0 -151
  91. package/docs/guides-generating-documentation.md +0 -151
  92. package/docs/guides-generating-documentation.zh-TW.md +0 -151
  93. package/docs/guides-generating-documentation.zh.md +0 -151
  94. package/docs/guides-interactive-chat.ja.md +0 -85
  95. package/docs/guides-interactive-chat.md +0 -85
  96. package/docs/guides-interactive-chat.zh-TW.md +0 -85
  97. package/docs/guides-interactive-chat.zh.md +0 -85
  98. package/docs/guides-managing-history.ja.md +0 -48
  99. package/docs/guides-managing-history.md +0 -48
  100. package/docs/guides-managing-history.zh-TW.md +0 -48
  101. package/docs/guides-managing-history.zh.md +0 -48
  102. package/docs/guides-publishing-your-docs.ja.md +0 -78
  103. package/docs/guides-publishing-your-docs.md +0 -78
  104. package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
  105. package/docs/guides-publishing-your-docs.zh.md +0 -78
  106. package/docs/guides-translating-documentation.ja.md +0 -95
  107. package/docs/guides-translating-documentation.md +0 -95
  108. package/docs/guides-translating-documentation.zh-TW.md +0 -95
  109. package/docs/guides-translating-documentation.zh.md +0 -95
  110. package/docs/guides-updating-documentation.ja.md +0 -77
  111. package/docs/guides-updating-documentation.md +0 -77
  112. package/docs/guides-updating-documentation.zh-TW.md +0 -77
  113. package/docs/guides-updating-documentation.zh.md +0 -77
  114. package/docs/guides.ja.md +0 -32
  115. package/docs/guides.md +0 -32
  116. package/docs/guides.zh-TW.md +0 -32
  117. package/docs/guides.zh.md +0 -32
  118. package/docs/overview.ja.md +0 -61
  119. package/docs/overview.md +0 -61
  120. package/docs/overview.zh-TW.md +0 -61
  121. package/docs/overview.zh.md +0 -61
  122. package/docs/release-notes.ja.md +0 -255
  123. package/docs/release-notes.md +0 -255
  124. package/docs/release-notes.zh-TW.md +0 -255
  125. package/docs/release-notes.zh.md +0 -255
  126. package/media.md +0 -19
  127. package/prompts/common/afs/afs-tools-usage.md +0 -5
  128. package/prompts/common/afs/use-afs-instruction.md +0 -1
  129. package/release-please-config.json +0 -14
  130. package/tests/agents/chat/chat.test.mjs +0 -46
  131. package/tests/agents/clear/choose-contents.test.mjs +0 -284
  132. package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
  133. package/tests/agents/clear/clear-document-config.test.mjs +0 -167
  134. package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
  135. package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
  136. package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
  137. package/tests/agents/evaluate/fixtures/api-services.md +0 -87
  138. package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
  139. package/tests/agents/evaluate/generate-report.test.mjs +0 -312
  140. package/tests/agents/generate/check-document-structure.test.mjs +0 -45
  141. package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
  142. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
  143. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
  144. package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
  145. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
  146. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
  147. package/tests/agents/generate/generate-structure.test.mjs +0 -45
  148. package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
  149. package/tests/agents/history/view.test.mjs +0 -97
  150. package/tests/agents/init/init.test.mjs +0 -1657
  151. package/tests/agents/prefs/prefs.test.mjs +0 -431
  152. package/tests/agents/publish/publish-docs.test.mjs +0 -787
  153. package/tests/agents/translate/choose-language.test.mjs +0 -311
  154. package/tests/agents/translate/translate-document.test.mjs +0 -51
  155. package/tests/agents/update/check-document.test.mjs +0 -463
  156. package/tests/agents/update/check-update-is-single.test.mjs +0 -300
  157. package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
  158. package/tests/agents/update/generate-document.test.mjs +0 -51
  159. package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
  160. package/tests/agents/update/user-review-document.test.mjs +0 -582
  161. package/tests/agents/utils/action-success.test.mjs +0 -54
  162. package/tests/agents/utils/check-detail-result.test.mjs +0 -743
  163. package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
  164. package/tests/agents/utils/choose-docs.test.mjs +0 -406
  165. package/tests/agents/utils/exit.test.mjs +0 -70
  166. package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
  167. package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
  168. package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
  169. package/tests/agents/utils/format-document-structure.test.mjs +0 -364
  170. package/tests/agents/utils/fs.test.mjs +0 -267
  171. package/tests/agents/utils/load-sources.test.mjs +0 -1470
  172. package/tests/agents/utils/save-docs.test.mjs +0 -109
  173. package/tests/agents/utils/save-output.test.mjs +0 -315
  174. package/tests/agents/utils/save-single-doc.test.mjs +0 -364
  175. package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
  176. package/tests/utils/auth-utils.test.mjs +0 -596
  177. package/tests/utils/blocklet.test.mjs +0 -336
  178. package/tests/utils/conflict-detector.test.mjs +0 -355
  179. package/tests/utils/constants.test.mjs +0 -295
  180. package/tests/utils/d2-utils.test.mjs +0 -437
  181. package/tests/utils/deploy.test.mjs +0 -399
  182. package/tests/utils/docs-finder-utils.test.mjs +0 -650
  183. package/tests/utils/file-utils.test.mjs +0 -521
  184. package/tests/utils/history-utils.test.mjs +0 -206
  185. package/tests/utils/kroki-utils.test.mjs +0 -646
  186. package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
  187. package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
  188. package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
  189. package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
  190. package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
  191. package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
  192. package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
  193. package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
  194. package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
  195. package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
  196. package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
  197. package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
  198. package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
  199. package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
  200. package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
  201. package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
  202. package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
  203. package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
  204. package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
  205. package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
  206. package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
  207. package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
  208. package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
  209. package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
  210. package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
  211. package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
  212. package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
  213. package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
  214. package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
  215. package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
  216. package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
  217. package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
  218. package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
  219. package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
  220. package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
  221. package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
  222. package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
  223. package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
  224. package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
  225. package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
  226. package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
  227. package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
  228. package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
  229. package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
  230. package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
  231. package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
  232. package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
  233. package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
  234. package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
  235. package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
  236. package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
  237. package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
  238. package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
  239. package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
  240. package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
  241. package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
  242. package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
  243. package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
  244. package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
  245. package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
  246. package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
  247. package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
  248. package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
  249. package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
  250. package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
  251. package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
  252. package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
  253. package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
  254. package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
  255. package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
  256. package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
  257. package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
  258. package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
  259. package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
  260. package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
  261. package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
  262. package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
  263. package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
  264. package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
  265. package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
  266. package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
  267. package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
  268. package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
  269. package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
  270. package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
  271. package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
  272. package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
  273. package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
  274. package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
  275. package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
  276. package/tests/utils/linter/index.test.mjs +0 -440
  277. package/tests/utils/linter/scan-results.mjs +0 -42
  278. package/tests/utils/load-config.test.mjs +0 -141
  279. package/tests/utils/markdown/index.test.mjs +0 -478
  280. package/tests/utils/mermaid-validator.test.mjs +0 -541
  281. package/tests/utils/mock-chat-model.mjs +0 -12
  282. package/tests/utils/preferences-utils.test.mjs +0 -465
  283. package/tests/utils/save-value-to-config.test.mjs +0 -483
  284. package/tests/utils/utils.test.mjs +0 -941
@@ -1,465 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
- import { existsSync } from "node:fs";
3
- import { mkdir, rm, writeFile } from "node:fs/promises";
4
- import { dirname, join } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
-
7
- import { DOC_SMITH_DIR } from "../../utils/constants/index.mjs";
8
- import {
9
- addPreferenceRule,
10
- deactivateRule,
11
- getActiveRulesForScope,
12
- readPreferences,
13
- removeRule,
14
- writePreferences,
15
- } from "../../utils/preferences-utils.mjs";
16
-
17
- const __dirname = dirname(fileURLToPath(import.meta.url));
18
-
19
- describe("preferences-utils", () => {
20
- let testDir;
21
- let originalCwd;
22
-
23
- beforeEach(async () => {
24
- // Create isolated test directory
25
- testDir = join(__dirname, "test-preferences");
26
- await mkdir(testDir, { recursive: true });
27
-
28
- // Change to test directory
29
- originalCwd = process.cwd();
30
- process.chdir(testDir);
31
- });
32
-
33
- afterEach(async () => {
34
- // Restore original working directory
35
- process.chdir(originalCwd);
36
-
37
- // Clean up test directory
38
- await rm(testDir, { recursive: true, force: true });
39
- });
40
-
41
- describe("readPreferences", () => {
42
- test("should return empty rules array when preferences file doesn't exist", () => {
43
- const preferences = readPreferences();
44
- expect(preferences).toEqual({ rules: [] });
45
- });
46
-
47
- test("should read existing preferences file", async () => {
48
- // Create preferences directory and file
49
- const prefsDir = join(testDir, DOC_SMITH_DIR);
50
- await mkdir(prefsDir, { recursive: true });
51
-
52
- await writeFile(
53
- join(prefsDir, "preferences.yml"),
54
- `rules:
55
- - id: test_rule_1
56
- active: true
57
- scope: global
58
- rule: Test rule
59
- feedback: Test feedback
60
- createdAt: '2023-01-01T00:00:00.000Z'
61
- `,
62
- "utf8",
63
- );
64
-
65
- const preferences = readPreferences();
66
- expect(preferences.rules).toHaveLength(1);
67
- expect(preferences.rules[0].id).toBe("test_rule_1");
68
- expect(preferences.rules[0].active).toBe(true);
69
- expect(preferences.rules[0].scope).toBe("global");
70
- });
71
-
72
- test("should handle malformed YAML gracefully", async () => {
73
- // Create preferences directory and invalid file
74
- const prefsDir = join(testDir, DOC_SMITH_DIR);
75
- await mkdir(prefsDir, { recursive: true });
76
-
77
- await writeFile(join(prefsDir, "preferences.yml"), "invalid: yaml: content: [", "utf8");
78
-
79
- const preferences = readPreferences();
80
- expect(preferences).toEqual({ rules: [] });
81
- });
82
- });
83
-
84
- describe("writePreferences", () => {
85
- test("should create preferences directory if it doesn't exist", () => {
86
- const testPreferences = { rules: [] };
87
-
88
- writePreferences(testPreferences);
89
-
90
- const prefsDir = join(testDir, DOC_SMITH_DIR);
91
- expect(existsSync(prefsDir)).toBe(true);
92
- expect(existsSync(join(prefsDir, "preferences.yml"))).toBe(true);
93
- });
94
-
95
- test("should write preferences to YAML file", () => {
96
- const testPreferences = {
97
- rules: [
98
- {
99
- id: "test_rule_1",
100
- active: true,
101
- scope: "global",
102
- rule: "Test rule",
103
- feedback: "Test feedback",
104
- createdAt: "2023-01-01T00:00:00.000Z",
105
- },
106
- ],
107
- };
108
-
109
- writePreferences(testPreferences);
110
-
111
- // Read back and verify
112
- const savedPreferences = readPreferences();
113
- expect(savedPreferences.rules).toHaveLength(1);
114
- expect(savedPreferences.rules[0]).toEqual(testPreferences.rules[0]);
115
- });
116
- });
117
-
118
- describe("addPreferenceRule", () => {
119
- test("should add a new rule with generated ID", () => {
120
- const ruleData = {
121
- rule: "Always use proper punctuation",
122
- scope: "document",
123
- limitToInputPaths: false,
124
- };
125
- const feedback = "Please ensure proper punctuation";
126
-
127
- const newRule = addPreferenceRule(ruleData, feedback);
128
-
129
- expect(newRule.id).toMatch(/^pref_[a-f0-9]{16}$/);
130
- expect(newRule.active).toBe(true);
131
- expect(newRule.scope).toBe("document");
132
- expect(newRule.rule).toBe("Always use proper punctuation");
133
- expect(newRule.feedback).toBe("Please ensure proper punctuation");
134
- expect(newRule.createdAt).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/);
135
-
136
- // Verify it was saved
137
- const preferences = readPreferences();
138
- expect(preferences.rules).toHaveLength(1);
139
- expect(preferences.rules[0]).toEqual(newRule);
140
- });
141
-
142
- test("should add paths when limitToInputPaths is true", () => {
143
- const ruleData = {
144
- rule: "Use consistent naming",
145
- scope: "structure",
146
- limitToInputPaths: true,
147
- };
148
- const feedback = "Keep naming consistent";
149
- const paths = ["/docs/api", "/docs/guide"];
150
-
151
- const newRule = addPreferenceRule(ruleData, feedback, paths);
152
-
153
- expect(newRule.paths).toEqual(["/docs/api", "/docs/guide"]);
154
-
155
- // Verify it was saved with paths
156
- const preferences = readPreferences();
157
- expect(preferences.rules[0].paths).toEqual(paths);
158
- });
159
-
160
- test("should not add paths when limitToInputPaths is false", () => {
161
- const ruleData = {
162
- rule: "Global rule",
163
- scope: "global",
164
- limitToInputPaths: false,
165
- };
166
- const feedback = "Global feedback";
167
- const paths = ["/docs/api"];
168
-
169
- const newRule = addPreferenceRule(ruleData, feedback, paths);
170
-
171
- expect(newRule.paths).toBeUndefined();
172
- });
173
-
174
- test("should add new rules to the beginning of the array", () => {
175
- // Add first rule
176
- const rule1 = addPreferenceRule(
177
- { rule: "Rule 1", scope: "global", limitToInputPaths: false },
178
- "Feedback 1",
179
- );
180
-
181
- // Add second rule
182
- const rule2 = addPreferenceRule(
183
- { rule: "Rule 2", scope: "document", limitToInputPaths: false },
184
- "Feedback 2",
185
- );
186
-
187
- const preferences = readPreferences();
188
- expect(preferences.rules).toHaveLength(2);
189
- expect(preferences.rules[0]).toEqual(rule2); // Most recent first
190
- expect(preferences.rules[1]).toEqual(rule1);
191
- });
192
-
193
- test("should handle rules with special characters and colons", () => {
194
- const ruleData = {
195
- rule: 'Always use proper punctuation: semicolons, colons, and quotes"like this"',
196
- scope: "document",
197
- limitToInputPaths: false,
198
- };
199
- const feedback = 'Please ensure proper punctuation: don\'t forget quotes"and colons"';
200
-
201
- const newRule = addPreferenceRule(ruleData, feedback);
202
-
203
- expect(newRule.rule).toBe(
204
- 'Always use proper punctuation: semicolons, colons, and quotes"like this"',
205
- );
206
- expect(newRule.feedback).toBe(
207
- 'Please ensure proper punctuation: don\'t forget quotes"and colons"',
208
- );
209
-
210
- // Verify it was saved and can be read back
211
- const preferences = readPreferences();
212
- expect(preferences.rules).toHaveLength(1);
213
- expect(preferences.rules[0].rule).toEqual(newRule.rule);
214
- expect(preferences.rules[0].feedback).toEqual(newRule.feedback);
215
- });
216
-
217
- test("should handle rules with multiline content and special YAML characters", () => {
218
- const ruleData = {
219
- rule: "Multi-line rule:\\nLine 1: Use proper formatting\\nLine 2: Handle | pipe characters\\nLine 3: And > greater than symbols",
220
- scope: "structure",
221
- limitToInputPaths: false,
222
- };
223
- const feedback =
224
- "Multi-line feedback:\\n- Check formatting\\n- Validate | pipes\\n- Handle > symbols\\n- Process 'single quotes' and \"double quotes\"";
225
-
226
- const newRule = addPreferenceRule(ruleData, feedback);
227
-
228
- expect(newRule.rule).toContain("Multi-line rule:\\nLine 1");
229
- expect(newRule.feedback).toContain("Multi-line feedback:\\n- Check");
230
-
231
- // Verify it was saved and can be read back correctly
232
- const preferences = readPreferences();
233
- expect(preferences.rules).toHaveLength(1);
234
- expect(preferences.rules[0].rule).toEqual(ruleData.rule);
235
- expect(preferences.rules[0].feedback).toEqual(feedback);
236
- });
237
-
238
- test("should handle rules with Chinese and Unicode characters", () => {
239
- const ruleData = {
240
- rule: "使用正确的中文标点符号:逗号,句号。还有emoji 🔥 和特殊符号 @#$%^&*()",
241
- scope: "document",
242
- limitToInputPaths: false,
243
- };
244
- const feedback = '请确保正确使用标点:引号"这样"和冒号:还有各种符号!@#$%';
245
-
246
- const newRule = addPreferenceRule(ruleData, feedback);
247
-
248
- expect(newRule.rule).toBe(
249
- "使用正确的中文标点符号:逗号,句号。还有emoji 🔥 和特殊符号 @#$%^&*()",
250
- );
251
- expect(newRule.feedback).toBe('请确保正确使用标点:引号"这样"和冒号:还有各种符号!@#$%');
252
-
253
- // Verify it was saved and can be read back
254
- const preferences = readPreferences();
255
- expect(preferences.rules).toHaveLength(1);
256
- expect(preferences.rules[0].rule).toEqual(newRule.rule);
257
- expect(preferences.rules[0].feedback).toEqual(newRule.feedback);
258
- });
259
-
260
- test("should handle paths with special characters", () => {
261
- const ruleData = {
262
- rule: "Path-specific rule for special directories",
263
- scope: "structure",
264
- limitToInputPaths: true,
265
- };
266
- const feedback = "Apply to special paths only";
267
- const paths = [
268
- "/docs/api: advanced",
269
- "/docs/guide-中文",
270
- "/path with spaces",
271
- "/symbols@#$%/file",
272
- ];
273
-
274
- const newRule = addPreferenceRule(ruleData, feedback, paths);
275
-
276
- expect(newRule.paths).toEqual(paths);
277
-
278
- // Verify it was saved with all special character paths
279
- const preferences = readPreferences();
280
- expect(preferences.rules[0].paths).toEqual(paths);
281
- expect(preferences.rules[0].paths).toContain("/docs/api: advanced");
282
- expect(preferences.rules[0].paths).toContain("/docs/guide-中文");
283
- expect(preferences.rules[0].paths).toContain("/path with spaces");
284
- expect(preferences.rules[0].paths).toContain("/symbols@#$%/file");
285
- });
286
- });
287
-
288
- describe("getActiveRulesForScope", () => {
289
- beforeEach(() => {
290
- // Set up test preferences
291
- const testPreferences = {
292
- rules: [
293
- {
294
- id: "rule1",
295
- active: true,
296
- scope: "global",
297
- rule: "Global rule 1",
298
- feedback: "Global feedback",
299
- createdAt: "2023-01-01T00:00:00.000Z",
300
- },
301
- {
302
- id: "rule2",
303
- active: false,
304
- scope: "global",
305
- rule: "Inactive global rule",
306
- feedback: "Inactive feedback",
307
- createdAt: "2023-01-02T00:00:00.000Z",
308
- },
309
- {
310
- id: "rule3",
311
- active: true,
312
- scope: "document",
313
- rule: "Document rule",
314
- feedback: "Document feedback",
315
- createdAt: "2023-01-03T00:00:00.000Z",
316
- },
317
- {
318
- id: "rule4",
319
- active: true,
320
- scope: "global",
321
- rule: "Path-restricted rule",
322
- feedback: "Path feedback",
323
- paths: ["/docs/api", "/docs/guide"],
324
- createdAt: "2023-01-04T00:00:00.000Z",
325
- },
326
- ],
327
- };
328
-
329
- writePreferences(testPreferences);
330
- });
331
-
332
- test("should return only active rules for specified scope (excluding path-restricted without matching paths)", () => {
333
- const rules = getActiveRulesForScope("global");
334
-
335
- expect(rules).toHaveLength(1);
336
- expect(rules[0].id).toBe("rule1");
337
- // rule4 is excluded because it has path restrictions but no matching paths were provided
338
- });
339
-
340
- test("should return empty array for non-matching scope", () => {
341
- const rules = getActiveRulesForScope("structure");
342
- expect(rules).toHaveLength(0);
343
- });
344
-
345
- test("should filter out inactive rules", () => {
346
- const rules = getActiveRulesForScope("global");
347
- const inactiveRule = rules.find((r) => r.id === "rule2");
348
- expect(inactiveRule).toBeUndefined();
349
- });
350
-
351
- test("should include path-restricted rules when matching paths provided", () => {
352
- const rules = getActiveRulesForScope("global", ["/docs/api"]);
353
-
354
- expect(rules).toHaveLength(2);
355
- const pathRestrictedRule = rules.find((r) => r.id === "rule4");
356
- expect(pathRestrictedRule).toBeDefined();
357
- });
358
-
359
- test("should exclude path-restricted rules when no matching paths", () => {
360
- const rules = getActiveRulesForScope("global", ["/other/path"]);
361
-
362
- expect(rules).toHaveLength(1);
363
- expect(rules[0].id).toBe("rule1"); // Only the unrestricted global rule
364
- });
365
-
366
- test("should exclude path-restricted rules when no paths provided", () => {
367
- const rules = getActiveRulesForScope("global", []);
368
-
369
- expect(rules).toHaveLength(1);
370
- expect(rules[0].id).toBe("rule1"); // Only the unrestricted global rule
371
- });
372
- });
373
-
374
- describe("deactivateRule", () => {
375
- beforeEach(() => {
376
- const testPreferences = {
377
- rules: [
378
- {
379
- id: "rule1",
380
- active: true,
381
- scope: "global",
382
- rule: "Test rule 1",
383
- feedback: "Feedback 1",
384
- createdAt: "2023-01-01T00:00:00.000Z",
385
- },
386
- {
387
- id: "rule2",
388
- active: true,
389
- scope: "document",
390
- rule: "Test rule 2",
391
- feedback: "Feedback 2",
392
- createdAt: "2023-01-02T00:00:00.000Z",
393
- },
394
- ],
395
- };
396
-
397
- writePreferences(testPreferences);
398
- });
399
-
400
- test("should deactivate existing rule", () => {
401
- const result = deactivateRule("rule1");
402
-
403
- expect(result).toBe(true);
404
-
405
- const preferences = readPreferences();
406
- const rule = preferences.rules.find((r) => r.id === "rule1");
407
- expect(rule.active).toBe(false);
408
-
409
- // Other rule should remain unchanged
410
- const otherRule = preferences.rules.find((r) => r.id === "rule2");
411
- expect(otherRule.active).toBe(true);
412
- });
413
-
414
- test("should return false for non-existent rule", () => {
415
- const result = deactivateRule("nonexistent");
416
- expect(result).toBe(false);
417
- });
418
- });
419
-
420
- describe("removeRule", () => {
421
- beforeEach(() => {
422
- const testPreferences = {
423
- rules: [
424
- {
425
- id: "rule1",
426
- active: true,
427
- scope: "global",
428
- rule: "Test rule 1",
429
- feedback: "Feedback 1",
430
- createdAt: "2023-01-01T00:00:00.000Z",
431
- },
432
- {
433
- id: "rule2",
434
- active: true,
435
- scope: "document",
436
- rule: "Test rule 2",
437
- feedback: "Feedback 2",
438
- createdAt: "2023-01-02T00:00:00.000Z",
439
- },
440
- ],
441
- };
442
-
443
- writePreferences(testPreferences);
444
- });
445
-
446
- test("should remove existing rule", () => {
447
- const result = removeRule("rule1");
448
-
449
- expect(result).toBe(true);
450
-
451
- const preferences = readPreferences();
452
- expect(preferences.rules).toHaveLength(1);
453
- expect(preferences.rules[0].id).toBe("rule2");
454
- });
455
-
456
- test("should return false for non-existent rule", () => {
457
- const result = removeRule("nonexistent");
458
- expect(result).toBe(false);
459
-
460
- // Rules should remain unchanged
461
- const preferences = readPreferences();
462
- expect(preferences.rules).toHaveLength(2);
463
- });
464
- });
465
- });