Codex Handbook
tui/src/markdown_render_tests.rs 1797 lines
use pretty_assertions::assert_eq;use ratatui::style::Modifier;use ratatui::style::Stylize;use ratatui::text::Line;use ratatui::text::Span;use ratatui::text::Text;use std::path::Path;use crate::markdown_render::COLON_LOCATION_SUFFIX_RE;use crate::markdown_render::HASH_LOCATION_SUFFIX_RE;use crate::markdown_render::render_markdown_lines_with_width_and_cwd;use crate::markdown_render::render_markdown_text;use crate::markdown_render::render_markdown_text_with_width;use crate::markdown_render::render_markdown_text_with_width_and_cwd;use insta::assert_debug_snapshot;use insta::assert_snapshot;fn render_markdown_text_for_cwd(input: &str, cwd: &Path) -> Text<'static> {    render_markdown_text_with_width_and_cwd(input, /*width*/ None, Some(cwd))}fn plain_lines(text: &Text<'_>) -> Vec<String> {    text.lines        .iter()        .map(|line| {            line.spans                .iter()                .map(|span| span.content.clone())                .collect::<String>()        })        .collect()}#[test]fn bare_url_with_tilde_keeps_complete_hyperlink() {    let destination =        "https://www.cs.tufts.edu/~nr/cs257/archive/olin-shivers/dissertation.pdf";    let lines = render_markdown_lines_with_width_and_cwd(        destination,        /*width*/ Some(80),        /*cwd*/ None,    );    let rendered = lines        .iter()        .map(|line| {            let text = line                .line                .spans                .iter()                .map(|span| span.content.as_ref())                .collect::<String>();            let hyperlinks = line                .hyperlinks                .iter()                .map(|link| (link.columns.clone(), link.destination.as_str()))                .collect::<Vec<_>>();            (text, hyperlinks)        })        .collect::<Vec<_>>();    assert_debug_snapshot!(rendered);}#[test]fn table_url_with_tilde_keeps_complete_hyperlink() {    let destination =        "https://www.cs.tufts.edu/~nr/cs257/archive/olin-shivers/dissertation.pdf";    let markdown = format!("| URL |\n| --- |\n| {destination} |\n");    let lines = render_markdown_lines_with_width_and_cwd(        &markdown,        /*width*/ Some(32),        /*cwd*/ None,    );    let destinations = lines        .iter()        .flat_map(|line| line.hyperlinks.iter())        .map(|link| link.destination.as_str())        .collect::<Vec<_>>();    assert!(!destinations.is_empty());    assert_eq!(destinations, vec![destination; destinations.len()]);}#[test]fn merged_text_events_preserve_entity_decoding() {    let source = "https://example.com/a&amp;b~c";    let destination = "https://example.com/a&b~c";    let lines = render_markdown_lines_with_width_and_cwd(        source,        /*width*/ Some(80),        /*cwd*/ None,    );    let rendered = lines        .iter()        .map(|line| {            let text = line                .line                .spans                .iter()                .map(|span| span.content.as_ref())                .collect::<String>();            let hyperlinks = line                .hyperlinks                .iter()                .map(|link| (link.columns.clone(), link.destination.as_str()))                .collect::<Vec<_>>();            (text, hyperlinks)        })        .collect::<Vec<_>>();    assert_eq!(        rendered,        vec![(            destination.to_string(),            vec![(0..destination.len(), destination)],        )],    );}#[test]fn empty() {    assert_eq!(render_markdown_text(""), Text::default());}#[test]fn paragraph_single() {    assert_eq!(        render_markdown_text("Hello, world!"),        Text::from("Hello, world!")    );}#[test]fn paragraph_soft_break() {    assert_eq!(        render_markdown_text("Hello\nWorld"),        Text::from_iter(["Hello", "World"])    );}#[test]fn paragraph_multiple() {    assert_eq!(        render_markdown_text("Paragraph 1\n\nParagraph 2"),        Text::from_iter(["Paragraph 1", "", "Paragraph 2"])    );}#[test]fn headings() {    let md = "# Heading 1\n## Heading 2\n### Heading 3\n#### Heading 4\n##### Heading 5\n###### Heading 6\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["# ".bold().underlined(), "Heading 1".bold().underlined()]),        Line::default(),        Line::from_iter(["## ".bold(), "Heading 2".bold()]),        Line::default(),        Line::from_iter(["### ".bold().italic(), "Heading 3".bold().italic()]),        Line::default(),        Line::from_iter(["#### ".italic(), "Heading 4".italic()]),        Line::default(),        Line::from_iter(["##### ".italic(), "Heading 5".italic()]),        Line::default(),        Line::from_iter(["###### ".italic(), "Heading 6".italic()]),    ]);    assert_eq!(text, expected);}#[test]fn blockquote_single() {    let text = render_markdown_text("> Blockquote");    let expected = Text::from(Line::from_iter(["> ", "Blockquote"]).green());    assert_eq!(text, expected);}#[test]fn blockquote_soft_break() {    // Soft break via lazy continuation should render as a new line in blockquotes.    let text = render_markdown_text("> This is a blockquote\nwith a soft break\n");    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(        lines,        vec![            "> This is a blockquote".to_string(),            "> with a soft break".to_string()        ]    );}#[test]fn blockquote_multiple_with_break() {    let text = render_markdown_text("> Blockquote 1\n\n> Blockquote 2\n");    let expected = Text::from_iter([        Line::from_iter(["> ", "Blockquote 1"]).green(),        Line::default(),        Line::from_iter(["> ", "Blockquote 2"]).green(),    ]);    assert_eq!(text, expected);}#[test]fn blockquote_three_paragraphs_short_lines() {    let md = "> one\n>\n> two\n>\n> three\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["> ", "one"]).green(),        Line::from_iter(["> "]).green(),        Line::from_iter(["> ", "two"]).green(),        Line::from_iter(["> "]).green(),        Line::from_iter(["> ", "three"]).green(),    ]);    assert_eq!(text, expected);}#[test]fn blockquote_nested_two_levels() {    let md = "> Level 1\n>> Level 2\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["> ", "Level 1"]).green(),        Line::from_iter(["> "]).green(),        Line::from_iter(["> ", "> ", "Level 2"]).green(),    ]);    assert_eq!(text, expected);}#[test]fn blockquote_with_list_items() {    let md = "> - item 1\n> - item 2\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["> ", "- ", "item 1"]).green(),        Line::from_iter(["> ", "- ", "item 2"]).green(),    ]);    assert_eq!(text, expected);}#[test]fn blockquote_with_ordered_list() {    let md = "> 1. first\n> 2. second\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(vec![            Span::from("> "),            "1. ".light_blue(),            Span::from("first"),        ])        .green(),        Line::from_iter(vec![            Span::from("> "),            "2. ".light_blue(),            Span::from("second"),        ])        .green(),    ]);    assert_eq!(text, expected);}#[test]fn blockquote_list_then_nested_blockquote() {    let md = "> - parent\n>   > child\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["> ", "- ", "parent"]).green(),        Line::from_iter(["> ", "  ", "> ", "child"]).green(),    ]);    assert_eq!(text, expected);}#[test]fn list_item_with_inline_blockquote_on_same_line() {    let md = "1. > quoted\n";    let text = render_markdown_text(md);    let mut lines = text.lines.iter();    let first = lines.next().expect("one line");    // Expect content to include the ordered marker, a space, "> ", and the text    let s: String = first.spans.iter().map(|sp| sp.content.clone()).collect();    assert_eq!(s, "1. > quoted");}#[test]fn blockquote_surrounded_by_blank_lines() {    let md = "foo\n\n> bar\n\nbaz\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(        lines,        vec![            "foo".to_string(),            "".to_string(),            "> bar".to_string(),            "".to_string(),            "baz".to_string(),        ]    );}#[test]fn blockquote_in_ordered_list_on_next_line() {    // Blockquote begins on a new line within an ordered list item; it should    // render inline on the same marker line.    let md = "1.\n   > quoted\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["1. > quoted".to_string()]);}#[test]fn blockquote_in_unordered_list_on_next_line() {    // Blockquote begins on a new line within an unordered list item; it should    // render inline on the same marker line.    let md = "-\n  > quoted\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["- > quoted".to_string()]);}#[test]fn blockquote_two_paragraphs_inside_ordered_list_has_blank_line() {    // Two blockquote paragraphs inside a list item should be separated by a blank line.    let md = "1.\n   > para 1\n   >\n   > para 2\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(        lines,        vec![            "1. > para 1".to_string(),            "   > ".to_string(),            "   > para 2".to_string(),        ],        "expected blockquote content to stay aligned after list marker"    );}#[test]fn blockquote_inside_nested_list() {    let md = "1. A\n    - B\n      > inner\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["1. A", "    - B", "      > inner"]);}#[test]fn list_item_text_then_blockquote() {    let md = "1. before\n   > quoted\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["1. before", "   > quoted"]);}#[test]fn list_item_blockquote_then_text() {    let md = "1.\n   > quoted\n   after\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["1. > quoted", "   > after"]);}#[test]fn list_item_text_blockquote_text() {    let md = "1. before\n   > quoted\n   after\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["1. before", "   > quoted", "   > after"]);}#[test]fn blockquote_with_heading_and_paragraph() {    let md = "> # Heading\n> paragraph text\n";    let text = render_markdown_text(md);    // Validate on content shape; styling is handled elsewhere    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(        lines,        vec![            "> # Heading".to_string(),            "> ".to_string(),            "> paragraph text".to_string(),        ]    );}#[test]fn blockquote_heading_inherits_heading_style() {    let text = render_markdown_text("> # test header\n> in blockquote\n");    assert_eq!(        text.lines,        [            Line::from_iter([                "> ".into(),                "# ".bold().underlined(),                "test header".bold().underlined(),            ])            .green(),            Line::from_iter(["> "]).green(),            Line::from_iter(["> ", "in blockquote"]).green(),        ]    );}#[test]fn blockquote_with_code_block() {    let md = "> ```\n> code\n> ```\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["> code".to_string()]);}#[test]fn blockquote_with_multiline_code_block() {    let md = "> ```\n> first\n> second\n> ```\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["> first", "> second"]);}#[test]fn nested_blockquote_with_inline_and_fenced_code() {    /*    let md = \"> Nested quote with code:\n\    > > Inner quote and `inline code`\n\    > >\n\    > > ```\n\    > > # fenced code inside a quote\n\    > > echo \"hello from a quote\"\n\    > > ```\n";    */    let md = r#"> Nested quote with code:> > Inner quote and `inline code`> >> > ```> > # fenced code inside a quote> > echo "hello from a quote"> > ```"#;    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(        lines,        vec![            "> Nested quote with code:".to_string(),            "> ".to_string(),            "> > Inner quote and inline code".to_string(),            "> > ".to_string(),            "> > # fenced code inside a quote".to_string(),            "> > echo \"hello from a quote\"".to_string(),        ]    );}#[test]fn list_unordered_single() {    let text = render_markdown_text("- List item 1\n");    let expected = Text::from_iter([Line::from_iter(["- ", "List item 1"])]);    assert_eq!(text, expected);}#[test]fn list_unordered_multiple() {    let text = render_markdown_text("- List item 1\n- List item 2\n");    let expected = Text::from_iter([        Line::from_iter(["- ", "List item 1"]),        Line::from_iter(["- ", "List item 2"]),    ]);    assert_eq!(text, expected);}#[test]fn list_ordered() {    let text = render_markdown_text("1. List item 1\n2. List item 2\n");    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "List item 1".into()]),        Line::from_iter(["2. ".light_blue(), "List item 2".into()]),    ]);    assert_eq!(text, expected);}#[test]fn list_nested() {    let text = render_markdown_text("- List item 1\n  - Nested list item 1\n");    let expected = Text::from_iter([        Line::from_iter(["- ", "List item 1"]),        Line::from_iter(["    - ", "Nested list item 1"]),    ]);    assert_eq!(text, expected);}#[test]fn list_ordered_custom_start() {    let text = render_markdown_text("3. First\n4. Second\n");    let expected = Text::from_iter([        Line::from_iter(["3. ".light_blue(), "First".into()]),        Line::from_iter(["4. ".light_blue(), "Second".into()]),    ]);    assert_eq!(text, expected);}#[test]fn nested_unordered_in_ordered() {    let md = "1. Outer\n    - Inner A\n    - Inner B\n2. Next\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "Outer".into()]),        Line::from_iter(["    - ", "Inner A"]),        Line::from_iter(["    - ", "Inner B"]),        Line::default(),        Line::from_iter(["2. ".light_blue(), "Next".into()]),    ]);    assert_eq!(text, expected);}#[test]fn nested_ordered_in_unordered() {    let md = "- Outer\n    1. One\n    2. Two\n- Last\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["- ", "Outer"]),        Line::from_iter(["    1. ".light_blue(), "One".into()]),        Line::from_iter(["    2. ".light_blue(), "Two".into()]),        Line::default(),        Line::from_iter(["- ", "Last"]),    ]);    assert_eq!(text, expected);}#[test]fn loose_list_item_multiple_paragraphs() {    let md = "1. First paragraph\n\n   Second paragraph of same item\n\n2. Next item\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "First paragraph".into()]),        Line::default(),        Line::from_iter(["   ", "Second paragraph of same item"]),        Line::default(),        Line::from_iter(["2. ".light_blue(), "Next item".into()]),    ]);    assert_eq!(text, expected);}#[test]fn tight_item_with_soft_break() {    let md = "- item line1\n  item line2\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["- ", "item line1"]),        Line::from_iter(["  ", "item line2"]),    ]);    assert_eq!(text, expected);}#[test]fn deeply_nested_mixed_three_levels() {    let md = "1. A\n    - B\n        1. C\n2. D\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "A".into()]),        Line::from_iter(["    - ", "B"]),        Line::from_iter(["        1. ".light_blue(), "C".into()]),        Line::default(),        Line::from_iter(["2. ".light_blue(), "D".into()]),    ]);    assert_eq!(text, expected);}#[test]fn loose_items_due_to_blank_line_between_items() {    let md = "1. First\n\n2. Second\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "First".into()]),        Line::from_iter(["2. ".light_blue(), "Second".into()]),    ]);    assert_eq!(text, expected);}#[test]fn mixed_tight_then_loose_in_one_list() {    let md = "1. Tight\n\n2.\n   Loose\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "Tight".into()]),        Line::from_iter(["2. ".light_blue(), "Loose".into()]),    ]);    assert_eq!(text, expected);}#[test]fn ordered_item_with_indented_continuation_is_tight() {    let md = "1. Foo\n   Bar\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "Foo".into()]),        Line::from_iter(["   ", "Bar"]),    ]);    assert_eq!(text, expected);}#[test]fn inline_code() {    let text = render_markdown_text("Example of `Inline code`");    let expected = Line::from_iter(["Example of ".into(), "Inline code".cyan()]).into();    assert_eq!(text, expected);}#[test]fn strong() {    assert_eq!(        render_markdown_text("**Strong**"),        Text::from(Line::from("Strong".bold()))    );}#[test]fn emphasis() {    assert_eq!(        render_markdown_text("*Emphasis*"),        Text::from(Line::from("Emphasis".italic()))    );}#[test]fn strikethrough() {    assert_eq!(        render_markdown_text("~~Strikethrough~~"),        Text::from(Line::from("Strikethrough".crossed_out()))    );}#[test]fn strong_emphasis() {    let text = render_markdown_text("**Strong *emphasis***");    let expected = Text::from(Line::from_iter([        "Strong ".bold(),        "emphasis".bold().italic(),    ]));    assert_eq!(text, expected);}#[test]fn link() {    let text = render_markdown_text("[Link](https://example.com)");    let expected = Text::from(Line::from_iter([        "Link".into(),        " (".into(),        "https://example.com".cyan().underlined(),        ")".into(),    ]));    assert_eq!(text, expected);}#[test]fn load_location_suffix_regexes() {    let _colon = &*COLON_LOCATION_SUFFIX_RE;    let _hash = &*HASH_LOCATION_SUFFIX_RE;}#[test]fn file_link_hides_destination() {    let text = render_markdown_text_for_cwd(        "[codex-rs/tui/src/markdown_render.rs](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs)",        Path::new("/Users/example/code/codex"),    );    let expected =        Text::from(Line::from_iter(["codex-rs/tui/src/markdown_render.rs".cyan()]));    assert_eq!(text, expected);}#[test]fn file_link_decodes_percent_encoded_bare_path_destination() {    let text = render_markdown_text_for_cwd(        "[report](/Users/example/code/codex/Example%20Folder/R%C3%A9sum%C3%A9/report.md)",        Path::new("/Users/example/code/codex"),    );    let expected = Text::from(Line::from_iter([        "Example Folder/Résumé/report.md".cyan(),    ]));    assert_eq!(text, expected);}#[test]fn file_link_appends_line_number_when_label_lacks_it() {    let text = render_markdown_text_for_cwd(        "[markdown_render.rs](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs:74)",        Path::new("/Users/example/code/codex"),    );    let expected = Text::from(Line::from_iter([        "codex-rs/tui/src/markdown_render.rs:74".cyan(),    ]));    assert_eq!(text, expected);}#[test]fn file_link_keeps_absolute_paths_outside_cwd() {    let text = render_markdown_text_for_cwd(        "[README.md:74](/Users/example/code/codex/README.md:74)",        Path::new("/Users/example/code/codex/codex-rs/tui"),    );    let expected = Text::from(Line::from_iter(["/Users/example/code/codex/README.md:74".cyan()]));    assert_eq!(text, expected);}#[test]fn file_link_appends_hash_anchor_when_label_lacks_it() {    let text = render_markdown_text_for_cwd(        "[markdown_render.rs](file:///Users/example/code/codex/codex-rs/tui/src/markdown_render.rs#L74C3)",        Path::new("/Users/example/code/codex"),    );    let expected =        Text::from(Line::from_iter([            "codex-rs/tui/src/markdown_render.rs:74:3".cyan(),        ]));    assert_eq!(text, expected);}#[test]fn file_link_uses_target_path_for_hash_anchor() {    let text = render_markdown_text_for_cwd(        "[markdown_render.rs#L74C3](file:///Users/example/code/codex/codex-rs/tui/src/markdown_render.rs#L74C3)",        Path::new("/Users/example/code/codex"),    );    let expected =        Text::from(Line::from_iter([            "codex-rs/tui/src/markdown_render.rs:74:3".cyan(),        ]));    assert_eq!(text, expected);}#[test]fn file_link_appends_range_when_label_lacks_it() {    let text = render_markdown_text_for_cwd(        "[markdown_render.rs](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs:74:3-76:9)",        Path::new("/Users/example/code/codex"),    );    let expected =        Text::from(Line::from_iter([            "codex-rs/tui/src/markdown_render.rs:74:3-76:9".cyan(),        ]));    assert_eq!(text, expected);}#[test]fn file_link_uses_target_path_for_range() {    let text = render_markdown_text_for_cwd(        "[markdown_render.rs:74:3-76:9](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs:74:3-76:9)",        Path::new("/Users/example/code/codex"),    );    let expected =        Text::from(Line::from_iter([            "codex-rs/tui/src/markdown_render.rs:74:3-76:9".cyan(),        ]));    assert_eq!(text, expected);}#[test]fn file_link_appends_hash_range_when_label_lacks_it() {    let text = render_markdown_text_for_cwd(        "[markdown_render.rs](file:///Users/example/code/codex/codex-rs/tui/src/markdown_render.rs#L74C3-L76C9)",        Path::new("/Users/example/code/codex"),    );    let expected =        Text::from(Line::from_iter([            "codex-rs/tui/src/markdown_render.rs:74:3-76:9".cyan(),        ]));    assert_eq!(text, expected);}#[test]fn multiline_file_link_label_after_styled_prefix_does_not_panic() {    let text = render_markdown_text_for_cwd(        "**bold** plain [foo\nbar](file:///Users/example/code/codex/codex-rs/tui/src/markdown_render.rs#L74C3)",        Path::new("/Users/example/code/codex"),    );    let expected = Text::from(Line::from_iter([        "bold".bold(),        " plain ".into(),        "codex-rs/tui/src/markdown_render.rs:74:3".cyan(),    ]));    assert_eq!(text, expected);}#[test]fn file_link_uses_target_path_for_hash_range() {    let text = render_markdown_text_for_cwd(        "[markdown_render.rs#L74C3-L76C9](file:///Users/example/code/codex/codex-rs/tui/src/markdown_render.rs#L74C3-L76C9)",        Path::new("/Users/example/code/codex"),    );    let expected =        Text::from(Line::from_iter([            "codex-rs/tui/src/markdown_render.rs:74:3-76:9".cyan(),        ]));    assert_eq!(text, expected);}#[test]fn url_link_shows_destination() {    let text = render_markdown_text("[docs](https://example.com/docs)");    let expected = Text::from(Line::from_iter([        "docs".into(),        " (".into(),        "https://example.com/docs".cyan().underlined(),        ")".into(),    ]));    assert_eq!(text, expected);}#[test]fn markdown_render_file_link_snapshot() {    let text = render_markdown_text_for_cwd(        "See [markdown_render.rs:74](/Users/example/code/codex/codex-rs/tui/src/markdown_render.rs:74).",        Path::new("/Users/example/code/codex"),    );    let rendered = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect::<Vec<_>>()        .join("\n");    assert_snapshot!(rendered);}#[test]fn unordered_list_local_file_link_stays_inline_with_following_text() {    let text = render_markdown_text_with_width_and_cwd(        "- [binary](/Users/example/code/codex/codex-rs/README.md:93): core is the agent/business logic, tui is the terminal UI, exec is the headless automation surface, and cli is the top-level multitool binary.",        Some(72),        Some(Path::new("/Users/example/code/codex")),    );    let rendered = text        .lines        .iter()        .map(|line| {            line.spans                .iter()                .map(|span| span.content.as_ref())                .collect::<String>()        })        .collect::<Vec<_>>();    assert_eq!(        rendered,        vec![            "- codex-rs/README.md:93: core is the agent/business logic, tui is the",            "  terminal UI, exec is the headless automation surface, and cli is the",            "  top-level multitool binary.",        ]    );}#[test]fn unordered_list_local_file_link_soft_break_before_colon_stays_inline() {    let text = render_markdown_text_with_width_and_cwd(        "- [binary](/Users/example/code/codex/codex-rs/README.md:93)\n  : core is the agent/business logic.",        Some(72),        Some(Path::new("/Users/example/code/codex")),    );    let rendered = text        .lines        .iter()        .map(|line| {            line.spans                .iter()                .map(|span| span.content.as_ref())                .collect::<String>()        })        .collect::<Vec<_>>();    assert_eq!(        rendered,        vec!["- codex-rs/README.md:93: core is the agent/business logic.",]    );}#[test]fn consecutive_unordered_list_local_file_links_do_not_detach_paths() {    let text = render_markdown_text_with_width_and_cwd(        "- [binary](/Users/example/code/codex/codex-rs/README.md:93)\n  : cli is the top-level multitool binary.\n- [expectations](/Users/example/code/codex/codex-rs/core/README.md:1)\n  : codex-core owns the real runtime behavior.",        Some(72),        Some(Path::new("/Users/example/code/codex")),    );    let rendered = text        .lines        .iter()        .map(|line| {            line.spans                .iter()                .map(|span| span.content.as_ref())                .collect::<String>()        })        .collect::<Vec<_>>();    assert_eq!(        rendered,        vec![            "- codex-rs/README.md:93: cli is the top-level multitool binary.",            "- codex-rs/core/README.md:1: codex-core owns the real runtime behavior.",        ]    );}#[test]fn code_block_known_lang_has_syntax_colors() {    let text = render_markdown_text("```rust\nfn main() {}\n```\n");    let content: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    // Content should be preserved; ignore trailing empty line from highlighting.    let content: Vec<&str> = content        .iter()        .map(std::string::String::as_str)        .filter(|s| !s.is_empty())        .collect();    assert_eq!(content, vec!["fn main() {}"]);    // At least one span should have non-default style (syntax highlighting).    let has_colored_span = text        .lines        .iter()        .flat_map(|l| l.spans.iter())        .any(|sp| sp.style.fg.is_some());    assert!(has_colored_span, "expected syntax-highlighted spans with color");}#[test]fn code_block_unknown_lang_plain() {    let text = render_markdown_text("```xyzlang\nhello world\n```\n");    let content: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    let content: Vec<&str> = content        .iter()        .map(std::string::String::as_str)        .filter(|s| !s.is_empty())        .collect();    assert_eq!(content, vec!["hello world"]);    // No syntax coloring for unknown language — all spans have default style.    let has_colored_span = text        .lines        .iter()        .flat_map(|l| l.spans.iter())        .any(|sp| sp.style.fg.is_some());    assert!(!has_colored_span, "expected no syntax coloring for unknown lang");}#[test]fn code_block_no_lang_plain() {    let text = render_markdown_text("```\nno lang specified\n```\n");    let content: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    let content: Vec<&str> = content        .iter()        .map(std::string::String::as_str)        .filter(|s| !s.is_empty())        .collect();    assert_eq!(content, vec!["no lang specified"]);}#[test]fn code_block_multiple_lines_root() {    let md = "```\nfirst\nsecond\n```\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["", "first"]),        Line::from_iter(["", "second"]),    ]);    assert_eq!(text, expected);}#[test]fn code_block_indented() {    let md = "    function greet() {\n      console.log(\"Hi\");\n    }\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["    ", "function greet() {"]),        Line::from_iter(["    ", "  console.log(\"Hi\");"]),        Line::from_iter(["    ", "}"]),    ]);    assert_eq!(text, expected);}#[test]fn horizontal_rule_renders_em_dashes() {    let md = "Before\n\n---\n\nAfter\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["Before", "", "———", "", "After"]);}#[test]fn code_block_with_inner_triple_backticks_outer_four() {    let md = r#"````textHere is a code block that shows another fenced block:```md# Inside fence- bullet- `inline code````````"#;    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    // Filter empty trailing lines for stability; the code block may or may    // not emit a trailing blank depending on the highlighting path.    let trimmed: Vec<&str> = {        let mut v: Vec<&str> = lines.iter().map(std::string::String::as_str).collect();        while v.last() == Some(&"") {            v.pop();        }        v    };    assert_eq!(        trimmed,        vec![            "Here is a code block that shows another fenced block:",            "",            "```md",            "# Inside fence",            "- bullet",            "- `inline code`",            "```",        ]    );}#[test]fn code_block_inside_unordered_list_item_is_indented() {    let md = "- Item\n\n  ```\n  code line\n  ```\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["- Item", "", "  code line"]);}#[test]fn code_block_multiple_lines_inside_unordered_list() {    let md = "- Item\n\n  ```\n  first\n  second\n  ```\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["- Item", "", "  first", "  second"]);}#[test]fn code_block_inside_unordered_list_item_multiple_lines() {    let md = "- Item\n\n  ```\n  first\n  second\n  ```\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(lines, vec!["- Item", "", "  first", "  second"]);}#[test]fn list_item_after_code_block_keeps_blank_separator() {    let md = "1. First:\n\n   ```rust\n   fn first() {}\n   ```\n\n2. Second:\n";    let text = render_markdown_text(md);    let lines = plain_lines(&text);    assert_eq!(        lines,        vec!["1. First:", "", "   fn first() {}", "", "2. Second:"]    );    assert_snapshot!(        "list_item_after_code_block_keeps_blank_separator",        lines.join("\n")    );}#[test]fn outer_list_item_after_nested_code_block_keeps_blank_separator() {    let md = "1. First:\n   - Nested:\n\n     ```rust\n     fn first() {}\n     ```\n\n2. Second:\n";    let text = render_markdown_text(md);    let lines = plain_lines(&text);    assert_eq!(        lines,        vec![            "1. First:",            "    - Nested:",            "",            "      fn first() {}",            "",            "2. Second:",        ]    );}#[test]fn list_item_after_simple_item_stays_compact() {    let md = "1. First\n\n2. Second\n";    let text = render_markdown_text(md);    assert_eq!(plain_lines(&text), vec!["1. First", "2. Second"]);}#[test]fn multiline_finding_items_are_separated_snapshot() {    let md = r#"**Findings**1. **Correctness issue: server tool-search completions are always rejected.**   In `next_prompt_suggestion.rs`, the output is ignored, suppressing suggestions after completed searches.   Minimal correction: count matching outputs and suppress only missing ones.2. **High-confidence simplification: remove the unused error channel.**   The implementation resolves failures to `None`, so its contract can be narrower.3. **High-confidence churn reduction: consolidate table-driven filter tests.**"#;    let text = render_markdown_text(md);    assert_snapshot!(plain_lines(&text).join("\n"));}#[test]fn wrapped_list_item_is_separated_from_next_sibling() {    let md = "1. This item wraps onto another visible rendered line\n2. Next item\n";    let text = render_markdown_text_with_width(md, Some(/*width*/ 24));    assert_eq!(        plain_lines(&text),        vec![            "1. This item wraps onto",            "   another visible",            "   rendered line",            "",            "2. Next item",        ]    );}#[test]fn mixed_url_markdown_wraps_prose_without_splitting_words_snapshot() {    let md = "This paragraph keeps **strikethrough** intact near a [link](https://example.com/path) while enough surrounding prose forces wrapping.";    let text = render_markdown_text_with_width(md, Some(/*width*/ 48));    assert_snapshot!(plain_lines(&text).join("\n"));}#[test]fn markdown_render_complex_snapshot() {    let md = r#"# H1: Markdown Streaming TestIntro paragraph with bold **text**, italic *text*, and inline code `x=1`.Combined bold-italic ***both*** and escaped asterisks \*literal\*.Auto-link: <https://example.com> and reference link [ref][r1].Link with title: [hover me](https://example.com "Example") and mailto <mailto:test@example.com>.Image: ![alt text](https://example.com/img.png "Title")> Blockquote level 1>> Blockquote level 2 with `inline code`- Unordered list item 1  - Nested bullet with italics _inner_- Unordered list item 2 with ~~strikethrough~~1. Ordered item one2. Ordered item two with sublist:   1) Alt-numbered subitem- [ ] Task: unchecked- [x] Task: checked with link [home](https://example.org)---Table below (alignment test):| Left | Center | Right ||:-----|:------:|------:|| a    |   b    |     c |Inline HTML: <sup>sup</sup> and <sub>sub</sub>.HTML block:<div style="border:1px solid #ccc;padding:2px">inline block</div>Escapes: \_underscores\_, backslash \\, ticks ``code with `backtick` inside``.Emoji shortcodes: :sparkles: :tada: (if supported).Hard break test (line ends with two spaces)  Next line should be close to previous.Footnote reference here[^1] and another[^longnote].Horizontal rule with asterisks:***Fenced code block (JSON):```json{ "a": 1, "b": [true, false] }```Fenced code with tildes and triple backticks inside:~~~markdownTo close ``` you need tildes.~~~Indented code block:    for i in range(3): print(i)Definition-like list:Term: Definition with `code`.Character entities: &amp; &lt; &gt; &quot; &#39;[^1]: This is the first footnote.[^longnote]: A longer footnote with a link to [Rust](https://www.rust-lang.org/).Escaped pipe in text: a \| b \| c.URL with parentheses: [link](https://example.com/path_(with)_parens).[r1]: https://example.com/ref "Reference link title""#;    let text = render_markdown_text(md);    // Convert to plain text lines for snapshot (ignore styles)    let rendered = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect::<Vec<_>>()        .join("\n");    assert_snapshot!(rendered);}#[test]fn ordered_item_with_code_block_and_nested_bullet() {    let md = "1. **item 1**\n\n2. **item 2**\n   ```\n   code\n   ```\n   - `PROCESS_START` (a `OnceLock<Instant>`) keeps the start time for the entire process.\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|line| {            line.spans                .iter()                .map(|span| span.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(        lines,        vec![            "1. item 1".to_string(),            "2. item 2".to_string(),            String::new(),            "   code".to_string(),            "    - PROCESS_START (a OnceLock<Instant>) keeps the start time for the entire process.".to_string(),        ]    );}#[test]fn nested_five_levels_mixed_lists() {    let md = "1. First\n   - Second level\n     1. Third level (ordered)\n        - Fourth level (bullet)\n          - Fifth level to test indent consistency\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "First".into()]),        Line::from_iter(["    - ", "Second level"]),        Line::from_iter(["        1. ".light_blue(), "Third level (ordered)".into()]),        Line::from_iter(["            - ", "Fourth level (bullet)"]),        Line::from_iter([            "                - ",            "Fifth level to test indent consistency",        ]),    ]);    assert_eq!(text, expected);}#[test]fn html_inline_is_verbatim() {    let md = "Hello <span>world</span>!";    let text = render_markdown_text(md);    let expected: Text = Line::from_iter(["Hello ", "<span>", "world", "</span>", "!"]).into();    assert_eq!(text, expected);}#[test]fn html_block_is_verbatim_multiline() {    let md = "<div>\n  <span>hi</span>\n</div>\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["<div>"]),        Line::from_iter(["  <span>hi</span>"]),        Line::from_iter(["</div>"]),    ]);    assert_eq!(text, expected);}#[test]fn html_in_tight_ordered_item_soft_breaks_with_space() {    let md = "1. Foo\n   <i>Bar</i>\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "Foo".into()]),        Line::from_iter(["   ", "<i>", "Bar", "</i>"]),    ]);    assert_eq!(text, expected);}#[test]fn html_continuation_paragraph_in_unordered_item_indented() {    let md = "- Item\n\n  <em>continued</em>\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["- ", "Item"]),        Line::default(),        Line::from_iter(["  ", "<em>", "continued", "</em>"]),    ]);    assert_eq!(text, expected);}#[test]fn unordered_item_continuation_paragraph_is_indented() {    let md = "- Intro\n\n  Continuation paragraph line 1\n  Continuation paragraph line 2\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|line| {            line.spans                .iter()                .map(|span| span.content.clone())                .collect::<String>()        })        .collect();    assert_eq!(        lines,        vec![            "- Intro".to_string(),            String::new(),            "  Continuation paragraph line 1".to_string(),            "  Continuation paragraph line 2".to_string(),        ]    );}#[test]fn ordered_item_continuation_paragraph_is_indented() {    let md = "1. Intro\n\n   More details about intro\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "Intro".into()]),        Line::default(),        Line::from_iter(["   ", "More details about intro"]),    ]);    assert_eq!(text, expected);}#[test]fn nested_item_continuation_paragraph_is_indented() {    let md = "1. A\n    - B\n\n      Continuation for B\n2. C\n";    let text = render_markdown_text(md);    let expected = Text::from_iter([        Line::from_iter(["1. ".light_blue(), "A".into()]),        Line::from_iter(["    - ", "B"]),        Line::default(),        Line::from_iter(["      ", "Continuation for B"]),        Line::default(),        Line::from_iter(["2. ".light_blue(), "C".into()]),    ]);    assert_eq!(text, expected);}#[test]fn code_block_preserves_trailing_blank_lines() {    // A fenced code block with an intentional trailing blank line must keep it.    let md = "```rust\nfn main() {}\n\n```\n";    let text = render_markdown_text(md);    let content: Vec<String> = text        .lines        .iter()        .map(|l| {            l.spans                .iter()                .map(|s| s.content.clone())                .collect::<String>()        })        .collect();    // Should have: "fn main() {}" then "" (the blank line).    // Filter only to content lines (skip leading/trailing empty from rendering).    assert!(        content.iter().any(|c| c == "fn main() {}"),        "expected code line, got {content:?}"    );    // The trailing blank line inside the fence should be preserved.    let code_start = content.iter().position(|c| c == "fn main() {}").unwrap();    assert!(        content.len() > code_start + 1,        "expected a line after 'fn main() {{}}' but content ends: {content:?}"    );    assert_eq!(        content[code_start + 1], "",        "trailing blank line inside code fence was lost: {content:?}"    );}#[test]fn table_renders_app_style_rows_with_themed_bold_header() {    let md = "| A | B |\n|---|---|\n| 1 | 2 |\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|line| line.spans.iter().map(|span| span.content.clone()).collect())        .collect();    assert_eq!(        lines,        vec![            " A      B".to_string(),            "━━━━━  ━━━━━".to_string(),            " 1      2".to_string(),        ]    );    assert!(        text.lines[0]            .style            .add_modifier            .contains(Modifier::BOLD)    );    assert!(        text.lines[0].style.fg.is_some(),        "expected the syntax theme to provide a table header accent"    );    assert!(        text.lines[1].spans[0]            .style            .add_modifier            .contains(Modifier::DIM)    );    assert!(        !text.lines[2]            .style            .add_modifier            .contains(Modifier::BOLD)    );}#[test]fn table_alignment_respects_markers() {    let md = "| Left | Center | Right |\n|:-----|:------:|------:|\n| a | b | c |\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|line| line.spans.iter().map(|span| span.content.clone()).collect())        .collect();    assert_eq!(lines[0], " Left    Center    Right");    assert_eq!(lines[2], " a         b           c");}#[test]fn table_separates_logical_rows_after_wrapped_content() {    let md = "| Key | Description |\n| --- | --- |\n| -v | Enable very verbose logging output for debugging |\n| -q | Quiet output |\n";    let text = crate::markdown_render::render_markdown_text_with_width(md, Some(30));    let lines: Vec<String> = text        .lines        .iter()        .map(|line| line.spans.iter().map(|span| span.content.clone()).collect())        .collect();    assert!(        lines            .iter()            .any(|line| line.contains("Enable very verbose"))            && lines.iter().any(|line| line.contains("logging output")),        "expected wrapped row content: {lines:?}"    );    let separator_indices: Vec<usize> = lines        .iter()        .enumerate()        .filter_map(|(idx, line)| {            ((line.contains('━') || line.contains('─'))                && line.chars().all(|ch| matches!(ch, '━' | '─' | ' ')))            .then_some(idx)        })        .collect();    let wrapped_row_end = lines        .iter()        .position(|line| line.contains("logging output"))        .expect("expected final wrapped line");    assert_eq!(separator_indices.len(), 2);    assert!(separator_indices[1] > wrapped_row_end);    assert!(        !lines            .last()            .is_some_and(|line| line.contains('━') || line.contains('─'))    );}#[test]fn table_wraps_file_paths_before_collapsing_narrative_columns_snapshot() {    let md = r#"| Unit | Files | Adds | Removes | What It Adds ||---|---:|---:|---:|---|| Suggestion engine and unit coverage | [next_prompt_suggestion.rs](/Users/example/code/codex/codex-rs/core/src/next_prompt_suggestion.rs:1), [next_prompt_suggestion_tests.rs](/Users/example/code/codex/codex-rs/core/src/next_prompt_suggestion_tests.rs:1) | 704 | 0 | Sampling workflow, stable-history checks, tool-flow suppression, fast reasoning profile, filtering rules, cancellation and timeout. || Model instruction fragment and contextual isolation | [next_prompt_suggestion.rs](/Users/example/code/codex/codex-rs/core/src/context/next_prompt_suggestion.rs:1), [contextual_user_message_tests.rs](/Users/example/code/codex/codex-rs/core/src/context/contextual_user_message_tests.rs:1) | 54 | 0 | Synthetic suggestion prompt and an isolation test for ordinary user text. |"#;    let text = render_markdown_text_with_width_and_cwd(        md,        Some(/*width*/ 120),        Some(Path::new("/Users/example/code/codex")),    );    assert_snapshot!(plain_lines(&text).join("\n"));}#[test]fn table_renders_stacked_key_value_records_when_path_column_becomes_too_narrow_snapshot() {    let md = r#"| Session | Why useful | Detected table blocks || --- | --- | --- || [2026-05-25 current gallery](/Users/felipe.coury/.codex/sessions/2026/05/25/rollout-2026-05-25T18-13-09-019e60fc-0518-7c21-9596-980fe97225ba.jsonl) | The large gallery from this thread: emojis, links, emphasis, code, alignment, paragraphs, and a 30+ row table | 7 || [2026-05-14 renderer testing](/Users/felipe.coury/.codex/sessions/2026/05/14/rollout-2026-05-14T12-57-18-019e2734-e500-7011-8278-975c94d06000.jsonl) | Explicit "markdown tables for testing" session with several successive assistant samples | 16 || [2026-05-14 five-table test](/Users/felipe.coury/.codex/sessions/2026/05/14/rollout-2026-05-14T12-27-57-019e271a-064c-78c3-a5cd-a6f20a0c1ad5.jsonl) | Explicit request for five tables containing emojis, code, italics, and varied cell content | 10 |"#;    let text = render_markdown_text_with_width(md, Some(/*width*/ 42));    assert_snapshot!(plain_lines(&text).join("\n"));}#[test]fn table_renders_records_when_multiple_prose_columns_are_starved_snapshot() {    let md = r#"| Issue | Activity | Complexity | Why start || --- | ---: | ---: | --- || [#24485: newline shortcut fails in PyCharm terminal on Windows](https://github.com/openai/codex/issues/24485) | `+1` 0, substantive comments 0 | Low | New, deterministic regression range; localized composer/keymap path. || [#23926: Vim composer `e` stalls at word end](https://github.com/openai/codex/issues/23926) | `+1` 0, comments 0 | Low | Standing best quick win; deterministic motion bug. || [#23651: Zellij scrollback misses Codex transcript over SSH](https://github.com/openai/codex/issues/23651) | `+1` 3, human comments 2 | Medium | Clear regression and strong scrollback evidence. || [#23740: raw ANSI/control sequences in Windows Terminal](https://github.com/openai/codex/issues/23740) | `+1` 7, human comments 7 | Medium | Highest activity; established Windows rendering regression family. || [#24527: typing lag increases with session length](https://github.com/openai/codex/issues/24527) | `+1` 0, substantive comments 0 | Medium | New TUI-visible performance report; needs profiling before implementation. |"#;    let text = render_markdown_text_with_width(md, Some(/*width*/ 76));    assert_snapshot!(plain_lines(&text).join("\n"));}#[test]fn table_keeps_grid_when_only_one_compact_record_fragments_snapshot() {    let md = r#"| Key | Date | State || --- | --- | --- || short | 2025-01-01 | Ready || verylongidentifier | 2025-02-02 | Ready || final | 2025-03-03 | Done |"#;    let text = render_markdown_text_with_width(md, Some(/*width*/ 40));    assert_snapshot!(plain_lines(&text).join("\n"));}#[test]fn table_renders_key_value_records_when_compact_fragmentation_is_systemic_snapshot() {    let md = r#"| Key | Notes || --- | --- || firstlongid | A readable explanatory sentence for this row. || secondlongid | Another readable explanatory sentence for this row. || short | A final readable explanatory sentence for this row. |"#;    let text = render_markdown_text_with_width(md, Some(/*width*/ 17));    assert_snapshot!(plain_lines(&text).join("\n"));}#[test]fn table_inside_blockquote_has_quote_prefix() {    let md = "> | A | B |\n> |---|---|\n> | 1 | 2 |\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|line| line.spans.iter().map(|span| span.content.clone()).collect())        .collect();    assert!(lines.iter().all(|line| line.starts_with("> ")));    assert!(lines.iter().any(|line| line.contains("━━━━━  ━━━━━")));}#[test]fn escaped_pipes_render_in_table_cells() {    let md = "| Col |\n| --- |\n| a \\| b |\n";    let text = render_markdown_text(md);    let lines: Vec<String> = text        .lines        .iter()        .map(|line| line.spans.iter().map(|span| span.content.clone()).collect())        .collect();    assert!(lines.iter().any(|line| line.contains("a | b")));}#[test]fn table_falls_back_to_key_value_records_if_grid_cannot_fit() {    let md = "| c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 |\n|---|---|---|---|---|---|---|---|---|---|\n| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n";    let text = crate::markdown_render::render_markdown_text_with_width(md, Some(/*width*/ 20));    let lines: Vec<String> = text        .lines        .iter()        .map(|line| line.spans.iter().map(|span| span.content.clone()).collect())        .collect();    assert!(lines.first().is_some_and(|line| line.contains("c1")));    assert!(lines.iter().any(|line| line.contains("c10") && line.contains("10")));    assert!(        !lines            .iter()            .any(|line| line.starts_with('|') || line.contains('━') || line.contains('─'))    );}#[test]fn table_key_value_fallback_preserves_rich_values_and_themed_labels() {    let md = "| Key | Content | Extra | More |\n|---|---|---|---|\n| item | [link](https://example.com) | **bold** | `code` |\n";    let text = crate::markdown_render::render_markdown_text_with_width(md, Some(/*width*/ 16));    let lines = plain_lines(&text);    assert!(lines.iter().any(|line| line.contains("Key")));    assert!(lines.iter().any(|line| line.contains("item")));    assert!(lines.iter().any(|line| line.contains("link")));    assert!(lines.iter().any(|line| line.contains("bold")));    assert!(lines.iter().any(|line| line.contains("code")));    assert!(        text.lines[0]            .spans            .iter()            .any(|span| span.content.contains("Key")                && span.style.add_modifier.contains(Modifier::BOLD)                && span.style.fg.is_some())    );    assert!(text.lines.iter().any(|line| {        line.spans            .iter()            .any(|span| span.style.add_modifier.contains(Modifier::UNDERLINED))    }));}