@aigne/doc-smith 0.7.1 → 0.8.0
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/.github/workflows/ci.yml +9 -1
- package/CHANGELOG.md +15 -0
- package/README.md +5 -0
- package/agents/check-detail-result.mjs +7 -0
- package/agents/check-detail.mjs +3 -1
- package/agents/detail-regenerator.yaml +3 -0
- package/agents/find-items-by-paths.mjs +9 -1
- package/agents/input-generator.mjs +3 -3
- package/agents/load-sources.mjs +2 -1
- package/agents/save-docs.mjs +1 -5
- package/codecov.yml +15 -0
- package/package.json +1 -1
- package/prompts/content-detail-generator.md +1 -0
- package/prompts/document/custom-components.md +36 -12
- package/tests/check-detail-result.test.mjs +656 -17
- package/tests/conflict-resolution.test.mjs +118 -0
- package/tests/input-generator.test.mjs +594 -1
- package/tests/kroki-utils.test.mjs +588 -0
- package/tests/load-sources.test.mjs +362 -2
- package/tests/mermaid-validation.test.mjs +541 -0
- package/tests/save-docs.test.mjs +1 -1
- package/tests/utils.test.mjs +2020 -2
- package/utils/conflict-detector.mjs +0 -59
- package/utils/file-utils.mjs +5 -0
- package/utils/kroki-utils.mjs +4 -0
- package/utils/markdown-checker.mjs +3 -3
- package/utils/mermaid-validator.mjs +0 -13
- package/utils/utils.mjs +11 -5
- package/tests/all-validation-cases.test.mjs +0 -686
|
@@ -1,686 +0,0 @@
|
|
|
1
|
-
import { afterAll, describe, expect, test } from "bun:test";
|
|
2
|
-
import checkDetailResult from "../agents/check-detail-result.mjs";
|
|
3
|
-
import { checkMarkdown } from "../utils/markdown-checker.mjs";
|
|
4
|
-
import { shutdownValidation } from "../utils/mermaid-validator.mjs";
|
|
5
|
-
|
|
6
|
-
// Mock structure plan for link validation
|
|
7
|
-
const mockStructurePlan = [
|
|
8
|
-
{ path: "./getting-started" },
|
|
9
|
-
{ path: "/api/overview" },
|
|
10
|
-
{ path: "./advanced/configuration" },
|
|
11
|
-
{ path: "./tutorials/basic" },
|
|
12
|
-
{ path: "/reference/api" },
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
// Create allowed links set
|
|
16
|
-
const allowedLinks = new Set();
|
|
17
|
-
mockStructurePlan.forEach((item) => {
|
|
18
|
-
allowedLinks.add(item.path);
|
|
19
|
-
// Add processed .md path
|
|
20
|
-
let processedPath = item.path;
|
|
21
|
-
if (processedPath.startsWith(".")) {
|
|
22
|
-
processedPath = processedPath.replace(/^\./, "");
|
|
23
|
-
}
|
|
24
|
-
let flatPath = processedPath.replace(/^\//, "").replace(/\//g, "-");
|
|
25
|
-
flatPath = `./${flatPath}.md`;
|
|
26
|
-
allowedLinks.add(flatPath);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const testCases = [
|
|
30
|
-
// ========== PASSING CASES ==========
|
|
31
|
-
{
|
|
32
|
-
category: "✅ PASSING CASES",
|
|
33
|
-
name: "Perfect valid document",
|
|
34
|
-
expectPass: true,
|
|
35
|
-
content: `# Getting Started Guide
|
|
36
|
-
|
|
37
|
-
This is a complete document with proper structure and formatting.
|
|
38
|
-
|
|
39
|
-
## Introduction
|
|
40
|
-
|
|
41
|
-
Welcome to our comprehensive guide. This document follows all markdown best practices.
|
|
42
|
-
|
|
43
|
-
## Code Examples
|
|
44
|
-
|
|
45
|
-
Here's a properly formatted code block:
|
|
46
|
-
|
|
47
|
-
\`\`\`javascript
|
|
48
|
-
function validateInput(data) {
|
|
49
|
-
if (!data) {
|
|
50
|
-
throw new Error("Data is required");
|
|
51
|
-
}
|
|
52
|
-
return data.trim();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Export the function
|
|
56
|
-
export { validateInput };
|
|
57
|
-
\`\`\`
|
|
58
|
-
|
|
59
|
-
## Data Tables
|
|
60
|
-
|
|
61
|
-
Our API supports the following data types:
|
|
62
|
-
|
|
63
|
-
|Type|Description|Example|
|
|
64
|
-
|----|-----------|-------|
|
|
65
|
-
|String|Text data|"Hello"|
|
|
66
|
-
|Number|Numeric values|42|
|
|
67
|
-
|Boolean|True/false|true|
|
|
68
|
-
|
|
69
|
-
## Process Flow
|
|
70
|
-
|
|
71
|
-
The following diagram shows our validation process:
|
|
72
|
-
|
|
73
|
-
\`\`\`mermaid
|
|
74
|
-
flowchart TD
|
|
75
|
-
A[Start] --> B{Valid Input?}
|
|
76
|
-
B -->|Yes| C[Process Data]
|
|
77
|
-
B -->|No| D[Return Error]
|
|
78
|
-
C --> E[Save Results]
|
|
79
|
-
D --> F[Log Error]
|
|
80
|
-
E --> G[End]
|
|
81
|
-
F --> G
|
|
82
|
-
\`\`\`
|
|
83
|
-
|
|
84
|
-
## Related Documentation
|
|
85
|
-
|
|
86
|
-
For more information, see our [API reference](/reference/api) and [advanced configuration](./advanced/configuration).
|
|
87
|
-
|
|
88
|
-
This document ends with proper punctuation and formatting.
|
|
89
|
-
`,
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
{
|
|
93
|
-
category: "✅ PASSING CASES",
|
|
94
|
-
name: "Simple valid content",
|
|
95
|
-
expectPass: true,
|
|
96
|
-
content: `# Simple Document
|
|
97
|
-
|
|
98
|
-
This is a simple but valid document.
|
|
99
|
-
|
|
100
|
-
It has multiple paragraphs and proper structure.
|
|
101
|
-
|
|
102
|
-
The content ends with a period.
|
|
103
|
-
`,
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
{
|
|
107
|
-
category: "✅ PASSING CASES",
|
|
108
|
-
name: "Valid content with Chinese punctuation",
|
|
109
|
-
expectPass: true,
|
|
110
|
-
content: `# 中文文档
|
|
111
|
-
|
|
112
|
-
这是一个中文文档的示例。
|
|
113
|
-
|
|
114
|
-
## 内容说明
|
|
115
|
-
|
|
116
|
-
文档内容使用中文标点符号。
|
|
117
|
-
|
|
118
|
-
这个文档以中文句号结尾。
|
|
119
|
-
`,
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
// ========== LINK VALIDATION CASES ==========
|
|
123
|
-
{
|
|
124
|
-
category: "🔗 LINK VALIDATION",
|
|
125
|
-
name: "Dead internal link",
|
|
126
|
-
expectPass: false,
|
|
127
|
-
expectedErrors: ["dead link"],
|
|
128
|
-
content: `# Test Document
|
|
129
|
-
|
|
130
|
-
Check out this [broken link](./non-existent-page) for more info.
|
|
131
|
-
|
|
132
|
-
This content ends properly.
|
|
133
|
-
`,
|
|
134
|
-
},
|
|
135
|
-
|
|
136
|
-
{
|
|
137
|
-
category: "🔗 LINK VALIDATION",
|
|
138
|
-
name: "Multiple dead links",
|
|
139
|
-
expectPass: false,
|
|
140
|
-
expectedErrors: ["dead link"],
|
|
141
|
-
content: `# Test Document
|
|
142
|
-
|
|
143
|
-
See [invalid page](./invalid) and [another broken link](/broken/path).
|
|
144
|
-
|
|
145
|
-
External links like [Google](https://google.com) should be ignored.
|
|
146
|
-
|
|
147
|
-
This content ends properly.
|
|
148
|
-
`,
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
{
|
|
152
|
-
category: "🔗 LINK VALIDATION",
|
|
153
|
-
name: "Valid internal links",
|
|
154
|
-
expectPass: true,
|
|
155
|
-
content: `# Test Document
|
|
156
|
-
|
|
157
|
-
Check out our [getting started guide](./getting-started) and [API overview](/api/overview).
|
|
158
|
-
|
|
159
|
-
External links like [GitHub](https://github.com) and [email](mailto:test@example.com) are fine.
|
|
160
|
-
|
|
161
|
-
This content ends properly.
|
|
162
|
-
`,
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
// ========== CODE BLOCK VALIDATION CASES ==========
|
|
166
|
-
{
|
|
167
|
-
category: "💻 CODE BLOCK VALIDATION",
|
|
168
|
-
name: "Incomplete code block",
|
|
169
|
-
expectPass: false,
|
|
170
|
-
expectedErrors: ["incomplete code block"],
|
|
171
|
-
content: `# Test Document
|
|
172
|
-
|
|
173
|
-
Here's incomplete code:
|
|
174
|
-
|
|
175
|
-
\`\`\`javascript
|
|
176
|
-
function incomplete() {
|
|
177
|
-
console.log("missing closing");
|
|
178
|
-
`,
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
{
|
|
182
|
-
category: "💻 CODE BLOCK VALIDATION",
|
|
183
|
-
name: "Valid indented code block",
|
|
184
|
-
expectPass: true,
|
|
185
|
-
content: `# Test Document
|
|
186
|
-
|
|
187
|
-
Here's properly indented code:
|
|
188
|
-
|
|
189
|
-
\`\`\`javascript
|
|
190
|
-
function test() {
|
|
191
|
-
return "properly indented";
|
|
192
|
-
}
|
|
193
|
-
\`\`\`
|
|
194
|
-
|
|
195
|
-
This content ends properly.
|
|
196
|
-
`,
|
|
197
|
-
},
|
|
198
|
-
|
|
199
|
-
{
|
|
200
|
-
category: "💻 CODE BLOCK VALIDATION",
|
|
201
|
-
name: "Code block with inconsistent indentation (user case)",
|
|
202
|
-
expectPass: false,
|
|
203
|
-
expectedErrors: ["code block with inconsistent indentation"],
|
|
204
|
-
content: `# API Response Handling
|
|
205
|
-
|
|
206
|
-
You can retrieve the response body in various formats:
|
|
207
|
-
|
|
208
|
-
* **\`response.content\`**: Accesses the raw response body as bytes. This is useful for non-text data like images or binary files.
|
|
209
|
-
\`\`\`python
|
|
210
|
-
import requests
|
|
211
|
-
|
|
212
|
-
r = requests.get('https://httpbin.org/image/png')
|
|
213
|
-
print(type(r.content))
|
|
214
|
-
# Expected output: <class 'bytes'>
|
|
215
|
-
\`\`\`
|
|
216
|
-
|
|
217
|
-
* **\`response.text\`**: Accesses the response body as Unicode text. Requests automatically guesses the encoding, or you can explicitly set \`response.encoding\`.
|
|
218
|
-
\`\`\`python
|
|
219
|
-
import requests
|
|
220
|
-
|
|
221
|
-
r = requests.get('https://httpbin.org/get')
|
|
222
|
-
print(type(r.text))
|
|
223
|
-
# Expected output: <class 'str'>
|
|
224
|
-
print(r.text)
|
|
225
|
-
# Expected output: {"args": {}, "headers": ..., "origin": "...", "url": "https://httpbin.org/get"}
|
|
226
|
-
\`\`\`
|
|
227
|
-
|
|
228
|
-
* **\`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.
|
|
229
|
-
\`\`\`python
|
|
230
|
-
import requests
|
|
231
|
-
|
|
232
|
-
r = requests.get('https://httpbin.org/json')
|
|
233
|
-
print(type(r.json()))
|
|
234
|
-
# Expected output: <class 'dict'>
|
|
235
|
-
print(r.json())
|
|
236
|
-
# Expected output: {'slideshow': {'author': 'Yours Truly', 'date': 'date of publication', 'slides': [...], 'title': 'Sample Slide Show'}}
|
|
237
|
-
\`\`\`
|
|
238
|
-
|
|
239
|
-
**Status and Error Handling**
|
|
240
|
-
|
|
241
|
-
* **\`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\`.
|
|
242
|
-
|
|
243
|
-
* **\`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.
|
|
244
|
-
|
|
245
|
-
\`\`\`python
|
|
246
|
-
import requests
|
|
247
|
-
from requests.exceptions import HTTPError
|
|
248
|
-
|
|
249
|
-
try:
|
|
250
|
-
r = requests.get('https://httpbin.org/status/404')
|
|
251
|
-
r.raise_for_status() # This will raise an HTTPError for 404
|
|
252
|
-
except HTTPError as e:
|
|
253
|
-
print(f"HTTP Error occurred: {e}")
|
|
254
|
-
# Expected output: HTTP Error occurred: 404 Client Error: NOT FOUND for url: https://httpbin.org/status/404
|
|
255
|
-
\`\`\`
|
|
256
|
-
|
|
257
|
-
This document ends properly.
|
|
258
|
-
`,
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
// ========== CONTENT STRUCTURE CASES ==========
|
|
262
|
-
{
|
|
263
|
-
category: "📝 CONTENT STRUCTURE",
|
|
264
|
-
name: "Single line content",
|
|
265
|
-
expectPass: false,
|
|
266
|
-
expectedErrors: ["single line content"],
|
|
267
|
-
content: `This is just one line without any line breaks or proper structure`,
|
|
268
|
-
},
|
|
269
|
-
|
|
270
|
-
{
|
|
271
|
-
category: "📝 CONTENT STRUCTURE",
|
|
272
|
-
name: "Missing punctuation ending",
|
|
273
|
-
expectPass: false,
|
|
274
|
-
expectedErrors: ["incomplete content"],
|
|
275
|
-
content: `# Test Document
|
|
276
|
-
|
|
277
|
-
This content doesn't end with proper punctuation`,
|
|
278
|
-
},
|
|
279
|
-
|
|
280
|
-
{
|
|
281
|
-
category: "📝 CONTENT STRUCTURE",
|
|
282
|
-
name: "Content with proper line breaks",
|
|
283
|
-
expectPass: true,
|
|
284
|
-
content: `# Test Document
|
|
285
|
-
|
|
286
|
-
This content has proper line breaks.
|
|
287
|
-
|
|
288
|
-
Multiple paragraphs are formatted correctly.
|
|
289
|
-
|
|
290
|
-
The document ends with proper punctuation.
|
|
291
|
-
`,
|
|
292
|
-
},
|
|
293
|
-
|
|
294
|
-
// ========== TABLE VALIDATION CASES ==========
|
|
295
|
-
{
|
|
296
|
-
category: "📊 TABLE VALIDATION",
|
|
297
|
-
name: "Table separator with fewer columns",
|
|
298
|
-
expectPass: false,
|
|
299
|
-
expectedErrors: ["table separator with mismatched column count"],
|
|
300
|
-
content: `# Test Document
|
|
301
|
-
|
|
302
|
-
| Column 1 | Column 2 | Column 3 |
|
|
303
|
-
| - | - |
|
|
304
|
-
| Data 1 | Data 2 | Data 3 |
|
|
305
|
-
|
|
306
|
-
This content ends properly.
|
|
307
|
-
`,
|
|
308
|
-
},
|
|
309
|
-
|
|
310
|
-
{
|
|
311
|
-
category: "📊 TABLE VALIDATION",
|
|
312
|
-
name: "Table separator with more columns",
|
|
313
|
-
expectPass: false,
|
|
314
|
-
expectedErrors: ["table separator with mismatched column count"],
|
|
315
|
-
content: `# Test Document
|
|
316
|
-
|
|
317
|
-
| Column 1 | Column 2 |
|
|
318
|
-
|----------|----------|----------|
|
|
319
|
-
| Data 1 | Data 2 |
|
|
320
|
-
|
|
321
|
-
This content ends properly.
|
|
322
|
-
`,
|
|
323
|
-
},
|
|
324
|
-
|
|
325
|
-
{
|
|
326
|
-
category: "📊 TABLE VALIDATION",
|
|
327
|
-
name: "Table data row with mismatched columns",
|
|
328
|
-
expectPass: false,
|
|
329
|
-
expectedErrors: ["table data row with mismatched column count"],
|
|
330
|
-
content: `# Test Document
|
|
331
|
-
|
|
332
|
-
| Column 1 | Column 2 |
|
|
333
|
-
|----------|----------|
|
|
334
|
-
| Data 1 | Data 2 | Data 3 |
|
|
335
|
-
|
|
336
|
-
This content ends properly.
|
|
337
|
-
`,
|
|
338
|
-
},
|
|
339
|
-
|
|
340
|
-
{
|
|
341
|
-
category: "📊 TABLE VALIDATION",
|
|
342
|
-
name: "Valid table with consistent columns",
|
|
343
|
-
expectPass: true,
|
|
344
|
-
content: `# Test Document
|
|
345
|
-
|
|
346
|
-
|Column 1|Column 2|Column 3|
|
|
347
|
-
|--------|--------|--------|
|
|
348
|
-
|Data 1|Data 2|Data 3|
|
|
349
|
-
|Row 2|More|Data|
|
|
350
|
-
|
|
351
|
-
This content ends properly.
|
|
352
|
-
|
|
353
|
-
| 参数 | 类型 | 描述 |
|
|
354
|
-
|---|---|---|
|
|
355
|
-
| callback | () => void \\| Promise<void> | Payment Kit 组件运行后要执行的函数。这可以是一个异步函数。 |
|
|
356
|
-
| wait | boolean | 可选。如果为 ,稍后在组件启动时执行回调。 |
|
|
357
|
-
|
|
358
|
-
This document demonstrates escaped pipe handling.
|
|
359
|
-
`,
|
|
360
|
-
},
|
|
361
|
-
|
|
362
|
-
// ========== MERMAID VALIDATION CASES ==========
|
|
363
|
-
{
|
|
364
|
-
category: "🧩 MERMAID VALIDATION",
|
|
365
|
-
name: "Invalid Mermaid syntax",
|
|
366
|
-
expectPass: false,
|
|
367
|
-
expectedErrors: ["Mermaid syntax error"],
|
|
368
|
-
content: `# Test Document
|
|
369
|
-
|
|
370
|
-
\`\`\`mermaid
|
|
371
|
-
invalid diagram type
|
|
372
|
-
A --> B
|
|
373
|
-
\`\`\`
|
|
374
|
-
|
|
375
|
-
This content ends properly.
|
|
376
|
-
`,
|
|
377
|
-
},
|
|
378
|
-
|
|
379
|
-
{
|
|
380
|
-
category: "🧩 MERMAID VALIDATION",
|
|
381
|
-
name: "Mermaid with backticks in node labels",
|
|
382
|
-
expectPass: false,
|
|
383
|
-
expectedErrors: ["backticks in Mermaid node label"],
|
|
384
|
-
content: `# Test Document
|
|
385
|
-
|
|
386
|
-
\`\`\`mermaid
|
|
387
|
-
flowchart TD
|
|
388
|
-
A["label with \`backticks\`"] --> B[End]
|
|
389
|
-
C{"another \`label\` with backticks"} --> D[Final]
|
|
390
|
-
\`\`\`
|
|
391
|
-
|
|
392
|
-
This content ends properly.
|
|
393
|
-
`,
|
|
394
|
-
},
|
|
395
|
-
|
|
396
|
-
{
|
|
397
|
-
category: "🧩 MERMAID VALIDATION",
|
|
398
|
-
name: "Mermaid with numbered edge descriptions",
|
|
399
|
-
expectPass: false,
|
|
400
|
-
expectedErrors: ["numbered list format in Mermaid edge description"],
|
|
401
|
-
content: `# Test Document
|
|
402
|
-
|
|
403
|
-
\`\`\`mermaid
|
|
404
|
-
flowchart TD
|
|
405
|
-
A[Start] -- "1. First step" --> B[Middle]
|
|
406
|
-
B -- "2. Second step" --> C[End]
|
|
407
|
-
\`\`\`
|
|
408
|
-
|
|
409
|
-
This content ends properly.
|
|
410
|
-
`,
|
|
411
|
-
},
|
|
412
|
-
|
|
413
|
-
{
|
|
414
|
-
category: "🧩 MERMAID VALIDATION",
|
|
415
|
-
name: "Mermaid with unquoted special characters",
|
|
416
|
-
expectPass: false,
|
|
417
|
-
expectedErrors: ["unquoted special characters"],
|
|
418
|
-
content: `# Test Document
|
|
419
|
-
|
|
420
|
-
\`\`\`mermaid
|
|
421
|
-
flowchart LR
|
|
422
|
-
A[Start] --> B[Response.raw (file-like) is available]
|
|
423
|
-
B --> C[End]
|
|
424
|
-
\`\`\`
|
|
425
|
-
|
|
426
|
-
This content ends properly.
|
|
427
|
-
`,
|
|
428
|
-
},
|
|
429
|
-
|
|
430
|
-
{
|
|
431
|
-
category: "🧩 MERMAID VALIDATION",
|
|
432
|
-
name: "Valid Mermaid diagrams",
|
|
433
|
-
expectPass: true,
|
|
434
|
-
content: `# Test Document
|
|
435
|
-
|
|
436
|
-
\`\`\`mermaid
|
|
437
|
-
flowchart TD
|
|
438
|
-
A[Start] --> B{Decision}
|
|
439
|
-
B -->|Yes| C[Process]
|
|
440
|
-
B -->|No| D[End]
|
|
441
|
-
C --> E[Save]
|
|
442
|
-
E --> D
|
|
443
|
-
\`\`\`
|
|
444
|
-
|
|
445
|
-
\`\`\`mermaid
|
|
446
|
-
sequenceDiagram
|
|
447
|
-
participant A as Alice
|
|
448
|
-
participant B as Bob
|
|
449
|
-
A->>B: Hello Bob
|
|
450
|
-
B-->>A: Hello Alice
|
|
451
|
-
\`\`\`
|
|
452
|
-
|
|
453
|
-
This content ends properly.
|
|
454
|
-
`,
|
|
455
|
-
},
|
|
456
|
-
|
|
457
|
-
{
|
|
458
|
-
category: "🧩 MERMAID VALIDATION",
|
|
459
|
-
name: "Mermaid with subgraph reference issues (rendering failure)",
|
|
460
|
-
expectPass: false,
|
|
461
|
-
expectedErrors: ["Mermaid syntax error"],
|
|
462
|
-
content: `# Test Document
|
|
463
|
-
|
|
464
|
-
\`\`\`mermaid
|
|
465
|
-
flowchart TD
|
|
466
|
-
A["FastAPI Application"] --> B["Security & Authentication"];
|
|
467
|
-
A --> C["Error Handling"];
|
|
468
|
-
A --> D["WebSockets"];
|
|
469
|
-
A --> E["Middleware"];
|
|
470
|
-
A --> F["Lifespan Events"];
|
|
471
|
-
A --> G["Database Integration"];
|
|
472
|
-
H["Project Structure"] -- "Organizes" --> A;
|
|
473
|
-
I["Application Settings"] -- "Configures" --> A;
|
|
474
|
-
J["Testing FastAPI Applications"] -- "Ensures Reliability" --> A;
|
|
475
|
-
A --> K["Deployment"];
|
|
476
|
-
|
|
477
|
-
subgraph Advanced Capabilities
|
|
478
|
-
B
|
|
479
|
-
C
|
|
480
|
-
D
|
|
481
|
-
E
|
|
482
|
-
F
|
|
483
|
-
G
|
|
484
|
-
end
|
|
485
|
-
|
|
486
|
-
subgraph Operational Excellence
|
|
487
|
-
H
|
|
488
|
-
I
|
|
489
|
-
J
|
|
490
|
-
K
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
AdvancedCapabilities --> "Robustness" --> L["Production-Ready API"];
|
|
494
|
-
OperationalExcellence --> "Maintainability & Scalability" --> L;
|
|
495
|
-
\`\`\`
|
|
496
|
-
|
|
497
|
-
This content ends properly.
|
|
498
|
-
`,
|
|
499
|
-
},
|
|
500
|
-
|
|
501
|
-
{
|
|
502
|
-
category: "🧩 MERMAID VALIDATION",
|
|
503
|
-
name: "Mermaid with numbered list format in node labels",
|
|
504
|
-
expectPass: false,
|
|
505
|
-
expectedErrors: ["numbered list format in Mermaid node label"],
|
|
506
|
-
content: `# Test Document
|
|
507
|
-
|
|
508
|
-
\`\`\`mermaid
|
|
509
|
-
flowchart TD
|
|
510
|
-
A["1. Create Backend Implementation<br>api/src/providers/"]
|
|
511
|
-
B["2. Add Backend Configuration<br>api/src/providers/models.ts"]
|
|
512
|
-
C["3. Update Frontend Selector<br>src/pages/config/ai-providers/"]
|
|
513
|
-
D["4. Add Provider Logo<br>public/logo/"]
|
|
514
|
-
E["5. Update Documentation"]
|
|
515
|
-
|
|
516
|
-
A --> B --> C --> D --> E
|
|
517
|
-
\`\`\`
|
|
518
|
-
|
|
519
|
-
This content ends properly.
|
|
520
|
-
`,
|
|
521
|
-
},
|
|
522
|
-
|
|
523
|
-
// ========== COMPLEX MIXED CASES ==========
|
|
524
|
-
{
|
|
525
|
-
category: "🔄 COMPLEX MIXED CASES",
|
|
526
|
-
name: "Multiple issues in one document",
|
|
527
|
-
expectPass: false,
|
|
528
|
-
expectedErrors: [
|
|
529
|
-
"dead link",
|
|
530
|
-
"table separator with mismatched column count",
|
|
531
|
-
"incomplete content",
|
|
532
|
-
],
|
|
533
|
-
content: `# Complex Test Document
|
|
534
|
-
|
|
535
|
-
This document has [multiple issues](./broken-link).
|
|
536
|
-
|
|
537
|
-
| Column 1 | Column 2 | Column 3 |
|
|
538
|
-
| - | - |
|
|
539
|
-
| Data 1 | Data 2 | Data 3 |
|
|
540
|
-
|
|
541
|
-
\`\`\`mermaid
|
|
542
|
-
flowchart TD
|
|
543
|
-
A["node with \`backticks\`"] --> B[End]
|
|
544
|
-
\`\`\`
|
|
545
|
-
|
|
546
|
-
This content doesn't end properly`,
|
|
547
|
-
},
|
|
548
|
-
|
|
549
|
-
{
|
|
550
|
-
category: "🔄 COMPLEX MIXED CASES",
|
|
551
|
-
name: "Complex valid document with all elements",
|
|
552
|
-
expectPass: true,
|
|
553
|
-
content: `# Comprehensive Test Document
|
|
554
|
-
|
|
555
|
-
This document contains all supported elements in their correct form.
|
|
556
|
-
|
|
557
|
-
## Links Section
|
|
558
|
-
|
|
559
|
-
Internal links: [Getting Started](./getting-started) and [API Reference](/api/overview).
|
|
560
|
-
External links: [GitHub](https://github.com) and [Email](mailto:support@example.com).
|
|
561
|
-
|
|
562
|
-
## Code Examples
|
|
563
|
-
|
|
564
|
-
Standard code block:
|
|
565
|
-
|
|
566
|
-
\`\`\`javascript
|
|
567
|
-
function processData(input) {
|
|
568
|
-
const result = input.map(item => ({
|
|
569
|
-
id: item.id,
|
|
570
|
-
value: item.value * 2
|
|
571
|
-
}));
|
|
572
|
-
return result;
|
|
573
|
-
}
|
|
574
|
-
\`\`\`
|
|
575
|
-
|
|
576
|
-
## Data Tables
|
|
577
|
-
|
|
578
|
-
|Feature|Status|Notes|
|
|
579
|
-
|-------|------|-----|
|
|
580
|
-
|API v1|Active|Current version|
|
|
581
|
-
|API v2|Beta|Testing phase|
|
|
582
|
-
|Dashboard|Complete|Ready for use|
|
|
583
|
-
|
|
584
|
-
## Process Diagrams
|
|
585
|
-
|
|
586
|
-
Main workflow:
|
|
587
|
-
|
|
588
|
-
\`\`\`mermaid
|
|
589
|
-
flowchart TD
|
|
590
|
-
A[User Request] --> B{Validate Input}
|
|
591
|
-
B -->|Valid| C[Process Request]
|
|
592
|
-
B -->|Invalid| D[Return Error]
|
|
593
|
-
C --> E[Generate Response]
|
|
594
|
-
D --> F[Log Error]
|
|
595
|
-
E --> G[Send Response]
|
|
596
|
-
F --> G
|
|
597
|
-
\`\`\`
|
|
598
|
-
|
|
599
|
-
Sequence diagram:
|
|
600
|
-
|
|
601
|
-
\`\`\`mermaid
|
|
602
|
-
sequenceDiagram
|
|
603
|
-
participant U as User
|
|
604
|
-
participant A as API
|
|
605
|
-
participant D as Database
|
|
606
|
-
|
|
607
|
-
U->>A: Send Request
|
|
608
|
-
A->>D: Query Data
|
|
609
|
-
D-->>A: Return Results
|
|
610
|
-
A-->>U: Send Response
|
|
611
|
-
\`\`\`
|
|
612
|
-
|
|
613
|
-
## Conclusion
|
|
614
|
-
|
|
615
|
-
This comprehensive document demonstrates all validation rules in their correct usage.
|
|
616
|
-
`,
|
|
617
|
-
},
|
|
618
|
-
];
|
|
619
|
-
|
|
620
|
-
describe("Markdown Validation Test Suite", () => {
|
|
621
|
-
afterAll(async () => {
|
|
622
|
-
// Shutdown worker pool to ensure clean exit
|
|
623
|
-
try {
|
|
624
|
-
await shutdownValidation();
|
|
625
|
-
} catch {
|
|
626
|
-
// Ignore shutdown errors in tests
|
|
627
|
-
}
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
// Group tests by category
|
|
631
|
-
const testsByCategory = testCases.reduce((acc, testCase) => {
|
|
632
|
-
if (!acc[testCase.category]) {
|
|
633
|
-
acc[testCase.category] = [];
|
|
634
|
-
}
|
|
635
|
-
acc[testCase.category].push(testCase);
|
|
636
|
-
return acc;
|
|
637
|
-
}, {});
|
|
638
|
-
|
|
639
|
-
Object.entries(testsByCategory).forEach(([category, categoryTests]) => {
|
|
640
|
-
describe(category, () => {
|
|
641
|
-
categoryTests.forEach((testCase) => {
|
|
642
|
-
test(testCase.name, async () => {
|
|
643
|
-
// Test with checkMarkdown directly
|
|
644
|
-
const errors = await checkMarkdown(testCase.content, "test", {
|
|
645
|
-
allowedLinks,
|
|
646
|
-
});
|
|
647
|
-
|
|
648
|
-
// Test with checkDetailResult wrapper
|
|
649
|
-
const wrapperResult = await checkDetailResult({
|
|
650
|
-
structurePlan: mockStructurePlan,
|
|
651
|
-
reviewContent: testCase.content,
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
const hasErrors = errors.length > 0;
|
|
655
|
-
const expectPass = testCase.expectPass;
|
|
656
|
-
|
|
657
|
-
// Verify test expectation
|
|
658
|
-
if (expectPass) {
|
|
659
|
-
expect(hasErrors).toBe(false);
|
|
660
|
-
} else {
|
|
661
|
-
expect(hasErrors).toBe(true);
|
|
662
|
-
|
|
663
|
-
// Check if expected error types are present
|
|
664
|
-
if (testCase.expectedErrors) {
|
|
665
|
-
const foundExpectedErrors = testCase.expectedErrors.every((expectedError) =>
|
|
666
|
-
errors.some((error) => error.toLowerCase().includes(expectedError.toLowerCase())),
|
|
667
|
-
);
|
|
668
|
-
expect(foundExpectedErrors).toBe(true);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
// Verify consistency between direct call and wrapper
|
|
673
|
-
const wrapperErrors = wrapperResult.detailFeedback
|
|
674
|
-
? wrapperResult.detailFeedback.split("\n").filter((line) => line.trim())
|
|
675
|
-
: [];
|
|
676
|
-
|
|
677
|
-
// Note: We don't enforce exact equality as wrapper may format differently
|
|
678
|
-
expect(wrapperErrors.length > 0).toBe(hasErrors);
|
|
679
|
-
});
|
|
680
|
-
});
|
|
681
|
-
});
|
|
682
|
-
});
|
|
683
|
-
});
|
|
684
|
-
|
|
685
|
-
// Export test cases for external use
|
|
686
|
-
export { testCases, mockStructurePlan, allowedLinks };
|