Cursor Position Mapping
January 17, 2026 ยท View on GitHub
Overview
Maps cursor positions between displayed text (rendered without markdown formatting) and raw text (containing markdown markers like **, *, etc.). This enables accurate cursor placement when clicking on formatted content to enter edit mode.
Key Files
src/markdown/editor.rs- Containsmap_displayed_to_raw()function (~line 2467)
Implementation Details
The Problem
When a user clicks on formatted markdown content like **bold** text, the rendered view shows just bold. The click position is captured relative to the displayed text, but the cursor needs to be placed in the raw text which includes the ** markers.
Example:
- Raw text:
*h**e**re*(nested italic + bold) - Displayed:
here - Click on 'r' (displayed index 2) โ needs raw index 7
Solution: map_displayed_to_raw()
fn map_displayed_to_raw(displayed_idx: usize, raw_text: &str) -> usize
The function walks through the raw text character by character, skipping formatting markers while counting displayed characters. When the displayed count reaches the target index, it returns the raw position.
Formatting Markers Handled
| Marker | Pattern | Description |
|---|---|---|
| Bold | ** or __ | Skips 2 chars |
| Italic | * or _ | Skips 1 char (when not part of bold) |
| Code | ` | Skips backticks |
| Strikethrough | ~~ | Skips 2 chars |
| Links | [text](url) | Skips [, ](url), keeps text |
Algorithm
- Walk through raw text character by character
- Check for formatting marker patterns in priority order (double-char first)
- Skip marker characters without advancing displayed position
- For regular content, advance both raw and displayed positions
- Return raw position when displayed count reaches target
Link Handling
Links require special handling since the structure is [visible text](hidden url):
- Skip opening
[ - Count text characters normally (they're displayed)
- Skip
](url)entirely, including nested parentheses
Integration Points
The mapping is used in three click handlers in src/markdown/editor.rs:
- Formatted paragraph (first location) - ~line 1554
- Formatted paragraph (second location) - ~line 2268
- List items - ~line 3228
Each handler:
- Computes
displayed_idxusingcompute_displayed_cursor_index()(Galley-based) - Maps to
raw_idxusingmap_displayed_to_raw() - Sets
pending_cursor_posfor the edit state
Related Documentation
- Galley Cursor Positioning - Pixel-accurate displayed position via egui Galley
- Click-to-Edit Formatting - Hybrid editing for formatted content
Testing
Test with formatted content:
- This is **bold** text- Click on "bold" word- Click *here* to edit- Click on "here"- Link [example](https://example.com) text- Click on "example"- Nested ***bold italic*** test- Click in middle
Verify cursor appears within 1-2 characters of click position in edit mode.