Skip to content

Commit 9dd4cd6

Browse files
committed
Refactor - Automatically create anchors in Document::from_bytes
Document::from_bytes now calls create_anchors_from_tree internally, eliminating the need for callers to do this separately. Every production call site previously followed the pattern: let mut doc = Document::from_bytes(...)?; doc.create_anchors_from_tree(); This was error-prone boilerplate since anchors are required for snapshot() to work correctly. Now documents are fully initialized with anchors upon creation. Changes: - from_bytes() calls create_anchors_from_tree() before returning - create_anchors_from_tree made private (fn on Document, pub(crate) in anchors module for benchmark access) - Removed redundant calls from CLI, Dioxus app, FFI layer - Removed redundant calls from all test files - Updated documentation to reflect automatic behavior - Restructured anchors benchmark to measure via from_bytes Prompts: - "TODO document should probably automatically load anchors in frombytes - spotted in snapshot snap test" (with code snippet showing the two-step pattern in tests) - "yes" - "can we make create_anchors_from_tree private, nothing should need it" - "don't include the tour" (in response to staging tour file) Co-Authored-By: Claude <noreply@anthropic.com> Interesting that with the AI it is more likely to put up with duplication like this for longer, but it is also easier to fix when we decide to.
1 parent 19b4fb1 commit 9dd4cd6

22 files changed

Lines changed: 125 additions & 181 deletions

crates/markdown-neuraxis-cli/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ impl App {
9090
// Load and display file content
9191
match io::read_file(file.relative_path(), &self.notes_path) {
9292
Ok(content) => match Document::from_bytes(content.as_bytes()) {
93-
Ok(mut document) => {
94-
document.create_anchors_from_tree();
93+
Ok(document) => {
9594
self.selected_document = Some(document.clone());
9695
self.current_content = self.render_document_content(&document);
9796
}

crates/markdown-neuraxis-dioxus/src/ui/app.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,7 @@ fn load_existing_document(
247247

248248
match io::read_file(markdown_file.relative_path(), notes_path) {
249249
Ok(content) => match Document::from_bytes(content.as_bytes()) {
250-
Ok(mut document) => {
251-
// Create anchors for the document blocks
252-
document.create_anchors_from_tree();
253-
250+
Ok(document) => {
254251
// Create snapshot for rendering
255252
let snapshot = document.snapshot();
256253

@@ -290,8 +287,7 @@ pub fn load_document(
290287

291288
match io::read_file(markdown_file.relative_path(), notes_path) {
292289
Ok(content) => match Document::from_bytes(content.as_bytes()) {
293-
Ok(mut document) => {
294-
document.create_anchors_from_tree();
290+
Ok(document) => {
295291
let snapshot = document.snapshot();
296292
*current_document.write() = Some(Arc::new(document));
297293
*current_snapshot.write() = Some(snapshot);
@@ -308,8 +304,7 @@ pub fn load_document(
308304
Err(_) => {
309305
// File doesn't exist - create a blank document
310306
match Document::from_bytes(b"") {
311-
Ok(mut document) => {
312-
document.create_anchors_from_tree();
307+
Ok(document) => {
313308
let snapshot = document.snapshot();
314309
*current_document.write() = Some(Arc::new(document));
315310
*current_snapshot.write() = Some(snapshot);

crates/markdown-neuraxis-dioxus/tests/anchor_id_confusion_during_editing_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ fn test_anchor_id_confusion_after_editing() {
2626
"#;
2727

2828
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
29-
doc.create_anchors_from_tree();
3029

30+
// Anchors are created automatically in from_bytes
3131
// Take initial snapshot and record anchor IDs
3232
let source = doc.text();
3333
let initial_snapshot = doc.snapshot();
@@ -156,8 +156,8 @@ fn test_multiple_edit_cycles_preserve_anchor_identity() {
156156
- item 2"#;
157157

158158
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
159-
doc.create_anchors_from_tree();
160159

160+
// Anchors are created automatically in from_bytes
161161
// Record initial anchor mappings
162162
let initial_snapshot = doc.snapshot();
163163
let initial_blocks = flatten_blocks(&initial_snapshot.blocks);

crates/markdown-neuraxis-dioxus/tests/anchor_stability_tests.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ mod anchor_stability_tests {
4949
fn test_anchor_ids_stable_during_focus_cycles() {
5050
// Create document from the actual test data that shows the bug
5151
let markdown = include_str!("../test_data/nested_lists_bug_repro.md");
52-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
53-
doc.create_anchors_from_tree();
52+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
53+
// Anchors created automatically in from_bytes
5454

5555
// Capture initial anchor IDs
5656
let initial_snapshot = doc.snapshot();
@@ -76,9 +76,8 @@ mod anchor_stability_tests {
7676
println!("\nTesting anchor stability for: '{}'", nested_item.0);
7777
let original_anchor_id = nested_item.1.0;
7878

79-
// Step 1: Focus (this might trigger re-parsing)
79+
// Step 1: Focus - anchors are stable, just take snapshot
8080
println!("Step 1: Focusing on item...");
81-
doc.create_anchors_from_tree();
8281

8382
let after_focus_snapshot = doc.snapshot();
8483
let mut after_focus_blocks = Vec::new();
@@ -97,11 +96,11 @@ mod anchor_stability_tests {
9796
nested_item.0, original_anchor_id, after_focus_id
9897
);
9998

100-
// Step 2: Multiple regenerations without content changes
101-
println!("Step 2: Multiple anchor regenerations...");
99+
// Step 2: Multiple snapshots without content changes
100+
println!("Step 2: Multiple snapshots...");
102101

103102
for cycle in 0..3 {
104-
doc.create_anchors_from_tree();
103+
// Anchors are stable, just take snapshot
105104
let cycle_snapshot = doc.snapshot();
106105
let mut cycle_blocks = Vec::new();
107106
flatten_blocks(&cycle_snapshot.blocks, &mut cycle_blocks);
@@ -122,11 +121,11 @@ mod anchor_stability_tests {
122121
#[test]
123122
fn test_anchor_uniqueness_after_multiple_regenerations() {
124123
let markdown = include_str!("../test_data/nested_lists_bug_repro.md");
125-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
124+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
126125

127126
for cycle in 0..5 {
128-
println!("Anchor regeneration cycle {}", cycle);
129-
doc.create_anchors_from_tree();
127+
println!("Anchor snapshot cycle {}", cycle);
128+
// Anchors are created automatically and stable
130129

131130
let snapshot = doc.snapshot();
132131
let mut blocks = Vec::new();
@@ -167,8 +166,8 @@ mod anchor_stability_tests {
167166
#[test]
168167
fn test_specific_bug_scenario_from_diagnostics() {
169168
let markdown = include_str!("../test_data/nested_lists_bug_repro.md");
170-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
171-
doc.create_anchors_from_tree();
169+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
170+
// Anchors created automatically in from_bytes
172171

173172
let snapshot = doc.snapshot();
174173
let mut blocks = Vec::new();

crates/markdown-neuraxis-dioxus/tests/click_event_mapping_bug_test.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ fn test_ui_block_to_anchor_mapping_correctness() {
1111
// This suggests the UI rendering and click handling are using different block mappings
1212

1313
let markdown = include_str!("../test_data/actual_runtime_bug_repro.md");
14-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
15-
doc.create_anchors_from_tree();
14+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
1615

1716
let snapshot = doc.snapshot();
1817
let blocks = flatten_blocks(&snapshot.blocks);
@@ -95,8 +94,7 @@ fn test_snapshot_block_order_vs_ui_rendering_order() {
9594
// This could cause click events to get mapped to wrong blocks
9695

9796
let markdown = include_str!("../test_data/actual_runtime_bug_repro.md");
98-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
99-
doc.create_anchors_from_tree();
97+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
10098

10199
let snapshot = doc.snapshot();
102100
let blocks = flatten_blocks(&snapshot.blocks);
@@ -161,8 +159,7 @@ fn test_hierarchical_list_item_click_confusion() {
161159
// Maybe nested items inherit or share anchor IDs with their parents
162160

163161
let markdown = include_str!("../test_data/actual_runtime_bug_repro.md");
164-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
165-
doc.create_anchors_from_tree();
162+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
166163

167164
let snapshot = doc.snapshot();
168165
let blocks = flatten_blocks(&snapshot.blocks);

crates/markdown-neuraxis-dioxus/tests/different_content_same_anchor_test.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use test_helpers::flatten_blocks;
99
fn test_different_content_same_anchor_id_bug() {
1010
// Use the actual runtime data that shows the bug
1111
let markdown = include_str!("../test_data/actual_runtime_bug_repro.md");
12-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
13-
doc.create_anchors_from_tree();
12+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
13+
// Anchors created automatically in from_bytes
1414

1515
let snapshot = doc.snapshot();
1616
let blocks = flatten_blocks(&snapshot.blocks);
@@ -79,8 +79,8 @@ fn test_different_content_same_anchor_id_bug() {
7979
fn test_specific_indented_1_vs_indented_1_2_collision() {
8080
// Test the specific diagnostic case: "indented 1" vs "indented 1.2"
8181
let markdown = include_str!("../test_data/actual_runtime_bug_repro.md");
82-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
83-
doc.create_anchors_from_tree();
82+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
83+
// Anchors created automatically in from_bytes
8484

8585
let snapshot = doc.snapshot();
8686
let blocks = flatten_blocks(&snapshot.blocks);

crates/markdown-neuraxis-dioxus/tests/dioxus_rendering_tests.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ use test_helpers::flatten_blocks;
88
/// Test helper to create nested list document
99
fn create_nested_list_doc() -> Document {
1010
let markdown = "- item 1\n - nested 1.1\n - nested 1.2\n - deeply nested 1.2.1\n- item 2";
11-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
12-
doc.create_anchors_from_tree();
13-
doc
11+
Document::from_bytes(markdown.as_bytes()).unwrap()
1412
}
1513

1614
#[cfg(test)]

crates/markdown-neuraxis-dioxus/tests/document_clone_bug_test.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ fn test_document_clone_should_have_valid_anchor_node_references() {
1717
- item 1.2
1818
- item 2"#;
1919

20-
let mut original_doc = Document::from_bytes(markdown.as_bytes()).unwrap();
21-
original_doc.create_anchors_from_tree();
20+
let original_doc = Document::from_bytes(markdown.as_bytes()).unwrap();
2221

2322
println!("=== ORIGINAL DOCUMENT ===");
2423
println!(
@@ -100,8 +99,7 @@ fn test_document_clone_anchor_content_integrity() {
10099
- nested item
101100
- second item"#;
102101

103-
let mut original_doc = Document::from_bytes(markdown.as_bytes()).unwrap();
104-
original_doc.create_anchors_from_tree();
102+
let original_doc = Document::from_bytes(markdown.as_bytes()).unwrap();
105103
let original_snapshot = original_doc.snapshot();
106104
let original_blocks = flatten_blocks(&original_snapshot.blocks);
107105

@@ -169,8 +167,7 @@ fn test_document_clone_preserves_functionality() {
169167
let markdown = r#"- original item
170168
- nested original"#;
171169

172-
let mut original_doc = Document::from_bytes(markdown.as_bytes()).unwrap();
173-
original_doc.create_anchors_from_tree();
170+
let original_doc = Document::from_bytes(markdown.as_bytes()).unwrap();
174171

175172
let mut cloned_doc = original_doc.clone();
176173

crates/markdown-neuraxis-dioxus/tests/editing_lifecycle_bug_test.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ use test_helpers::flatten_blocks;
99
fn test_editing_lifecycle_causes_anchor_instability() {
1010
// Use the actual runtime data
1111
let markdown = include_str!("../test_data/actual_runtime_bug_repro.md");
12-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
12+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
1313

1414
// Step 1: Initial document load (like opening the file)
15-
doc.create_anchors_from_tree();
15+
// Anchors are created automatically in from_bytes
1616
let initial_snapshot = doc.snapshot();
1717
let initial_blocks = flatten_blocks(&initial_snapshot.blocks);
1818

@@ -39,8 +39,7 @@ fn test_editing_lifecycle_causes_anchor_instability() {
3939
// 1. Focus event triggered
4040
// 2. UI might regenerate anchors for consistency
4141
// 3. Document state changes
42-
43-
doc.create_anchors_from_tree(); // This is what might cause instability
42+
// Anchors are created automatically in from_bytes, so just take snapshot
4443

4544
let cycle_snapshot = doc.snapshot();
4645
let cycle_blocks = flatten_blocks(&cycle_snapshot.blocks);
@@ -115,9 +114,9 @@ fn test_editing_lifecycle_causes_anchor_instability() {
115114
fn test_rapid_focus_changes_cause_collision() {
116115
// Simulate rapid clicking between items (like a user quickly clicking different items)
117116
let markdown = include_str!("../test_data/actual_runtime_bug_repro.md");
118-
let mut doc = Document::from_bytes(markdown.as_bytes()).unwrap();
117+
let doc = Document::from_bytes(markdown.as_bytes()).unwrap();
119118

120-
doc.create_anchors_from_tree();
119+
// Anchors are created automatically in from_bytes
121120
let initial_snapshot = doc.snapshot();
122121
let initial_blocks = flatten_blocks(&initial_snapshot.blocks);
123122

@@ -137,10 +136,8 @@ fn test_rapid_focus_changes_cause_collision() {
137136
println!("Found {} 'indented 1.2' items", indented_1_2_items.len());
138137

139138
// Simulate rapid focus changes (like clicking back and forth)
139+
// Anchors are created automatically and stable, so just take repeated snapshots
140140
for rapid_cycle in 0..10 {
141-
// This simulates the sequence: click item → focus → anchor regeneration
142-
doc.create_anchors_from_tree();
143-
144141
let rapid_snapshot = doc.snapshot();
145142
let rapid_blocks = flatten_blocks(&rapid_snapshot.blocks);
146143

crates/markdown-neuraxis-dioxus/tests/exact_collision_reproduction_test.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ fn test_exact_diagnostic_collision_indented_1_vs_indented_1_2() {
3232
- indented 1.2.1 - then clicked this
3333
"#;
3434

35-
let mut doc = Document::from_bytes(actual_file_content.as_bytes()).unwrap();
36-
doc.create_anchors_from_tree();
35+
let doc = Document::from_bytes(actual_file_content.as_bytes()).unwrap();
36+
// Anchors created automatically in from_bytes
3737

3838
let snapshot = doc.snapshot();
3939
let blocks = flatten_blocks(&snapshot.blocks);
@@ -123,11 +123,9 @@ fn test_anchor_generation_algorithm_produces_unique_ids_for_similar_content() {
123123
let doc1_markdown = format!("- {}", content1);
124124
let doc2_markdown = format!("- {}", content2);
125125

126-
let mut doc1 = Document::from_bytes(doc1_markdown.as_bytes()).unwrap();
127-
let mut doc2 = Document::from_bytes(doc2_markdown.as_bytes()).unwrap();
128-
129-
doc1.create_anchors_from_tree();
130-
doc2.create_anchors_from_tree();
126+
let doc1 = Document::from_bytes(doc1_markdown.as_bytes()).unwrap();
127+
let doc2 = Document::from_bytes(doc2_markdown.as_bytes()).unwrap();
128+
// Anchors created automatically in from_bytes
131129

132130
let snapshot1 = doc1.snapshot();
133131
let snapshot2 = doc2.snapshot();
@@ -170,8 +168,8 @@ fn test_combined_document_collision_reproduction() {
170168
171169
"#;
172170

173-
let mut doc = Document::from_bytes(problematic_markdown.as_bytes()).unwrap();
174-
doc.create_anchors_from_tree();
171+
let doc = Document::from_bytes(problematic_markdown.as_bytes()).unwrap();
172+
// Anchors created automatically in from_bytes
175173

176174
let snapshot = doc.snapshot();
177175
let blocks = flatten_blocks(&snapshot.blocks);

0 commit comments

Comments
 (0)