Skip to content

Commit 5df2b9d

Browse files
timabellclaude
andcommitted
fix: Exclude closing fence markers from code block content
The process_fenced_code function was incorrectly including the closing ``` markers in the extracted code content. This happened because text.rfind('\n') found the trailing newline after the closing fence instead of the newline before it. Fixed by trimming trailing newlines before finding the last newline position, ensuring we correctly identify where the code content ends. Added test_code_fence_content_excludes_closing_fence to prevent regression. Prompts: - "code fences in dioxus are always showing the trailing ``` in the display mode" - "you really don't know how to tdd do you. anyway, commit" (in response to review rejection) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent e8937cf commit 5df2b9d

7 files changed

Lines changed: 40 additions & 9 deletions

File tree

crates/markdown-neuraxis-engine/src/editing/snapshot.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,13 @@ fn process_fenced_code(
479479
// Extract code content between opening and closing fences
480480
let segments = if let Some(first_newline) = text.find('\n') {
481481
let content_start = node_range.start + first_newline + 1;
482-
// Find last line (closing fence) by finding last newline before end
483-
let last_newline = text.rfind('\n').unwrap_or(text.len());
482+
// Find last line (closing fence) by finding last newline before the closing fence.
483+
// We need to trim any trailing newline that comes AFTER the closing fence,
484+
// otherwise rfind finds that trailing newline instead of the one before the fence.
485+
let text_without_trailing = text.trim_end_matches('\n');
486+
let last_newline = text_without_trailing
487+
.rfind('\n')
488+
.unwrap_or(text_without_trailing.len());
484489
// Content ends at the last newline (before closing fence line)
485490
let content_end = node_range.start + last_newline;
486491
if content_start < content_end {
@@ -1232,6 +1237,32 @@ mod tests {
12321237
assert_eq!(block.kind, BlockKind::FencedCode { language: None });
12331238
}
12341239

1240+
#[test]
1241+
fn test_code_fence_content_excludes_closing_fence() {
1242+
// The code fence content should NOT include the closing ``` markers
1243+
// Bug: when there's a trailing newline after closing fence, rfind('\n')
1244+
// finds that trailing newline instead of the one before the closing fence
1245+
let text = "```rust\nfn main() {}\n```\n";
1246+
let mut doc = Document::from_bytes(text.as_bytes()).unwrap();
1247+
doc.create_anchors_from_tree();
1248+
let snapshot = doc.snapshot();
1249+
1250+
assert_eq!(snapshot.blocks.len(), 1);
1251+
let block = &snapshot.blocks[0];
1252+
1253+
// Verify the segment content does not include the closing fence
1254+
assert_eq!(block.segments.len(), 1);
1255+
if let InlineNode::Text(content) = &block.segments[0].kind {
1256+
assert_eq!(content, "fn main() {}");
1257+
assert!(
1258+
!content.contains("```"),
1259+
"Content should not include closing fence, got: {content:?}"
1260+
);
1261+
} else {
1262+
panic!("Expected Text segment");
1263+
}
1264+
}
1265+
12351266
#[test]
12361267
fn test_snapshot_range_validity() {
12371268
let text = "# Heading\n\n- Item 1\n- Item 2\n\nParagraph text";

crates/markdown-neuraxis-engine/src/editing/snapshots/complex_document.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Heading { level: 2 } [125..141]
4040
Text [128..140] "Code Example"
4141
FencedCode { language: Some("javascript") } [142..190]
4242
segments:
43-
Text [156..189] "const x = 42;\nconsole.log(x);\n```"
43+
Text [156..185] "const x = 42;\nconsole.log(x);"
4444
Heading { level: 2 } [191..201]
4545
segments:
4646
Text [194..200] "Quotes"

crates/markdown-neuraxis-engine/src/editing/snapshots/fenced_code_no_inlines.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ expression: formatted
44
---
55
FencedCode { language: None } [0..49]
66
segments:
7-
Text [4..48] "*not emphasis* **not strong** `not code`\n```"
7+
Text [4..44] "*not emphasis* **not strong** `not code`"
88
FencedCode { language: Some("rust") } [50..92]
99
segments:
10-
Text [58..91] "let x = \"[[not a wikilink]]\";\n```"
10+
Text [58..87] "let x = \"[[not a wikilink]]\";"

crates/markdown-neuraxis-engine/src/editing/snapshots/fenced_code_no_lang.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ expression: formatted
44
---
55
FencedCode { language: None } [0..33]
66
segments:
7-
Text [4..32] "some code here\nmore code\n```"
7+
Text [4..28] "some code here\nmore code"

crates/markdown-neuraxis-engine/src/editing/snapshots/fenced_code_with_lang.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ expression: formatted
44
---
55
FencedCode { language: Some("rust") } [0..57]
66
segments:
7-
Text [8..56] "fn main() {\n println!(\"Hello, world!\");\n}\n```"
7+
Text [8..52] "fn main() {\n println!(\"Hello, world!\");\n}"

crates/markdown-neuraxis-engine/src/editing/snapshots/list_with_code_block.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ List { ordered: false } [0..68]
1212
FencedCode { language: Some("python") } [20..53]
1313
root_range: 0..68
1414
segments:
15-
Text [30..52] " print(\"hello\")\n ```"
15+
Text [30..46] " print(\"hello\")"
1616
ListItem { marker: "- " } [53..68]
1717
root_range: 0..68
1818
segments:

crates/markdown-neuraxis-engine/src/editing/snapshots/tilde_code_fence.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ expression: formatted
44
---
55
FencedCode { language: None } [0..25]
66
segments:
7-
Text [4..24] "code with tildes\n~~~"
7+
Text [4..20] "code with tildes"

0 commit comments

Comments
 (0)