mdtablefix 0.6.1

`mdtablefix` unb0rks and reflows Markdown tables so that each column has a uniform width. When the `--wrap` option is used, it also wraps paragraphs and list items to 80 columns.
Documentation
//! Blockquote wrapping tests.

use rstest::rstest;

use super::{wrap_assertions::assert_wrapped_blockquote, *};

#[test]
fn test_wrap_blockquote() {
    let input = lines_vec![
        "> **Deprecated**: A :class:`WebSocketRouter` and its `add_route` API should be used to \
         instantiate resources.",
    ];
    let output = process_stream(&input);
    assert_eq!(
        output,
        lines_vec![
            "> **Deprecated**: A :class:`WebSocketRouter` and its `add_route` API should be",
            "> used to instantiate resources.",
        ]
    );
}

#[test]
fn test_wrap_blockquote_nested() {
    let input = lines_vec![concat!(
        "> > This nested quote contains enough text to require wrapping so that we ",
        "can verify multi-level handling."
    )];
    let output = process_stream(&input);
    assert_wrapped_blockquote(&output, "> > ", 2);
    let joined = output
        .iter()
        .map(|l| l.trim_start_matches("> > "))
        .collect::<Vec<_>>()
        .join(" ");
    assert_eq!(joined, input[0].trim_start_matches("> > "));
}

#[test]
fn test_wrap_blockquote_mixed_indentation() {
    let input = lines_vec![
        "> \t> \tThis blockquote uses both spaces and tabs in the prefix to test mixed \
         indentation handling.",
    ];
    let output = process_stream(&input);
    assert_wrapped_blockquote(&output, "> \t> \t", 2);
    let joined = output
        .iter()
        .map(|l| l.trim_start_matches("> \t> \t"))
        .collect::<Vec<_>>()
        .join(" ");
    assert_eq!(joined, input[0].trim_start_matches("> \t> \t"));
}

#[test]
fn test_wrap_blockquote_with_blank_lines() {
    let input = lines_vec![
        concat!(
            "> The first paragraph in this quote is deliberately long enough to wrap ",
            "across multiple lines so"
        ),
        "> demonstrate the behaviour.",
        ">",
        concat!(
            "> The second paragraph is also extended to trigger wrapping in order to ",
            "ensure blank lines"
        ),
        "> are preserved correctly.",
    ];
    let output = process_stream(&input);
    assert_eq!(output[3], ">");
    assert_wrapped_blockquote(&output[..3], "> ", 3);
    assert_wrapped_blockquote(&output[4..], "> ", 3);
}

#[test]
fn test_wrap_blockquote_extra_whitespace() {
    let input = lines_vec![
        ">    Extra spacing should not prevent correct wrapping of this quoted text that exceeds \
         the line width.",
    ];
    let output = process_stream(&input);
    assert_wrapped_blockquote(&output, ">    ", 2);
    let joined = output
        .iter()
        .map(|l| l.trim_start_matches(">    "))
        .collect::<Vec<_>>()
        .join(" ");
    assert_eq!(joined, input[0].trim_start_matches(">    "));
}

#[test]
fn test_wrap_blockquote_short() {
    let input = lines_vec!["> short"];
    let output = process_stream(&input);
    assert_eq!(output, input);
}

#[rstest]
#[case::spaced("> > ")]
#[case::compact(">>")]
fn nested_blockquote_fences_are_preserved(#[case] prefix: &str) {
    let input = lines_vec![
        format!("{prefix}```rust"),
        format!("{prefix}fn main() {{}}"),
        format!("{prefix}```"),
    ];

    assert_eq!(process_stream(&input), input);
}

#[test]
fn decreasing_depth_ends_a_nested_blockquote_fence() {
    let input = lines_vec![
        "> > ```rust",
        "> > let quoted = true;",
        concat!(
            "> This depth-one prose follows the implicitly closed nested fence and is long ",
            "enough to wrap."
        ),
    ];

    let output = process_stream(&input);

    assert_eq!(
        output,
        lines_vec![
            "> > ```rust",
            "> > let quoted = true;",
            "> This depth-one prose follows the implicitly closed nested fence and is long",
            "> enough to wrap.",
        ]
    );
    let emitted_prose = output[2..]
        .iter()
        .map(|line| line.strip_prefix("> ").expect("prose should remain quoted"))
        .collect::<Vec<_>>()
        .join(" ");
    let source_prose = input[2]
        .strip_prefix("> ")
        .expect("source prose should be quoted");
    assert_eq!(emitted_prose, source_prose);
}

#[test]
fn wraps_a_list_item_inside_a_blockquote() {
    let input = lines_vec![concat!(
        "> - This list item contains enough prose to wrap onto multiple lines while retaining ",
        "its compound prefix."
    )];

    let output = process_stream(&input);

    assert_eq!(
        output,
        lines_vec![
            "> - This list item contains enough prose to wrap onto multiple lines while",
            ">   retaining its compound prefix.",
        ]
    );
}

#[test]
fn wraps_an_ordered_list_inside_a_nested_blockquote() {
    let input = lines_vec![concat!(
        "> > 1. This ordered item contains enough prose to wrap while preserving both quote ",
        "levels on every continuation."
    )];

    let output = process_stream(&input);

    assert_eq!(
        output,
        lines_vec![
            "> > 1. This ordered item contains enough prose to wrap while preserving both",
            "> >    quote levels on every continuation.",
        ]
    );
}