rustdoc_to_markdown: Recognize code blocks in other languages (#12484)

Marshall Bowers created

This PR updates `rustdoc_to_markdown` to be able to recognize code
blocks using non-Rust languages.

Release Notes:

- N/A

Change summary

crates/rustdoc_to_markdown/src/markdown_writer.rs     | 17 +++++-
crates/rustdoc_to_markdown/src/rustdoc_to_markdown.rs | 34 ++++++++++++
2 files changed, 47 insertions(+), 4 deletions(-)

Detailed changes

crates/rustdoc_to_markdown/src/markdown_writer.rs ๐Ÿ”—

@@ -148,10 +148,21 @@ impl MarkdownWriter {
                             .collect::<Vec<_>>()
                     })
                     .unwrap_or_default();
-                let is_rust = classes.into_iter().any(|class| class == "rust");
-                let language = if is_rust { "rs" } else { "" };
+                let is_rust = classes.iter().any(|class| class == &"rust");
+                let language = is_rust
+                    .then(|| "rs")
+                    .or_else(|| {
+                        classes.iter().find_map(|class| {
+                            if let Some((_, language)) = class.split_once("language-") {
+                                Some(language.trim())
+                            } else {
+                                None
+                            }
+                        })
+                    })
+                    .unwrap_or("");
 
-                self.push_str(&format!("\n```{language}\n"))
+                self.push_str(&format!("\n\n```{language}\n"))
             }
             "ul" | "ol" => self.push_newline(),
             "li" => self.push_str("- "),

crates/rustdoc_to_markdown/src/rustdoc_to_markdown.rs ๐Ÿ”—

@@ -45,7 +45,7 @@ mod tests {
     use super::*;
 
     #[test]
-    fn test_code_blocks() {
+    fn test_rust_code_block() {
         let html = indoc! {r#"
             <pre class="rust rust-example-rendered"><code><span class="kw">use </span>axum::extract::{Path, Query, Json};
             <span class="kw">use </span>std::collections::HashMap;
@@ -85,4 +85,36 @@ mod tests {
             expected
         )
     }
+
+    #[test]
+    fn test_toml_code_block() {
+        let html = indoc! {r##"
+            <h2 id="required-dependencies"><a class="doc-anchor" href="#required-dependencies">ยง</a>Required dependencies</h2>
+            <p>To use axum there are a few dependencies you have to pull in as well:</p>
+            <div class="example-wrap"><pre class="language-toml"><code>[dependencies]
+            axum = &quot;&lt;latest-version&gt;&quot;
+            tokio = { version = &quot;&lt;latest-version&gt;&quot;, features = [&quot;full&quot;] }
+            tower = &quot;&lt;latest-version&gt;&quot;
+            </code></pre></div>
+        "##};
+        let expected = indoc! {r#"
+            ## Required dependencies
+
+            To use axum there are a few dependencies you have to pull in as well:
+
+            ```toml
+            [dependencies]
+            axum = "<latest-version>"
+            tokio = { version = "<latest-version>", features = ["full"] }
+            tower = "<latest-version>"
+
+            ```
+        "#}
+        .trim();
+
+        assert_eq!(
+            convert_rustdoc_to_markdown(html.as_bytes()).unwrap(),
+            expected
+        )
+    }
 }