markdown: Fix parse inline `code` display (#30937)

CharlesChen0823 created

inline code startswith "\`", "\`\`", "\`\`\`", should all valid. current
implement only work with startswith "\`".

Release Notes:

- N/A

Change summary

crates/markdown/src/parser.rs | 48 +++++++++++++++++++++++++++++++++---
1 file changed, 44 insertions(+), 4 deletions(-)

Detailed changes

crates/markdown/src/parser.rs 🔗

@@ -33,7 +33,7 @@ pub fn parse_markdown(
     let mut parser = Parser::new_ext(text, PARSE_OPTIONS)
         .into_offset_iter()
         .peekable();
-    while let Some((pulldown_event, mut range)) = parser.next() {
+    while let Some((pulldown_event, range)) = parser.next() {
         if within_metadata {
             if let pulldown_cmark::Event::End(pulldown_cmark::TagEnd::MetadataBlock { .. }) =
                 pulldown_event
@@ -303,9 +303,10 @@ pub fn parse_markdown(
                 }
             }
             pulldown_cmark::Event::Code(_) => {
-                range.start += 1;
-                range.end -= 1;
-                events.push((range, MarkdownEvent::Code))
+                let content_range = extract_code_content_range(&text[range.clone()]);
+                let content_range =
+                    content_range.start + range.start..content_range.end + range.start;
+                events.push((content_range, MarkdownEvent::Code))
             }
             pulldown_cmark::Event::Html(_) => events.push((range, MarkdownEvent::Html)),
             pulldown_cmark::Event::InlineHtml(_) => events.push((range, MarkdownEvent::InlineHtml)),
@@ -497,6 +498,27 @@ pub struct CodeBlockMetadata {
     pub line_count: usize,
 }
 
+fn extract_code_content_range(text: &str) -> Range<usize> {
+    let text_len = text.len();
+    if text_len == 0 {
+        return 0..0;
+    }
+
+    let start_ticks = text.chars().take_while(|&c| c == '`').count();
+
+    if start_ticks == 0 || start_ticks > text_len {
+        return 0..text_len;
+    }
+
+    let end_ticks = text.chars().rev().take_while(|&c| c == '`').count();
+
+    if end_ticks != start_ticks || text_len < start_ticks + end_ticks {
+        return 0..text_len;
+    }
+
+    start_ticks..text_len - end_ticks
+}
+
 pub(crate) fn extract_code_block_content_range(text: &str) -> Range<usize> {
     let mut range = 0..text.len();
     if text.starts_with("```") {
@@ -679,6 +701,24 @@ mod tests {
         )
     }
 
+    #[test]
+    fn test_extract_code_content_range() {
+        let input = "```let x = 5;```";
+        assert_eq!(extract_code_content_range(input), 3..13);
+
+        let input = "``let x = 5;``";
+        assert_eq!(extract_code_content_range(input), 2..12);
+
+        let input = "`let x = 5;`";
+        assert_eq!(extract_code_content_range(input), 1..11);
+
+        let input = "plain text";
+        assert_eq!(extract_code_content_range(input), 0..10);
+
+        let input = "``let x = 5;`";
+        assert_eq!(extract_code_content_range(input), 0..13);
+    }
+
     #[test]
     fn test_extract_code_block_content_range() {
         let input = "```rust\nlet x = 5;\n```";