markdown_preview: Enable parser options individually (#50440)

Kunall Banerjee created

Closes #50170.

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- Enable parser options individually to avoid rendering issues

Change summary

Cargo.lock                                     |  1 
crates/markdown/src/parser.rs                  |  2 
crates/markdown_preview/Cargo.toml             |  1 
crates/markdown_preview/src/markdown_parser.rs | 28 ++++++++++++++++---
4 files changed, 26 insertions(+), 6 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -10203,6 +10203,7 @@ dependencies = [
  "language",
  "linkify",
  "log",
+ "markdown",
  "markup5ever_rcdom",
  "mermaid-rs-renderer",
  "pretty_assertions",

crates/markdown/src/parser.rs 🔗

@@ -10,7 +10,7 @@ use collections::HashSet;
 
 use crate::path_range::PathWithRange;
 
-const PARSE_OPTIONS: Options = Options::ENABLE_TABLES
+pub const PARSE_OPTIONS: Options = Options::ENABLE_TABLES
     .union(Options::ENABLE_FOOTNOTES)
     .union(Options::ENABLE_STRIKETHROUGH)
     .union(Options::ENABLE_TASKLISTS)

crates/markdown_preview/Cargo.toml 🔗

@@ -25,6 +25,7 @@ html5ever.workspace = true
 language.workspace = true
 linkify.workspace = true
 log.workspace = true
+markdown.workspace = true
 markup5ever_rcdom.workspace = true
 pretty_assertions.workspace = true
 pulldown-cmark.workspace = true

crates/markdown_preview/src/markdown_parser.rs 🔗

@@ -7,8 +7,9 @@ use collections::FxHashMap;
 use gpui::{DefiniteLength, FontWeight, px, relative};
 use html5ever::{ParseOpts, local_name, parse_document, tendril::TendrilSink};
 use language::LanguageRegistry;
+use markdown::parser::PARSE_OPTIONS;
 use markup5ever_rcdom::RcDom;
-use pulldown_cmark::{Alignment, Event, Options, Parser, Tag, TagEnd};
+use pulldown_cmark::{Alignment, Event, Parser, Tag, TagEnd};
 use std::{
     cell::RefCell, collections::HashMap, mem, ops::Range, path::PathBuf, rc::Rc, sync::Arc, vec,
 };
@@ -19,10 +20,7 @@ pub async fn parse_markdown(
     file_location_directory: Option<PathBuf>,
     language_registry: Option<Arc<LanguageRegistry>>,
 ) -> ParsedMarkdown {
-    let mut options = Options::all();
-    options.remove(pulldown_cmark::Options::ENABLE_DEFINITION_LIST);
-
-    let parser = Parser::new_ext(markdown_input, options);
+    let parser = Parser::new_ext(markdown_input, PARSE_OPTIONS);
     let parser = MarkdownParser::new(
         parser.into_offset_iter().collect(),
         file_location_directory,
@@ -3076,6 +3074,26 @@ More text
         );
     }
 
+    #[gpui::test]
+    async fn test_dollar_signs_are_plain_text() {
+        // Dollar signs should be preserved as plain text, not treated as math delimiters.
+        // Regression test for https://github.com/zed-industries/zed/issues/50170
+        let parsed = parse("$100$ per unit").await;
+        assert_eq!(parsed.children, vec![p("$100$ per unit", 0..14)]);
+    }
+
+    #[gpui::test]
+    async fn test_dollar_signs_in_list_items() {
+        let parsed = parse("- $18,000 budget\n- $20,000 budget\n").await;
+        assert_eq!(
+            parsed.children,
+            vec![
+                list_item(0..16, 1, Unordered, vec![p("$18,000 budget", 2..16)]),
+                list_item(17..33, 1, Unordered, vec![p("$20,000 budget", 19..33)]),
+            ]
+        );
+    }
+
     #[gpui::test]
     async fn test_code_block() {
         let parsed = parse(