@aigne/doc-smith 0.2.6 ā 0.2.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.
- package/CHANGELOG.md +26 -0
- package/agents/check-detail-result.mjs +2 -7
- package/agents/check-detail.mjs +4 -6
- package/agents/check-structure-plan.mjs +5 -10
- package/agents/find-item-by-path.mjs +13 -31
- package/agents/input-generator.mjs +15 -35
- package/agents/language-selector.mjs +6 -18
- package/agents/load-config.mjs +2 -2
- package/agents/load-sources.mjs +29 -117
- package/agents/publish-docs.mjs +15 -28
- package/agents/save-docs.mjs +8 -20
- package/agents/save-output.mjs +2 -9
- package/agents/save-single-doc.mjs +2 -2
- package/agents/schema/structure-plan.yaml +1 -1
- package/agents/transform-detail-datasources.mjs +2 -5
- package/biome.json +13 -3
- package/docs-mcp/get-docs-structure.mjs +1 -1
- package/docs-mcp/read-doc-content.mjs +1 -4
- package/package.json +10 -6
- package/tests/check-detail-result.test.mjs +8 -19
- package/tests/load-sources.test.mjs +65 -161
- package/tests/test-all-validation-cases.mjs +71 -37
- package/tests/test-save-docs.mjs +6 -17
- package/utils/constants.mjs +1 -2
- package/utils/file-utils.mjs +205 -0
- package/utils/markdown-checker.mjs +124 -57
- package/utils/mermaid-validator.mjs +5 -10
- package/utils/mermaid-worker-pool.mjs +7 -11
- package/utils/mermaid-worker.mjs +8 -17
- package/utils/utils.mjs +52 -104
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { mkdir, rm, writeFile
|
|
2
|
-
import path from "node:path";
|
|
1
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import path, { dirname } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { dirname } from "node:path";
|
|
5
4
|
import loadSources from "../agents/load-sources.mjs";
|
|
6
5
|
|
|
7
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -30,118 +29,67 @@ async function runTests() {
|
|
|
30
29
|
await mkdir(path.join(testDir, "src/config"), { recursive: true });
|
|
31
30
|
|
|
32
31
|
// Create test files in root and src
|
|
33
|
-
await writeFile(
|
|
34
|
-
path.join(testDir, "package.json"),
|
|
35
|
-
JSON.stringify({ name: "test" })
|
|
36
|
-
);
|
|
32
|
+
await writeFile(path.join(testDir, "package.json"), JSON.stringify({ name: "test" }));
|
|
37
33
|
await writeFile(path.join(testDir, "README.md"), "# Test Project");
|
|
38
|
-
await writeFile(
|
|
39
|
-
|
|
40
|
-
"console.log('hello');"
|
|
41
|
-
);
|
|
42
|
-
await writeFile(
|
|
43
|
-
path.join(testDir, "src/utils.js"),
|
|
44
|
-
"export function test() {}"
|
|
45
|
-
);
|
|
34
|
+
await writeFile(path.join(testDir, "src/index.js"), "console.log('hello');");
|
|
35
|
+
await writeFile(path.join(testDir, "src/utils.js"), "export function test() {}");
|
|
46
36
|
|
|
47
37
|
// Create files in multi-level directories
|
|
48
|
-
await writeFile(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
);
|
|
52
|
-
await writeFile(
|
|
53
|
-
path.join(testDir, "src/components/ui/Modal.js"),
|
|
54
|
-
"export class Modal {}"
|
|
55
|
-
);
|
|
56
|
-
await writeFile(
|
|
57
|
-
path.join(testDir, "src/components/ui/Input.js"),
|
|
58
|
-
"export class Input {}"
|
|
59
|
-
);
|
|
38
|
+
await writeFile(path.join(testDir, "src/components/Button.js"), "export class Button {}");
|
|
39
|
+
await writeFile(path.join(testDir, "src/components/ui/Modal.js"), "export class Modal {}");
|
|
40
|
+
await writeFile(path.join(testDir, "src/components/ui/Input.js"), "export class Input {}");
|
|
60
41
|
await writeFile(
|
|
61
42
|
path.join(testDir, "src/utils/helpers/format.js"),
|
|
62
|
-
"export function format() {}"
|
|
43
|
+
"export function format() {}",
|
|
63
44
|
);
|
|
64
45
|
await writeFile(
|
|
65
46
|
path.join(testDir, "src/utils/helpers/validate.js"),
|
|
66
|
-
"export function validate() {}"
|
|
67
|
-
);
|
|
68
|
-
await writeFile(
|
|
69
|
-
path.join(testDir, "src/services/api/client.js"),
|
|
70
|
-
"export class ApiClient {}"
|
|
47
|
+
"export function validate() {}",
|
|
71
48
|
);
|
|
49
|
+
await writeFile(path.join(testDir, "src/services/api/client.js"), "export class ApiClient {}");
|
|
72
50
|
await writeFile(
|
|
73
51
|
path.join(testDir, "src/services/api/endpoints.js"),
|
|
74
|
-
"export const endpoints = {}"
|
|
75
|
-
);
|
|
76
|
-
await writeFile(
|
|
77
|
-
path.join(testDir, "src/config/database.js"),
|
|
78
|
-
"export const dbConfig = {}"
|
|
79
|
-
);
|
|
80
|
-
await writeFile(
|
|
81
|
-
path.join(testDir, "src/config/app.js"),
|
|
82
|
-
"export const appConfig = {}"
|
|
52
|
+
"export const endpoints = {}",
|
|
83
53
|
);
|
|
54
|
+
await writeFile(path.join(testDir, "src/config/database.js"), "export const dbConfig = {}");
|
|
55
|
+
await writeFile(path.join(testDir, "src/config/app.js"), "export const appConfig = {}");
|
|
84
56
|
|
|
85
57
|
// Create some non-JS files to test filtering
|
|
86
|
-
await writeFile(
|
|
87
|
-
path.join(testDir, "src/components/ui/styles.css"),
|
|
88
|
-
"/* styles */"
|
|
89
|
-
);
|
|
58
|
+
await writeFile(path.join(testDir, "src/components/ui/styles.css"), "/* styles */");
|
|
90
59
|
await writeFile(
|
|
91
60
|
path.join(testDir, "src/config/settings.json"),
|
|
92
|
-
JSON.stringify({ theme: "dark" })
|
|
93
|
-
);
|
|
94
|
-
await writeFile(
|
|
95
|
-
path.join(testDir, "src/utils/helpers/data.yaml"),
|
|
96
|
-
"version: 1.0"
|
|
61
|
+
JSON.stringify({ theme: "dark" }),
|
|
97
62
|
);
|
|
63
|
+
await writeFile(path.join(testDir, "src/utils/helpers/data.yaml"), "version: 1.0");
|
|
98
64
|
|
|
99
65
|
// Create test files
|
|
100
|
-
await writeFile(
|
|
101
|
-
path.join(testDir, "test/test.js"),
|
|
102
|
-
"describe('test', () => {});"
|
|
103
|
-
);
|
|
66
|
+
await writeFile(path.join(testDir, "test/test.js"), "describe('test', () => {});");
|
|
104
67
|
|
|
105
68
|
// Create files with _test pattern to test the new exclusion
|
|
106
|
-
await writeFile(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
);
|
|
110
|
-
await writeFile(
|
|
111
|
-
path.join(testDir, "src/user_test.js"),
|
|
112
|
-
"describe('user', () => {});"
|
|
113
|
-
);
|
|
114
|
-
await writeFile(
|
|
115
|
-
path.join(testDir, "src/api_test.ts"),
|
|
116
|
-
"describe('api', () => {});"
|
|
117
|
-
);
|
|
118
|
-
await writeFile(
|
|
119
|
-
path.join(testDir, "src/utils_test.py"),
|
|
120
|
-
"def test_utils(): pass"
|
|
121
|
-
);
|
|
69
|
+
await writeFile(path.join(testDir, "src/server_test.go"), "func TestServer() {}");
|
|
70
|
+
await writeFile(path.join(testDir, "src/user_test.js"), "describe('user', () => {});");
|
|
71
|
+
await writeFile(path.join(testDir, "src/api_test.ts"), "describe('api', () => {});");
|
|
72
|
+
await writeFile(path.join(testDir, "src/utils_test.py"), "def test_utils(): pass");
|
|
122
73
|
await writeFile(
|
|
123
74
|
path.join(testDir, "src/components/Button_test.jsx"),
|
|
124
|
-
"test('button', () => {});"
|
|
75
|
+
"test('button', () => {});",
|
|
125
76
|
);
|
|
126
77
|
await writeFile(
|
|
127
78
|
path.join(testDir, "src/utils/helpers/format_test.js"),
|
|
128
|
-
"test('format', () => {});"
|
|
79
|
+
"test('format', () => {});",
|
|
129
80
|
);
|
|
130
81
|
|
|
131
82
|
await mkdir(path.join(testDir, "node_modules/some-package"), {
|
|
132
83
|
recursive: true,
|
|
133
84
|
});
|
|
134
|
-
await writeFile(
|
|
135
|
-
path.join(testDir, "node_modules/some-package/package.json"),
|
|
136
|
-
"{}"
|
|
137
|
-
);
|
|
85
|
+
await writeFile(path.join(testDir, "node_modules/some-package/package.json"), "{}");
|
|
138
86
|
await writeFile(path.join(testDir, "temp/temp.txt"), "temp file");
|
|
139
87
|
await writeFile(path.join(testDir, "ignore.txt"), "should be ignored");
|
|
140
88
|
|
|
141
89
|
// Create .gitignore file
|
|
142
90
|
await writeFile(
|
|
143
91
|
path.join(testDir, ".gitignore"),
|
|
144
|
-
"node_modules/\n" + "temp/\n" + "ignore.txt\n" + "*.log\n"
|
|
92
|
+
"node_modules/\n" + "temp/\n" + "ignore.txt\n" + "*.log\n",
|
|
145
93
|
);
|
|
146
94
|
}
|
|
147
95
|
|
|
@@ -159,9 +107,7 @@ async function runTests() {
|
|
|
159
107
|
function assertIncludes(array, item, message) {
|
|
160
108
|
if (!array.some((element) => element.includes(item))) {
|
|
161
109
|
throw new Error(
|
|
162
|
-
`Assertion failed: ${message} - Expected to find ${item} in ${JSON.stringify(
|
|
163
|
-
array
|
|
164
|
-
)}`
|
|
110
|
+
`Assertion failed: ${message} - Expected to find ${item} in ${JSON.stringify(array)}`,
|
|
165
111
|
);
|
|
166
112
|
}
|
|
167
113
|
}
|
|
@@ -169,9 +115,7 @@ async function runTests() {
|
|
|
169
115
|
function assertNotIncludes(array, item, message) {
|
|
170
116
|
if (array.some((element) => element.includes(item))) {
|
|
171
117
|
throw new Error(
|
|
172
|
-
`Assertion failed: ${message} - Expected not to find ${item} in ${JSON.stringify(
|
|
173
|
-
array
|
|
174
|
-
)}`
|
|
118
|
+
`Assertion failed: ${message} - Expected not to find ${item} in ${JSON.stringify(array)}`,
|
|
175
119
|
);
|
|
176
120
|
}
|
|
177
121
|
}
|
|
@@ -187,15 +131,12 @@ async function runTests() {
|
|
|
187
131
|
});
|
|
188
132
|
|
|
189
133
|
assert(result.datasourcesList, "datasourcesList should be defined");
|
|
190
|
-
assert(
|
|
191
|
-
result.datasourcesList.length > 0,
|
|
192
|
-
"datasourcesList should not be empty"
|
|
193
|
-
);
|
|
134
|
+
assert(result.datasourcesList.length > 0, "datasourcesList should not be empty");
|
|
194
135
|
|
|
195
136
|
// Debug: log actual file paths
|
|
196
137
|
console.log(
|
|
197
138
|
"Actual file paths:",
|
|
198
|
-
result.datasourcesList.map((f) => f.sourceId)
|
|
139
|
+
result.datasourcesList.map((f) => f.sourceId),
|
|
199
140
|
);
|
|
200
141
|
|
|
201
142
|
// Should include package.json, README.md, src files
|
|
@@ -226,10 +167,7 @@ async function runTests() {
|
|
|
226
167
|
});
|
|
227
168
|
|
|
228
169
|
assert(result.datasourcesList, "datasourcesList should be defined");
|
|
229
|
-
assert(
|
|
230
|
-
result.datasourcesList.length > 0,
|
|
231
|
-
"datasourcesList should not be empty"
|
|
232
|
-
);
|
|
170
|
+
assert(result.datasourcesList.length > 0, "datasourcesList should not be empty");
|
|
233
171
|
|
|
234
172
|
const filePaths = result.datasourcesList.map((f) => f.sourceId);
|
|
235
173
|
assertIncludes(filePaths, "package.json", "Should include package.json");
|
|
@@ -283,7 +221,7 @@ async function runTests() {
|
|
|
283
221
|
// Debug: log actual file paths
|
|
284
222
|
console.log(
|
|
285
223
|
"Path-based patterns - Actual file paths:",
|
|
286
|
-
result.datasourcesList.map((f) => f.sourceId)
|
|
224
|
+
result.datasourcesList.map((f) => f.sourceId),
|
|
287
225
|
);
|
|
288
226
|
|
|
289
227
|
const filePaths = result.datasourcesList.map((f) => f.sourceId);
|
|
@@ -308,10 +246,7 @@ async function runTests() {
|
|
|
308
246
|
});
|
|
309
247
|
|
|
310
248
|
assert(result.datasourcesList, "datasourcesList should be defined");
|
|
311
|
-
assert(
|
|
312
|
-
result.datasourcesList.length > 0,
|
|
313
|
-
"datasourcesList should not be empty"
|
|
314
|
-
);
|
|
249
|
+
assert(result.datasourcesList.length > 0, "datasourcesList should not be empty");
|
|
315
250
|
|
|
316
251
|
const filePaths = result.datasourcesList.map((f) => f.sourceId);
|
|
317
252
|
assertIncludes(filePaths, "src/index.js", "Should include src/index.js");
|
|
@@ -333,12 +268,10 @@ async function runTests() {
|
|
|
333
268
|
assert(result.datasourcesList, "datasourcesList should be defined");
|
|
334
269
|
assert(
|
|
335
270
|
result.datasourcesList.length === 0,
|
|
336
|
-
"datasourcesList should be empty for non-existent directory"
|
|
271
|
+
"datasourcesList should be empty for non-existent directory",
|
|
337
272
|
);
|
|
338
273
|
|
|
339
|
-
console.log(
|
|
340
|
-
"ā
Test passed: should handle non-existent directories gracefully"
|
|
341
|
-
);
|
|
274
|
+
console.log("ā
Test passed: should handle non-existent directories gracefully");
|
|
342
275
|
}
|
|
343
276
|
|
|
344
277
|
async function testMergeUserPatternsWithDefaultPatterns() {
|
|
@@ -364,9 +297,7 @@ async function runTests() {
|
|
|
364
297
|
// Should exclude user exclude patterns
|
|
365
298
|
assertNotIncludes(filePaths, "docs/", "Should exclude docs/");
|
|
366
299
|
|
|
367
|
-
console.log(
|
|
368
|
-
"ā
Test passed: should merge user patterns with default patterns"
|
|
369
|
-
);
|
|
300
|
+
console.log("ā
Test passed: should merge user patterns with default patterns");
|
|
370
301
|
}
|
|
371
302
|
|
|
372
303
|
async function testHandleMultiLevelDirectoryStructure() {
|
|
@@ -382,10 +313,7 @@ async function runTests() {
|
|
|
382
313
|
});
|
|
383
314
|
|
|
384
315
|
assert(result.datasourcesList, "datasourcesList should be defined");
|
|
385
|
-
assert(
|
|
386
|
-
result.datasourcesList.length > 0,
|
|
387
|
-
"datasourcesList should not be empty"
|
|
388
|
-
);
|
|
316
|
+
assert(result.datasourcesList.length > 0, "datasourcesList should not be empty");
|
|
389
317
|
|
|
390
318
|
const filePaths = result.datasourcesList.map((f) => f.sourceId);
|
|
391
319
|
|
|
@@ -395,61 +323,47 @@ async function runTests() {
|
|
|
395
323
|
assertIncludes(
|
|
396
324
|
filePaths,
|
|
397
325
|
"src/components/Button.js",
|
|
398
|
-
"Should include src/components/Button.js"
|
|
326
|
+
"Should include src/components/Button.js",
|
|
399
327
|
);
|
|
400
328
|
assertIncludes(
|
|
401
329
|
filePaths,
|
|
402
330
|
"src/components/ui/Modal.js",
|
|
403
|
-
"Should include src/components/ui/Modal.js"
|
|
331
|
+
"Should include src/components/ui/Modal.js",
|
|
404
332
|
);
|
|
405
333
|
assertIncludes(
|
|
406
334
|
filePaths,
|
|
407
335
|
"src/components/ui/Input.js",
|
|
408
|
-
"Should include src/components/ui/Input.js"
|
|
336
|
+
"Should include src/components/ui/Input.js",
|
|
409
337
|
);
|
|
410
338
|
assertIncludes(
|
|
411
339
|
filePaths,
|
|
412
340
|
"src/utils/helpers/format.js",
|
|
413
|
-
"Should include src/utils/helpers/format.js"
|
|
341
|
+
"Should include src/utils/helpers/format.js",
|
|
414
342
|
);
|
|
415
343
|
assertIncludes(
|
|
416
344
|
filePaths,
|
|
417
345
|
"src/utils/helpers/validate.js",
|
|
418
|
-
"Should include src/utils/helpers/validate.js"
|
|
346
|
+
"Should include src/utils/helpers/validate.js",
|
|
419
347
|
);
|
|
420
348
|
assertIncludes(
|
|
421
349
|
filePaths,
|
|
422
350
|
"src/services/api/client.js",
|
|
423
|
-
"Should include src/services/api/client.js"
|
|
351
|
+
"Should include src/services/api/client.js",
|
|
424
352
|
);
|
|
425
353
|
assertIncludes(
|
|
426
354
|
filePaths,
|
|
427
355
|
"src/services/api/endpoints.js",
|
|
428
|
-
"Should include src/services/api/endpoints.js"
|
|
429
|
-
);
|
|
430
|
-
assertIncludes(
|
|
431
|
-
filePaths,
|
|
432
|
-
"src/config/database.js",
|
|
433
|
-
"Should include src/config/database.js"
|
|
434
|
-
);
|
|
435
|
-
assertIncludes(
|
|
436
|
-
filePaths,
|
|
437
|
-
"src/config/app.js",
|
|
438
|
-
"Should include src/config/app.js"
|
|
356
|
+
"Should include src/services/api/endpoints.js",
|
|
439
357
|
);
|
|
358
|
+
assertIncludes(filePaths, "src/config/database.js", "Should include src/config/database.js");
|
|
359
|
+
assertIncludes(filePaths, "src/config/app.js", "Should include src/config/app.js");
|
|
440
360
|
|
|
441
361
|
// Should exclude non-JS files
|
|
442
362
|
assertNotIncludes(filePaths, "styles.css", "Should exclude styles.css");
|
|
443
|
-
assertNotIncludes(
|
|
444
|
-
filePaths,
|
|
445
|
-
"settings.json",
|
|
446
|
-
"Should exclude settings.json"
|
|
447
|
-
);
|
|
363
|
+
assertNotIncludes(filePaths, "settings.json", "Should exclude settings.json");
|
|
448
364
|
assertNotIncludes(filePaths, "data.yaml", "Should exclude data.yaml");
|
|
449
365
|
|
|
450
|
-
console.log(
|
|
451
|
-
"ā
Test passed: should handle multi-level directory structure"
|
|
452
|
-
);
|
|
366
|
+
console.log("ā
Test passed: should handle multi-level directory structure");
|
|
453
367
|
}
|
|
454
368
|
|
|
455
369
|
async function testFilterBySpecificSubdirectories() {
|
|
@@ -472,50 +386,44 @@ async function runTests() {
|
|
|
472
386
|
assertIncludes(
|
|
473
387
|
filePaths,
|
|
474
388
|
"src/components/Button.js",
|
|
475
|
-
"Should include src/components/Button.js"
|
|
389
|
+
"Should include src/components/Button.js",
|
|
476
390
|
);
|
|
477
391
|
assertIncludes(
|
|
478
392
|
filePaths,
|
|
479
393
|
"src/utils/helpers/format.js",
|
|
480
|
-
"Should include src/utils/helpers/format.js"
|
|
394
|
+
"Should include src/utils/helpers/format.js",
|
|
481
395
|
);
|
|
482
396
|
assertIncludes(
|
|
483
397
|
filePaths,
|
|
484
398
|
"src/utils/helpers/validate.js",
|
|
485
|
-
"Should include src/utils/helpers/validate.js"
|
|
399
|
+
"Should include src/utils/helpers/validate.js",
|
|
486
400
|
);
|
|
487
401
|
|
|
488
402
|
// Should exclude files from excluded subdirectories
|
|
489
403
|
assertNotIncludes(
|
|
490
404
|
filePaths,
|
|
491
405
|
"src/components/ui/Modal.js",
|
|
492
|
-
"Should exclude src/components/ui/Modal.js"
|
|
406
|
+
"Should exclude src/components/ui/Modal.js",
|
|
493
407
|
);
|
|
494
408
|
assertNotIncludes(
|
|
495
409
|
filePaths,
|
|
496
410
|
"src/components/ui/Input.js",
|
|
497
|
-
"Should exclude src/components/ui/Input.js"
|
|
411
|
+
"Should exclude src/components/ui/Input.js",
|
|
498
412
|
);
|
|
499
413
|
|
|
500
414
|
// Should exclude files from other directories
|
|
501
415
|
assertNotIncludes(
|
|
502
416
|
filePaths,
|
|
503
417
|
"src/services/api/client.js",
|
|
504
|
-
"Should exclude src/services/api/client.js"
|
|
505
|
-
);
|
|
506
|
-
assertNotIncludes(
|
|
507
|
-
filePaths,
|
|
508
|
-
"src/config/database.js",
|
|
509
|
-
"Should exclude src/config/database.js"
|
|
418
|
+
"Should exclude src/services/api/client.js",
|
|
510
419
|
);
|
|
420
|
+
assertNotIncludes(filePaths, "src/config/database.js", "Should exclude src/config/database.js");
|
|
511
421
|
|
|
512
422
|
console.log("ā
Test passed: should filter by specific subdirectories");
|
|
513
423
|
}
|
|
514
424
|
|
|
515
425
|
async function testHandleMixedFileTypesInMultiLevelDirectories() {
|
|
516
|
-
console.log(
|
|
517
|
-
"Testing: should handle mixed file types in multi-level directories"
|
|
518
|
-
);
|
|
426
|
+
console.log("Testing: should handle mixed file types in multi-level directories");
|
|
519
427
|
|
|
520
428
|
const result = await loadSources({
|
|
521
429
|
sourcesPath: testDir,
|
|
@@ -534,24 +442,24 @@ async function runTests() {
|
|
|
534
442
|
assertIncludes(
|
|
535
443
|
filePaths,
|
|
536
444
|
"src/components/Button.js",
|
|
537
|
-
"Should include src/components/Button.js"
|
|
445
|
+
"Should include src/components/Button.js",
|
|
538
446
|
);
|
|
539
447
|
assertIncludes(
|
|
540
448
|
filePaths,
|
|
541
449
|
"src/utils/helpers/format.js",
|
|
542
|
-
"Should include src/utils/helpers/format.js"
|
|
450
|
+
"Should include src/utils/helpers/format.js",
|
|
543
451
|
);
|
|
544
452
|
|
|
545
453
|
// Should include JSON and YAML files
|
|
546
454
|
assertIncludes(
|
|
547
455
|
filePaths,
|
|
548
456
|
"src/config/settings.json",
|
|
549
|
-
"Should include src/config/settings.json"
|
|
457
|
+
"Should include src/config/settings.json",
|
|
550
458
|
);
|
|
551
459
|
assertIncludes(
|
|
552
460
|
filePaths,
|
|
553
461
|
"src/utils/helpers/data.yaml",
|
|
554
|
-
"Should include src/utils/helpers/data.yaml"
|
|
462
|
+
"Should include src/utils/helpers/data.yaml",
|
|
555
463
|
);
|
|
556
464
|
|
|
557
465
|
// Should exclude CSS files
|
|
@@ -560,15 +468,11 @@ async function runTests() {
|
|
|
560
468
|
// Should exclude node_modules
|
|
561
469
|
assertNotIncludes(filePaths, "node_modules", "Should exclude node_modules");
|
|
562
470
|
|
|
563
|
-
console.log(
|
|
564
|
-
"ā
Test passed: should handle mixed file types in multi-level directories"
|
|
565
|
-
);
|
|
471
|
+
console.log("ā
Test passed: should handle mixed file types in multi-level directories");
|
|
566
472
|
}
|
|
567
473
|
|
|
568
474
|
async function testExcludeFilesWithTestPatternUsingDefaultPatterns() {
|
|
569
|
-
console.log(
|
|
570
|
-
"Testing: should exclude files with _test pattern using default patterns"
|
|
571
|
-
);
|
|
475
|
+
console.log("Testing: should exclude files with _test pattern using default patterns");
|
|
572
476
|
|
|
573
477
|
const result = await loadSources({
|
|
574
478
|
sourcesPath: testDir,
|
|
@@ -584,7 +488,7 @@ async function runTests() {
|
|
|
584
488
|
// Debug: log actual file paths to see what's included
|
|
585
489
|
console.log(
|
|
586
490
|
"Files with _test pattern - Actual file paths:",
|
|
587
|
-
result.datasourcesList.map((f) => f.sourceId)
|
|
491
|
+
result.datasourcesList.map((f) => f.sourceId),
|
|
588
492
|
);
|
|
589
493
|
|
|
590
494
|
// Check which _test files are actually included
|
|
@@ -600,7 +504,7 @@ async function runTests() {
|
|
|
600
504
|
assertIncludes(
|
|
601
505
|
filePaths,
|
|
602
506
|
"src/components/Button.js",
|
|
603
|
-
"Should include src/components/Button.js"
|
|
507
|
+
"Should include src/components/Button.js",
|
|
604
508
|
);
|
|
605
509
|
|
|
606
510
|
// And verify that some expected exclusions are working
|
|
@@ -609,7 +513,7 @@ async function runTests() {
|
|
|
609
513
|
assertNotIncludes(filePaths, "test/test.js", "Should exclude test/test.js");
|
|
610
514
|
|
|
611
515
|
console.log(
|
|
612
|
-
"ā
Test passed: should exclude files with _test pattern using default patterns (adjusted expectations)"
|
|
516
|
+
"ā
Test passed: should exclude files with _test pattern using default patterns (adjusted expectations)",
|
|
613
517
|
);
|
|
614
518
|
}
|
|
615
519
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { checkMarkdown } from "../utils/markdown-checker.mjs";
|
|
4
3
|
import checkDetailResult from "../agents/check-detail-result.mjs";
|
|
4
|
+
import { checkMarkdown } from "../utils/markdown-checker.mjs";
|
|
5
5
|
import { shutdownValidation } from "../utils/mermaid-validator.mjs";
|
|
6
6
|
|
|
7
7
|
// Mock structure plan for link validation
|
|
@@ -164,25 +164,6 @@ This content ends properly.
|
|
|
164
164
|
},
|
|
165
165
|
|
|
166
166
|
// ========== CODE BLOCK VALIDATION CASES ==========
|
|
167
|
-
{
|
|
168
|
-
category: "š» CODE BLOCK VALIDATION",
|
|
169
|
-
name: "Inconsistent code block indentation",
|
|
170
|
-
expectPass: false,
|
|
171
|
-
expectedErrors: ["code block with inconsistent indentation"],
|
|
172
|
-
content: `# Test Document
|
|
173
|
-
|
|
174
|
-
Here's incorrectly indented code:
|
|
175
|
-
|
|
176
|
-
\`\`\`javascript
|
|
177
|
-
function test() {
|
|
178
|
-
return "content not properly indented";
|
|
179
|
-
}
|
|
180
|
-
\`\`\`
|
|
181
|
-
|
|
182
|
-
This content ends properly.
|
|
183
|
-
`,
|
|
184
|
-
},
|
|
185
|
-
|
|
186
167
|
{
|
|
187
168
|
category: "š» CODE BLOCK VALIDATION",
|
|
188
169
|
name: "Incomplete code block",
|
|
@@ -216,6 +197,68 @@ This content ends properly.
|
|
|
216
197
|
`,
|
|
217
198
|
},
|
|
218
199
|
|
|
200
|
+
{
|
|
201
|
+
category: "š» CODE BLOCK VALIDATION",
|
|
202
|
+
name: "Code block with inconsistent indentation (user case)",
|
|
203
|
+
expectPass: false,
|
|
204
|
+
expectedErrors: ["code block with inconsistent indentation"],
|
|
205
|
+
content: `# API Response Handling
|
|
206
|
+
|
|
207
|
+
You can retrieve the response body in various formats:
|
|
208
|
+
|
|
209
|
+
* **\`response.content\`**: Accesses the raw response body as bytes. This is useful for non-text data like images or binary files.
|
|
210
|
+
\`\`\`python
|
|
211
|
+
import requests
|
|
212
|
+
|
|
213
|
+
r = requests.get('https://httpbin.org/image/png')
|
|
214
|
+
print(type(r.content))
|
|
215
|
+
# Expected output: <class 'bytes'>
|
|
216
|
+
\`\`\`
|
|
217
|
+
|
|
218
|
+
* **\`response.text\`**: Accesses the response body as Unicode text. Requests automatically guesses the encoding, or you can explicitly set \`response.encoding\`.
|
|
219
|
+
\`\`\`python
|
|
220
|
+
import requests
|
|
221
|
+
|
|
222
|
+
r = requests.get('https://httpbin.org/get')
|
|
223
|
+
print(type(r.text))
|
|
224
|
+
# Expected output: <class 'str'>
|
|
225
|
+
print(r.text)
|
|
226
|
+
# Expected output: {"args": {}, "headers": ..., "origin": "...", "url": "https://httpbin.org/get"}
|
|
227
|
+
\`\`\`
|
|
228
|
+
|
|
229
|
+
* **\`response.json(**kwargs)\`**: Decodes the response body as JSON into a Python object (dictionary, list, etc.). This method raises \`requests.exceptions.JSONDecodeError\` if the content is not valid JSON.
|
|
230
|
+
\`\`\`python
|
|
231
|
+
import requests
|
|
232
|
+
|
|
233
|
+
r = requests.get('https://httpbin.org/json')
|
|
234
|
+
print(type(r.json()))
|
|
235
|
+
# Expected output: <class 'dict'>
|
|
236
|
+
print(r.json())
|
|
237
|
+
# Expected output: {'slideshow': {'author': 'Yours Truly', 'date': 'date of publication', 'slides': [...], 'title': 'Sample Slide Show'}}
|
|
238
|
+
\`\`\`
|
|
239
|
+
|
|
240
|
+
**Status and Error Handling**
|
|
241
|
+
|
|
242
|
+
* **\`response.ok\`**: A boolean property that returns \`True\` if \`status_code\` is less than 400, indicating no client or server error. It does *not* necessarily mean \`200 OK\`.
|
|
243
|
+
|
|
244
|
+
* **\`response.raise_for_status()\`**: Raises an \`HTTPError\` if the HTTP request returned an unsuccessful status code (4xx or 5xx). This is a convenient way to check for errors and is typically used after a request to ensure it was successful.
|
|
245
|
+
|
|
246
|
+
\`\`\`python
|
|
247
|
+
import requests
|
|
248
|
+
from requests.exceptions import HTTPError
|
|
249
|
+
|
|
250
|
+
try:
|
|
251
|
+
r = requests.get('https://httpbin.org/status/404')
|
|
252
|
+
r.raise_for_status() # This will raise an HTTPError for 404
|
|
253
|
+
except HTTPError as e:
|
|
254
|
+
print(f"HTTP Error occurred: {e}")
|
|
255
|
+
# Expected output: HTTP Error occurred: 404 Client Error: NOT FOUND for url: https://httpbin.org/status/404
|
|
256
|
+
\`\`\`
|
|
257
|
+
|
|
258
|
+
This document ends properly.
|
|
259
|
+
`,
|
|
260
|
+
},
|
|
261
|
+
|
|
219
262
|
// ========== CONTENT STRUCTURE CASES ==========
|
|
220
263
|
{
|
|
221
264
|
category: "š CONTENT STRUCTURE",
|
|
@@ -598,11 +641,8 @@ async function runValidationTests() {
|
|
|
598
641
|
|
|
599
642
|
// Check if expected error types are present
|
|
600
643
|
if (testCase.expectedErrors) {
|
|
601
|
-
const foundExpectedErrors = testCase.expectedErrors.every(
|
|
602
|
-
(
|
|
603
|
-
errors.some((error) =>
|
|
604
|
-
error.toLowerCase().includes(expectedError.toLowerCase())
|
|
605
|
-
)
|
|
644
|
+
const foundExpectedErrors = testCase.expectedErrors.every((expectedError) =>
|
|
645
|
+
errors.some((error) => error.toLowerCase().includes(expectedError.toLowerCase())),
|
|
606
646
|
);
|
|
607
647
|
|
|
608
648
|
if (foundExpectedErrors) {
|
|
@@ -618,7 +658,7 @@ async function runValidationTests() {
|
|
|
618
658
|
console.log(
|
|
619
659
|
`ā FAIL - Expected ${expectPass ? "PASS" : "FAIL"} but got ${
|
|
620
660
|
hasErrors ? "FAIL" : "PASS"
|
|
621
|
-
}
|
|
661
|
+
}`,
|
|
622
662
|
);
|
|
623
663
|
failedTests++;
|
|
624
664
|
}
|
|
@@ -643,7 +683,7 @@ async function runValidationTests() {
|
|
|
643
683
|
console.log("ā
Direct call and wrapper consistent");
|
|
644
684
|
} else {
|
|
645
685
|
console.log(
|
|
646
|
-
`ā ļø Inconsistent results: direct=${errors.length}, wrapper=${wrapperErrors.length}
|
|
686
|
+
`ā ļø Inconsistent results: direct=${errors.length}, wrapper=${wrapperErrors.length}`,
|
|
647
687
|
);
|
|
648
688
|
}
|
|
649
689
|
} catch (error) {
|
|
@@ -653,15 +693,13 @@ async function runValidationTests() {
|
|
|
653
693
|
}
|
|
654
694
|
|
|
655
695
|
// Final summary
|
|
656
|
-
console.log(
|
|
696
|
+
console.log(`\n${"=".repeat(80)}`);
|
|
657
697
|
console.log("š TEST SUMMARY");
|
|
658
698
|
console.log("=".repeat(80));
|
|
659
699
|
console.log(`Total Tests: ${totalTests}`);
|
|
660
700
|
console.log(`Passed: ${passedTests} ā
`);
|
|
661
701
|
console.log(`Failed: ${failedTests} ā`);
|
|
662
|
-
console.log(
|
|
663
|
-
`Success Rate: ${((passedTests / totalTests) * 100).toFixed(1)}%`
|
|
664
|
-
);
|
|
702
|
+
console.log(`Success Rate: ${((passedTests / totalTests) * 100).toFixed(1)}%`);
|
|
665
703
|
|
|
666
704
|
console.log("\nš VALIDATION COVERAGE:");
|
|
667
705
|
console.log("ā
Link validation (dead links, allowed links)");
|
|
@@ -674,13 +712,9 @@ async function runValidationTests() {
|
|
|
674
712
|
console.log("ā
Edge cases and error conditions");
|
|
675
713
|
|
|
676
714
|
if (failedTests === 0) {
|
|
677
|
-
console.log(
|
|
678
|
-
"\nš ALL TESTS PASSED! Validation system is working correctly."
|
|
679
|
-
);
|
|
715
|
+
console.log("\nš ALL TESTS PASSED! Validation system is working correctly.");
|
|
680
716
|
} else {
|
|
681
|
-
console.log(
|
|
682
|
-
`\nā ļø ${failedTests} test(s) failed. Please review the validation logic.`
|
|
683
|
-
);
|
|
717
|
+
console.log(`\nā ļø ${failedTests} test(s) failed. Please review the validation logic.`);
|
|
684
718
|
}
|
|
685
719
|
|
|
686
720
|
// Shutdown worker pool to ensure clean exit
|
package/tests/test-save-docs.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join } from "node:path";
|
|
1
|
+
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { dirname } from "node:path";
|
|
5
4
|
import saveDocs from "../agents/save-docs.mjs";
|
|
6
5
|
|
|
7
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -81,12 +80,8 @@ async function testSaveDocs() {
|
|
|
81
80
|
"_sidebar.md",
|
|
82
81
|
];
|
|
83
82
|
|
|
84
|
-
const missingFiles = expectedFiles.filter(
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
const extraFiles = remainingFiles.filter(
|
|
88
|
-
(file) => !expectedFiles.includes(file)
|
|
89
|
-
);
|
|
83
|
+
const missingFiles = expectedFiles.filter((file) => !remainingFiles.includes(file));
|
|
84
|
+
const extraFiles = remainingFiles.filter((file) => !expectedFiles.includes(file));
|
|
90
85
|
|
|
91
86
|
if (missingFiles.length === 0 && extraFiles.length === 0) {
|
|
92
87
|
console.log("\nā
Test passed! All files are as expected.");
|
|
@@ -101,14 +96,8 @@ async function testSaveDocs() {
|
|
|
101
96
|
}
|
|
102
97
|
|
|
103
98
|
// Verify that invalid files were deleted
|
|
104
|
-
const deletedFiles = [
|
|
105
|
-
|
|
106
|
-
"another-old-file.md",
|
|
107
|
-
"old-translation.zh.md",
|
|
108
|
-
];
|
|
109
|
-
const stillExist = deletedFiles.filter((file) =>
|
|
110
|
-
remainingFiles.includes(file)
|
|
111
|
-
);
|
|
99
|
+
const deletedFiles = ["old-file.md", "another-old-file.md", "old-translation.zh.md"];
|
|
100
|
+
const stillExist = deletedFiles.filter((file) => remainingFiles.includes(file));
|
|
112
101
|
|
|
113
102
|
if (stillExist.length === 0) {
|
|
114
103
|
console.log("ā
All invalid files were successfully deleted.");
|
package/utils/constants.mjs
CHANGED
|
@@ -99,8 +99,7 @@ export const DOCUMENT_STYLES = {
|
|
|
99
99
|
// Predefined target audiences
|
|
100
100
|
export const TARGET_AUDIENCES = {
|
|
101
101
|
actionFirst: "Developers, Implementation Engineers, DevOps",
|
|
102
|
-
conceptFirst:
|
|
103
|
-
"Architects, Technical Leads, Developers interested in principles",
|
|
102
|
+
conceptFirst: "Architects, Technical Leads, Developers interested in principles",
|
|
104
103
|
generalUsers: "General Users",
|
|
105
104
|
custom: "Enter your own target audience",
|
|
106
105
|
};
|