feat(highlight): add markdown syntax highlighting with injection

Add tree-sitter-md for markdown parsing with injection support for
fenced code blocks. Code inside markdown code fences (```rust, ```bash,
etc.) is now fully syntax highlighted.

Key fix: Use `#set! injection.include-children` directive in the
injection query to override tree-sitter-md's internal tokenization
of code_fence_content, allowing proper language injection.

- Add tree-sitter-md v0.5.2 dependency
- Add Markdown variant to Language enum (md, markdown aliases)
- Create queries/md-highlights.scm (minimal markdown highlights)
- Create queries/md-injections.scm (with include-children directive)
- Add test: test_markdown_injection_rust
This commit is contained in:
Timothy DeHerrera
2026-01-31 16:41:11 -07:00
parent 69cd81621f
commit 8c54882118
6 changed files with 92 additions and 1 deletions

View File

@@ -77,6 +77,7 @@ pub enum Language {
Html,
JavaScript,
Json,
Markdown,
Nix,
Python,
Rust,
@@ -95,6 +96,7 @@ impl Language {
"html" => Some(Language::Html),
"javascript" | "js" => Some(Language::JavaScript),
"json" => Some(Language::Json),
"markdown" | "md" => Some(Language::Markdown),
"nix" => Some(Language::Nix),
"python" | "py" => Some(Language::Python),
"rust" | "rs" => Some(Language::Rust),
@@ -183,6 +185,15 @@ static JSON_CONFIG: LazyLock<HighlightConfiguration> = LazyLock::new(|| {
)
});
static MARKDOWN_CONFIG: LazyLock<HighlightConfiguration> = LazyLock::new(|| {
make_config(
tree_sitter_md::LANGUAGE.into(),
"markdown",
include_str!("../queries/md-highlights.scm"),
include_str!("../queries/md-injections.scm"),
)
});
static NIX_CONFIG: LazyLock<HighlightConfiguration> = LazyLock::new(|| {
make_config(
tree_sitter_nix::LANGUAGE.into(),
@@ -238,6 +249,7 @@ fn get_config(lang: Language) -> &'static HighlightConfiguration {
Language::Html => &HTML_CONFIG,
Language::JavaScript => &JAVASCRIPT_CONFIG,
Language::Json => &JSON_CONFIG,
Language::Markdown => &MARKDOWN_CONFIG,
Language::Nix => &NIX_CONFIG,
Language::Python => &PYTHON_CONFIG,
Language::Rust => &RUST_CONFIG,
@@ -387,4 +399,29 @@ pkgs.stdenv.mkDerivation {
// String content should be present
assert!(html.contains("Hello from bash"));
}
#[test]
fn test_markdown_injection_rust() {
// Markdown code block with embedded Rust should have full Rust highlighting
let md = "```rust\nfn main() {\n println!(\"Hello\");\n}\n```";
let html = highlight_code(Language::Markdown, md);
// All Rust tokens should be highlighted
assert!(
html.contains("hl-keyword"),
"fn should be highlighted as keyword"
);
assert!(
html.contains("hl-function"),
"main/println should be highlighted as function"
);
assert!(
html.contains("hl-string"),
"string literal should be highlighted"
);
assert!(
html.contains("hl-punctuation-bracket"),
"brackets should be highlighted"
);
}
}