@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.
@@ -37,23 +37,6 @@ describe("checkDetailResult", () => {
37
37
  expect(result.detailFeedback).toBe("");
38
38
  });
39
39
 
40
- test("should reject content with multiple issues", async () => {
41
- const structurePlan = [{ path: "/getting-started" }];
42
- const reviewContent = "This has a [dead link](/dead-link).";
43
- const result = await checkDetailResult({ structurePlan, reviewContent });
44
- expect(result.isApproved).toBe(false);
45
- expect(result.detailFeedback).toContain("dead link");
46
- });
47
-
48
- test("should approve content with external image syntax", async () => {
49
- const structurePlan = [];
50
- const reviewContent =
51
- "This is an image ![MCP Go Logo](https://example.com/logo.png).\n\nThis has proper structure.";
52
- const result = await checkDetailResult({ structurePlan, reviewContent });
53
- expect(result.isApproved).toBe(true);
54
- expect(result.detailFeedback).toBe("");
55
- });
56
-
57
40
  test("should approve content with valid local image path", async () => {
58
41
  const structurePlan = [];
59
42
  const reviewContent =
@@ -101,4 +84,660 @@ describe("checkDetailResult", () => {
101
84
  expect(result.isApproved).toBe(true);
102
85
  expect(result.detailFeedback).toBe("");
103
86
  });
87
+
88
+ describe("Table validation", () => {
89
+ test("should reject table with mismatched column count", async () => {
90
+ const structurePlan = [];
91
+ const reviewContent =
92
+ "| Header 1 | Header 2 | Header 3 |\n" +
93
+ "|----------|----------|\n" + // Only 2 separator columns but 3 header columns
94
+ "| Cell 1 | Cell 2 | Cell 3 |";
95
+ const result = await checkDetailResult({ structurePlan, reviewContent });
96
+ expect(result.isApproved).toBe(false);
97
+ expect(result.detailFeedback).toContain("separator has 2 columns but header has 3 columns");
98
+ });
99
+
100
+ test("should reject table with data row column mismatch", async () => {
101
+ const structurePlan = [];
102
+ const reviewContent =
103
+ "| Header 1 | Header 2 |\n" + "|----------|----------|\n" + "| Cell 1 | Cell 2 | Cell 3 |"; // Data row has 3 columns but separator defines 2
104
+ const result = await checkDetailResult({ structurePlan, reviewContent });
105
+ expect(result.isApproved).toBe(false);
106
+ expect(result.detailFeedback).toContain(
107
+ "data row has 3 columns but separator defines 2 columns",
108
+ );
109
+ });
110
+
111
+ test("should handle complex table with pipes in content", async () => {
112
+ const structurePlan = [];
113
+ const reviewContent =
114
+ "| Code | Description |\n" +
115
+ "|------|-------------|\n" +
116
+ "| `a \\| b` | This has escaped pipe |\n" +
117
+ "| `c | d` | This has unescaped pipe in code |";
118
+ const result = await checkDetailResult({ structurePlan, reviewContent });
119
+ expect(result.isApproved).toBe(true);
120
+ });
121
+ });
122
+
123
+ describe("Code block validation", () => {
124
+ test("should reject incomplete code blocks", async () => {
125
+ const structurePlan = [];
126
+ const reviewContent =
127
+ "Here is some code:\n\n" +
128
+ "```javascript\n" +
129
+ "function test() {\n" +
130
+ " return 'incomplete';\n" +
131
+ "}\n"; // Missing closing ```
132
+ const result = await checkDetailResult({ structurePlan, reviewContent });
133
+ expect(result.isApproved).toBe(false);
134
+ expect(result.detailFeedback).toContain("incomplete code block");
135
+ });
136
+
137
+ test("should detect code block indentation issues", async () => {
138
+ const structurePlan = [];
139
+ const reviewContent =
140
+ " ```javascript\n" +
141
+ "function test() {\n" + // This line has insufficient indentation
142
+ " return 'test';\n" +
143
+ " }\n" +
144
+ " ```";
145
+ const result = await checkDetailResult({ structurePlan, reviewContent });
146
+ expect(result.isApproved).toBe(false);
147
+ expect(result.detailFeedback).toContain("insufficient indentation");
148
+ });
149
+
150
+ test("should approve various programming language code blocks with proper detection", async () => {
151
+ const structurePlan = [];
152
+ const reviewContent = `Programming Language Examples:
153
+
154
+ ## Rust with Configuration
155
+ \`\`\`rust,no_run
156
+ use tokio::signal::windows::ctrl_shutdown;
157
+
158
+ #[tokio::main]
159
+ async fn main() -> Result<(), Box<dyn std::error::Error>> {
160
+ let mut signal = ctrl_shutdown()?;
161
+ signal.recv().await;
162
+ println!("got CTRL-SHUTDOWN. Cleaning up before exiting");
163
+ Ok(())
164
+ }
165
+ \`\`\`
166
+
167
+ ## C# .NET Example
168
+ \`\`\`c#
169
+ using System;
170
+ using System.Threading.Tasks;
171
+
172
+ public class Program
173
+ {
174
+ public static async Task Main(string[] args)
175
+ {
176
+ Console.WriteLine("Hello C#!");
177
+ await Task.Delay(1000);
178
+ }
179
+ }
180
+ \`\`\`
181
+
182
+ ## C++ with CLI Extension
183
+ \`\`\`c++/cli
184
+ #include <iostream>
185
+ #include <vector>
186
+
187
+ int main() {
188
+ std::vector<int> numbers = {1, 2, 3, 4, 5};
189
+ for (const auto& num : numbers) {
190
+ std::cout << num << " ";
191
+ }
192
+ return 0;
193
+ }
194
+ \`\`\`
195
+
196
+ ## TypeScript with Extension
197
+ \`\`\`typescript.tsx
198
+ interface Props {
199
+ title: string;
200
+ count: number;
201
+ }
202
+
203
+ const Component: React.FC<Props> = ({ title, count }) => {
204
+ return <div>{title}: {count}</div>;
205
+ };
206
+
207
+ export default Component;
208
+ \`\`\`
209
+
210
+ ## Python with Version
211
+ \`\`\`python,version=3.9
212
+ import asyncio
213
+ from typing import List, Optional
214
+
215
+ async def fetch_data(urls: List[str]) -> Optional[dict]:
216
+ tasks = [asyncio.create_task(process_url(url)) for url in urls]
217
+ results = await asyncio.gather(*tasks)
218
+ return {"results": results}
219
+
220
+ if __name__ == "__main__":
221
+ asyncio.run(fetch_data(["http://example.com"]))
222
+ \`\`\`
223
+
224
+ ## Shell Script with Latest Tag
225
+ \`\`\`bash:latest
226
+ #!/bin/bash
227
+ set -euo pipefail
228
+
229
+ function deploy_app() {
230
+ local app_name="$1"
231
+ local version="$2"
232
+
233
+ echo "Deploying $app_name version $version"
234
+ docker run --rm "$app_name:$version"
235
+ }
236
+
237
+ deploy_app "my-app" "v1.0.0"
238
+ \`\`\`
239
+
240
+ ## Node.js Configuration
241
+ \`\`\`node.js
242
+ const express = require('express');
243
+ const app = express();
244
+ const PORT = process.env.PORT || 3000;
245
+
246
+ app.get('/health', (req, res) => {
247
+ res.json({ status: 'ok', timestamp: new Date().toISOString() });
248
+ });
249
+
250
+ app.listen(PORT, () => {
251
+ console.log(\`Server running on port \${PORT}\`);
252
+ });
253
+ \`\`\`
254
+
255
+ This document demonstrates various programming language code blocks.`;
256
+
257
+ const result = await checkDetailResult({ structurePlan, reviewContent });
258
+ expect(result.isApproved).toBe(true);
259
+ expect(result.detailFeedback).toBe("");
260
+ });
261
+ });
262
+
263
+ describe("Content structure validation", () => {
264
+ test("should reject single line content", async () => {
265
+ const structurePlan = [];
266
+ const reviewContent = "This is a single line without proper line breaks";
267
+ const result = await checkDetailResult({ structurePlan, reviewContent });
268
+ expect(result.isApproved).toBe(false);
269
+ expect(result.detailFeedback).toContain("single line content");
270
+ });
271
+
272
+ test("should reject incomplete content without proper ending", async () => {
273
+ const structurePlan = [];
274
+ const reviewContent = "This content doesn't end properly\n\nNo proper punctuation";
275
+ const result = await checkDetailResult({ structurePlan, reviewContent });
276
+ expect(result.isApproved).toBe(false);
277
+ expect(result.detailFeedback).toContain("incomplete content");
278
+ });
279
+
280
+ test("should approve content with valid ending punctuation", async () => {
281
+ const structurePlan = [];
282
+ const reviewContent = "This content ends properly.\n\nWith valid punctuation.";
283
+ const result = await checkDetailResult({ structurePlan, reviewContent });
284
+ expect(result.isApproved).toBe(true);
285
+ });
286
+ });
287
+
288
+ describe("Mermaid syntax validation", () => {
289
+ test("should reject Mermaid with backticks in node labels", async () => {
290
+ const structurePlan = [];
291
+ const reviewContent =
292
+ "```mermaid\n" + "graph TD\n" + ' A["Contains `backticks` in label"]\n' + "```";
293
+ const result = await checkDetailResult({ structurePlan, reviewContent });
294
+ expect(result.isApproved).toBe(false);
295
+ expect(result.detailFeedback).toContain("backticks in Mermaid node label");
296
+ });
297
+
298
+ test("should reject Mermaid with numbered lists in node labels", async () => {
299
+ const structurePlan = [];
300
+ const reviewContent =
301
+ "```mermaid\n" + "graph TD\n" + ' A["1. First item\\n2. Second item"]\n' + "```";
302
+ const result = await checkDetailResult({ structurePlan, reviewContent });
303
+ expect(result.isApproved).toBe(false);
304
+ expect(result.detailFeedback).toContain("numbered list format in Mermaid node label");
305
+ });
306
+
307
+ test("should reject Mermaid with numbered lists in edge descriptions", async () => {
308
+ const structurePlan = [];
309
+ const reviewContent =
310
+ "```mermaid\n" + "graph TD\n" + ' A -- "1. First step" --> B\n' + "```";
311
+ const result = await checkDetailResult({ structurePlan, reviewContent });
312
+ expect(result.isApproved).toBe(false);
313
+ expect(result.detailFeedback).toContain("numbered list format in Mermaid edge description");
314
+ });
315
+
316
+ test("should reject Mermaid with unquoted special characters", async () => {
317
+ const structurePlan = [];
318
+ const reviewContent =
319
+ "```mermaid\n" + "graph TD\n" + " A[Node with: special chars]\n" + "```";
320
+ const result = await checkDetailResult({ structurePlan, reviewContent });
321
+ expect(result.isApproved).toBe(false);
322
+ expect(result.detailFeedback).toContain("unquoted special characters in Mermaid node label");
323
+ });
324
+
325
+ test("should approve properly formatted Mermaid", async () => {
326
+ const structurePlan = [];
327
+ const reviewContent =
328
+ "```mermaid\n" +
329
+ "graph TD\n" +
330
+ ' A["Properly quoted label"]\n' +
331
+ ' B["Another node"]\n' +
332
+ " A --> B\n" +
333
+ "```\n\n" +
334
+ "This diagram is properly formatted.";
335
+ const result = await checkDetailResult({ structurePlan, reviewContent });
336
+ expect(result.isApproved).toBe(true);
337
+ });
338
+ });
339
+
340
+ describe("D2 syntax validation", () => {
341
+ test("should handle D2 syntax errors", async () => {
342
+ const structurePlan = [];
343
+ const reviewContent =
344
+ "```d2\n" +
345
+ "invalid d2 syntax {{\n" + // Malformed D2
346
+ "```\n\n" +
347
+ "This has proper structure.";
348
+ const result = await checkDetailResult({ structurePlan, reviewContent });
349
+ expect(result.isApproved).toBe(false);
350
+ });
351
+ });
352
+
353
+ describe("Advanced table edge cases", () => {
354
+ test("should handle empty table cells correctly", async () => {
355
+ const structurePlan = [];
356
+ const reviewContent =
357
+ "| Header 1 | Header 2 | Header 3 |\n" +
358
+ "|----------|----------|----------|\n" +
359
+ "| Cell 1 | | Cell 3 |\n" +
360
+ "| | Cell 2 | |";
361
+ const result = await checkDetailResult({ structurePlan, reviewContent });
362
+ expect(result.isApproved).toBe(true);
363
+ });
364
+
365
+ test("should handle tables with code spans containing pipes", async () => {
366
+ const structurePlan = [];
367
+ const reviewContent =
368
+ "| Function | Code Example |\n" +
369
+ "|----------|---------------|\n" +
370
+ "| pipe | `a \\| b` |\n" +
371
+ "| filter | `data \\| filter` |";
372
+ const result = await checkDetailResult({ structurePlan, reviewContent });
373
+ expect(result.isApproved).toBe(true);
374
+ });
375
+ });
376
+
377
+ describe("Code block edge cases", () => {
378
+ test("should handle nested code blocks properly", async () => {
379
+ const structurePlan = [];
380
+ const reviewContent =
381
+ "Here's a markdown example:\n\n" +
382
+ "```markdown\n" +
383
+ "# Title\n" +
384
+ "\n" +
385
+ "```javascript\n" +
386
+ "function test() { return true; }\n" +
387
+ "```\n" +
388
+ "```\n\n" +
389
+ "This content ends properly.";
390
+ const result = await checkDetailResult({ structurePlan, reviewContent });
391
+ expect(result.isApproved).toBe(true);
392
+ });
393
+
394
+ test("should handle code blocks with unusual indentation patterns", async () => {
395
+ const structurePlan = [];
396
+ const reviewContent =
397
+ " ```javascript\n" +
398
+ " function test() {\n" +
399
+ " return 'properly indented';\n" +
400
+ " }\n" +
401
+ " ```\n\n" +
402
+ "This has proper structure.";
403
+ const result = await checkDetailResult({ structurePlan, reviewContent });
404
+ expect(result.isApproved).toBe(true);
405
+ });
406
+ });
407
+
408
+ describe("Complex Mermaid scenarios", () => {
409
+ test("should handle Mermaid with curly brace syntax", async () => {
410
+ const structurePlan = [];
411
+ const reviewContent =
412
+ "```mermaid\n" +
413
+ "graph TD\n" +
414
+ ' A{"Decision point"}\n' +
415
+ ' B["Action"]\n' +
416
+ " A --> B\n" +
417
+ "```\n\n" +
418
+ "This diagram uses proper syntax.";
419
+ const result = await checkDetailResult({ structurePlan, reviewContent });
420
+ expect(result.isApproved).toBe(true);
421
+ });
422
+
423
+ test("should reject Mermaid with problematic curly brace labels", async () => {
424
+ const structurePlan = [];
425
+ const reviewContent =
426
+ "```mermaid\n" + "graph TD\n" + ' A{"Contains `backticks` problem"}\n' + "```";
427
+ const result = await checkDetailResult({ structurePlan, reviewContent });
428
+ expect(result.isApproved).toBe(false);
429
+ expect(result.detailFeedback).toContain("backticks in Mermaid node label");
430
+ });
431
+ });
432
+
433
+ describe("Image validation edge cases", () => {
434
+ test("should approve data URLs in images", async () => {
435
+ const structurePlan = [];
436
+ const reviewContent =
437
+ "Here's an inline image ![Inline](data:image/svg+xml;base64,PHN2Zz4KPC9zdmc+).\n\n" +
438
+ "This has proper structure.";
439
+ const result = await checkDetailResult({ structurePlan, reviewContent });
440
+ expect(result.isApproved).toBe(true);
441
+ });
442
+
443
+ test("should handle images with complex alt text", async () => {
444
+ const structurePlan = [];
445
+ const reviewContent =
446
+ "![Complex alt text with [brackets] and (parentheses)](https://example.com/image.png)\n\n" +
447
+ "This has proper structure.";
448
+ const result = await checkDetailResult({ structurePlan, reviewContent });
449
+ expect(result.isApproved).toBe(true);
450
+ });
451
+ });
452
+
453
+ describe("Link validation edge cases", () => {
454
+ test("should handle mailto links correctly", async () => {
455
+ const structurePlan = [];
456
+ const reviewContent =
457
+ "Contact us at [email](mailto:test@example.com).\n\n" + "This has proper structure.";
458
+ const result = await checkDetailResult({ structurePlan, reviewContent });
459
+ expect(result.isApproved).toBe(true);
460
+ });
461
+
462
+ test("should handle links with anchors", async () => {
463
+ const structurePlan = [{ path: "/getting-started" }];
464
+ const reviewContent =
465
+ "See the [installation section](/getting-started#installation).\n\n" +
466
+ "This has proper structure.";
467
+ const result = await checkDetailResult({ structurePlan, reviewContent });
468
+ expect(result.isApproved).toBe(true);
469
+ });
470
+
471
+ test("should handle anchor-only links without base path", async () => {
472
+ const structurePlan = [];
473
+ const reviewContent =
474
+ "See the [section](#non-existent-anchor).\n\n" + "This has proper structure.";
475
+ const result = await checkDetailResult({ structurePlan, reviewContent });
476
+ expect(result.isApproved).toBe(true);
477
+ });
478
+ });
479
+
480
+ describe("Content structure edge cases", () => {
481
+ test("should approve content ending with table", async () => {
482
+ const structurePlan = [];
483
+ const reviewContent =
484
+ "Here's a data table:\n\n" +
485
+ "| Column 1 | Column 2 |\n" +
486
+ "|----------|----------|\n" +
487
+ "| Data 1 | Data 2 |";
488
+ const result = await checkDetailResult({ structurePlan, reviewContent });
489
+ expect(result.isApproved).toBe(true);
490
+ });
491
+
492
+ test("should approve content ending with list", async () => {
493
+ const structurePlan = [];
494
+ const reviewContent =
495
+ "Here are the requirements:\n\n" +
496
+ "- First requirement\n" +
497
+ "- Second requirement\n" +
498
+ "- Third requirement*";
499
+ const result = await checkDetailResult({ structurePlan, reviewContent });
500
+ expect(result.isApproved).toBe(true);
501
+ });
502
+
503
+ test("should approve content ending with blockquote", async () => {
504
+ const structurePlan = [];
505
+ const reviewContent =
506
+ "As they say:\n\n" + "> This is a famous quote that ends with proper punctuation.";
507
+ const result = await checkDetailResult({ structurePlan, reviewContent });
508
+ expect(result.isApproved).toBe(true);
509
+ });
510
+ });
511
+
512
+ describe("Real-world scenario tests", () => {
513
+ test("should approve comprehensive valid document", async () => {
514
+ const structurePlan = [
515
+ { path: "./getting-started" },
516
+ { path: "/api/overview" },
517
+ { path: "./advanced/configuration" },
518
+ ];
519
+ const reviewContent = `# Getting Started Guide
520
+
521
+ This is a complete document with proper structure and formatting.
522
+
523
+ ## Introduction
524
+
525
+ Welcome to our comprehensive guide. This document follows all markdown best practices.
526
+
527
+ ## Code Examples
528
+
529
+ Here's a properly formatted code block:
530
+
531
+ \`\`\`javascript
532
+ function validateInput(data) {
533
+ if (!data) {
534
+ throw new Error("Data is required");
535
+ }
536
+ return data.trim();
537
+ }
538
+
539
+ // Export the function
540
+ export { validateInput };
541
+ \`\`\`
542
+
543
+ ## Data Tables
544
+
545
+ Our API supports the following data types:
546
+
547
+ |Type|Description|Example|
548
+ |----|-----------|-------|
549
+ |String|Text data|"Hello"|
550
+ |Number|Numeric values|42|
551
+ |Boolean|True/false|true|
552
+
553
+ ## Process Flow
554
+
555
+ The following diagram shows our validation process:
556
+
557
+ \`\`\`mermaid
558
+ flowchart TD
559
+ A[Start] --> B{Valid Input?}
560
+ B -->|Yes| C[Process Data]
561
+ B -->|No| D[Return Error]
562
+ C --> E[Save Results]
563
+ D --> F[Log Error]
564
+ E --> G[End]
565
+ F --> G
566
+ \`\`\`
567
+
568
+ ## Related Documentation
569
+
570
+ For more information, see our [API reference](/api/overview) and [advanced configuration](./advanced/configuration).
571
+
572
+ This document ends with proper punctuation and formatting.
573
+ `;
574
+ const result = await checkDetailResult({ structurePlan, reviewContent });
575
+ expect(result.isApproved).toBe(true);
576
+ });
577
+
578
+ test("should approve content with Chinese punctuation", async () => {
579
+ const structurePlan = [];
580
+ const reviewContent = `# 中文文档
581
+
582
+ 这是一个中文文档的示例。
583
+
584
+ ## 内容说明
585
+
586
+ 文档内容使用中文标点符号。
587
+
588
+ 这个文档以中文句号结尾。
589
+ `;
590
+ const result = await checkDetailResult({ structurePlan, reviewContent });
591
+ expect(result.isApproved).toBe(true);
592
+ });
593
+
594
+ test("should reject document with multiple validation issues", async () => {
595
+ const structurePlan = [{ path: "/getting-started" }];
596
+ const reviewContent = `# Complex Test Document
597
+
598
+ This document has [multiple issues](./broken-link).
599
+
600
+ | Column 1 | Column 2 | Column 3 |
601
+ | - | - |
602
+ | Data 1 | Data 2 | Data 3 |
603
+
604
+ \`\`\`mermaid
605
+ flowchart TD
606
+ A["node with \`backticks\`"] --> B[End]
607
+ \`\`\`
608
+
609
+ This content doesn't end properly`;
610
+ const result = await checkDetailResult({ structurePlan, reviewContent });
611
+ expect(result.isApproved).toBe(false);
612
+ expect(result.detailFeedback).toContain("dead link");
613
+ expect(result.detailFeedback).toContain("separator has 2 columns but header has 3 columns");
614
+ expect(result.detailFeedback).toContain("incomplete content");
615
+ });
616
+ });
617
+
618
+ describe("Complex code block indentation cases", () => {
619
+ test("should reject real-world code block indentation issue", async () => {
620
+ const structurePlan = [];
621
+ const reviewContent = `# API Response Handling
622
+
623
+ You can retrieve the response body in various formats:
624
+
625
+ * **\`response.content\`**: Accesses the raw response body as bytes. This is useful for non-text data like images or binary files.
626
+ \`\`\`python
627
+ import requests
628
+
629
+ r = requests.get('https://httpbin.org/image/png')
630
+ print(type(r.content))
631
+ # Expected output: <class 'bytes'>
632
+ \`\`\`
633
+
634
+ * **\`response.text\`**: Accesses the response body as Unicode text. Requests automatically guesses the encoding, or you can explicitly set \`response.encoding\`.
635
+ \`\`\`python
636
+ import requests
637
+
638
+ r = requests.get('https://httpbin.org/get')
639
+ print(type(r.text))
640
+ # Expected output: <class 'str'>
641
+ print(r.text)
642
+ # Expected output: {"args": {}, "headers": ..., "origin": "...", "url": "https://httpbin.org/get"}
643
+ \`\`\`
644
+
645
+ This document ends properly.
646
+ `;
647
+ const result = await checkDetailResult({ structurePlan, reviewContent });
648
+ expect(result.isApproved).toBe(false);
649
+ expect(result.detailFeedback).toContain("insufficient indentation");
650
+ });
651
+ });
652
+
653
+ describe("Advanced Mermaid validation cases", () => {
654
+ test("should reject Mermaid with numbered list in node labels", async () => {
655
+ const structurePlan = [];
656
+ const reviewContent = `# Test Document
657
+
658
+ \`\`\`mermaid
659
+ flowchart TD
660
+ A["1. Create Backend Implementation<br>api/src/providers/"]
661
+ B["2. Add Backend Configuration<br>api/src/providers/models.ts"]
662
+ C["3. Update Frontend Selector<br>src/pages/config/ai-providers/"]
663
+
664
+ A --> B --> C
665
+ \`\`\`
666
+
667
+ This content ends properly.
668
+ `;
669
+ const result = await checkDetailResult({ structurePlan, reviewContent });
670
+ expect(result.isApproved).toBe(false);
671
+ expect(result.detailFeedback).toContain("numbered list format in Mermaid node label");
672
+ });
673
+
674
+ test("should handle complex Mermaid with subgraph issues", async () => {
675
+ const structurePlan = [];
676
+ const reviewContent = `# Test Document
677
+
678
+ \`\`\`mermaid
679
+ flowchart TD
680
+ A["FastAPI Application"] --> B["Security & Authentication"];
681
+ A --> C["Error Handling"];
682
+ H["Project Structure"] -- "Organizes" --> A;
683
+
684
+ subgraph Advanced Capabilities
685
+ B
686
+ C
687
+ end
688
+
689
+ AdvancedCapabilities --> "Robustness" --> L["Production-Ready API"];
690
+ \`\`\`
691
+
692
+ This content ends properly.
693
+ `;
694
+ const result = await checkDetailResult({ structurePlan, reviewContent });
695
+ // This may pass or fail depending on Mermaid validation - we just ensure it doesn't crash
696
+ expect(typeof result.isApproved).toBe("boolean");
697
+ });
698
+ });
699
+
700
+ describe("Table validation with real content", () => {
701
+ test("should approve table with escaped pipes", async () => {
702
+ const structurePlan = [];
703
+ const reviewContent = `# Test Document
704
+
705
+ | 参数 | 类型 | 描述 |
706
+ |---|---|---|
707
+ | callback | () => void \\| Promise<void> | Payment Kit 组件运行后要执行的函数。这可以是一个异步函数。 |
708
+ | wait | boolean | 可选。如果为,稍后在组件启动时执行回调。 |
709
+
710
+ This document demonstrates escaped pipe handling.
711
+ `;
712
+ const result = await checkDetailResult({ structurePlan, reviewContent });
713
+ expect(result.isApproved).toBe(true);
714
+ });
715
+ });
716
+
717
+ describe("Error handling", () => {
718
+ test("should handle markdown processing errors gracefully", async () => {
719
+ const structurePlan = [];
720
+ // Test with extremely malformed content that might cause parsing errors
721
+ const reviewContent = null;
722
+ const result = await checkDetailResult({ structurePlan, reviewContent });
723
+ expect(result.isApproved).toBe(false);
724
+ expect(result.detailFeedback).toBe("Review content is empty");
725
+ });
726
+
727
+ test("should handle empty content gracefully", async () => {
728
+ const structurePlan = [];
729
+ const reviewContent = "";
730
+ const result = await checkDetailResult({ structurePlan, reviewContent });
731
+ expect(result.isApproved).toBe(false);
732
+ expect(result.detailFeedback).toBe("Review content is empty");
733
+ });
734
+
735
+ test("should handle whitespace-only content", async () => {
736
+ const structurePlan = [];
737
+ const reviewContent = " \n\n \t \n ";
738
+ const result = await checkDetailResult({ structurePlan, reviewContent });
739
+ expect(result.isApproved).toBe(false);
740
+ expect(result.detailFeedback).toBe("Review content is empty");
741
+ });
742
+ });
104
743
  });