Skip to content

Commit 2fd919c

Browse files
committed
feat(core): highlight markdown code fences
Parse Markdown fenced code blocks as Tree-sitter injections and merge their spans back into the outer document. Resolve fence languages through the highlighter registry so aliases and registered extensions can target supported parsers. Prefer narrower, later style spans during rendering so injected syntax can override broad Markdown raw-block styling.
1 parent f6b95a6 commit 2fd919c

2 files changed

Lines changed: 317 additions & 24 deletions

File tree

src/editor.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4594,11 +4594,26 @@ fn directory_listing(path: &str) -> Value {
45944594
}
45954595

45964596
fn determine_style_for_position(style_info: &[StyleInfo], pos: usize) -> Option<Style> {
4597-
if let Some(s) = style_info.iter().find(|si| si.contains(pos)) {
4598-
return Some(s.style.clone());
4597+
let mut best = None;
4598+
4599+
for (index, style) in style_info.iter().enumerate() {
4600+
if !style.contains(pos) {
4601+
continue;
4602+
}
4603+
4604+
let range_len = style.end.saturating_sub(style.start);
4605+
let should_replace = best
4606+
.map(|(best_index, best_len): (usize, usize)| {
4607+
range_len < best_len || (range_len == best_len && index > best_index)
4608+
})
4609+
.unwrap_or(true);
4610+
4611+
if should_replace {
4612+
best = Some((index, range_len));
4613+
}
45994614
}
46004615

4601-
None
4616+
best.map(|(index, _)| style_info[index].style.clone())
46024617
}
46034618

46044619
fn adjust_color_brightness(color: Option<Color>, percentage: i32) -> Option<Color> {
@@ -4805,6 +4820,48 @@ mod test {
48054820
std::fs::remove_dir_all(root).unwrap();
48064821
}
48074822

4823+
#[test]
4824+
fn style_for_position_prefers_narrower_and_later_spans() {
4825+
let outer_style = Style {
4826+
fg: Some(Color::Rgb { r: 1, g: 1, b: 1 }),
4827+
..Style::default()
4828+
};
4829+
let inner_style = Style {
4830+
fg: Some(Color::Rgb { r: 2, g: 2, b: 2 }),
4831+
..Style::default()
4832+
};
4833+
let later_style = Style {
4834+
fg: Some(Color::Rgb { r: 3, g: 3, b: 3 }),
4835+
..Style::default()
4836+
};
4837+
let style_info = vec![
4838+
StyleInfo {
4839+
start: 0,
4840+
end: 20,
4841+
style: outer_style.clone(),
4842+
},
4843+
StyleInfo {
4844+
start: 5,
4845+
end: 10,
4846+
style: inner_style.clone(),
4847+
},
4848+
StyleInfo {
4849+
start: 5,
4850+
end: 10,
4851+
style: later_style.clone(),
4852+
},
4853+
];
4854+
4855+
assert_eq!(
4856+
determine_style_for_position(&style_info, 2),
4857+
Some(outer_style)
4858+
);
4859+
assert_eq!(
4860+
determine_style_for_position(&style_info, 6),
4861+
Some(later_style)
4862+
);
4863+
}
4864+
48084865
#[test]
48094866
fn test_buffer_diff() {
48104867
let contents1 = vec![" 1:2 ".to_string()];

0 commit comments

Comments
 (0)