@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,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
- });