Allow file paths ending in a language-specific-extension to be used as the language name for injections (#12368)

This allows us to detect the language from the extension if we use paths
in fenced code blocks.

Release Notes:

- You can now use file paths ending in a language-specific file
extension at the start of markdown code blocks.
This commit is contained in:
Nathan Sobo 2024-08-22 19:02:49 -06:00 committed by GitHub
parent db4ff7da6b
commit 88b03bc074
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 16 deletions

View file

@ -1252,19 +1252,27 @@ fn get_injections(
prev_match = Some((mat.pattern_index, content_range.clone())); prev_match = Some((mat.pattern_index, content_range.clone()));
let combined = config.patterns[mat.pattern_index].combined; let combined = config.patterns[mat.pattern_index].combined;
let mut language_name = None;
let mut step_range = content_range.clone(); let mut step_range = content_range.clone();
let language_name =
if let Some(name) = config.patterns[mat.pattern_index].language.as_ref() { if let Some(name) = config.patterns[mat.pattern_index].language.as_ref() {
language_name = Some(Cow::Borrowed(name.as_ref())) Some(Cow::Borrowed(name.as_ref()))
} else if let Some(language_node) = config } else if let Some(language_node) = config
.language_capture_ix .language_capture_ix
.and_then(|ix| mat.nodes_for_capture_index(ix).next()) .and_then(|ix| mat.nodes_for_capture_index(ix).next())
{ {
step_range.start = cmp::min(content_range.start, language_node.start_byte()); step_range.start = cmp::min(content_range.start, language_node.start_byte());
step_range.end = cmp::max(content_range.end, language_node.end_byte()); step_range.end = cmp::max(content_range.end, language_node.end_byte());
language_name = Some(Cow::Owned( let language_name: String =
text.text_for_range(language_node.byte_range()).collect(), text.text_for_range(language_node.byte_range()).collect();
))
// Enable paths ending in a language extension to represent a language name: e.g. "foo/bar/baz.rs"
if let Some(last_dot_pos) = language_name.rfind('.') {
Some(Cow::Owned(language_name[last_dot_pos + 1..].to_string()))
} else {
Some(Cow::Owned(language_name))
}
} else {
None
}; };
if let Some(language_name) = language_name { if let Some(language_name) = language_name {

View file

@ -214,9 +214,9 @@ fn test_dynamic_language_injection(cx: &mut AppContext) {
], ],
); );
// Replace Rust with Ruby in code block. // Replace `rs` with a path to ending in `.rb` in code block.
let macro_name_range = range_for_text(&buffer, "rs"); let macro_name_range = range_for_text(&buffer, "rs");
buffer.edit([(macro_name_range, "ruby")]); buffer.edit([(macro_name_range, "foo/bar/baz.rb")]);
syntax_map.interpolate(&buffer); syntax_map.interpolate(&buffer);
syntax_map.reparse(markdown.clone(), &buffer); syntax_map.reparse(markdown.clone(), &buffer);
syntax_map.reparse(markdown_inline.clone(), &buffer); syntax_map.reparse(markdown_inline.clone(), &buffer);
@ -232,7 +232,7 @@ fn test_dynamic_language_injection(cx: &mut AppContext) {
); );
// Replace Ruby with a language that hasn't been loaded yet. // Replace Ruby with a language that hasn't been loaded yet.
let macro_name_range = range_for_text(&buffer, "ruby"); let macro_name_range = range_for_text(&buffer, "foo/bar/baz.rb");
buffer.edit([(macro_name_range, "html")]); buffer.edit([(macro_name_range, "html")]);
syntax_map.interpolate(&buffer); syntax_map.interpolate(&buffer);
syntax_map.reparse(markdown.clone(), &buffer); syntax_map.reparse(markdown.clone(), &buffer);