@@ -15,3 +15,73 @@ describe("Markdown utils", () => {
1515 expect ( namedAnchors ) . toStrictEqual ( [ ] ) ;
1616 } ) ;
1717} ) ;
18+
19+ describe ( "truncateMarkdown" , ( ) => {
20+ const { truncateMarkdown } = utils ;
21+
22+ it ( "returns content unchanged when length is less than cutOff" , ( ) => {
23+ const content = "Short content." ;
24+ expect ( truncateMarkdown ( content , 1000 ) ) . toBe ( content ) ;
25+ } ) ;
26+
27+ it ( "cuts at the last paragraph boundary before the cutOff" , ( ) => {
28+ const content = "First paragraph.\n\nSecond paragraph that is longer." ;
29+ // cutOff at 30 — inside "Second paragraph", should cut after first \n\n
30+ const result = truncateMarkdown ( content , 30 , "..." ) ;
31+ expect ( result ) . toBe ( "First paragraph.\n\n..." ) ;
32+ } ) ;
33+
34+ it ( "cuts at the nearest paragraph boundary when multiple exist" , ( ) => {
35+ const content = "Para one.\n\nPara two.\n\nPara three that pushes past the limit." ;
36+ const result = truncateMarkdown ( content , 35 , "..." ) ;
37+ expect ( result ) . toBe ( "Para one.\n\nPara two.\n\n..." ) ;
38+ } ) ;
39+
40+ it ( "appends nothing when suffix is empty string" , ( ) => {
41+ const content = "First paragraph.\n\nSecond paragraph that exceeds the limit." ;
42+ const result = truncateMarkdown ( content , 30 , "" ) ;
43+ expect ( result ) . toBe ( "First paragraph." ) ;
44+ } ) ;
45+
46+ it ( "falls back to word boundary when no paragraph boundary exists" , ( ) => {
47+ const content = "This is a single long line with no paragraph breaks anywhere." ;
48+ const result = truncateMarkdown ( content , 25 , "..." ) ;
49+ expect ( result ) . toBe ( "This is a single long\n\n..." ) ;
50+ } ) ;
51+
52+ it ( "hard-cuts at cutOff when no word boundary exists" , ( ) => {
53+ const content = "abcdefghijklmnopqrstuvwxyz" ;
54+ const result = truncateMarkdown ( content , 10 , "..." ) ;
55+ expect ( result ) . toBe ( "abcdefghij\n\n..." ) ;
56+ } ) ;
57+
58+ it ( "skips \\n\\n inside a code fence and backs up to pre-fence boundary" , ( ) => {
59+ const content = [ "Safe paragraph." , "" , "```" , "line one" , "" , "line two" , "```" , "" , "After fence." ] . join (
60+ "\n"
61+ ) ;
62+ const fenceStart = content . indexOf ( "```" ) ;
63+ const cutOff = fenceStart + 15 ; // somewhere inside the fence
64+ const result = truncateMarkdown ( content , cutOff , "..." ) ;
65+ expect ( result ) . toBe ( "Safe paragraph.\n\n..." ) ;
66+ } ) ;
67+
68+ it ( "backs up past the fence when cutOff falls on the closing fence marker" , ( ) => {
69+ const content = [ "Intro." , "" , "```" , "some code" , "```" , "" , "Outro." ] . join ( "\n" ) ;
70+ const closingFenceIdx = content . lastIndexOf ( "```" ) ;
71+ const result = truncateMarkdown ( content , closingFenceIdx , "..." ) ;
72+ expect ( result ) . toBe ( "Intro.\n\n..." ) ;
73+ } ) ;
74+
75+ it ( "backs up past the fence when cutOff falls on the opening fence marker" , ( ) => {
76+ const content = [ "Before." , "" , "```" , "code here" , "```" ] . join ( "\n" ) ;
77+ const openingFenceIdx = content . indexOf ( "```" ) ;
78+ const result = truncateMarkdown ( content , openingFenceIdx , "..." ) ;
79+ expect ( result ) . toBe ( "Before.\n\n..." ) ;
80+ } ) ;
81+
82+ it ( "falls back to word boundary when content is entirely one code fence" , ( ) => {
83+ const content = "```\nsome code line here\n```" ;
84+ const result = truncateMarkdown ( content , 15 , "..." ) ;
85+ expect ( result ) . toBe ( "```\nsome code\n\n..." ) ;
86+ } ) ;
87+ } ) ;
0 commit comments