diff --git a/crates/grammars/src/markdown-inline/injections.scm b/crates/grammars/src/markdown-inline/injections.scm
index 074b08fd874..3b82d3697c6 100644
--- a/crates/grammars/src/markdown-inline/injections.scm
+++ b/crates/grammars/src/markdown-inline/injections.scm
@@ -1,2 +1,6 @@
+((html_tag) @injection.content
+ (#set! injection.language "html")
+ (#set! injection.combined))
+
((latex_block) @injection.content
(#set! injection.language "latex"))
diff --git a/crates/language/src/buffer_tests.rs b/crates/language/src/buffer_tests.rs
index ea4c49d920c..a5dd8f4b07e 100644
--- a/crates/language/src/buffer_tests.rs
+++ b/crates/language/src/buffer_tests.rs
@@ -2981,6 +2981,104 @@ fn test_language_at_for_markdown_code_block(cx: &mut App) {
});
}
+#[gpui::test]
+async fn test_markdown_inline_html_highlighting(cx: &mut TestAppContext) {
+ let markdown_language = markdown_lang();
+ let markdown_inline_language = Arc::new(
+ Language::new(
+ LanguageConfig {
+ name: "markdown-inline".into(),
+ grammar: Some("markdown-inline".into()),
+ ..Default::default()
+ },
+ Some(tree_sitter_md::INLINE_LANGUAGE.into()),
+ )
+ .with_highlights_query(include_str!(
+ "../../grammars/src/markdown-inline/highlights.scm"
+ ))
+ .unwrap()
+ .with_injection_query(include_str!(
+ "../../grammars/src/markdown-inline/injections.scm"
+ ))
+ .unwrap(),
+ );
+ let html_language = Arc::new(
+ Language::new(
+ LanguageConfig {
+ name: "HTML".into(),
+ ..Default::default()
+ },
+ Some(tree_sitter_html::LANGUAGE.into()),
+ )
+ .with_highlights_query("(comment) @comment (tag_name) @tag")
+ .unwrap(),
+ );
+ let syntax_theme = SyntaxTheme::new([
+ ("comment".to_string(), gpui::rgba(0xffffffff).into()),
+ ("tag".to_string(), gpui::rgba(0xff0000ff).into()),
+ ]);
+ markdown_language.set_theme(&syntax_theme);
+ markdown_inline_language.set_theme(&syntax_theme);
+ html_language.set_theme(&syntax_theme);
+ let language_registry = Arc::new(LanguageRegistry::test(cx.background_executor.clone()));
+ language_registry.add(markdown_language.clone());
+ language_registry.add(markdown_inline_language);
+ language_registry.add(html_language);
+
+ let text = "\n\n\
+ Annotation in the middle \n\n\
+ An inline comment can span within a paragraph.\n\n\
+ Ordinary inline HTML: emphasized.";
+ let buffer = cx.new(|cx| {
+ let mut buffer = Buffer::local(text, cx);
+ buffer.set_language_registry(language_registry);
+ buffer.set_language(Some(markdown_language), cx);
+ buffer
+ });
+
+ cx.run_until_parked();
+
+ buffer.read_with(cx, |buffer, _cx| {
+ let snapshot = buffer.snapshot();
+ let highlighted_text = |capture_name: &str| {
+ let highlight_id = syntax_theme
+ .highlight_id(capture_name)
+ .map(HighlightId::new);
+ assert!(highlight_id.is_some(), "{capture_name} not in test theme");
+ let mut runs: Vec = Vec::new();
+ let mut previous_chunk_matched = false;
+ let chunks = snapshot.chunks(
+ 0..snapshot.len(),
+ LanguageAwareStyling {
+ tree_sitter: true,
+ diagnostics: false,
+ },
+ );
+ for chunk in chunks {
+ let chunk_matches = chunk.syntax_highlight_id == highlight_id;
+ if chunk_matches {
+ match runs.last_mut() {
+ Some(last_run) if previous_chunk_matched => last_run.push_str(chunk.text),
+ _ => runs.push(chunk.text.to_string()),
+ }
+ }
+ previous_chunk_matched = chunk_matches;
+ }
+ runs
+ };
+
+ assert_eq!(
+ highlighted_text("comment"),
+ vec![
+ "",
+ "",
+ "",
+ ]
+ );
+ assert_eq!(highlighted_text("tag"), vec!["em", "em"]);
+ });
+}
+
#[gpui::test]
fn test_syntax_layer_at_for_combined_injections(cx: &mut App) {
init_settings(cx, |_| {});