diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94fb842f..8887cb1a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: restore-keys: | ${{ runner.os }}-cargo- - name: Format - run: cargo fmt --all -- --check + run: rustup component add rustfmt --toolchain nightly-2025-06-10 && cargo +nightly-2025-06-10 fmt --all -- --check - name: Lint run: cargo clippy --all-targets --all-features -- -D warnings - name: Test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 20e33d6c..84c06235 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,7 +79,7 @@ jobs: restore-keys: | ${{ runner.os }}-cargo- - name: Build release binary - run: cross build --release --target ${{ matrix.target }} + run: cross +stable build --release --target ${{ matrix.target }} - name: Prepare artifact run: | mkdir -p artifacts/${{ matrix.os }}-${{ matrix.arch }} diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..f7ad026b --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,14 @@ +unstable_features = true +comment_width = 100 +format_code_in_doc_comments = true +imports_granularity = "Crate" +imports_layout = "HorizontalVertical" +wrap_comments = true +group_imports = "StdExternalCrate" +use_try_shorthand = true +hex_literal_case = "Lower" +format_strings = true +format_macro_matchers = true +fn_single_line = true +condense_wildcard_suffixes = true +use_field_init_shorthand = true diff --git a/AGENTS.md b/AGENTS.md index a83b0918..c95e19f5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -94,10 +94,12 @@ This repository is written in Rust and uses Cargo for building and dependency management. Contributors should follow these best practices when working on the project: -- Run cargo fmt, cargo clippy -- -D warnings, and RUSTFLAGS="-D warnings" cargo - test before committing. +- Run `cargo +nightly-2025-06-10 fmt --all` after any change and before + committing. Follow this with `cargo clippy -- -D warnings` and + `RUSTFLAGS="-D warnings" cargo test`. - Clippy warnings MUST be disallowed. -- Fix any warnings emitted during tests in the code itself rather than silencing them. +- Fix any warnings emitted during tests in the code itself instead of silencing + them. - Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS. - Where a function has too many parameters, group related parameters in diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000..5f1b4070 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly-2025-06-10" +components = ["rustfmt", "clippy"] diff --git a/src/html.rs b/src/html.rs index dfc0fd4d..d1accdaf 100644 --- a/src/html.rs +++ b/src/html.rs @@ -6,11 +6,11 @@ //! are ignored. The resulting Markdown lines are passed to //! `reflow_table` to ensure consistent column widths. -use html5ever::driver::ParseOpts; -use html5ever::{parse_document, tendril::TendrilSink}; +use std::sync::LazyLock; + +use html5ever::{driver::ParseOpts, parse_document, tendril::TendrilSink}; use markup5ever_rcdom::{Handle, NodeData, RcDom}; use regex::Regex; -use std::sync::LazyLock; use crate::is_fence; @@ -71,10 +71,10 @@ fn collect_text(handle: &Handle, out: &mut String, last_space: &mut bool) { /// Walks the DOM tree collecting `` nodes under `handle`. fn collect_tables(handle: &Handle, tables: &mut Vec) { - if let NodeData::Element { name, .. } = &handle.data { - if name.local.as_ref() == "table" { - tables.push(handle.clone()); - } + if let NodeData::Element { name, .. } = &handle.data + && name.local.as_ref() == "table" + { + tables.push(handle.clone()); } for child in handle.children.borrow().iter() { collect_tables(child, tables); @@ -83,10 +83,10 @@ fn collect_tables(handle: &Handle, tables: &mut Vec) { /// Collects all `` nodes beneath `handle`. fn collect_rows(handle: &Handle, rows: &mut Vec) { - if let NodeData::Element { name, .. } = &handle.data { - if name.local.as_ref() == "tr" { - rows.push(handle.clone()); - } + if let NodeData::Element { name, .. } = &handle.data + && name.local.as_ref() == "tr" + { + rows.push(handle.clone()); } for child in handle.children.borrow().iter() { collect_rows(child, rows); @@ -121,16 +121,16 @@ fn table_node_to_markdown(table: &Handle) -> Vec { let mut cells = Vec::new(); let mut all_header = true; for child in row.children.borrow().iter() { - if let NodeData::Element { name, .. } = &child.data { - if name.local.as_ref() == "td" || name.local.as_ref() == "th" { - let is_header = if name.local.as_ref() == "th" { - true - } else { - contains_strong(child) - }; - all_header &= is_header; - cells.push(node_text(child)); - } + if let NodeData::Element { name, .. } = &child.data + && (name.local.as_ref() == "td" || name.local.as_ref() == "th") + { + let is_header = if name.local.as_ref() == "th" { + true + } else { + contains_strong(child) + }; + all_header &= is_header; + cells.push(node_text(child)); } } if i == 0 { @@ -178,9 +178,12 @@ fn table_lines_to_markdown(lines: &[String]) -> Vec { } /// Buffers a single line of HTML, updating nesting depth and emitting completed -/// Buffers a line of HTML table markup and processes the buffer into Markdown when the table is fully closed. +/// Buffers a line of HTML table markup and processes the buffer into Markdown when the table is +/// fully closed. /// -/// Tracks the nesting depth of `
` tags, appending each line to the buffer. When all opened tables are closed (depth reaches zero), converts the buffered HTML table lines to Markdown and appends them to the output vector. Resets the buffer and updates the HTML state accordingly. +/// Tracks the nesting depth of `
` tags, appending each line to the buffer. When all opened +/// tables are closed (depth reaches zero), converts the buffered HTML table lines to Markdown and +/// appends them to the output vector. Resets the buffer and updates the HTML state accordingly. fn push_html_line( line: &str, buf: &mut Vec, @@ -202,7 +205,9 @@ fn push_html_line( /// Replaces HTML tables in the provided lines with equivalent Markdown table syntax. /// -/// Scans the input lines for HTML `
` blocks, converts each detected table to Markdown using `table_lines_to_markdown`, and preserves all other content unchanged. Handles nested tables and maintains original line formatting outside of tables. +/// Scans the input lines for HTML `
` blocks, converts each detected table to Markdown using +/// `table_lines_to_markdown`, and preserves all other content unchanged. Handles nested tables and +/// maintains original line formatting outside of tables. /// /// # Arguments /// @@ -216,9 +221,8 @@ fn push_html_line( /// /// ```no_run /// use mdtablefix::html_table_to_markdown; -/// let html_lines = vec![ -/// "
Header
Cell
".to_string() -/// ]; +/// let html_lines = +/// vec!["
Header
Cell
".to_string()]; /// let md_lines = html_table_to_markdown(&html_lines); /// assert!(md_lines[0].starts_with("| Header |")); /// ``` @@ -258,7 +262,9 @@ pub(crate) fn html_table_to_markdown(lines: &[String]) -> Vec { #[must_use] /// Converts HTML tables embedded in Markdown lines to Markdown table syntax. /// -/// Scans the input lines, detects HTML table blocks outside of fenced code blocks, and replaces them with equivalent Markdown tables. Fenced code blocks are left unmodified. Handles nested tables and preserves original line formatting outside of tables. +/// Scans the input lines, detects HTML table blocks outside of fenced code blocks, and replaces +/// them with equivalent Markdown tables. Fenced code blocks are left unmodified. Handles nested +/// tables and preserves original line formatting outside of tables. /// /// # Examples /// diff --git a/src/lib.rs b/src/lib.rs index d008d632..d1ee0ece 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,16 +13,16 @@ pub fn html_table_to_markdown(lines: &[String]) -> Vec { html::html_table_to_markdown(lines) } -pub use html::convert_html_tables; +use std::{fs, path::Path}; +pub use html::convert_html_tables; use regex::Regex; -use std::fs; -use std::path::Path; use textwrap::fill; /// Splits a markdown table line into trimmed cell strings. /// -/// Removes leading and trailing pipe characters, splits the line by pipes, trims whitespace from each cell, and returns the resulting cell strings as a vector. +/// Removes leading and trailing pipe characters, splits the line by pipes, trims whitespace from +/// each cell, and returns the resulting cell strings as a vector. /// /// # Examples /// @@ -47,13 +47,13 @@ pub fn split_cells(line: &str) -> Vec { let mut chars = s.chars().peekable(); while let Some(ch) = chars.next() { if ch == '\\' { - if let Some(&next) = chars.peek() { - if next == '|' { - // `\|` escapes the pipe so it becomes part of the cell - chars.next(); - current.push('|'); - continue; - } + if let Some(&next) = chars.peek() + && next == '|' + { + // `\|` escapes the pipe so it becomes part of the cell + chars.next(); + current.push('|'); + continue; } current.push(ch); continue; @@ -105,21 +105,20 @@ fn format_separator_cells(widths: &[usize], sep_cells: &[String]) -> Vec /// Panics if the internal regex fails to compile. /// Reflows a broken markdown table into properly aligned rows and columns. /// -/// Takes a slice of strings representing lines of a markdown table, reconstructs the table by splitting and aligning cells, and returns the reflowed table as a vector of strings. If the rows have inconsistent numbers of non-empty columns, the original lines are returned unchanged. +/// Takes a slice of strings representing lines of a markdown table, reconstructs the table by +/// splitting and aligning cells, and returns the reflowed table as a vector of strings. If the rows +/// have inconsistent numbers of non-empty columns, the original lines are returned unchanged. /// /// # Examples /// /// ```no_run /// use mdtablefix::reflow_table; -/// let lines = vec![ -/// "| a | b |".to_string(), -/// "| c | d |".to_string(), -/// ]; +/// let lines = vec!["| a | b |".to_string(), "| c | d |".to_string()]; /// let fixed = reflow_table(&lines); -/// assert_eq!(fixed, vec![ -/// "| a | b |".to_string(), -/// "| c | d |".to_string(), -/// ]); +/// assert_eq!( +/// fixed, +/// vec!["| a | b |".to_string(), "| c | d |".to_string(),] +/// ); /// ``` pub(crate) static SEP_RE: std::sync::LazyLock = std::sync::LazyLock::new(|| Regex::new(r"^[\s|:-]+$").unwrap()); @@ -150,20 +149,18 @@ pub fn reflow_table(lines: &[String]) -> Vec { let cleaned = reflow::clean_rows(rows); let mut output_rows = cleaned.clone(); - if let Some(idx) = sep_row_idx { - if idx < output_rows.len() { - output_rows.remove(idx); - } + if let Some(idx) = sep_row_idx + && idx < output_rows.len() + { + output_rows.remove(idx); } - if !split_within_line { - if let Some(first_len) = cleaned.first().map(Vec::len) { - let mismatch = cleaned[1..] - .iter() - .any(|row| row.len() != first_len && !row.iter().all(|c| SEP_RE.is_match(c))); - if mismatch { - return lines.to_vec(); - } + if !split_within_line && let Some(first_len) = cleaned.first().map(Vec::len) { + let mismatch = cleaned[1..] + .iter() + .any(|row| row.len() != first_len && !row.iter().all(|c| SEP_RE.is_match(c))); + if mismatch { + return lines.to_vec(); } } @@ -174,9 +171,12 @@ pub fn reflow_table(lines: &[String]) -> Vec { reflow::insert_separator(out, sep_cells, &widths, &indent) } -/// Processes a stream of markdown lines, reflowing tables while preserving code blocks and other content. +/// Processes a stream of markdown lines, reflowing tables while preserving code blocks and other +/// content. /// -/// Detects fenced code blocks and avoids modifying their contents. Buffers lines that appear to be part of a markdown table and reflows them when the table ends. Non-table lines and code blocks are output unchanged. +/// Detects fenced code blocks and avoids modifying their contents. Buffers lines that appear to be +/// part of a markdown table and reflows them when the table ends. Non-table lines and code blocks +/// are output unchanged. /// /// # Returns /// @@ -221,13 +221,15 @@ static BULLET_RE: std::sync::LazyLock = /// assert!(!is_fence("| foo | bar |")); /// ``` #[doc(hidden)] -pub fn is_fence(line: &str) -> bool { - FENCE_RE.is_match(line) -} +pub fn is_fence(line: &str) -> bool { FENCE_RE.is_match(line) } -/// Flushes a buffered paragraph to the output, wrapping text to the specified width and applying indentation. +/// Flushes a buffered paragraph to the output, wrapping text to the specified width and applying +/// indentation. /// -/// Concatenates buffered lines into a single paragraph, respecting hard line breaks, and writes the wrapped lines to the output vector with the given indentation. Lines are wrapped to the specified width minus the indentation length. Hard breaks in the buffer force a line break at that point. +/// Concatenates buffered lines into a single paragraph, respecting hard line breaks, and writes the +/// wrapped lines to the output vector with the given indentation. Lines are wrapped to the +/// specified width minus the indentation length. Hard breaks in the buffer force a line break at +/// that point. fn flush_paragraph(out: &mut Vec, buf: &[(String, bool)], indent: &str, width: usize) { if buf.is_empty() { return; @@ -254,7 +256,9 @@ fn flush_paragraph(out: &mut Vec, buf: &[(String, bool)], indent: &str, /// Wraps text lines to a specified width, preserving markdown structure. /// -/// Paragraphs and list items are reflowed to the given width, while code blocks, tables, headers, and blank lines are left unchanged. Indentation and bullet/numbered list prefixes are preserved. Hard line breaks (two spaces or `
` tags) are respected. +/// Paragraphs and list items are reflowed to the given width, while code blocks, tables, headers, +/// and blank lines are left unchanged. Indentation and bullet/numbered list prefixes are preserved. +/// Hard line breaks (two spaces or `
` tags) are respected. /// /// # Parameters /// - `lines`: The input lines of markdown text. @@ -370,9 +374,12 @@ pub fn wrap_text(lines: &[String], width: usize) -> Vec { } #[must_use] -/// Processes a stream of markdown lines, converting HTML tables, reflowing markdown tables, and wrapping text to 80 columns. +/// Processes a stream of markdown lines, converting HTML tables, reflowing markdown tables, and +/// wrapping text to 80 columns. /// -/// Converts simple HTML tables to markdown, reflows markdown tables for consistent alignment, and wraps paragraphs and list items to 80 characters. Preserves code blocks, headers, and special markdown structures. +/// Converts simple HTML tables to markdown, reflows markdown tables for consistent alignment, and +/// wraps paragraphs and list items to 80 characters. Preserves code blocks, headers, and special +/// markdown structures. /// /// # Returns /// @@ -388,7 +395,9 @@ pub fn wrap_text(lines: &[String], width: usize) -> Vec { /// "|---|---|".to_string(), /// "| 1 | 2 |".to_string(), /// "".to_string(), -/// "A paragraph that will be wrapped to fit within eighty columns. This sentence is intentionally long to demonstrate wrapping.".to_string(), +/// "A paragraph that will be wrapped to fit within eighty columns. This sentence is \ +/// intentionally long to demonstrate wrapping." +/// .to_string(), /// ]; /// let output = process_stream(&input); /// assert!(output.iter().any(|line| line.contains("| foo | bar |"))); @@ -460,9 +469,7 @@ fn process_stream_inner(lines: &[String], wrap: bool) -> Vec { } #[must_use] -pub fn process_stream(lines: &[String]) -> Vec { - process_stream_inner(lines, true) -} +pub fn process_stream(lines: &[String]) -> Vec { process_stream_inner(lines, true) } #[must_use] pub fn process_stream_no_wrap(lines: &[String]) -> Vec { @@ -472,7 +479,8 @@ pub fn process_stream_no_wrap(lines: &[String]) -> Vec { /// Rewrite a file in place with fixed tables. /// /// # Errors -/// Reads a markdown file, reflows any broken tables within it, and writes the updated content back to the same file. +/// Reads a markdown file, reflows any broken tables within it, and writes the updated content back +/// to the same file. /// /// Returns an error if the file cannot be read or written. /// @@ -480,6 +488,7 @@ pub fn process_stream_no_wrap(lines: &[String]) -> Vec { /// /// ```no_run /// use std::path::Path; +/// /// use mdtablefix::rewrite; /// let path = Path::new("example.md"); /// rewrite(path).unwrap(); diff --git a/src/main.rs b/src/main.rs index fb489c14..478e158a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,11 @@ +use std::{ + fs, + io::{self, Read}, + path::{Path, PathBuf}, +}; + use clap::Parser; use mdtablefix::{process_stream, process_stream_no_wrap, rewrite, rewrite_no_wrap}; -use std::fs; -use std::io::{self, Read}; -use std::path::{Path, PathBuf}; #[derive(Parser)] #[command(about = "Reflow broken markdown tables")] @@ -35,11 +38,14 @@ fn rewrite_path(path: &Path, wrap: bool) -> std::io::Result<()> { /// Entry point for the command-line tool that reflows broken markdown tables. /// -/// Parses command-line arguments to determine whether to process files in place, print fixed output to standard output, or read from standard input. Handles file I/O and error propagation as needed. +/// Parses command-line arguments to determine whether to process files in place, print fixed output +/// to standard output, or read from standard input. Handles file I/O and error propagation as +/// needed. /// /// # Returns /// -/// Returns `Ok(())` if all operations complete successfully; otherwise, returns an error if argument validation or file processing fails. +/// Returns `Ok(())` if all operations complete successfully; otherwise, returns an error if +/// argument validation or file processing fails. /// /// # Examples /// diff --git a/src/reflow.rs b/src/reflow.rs index 46abdcfe..f24e419e 100644 --- a/src/reflow.rs +++ b/src/reflow.rs @@ -3,9 +3,10 @@ // These small utilities break down the steps of `reflow_table` so each // piece can be understood and tested independently. -use crate::{format_separator_cells, split_cells}; use regex::Regex; +use crate::{format_separator_cells, split_cells}; + static SENTINEL_RE: std::sync::LazyLock = std::sync::LazyLock::new(|| Regex::new(r"\|\s*\|\s*").unwrap()); diff --git a/tests/integration.rs b/tests/integration.rs index 3d4fe47d..08e0d4e5 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,8 +1,8 @@ +use std::{fs::File, io::Write}; + use assert_cmd::Command; use mdtablefix::{convert_html_tables, process_stream, reflow_table}; use rstest::{fixture, rstest}; -use std::fs::File; -use std::io::Write; use tempfile::tempdir; #[macro_use] @@ -11,7 +11,8 @@ mod common; #[fixture] /// Provides a sample Markdown table with broken rows for testing purposes. /// -/// The returned vector contains lines representing a table with inconsistent columns, useful for validating table reflow logic. +/// The returned vector contains lines representing a table with inconsistent columns, useful for +/// validating table reflow logic. /// /// # Examples /// @@ -20,22 +21,28 @@ mod common; /// assert_eq!(table[0], "| A | B | |"); /// ``` fn broken_table() -> Vec { - lines_vec!("| A | B | |", "| 1 | 2 | | 3 | 4 |",) + let lines = lines_vec!("| A | B | |", "| 1 | 2 | | 3 | 4 |",); + lines } #[fixture] /// Returns a vector of strings representing a malformed Markdown table with inconsistent columns. /// -/// The returned table has rows with differing numbers of columns, making it invalid for standard Markdown table parsing. +/// The returned table has rows with differing numbers of columns, making it invalid for standard +/// Markdown table parsing. /// /// # Examples /// /// ``` /// let table = malformed_table(); -/// assert_eq!(table, vec![String::from("| A | |"), String::from("| 1 | 2 | 3 |")]); +/// assert_eq!( +/// table, +/// vec![String::from("| A | |"), String::from("| 1 | 2 | 3 |")] +/// ); /// ``` fn malformed_table() -> Vec { - lines_vec!("| A | |", "| 1 | 2 | 3 |") + let lines = lines_vec!("| A | |", "| 1 | 2 | 3 |"); + lines } #[fixture] @@ -50,7 +57,8 @@ fn escaped_pipe_table() -> Vec { #[fixture] fn indented_table() -> Vec { - lines_vec!(" | I | J | |", " | 1 | 2 | | 3 | 4 |",) + let lines = lines_vec!(" | I | J | |", " | 1 | 2 | | 3 | 4 |",); + lines } #[fixture] @@ -95,12 +103,14 @@ fn html_table_no_header() -> Vec { #[fixture] fn html_table_empty() -> Vec { - lines_vec!("
") + let lines = lines_vec!("
"); + lines } #[fixture] fn html_table_unclosed() -> Vec { - lines_vec!("", "") + let lines = lines_vec!("
1
", ""); + lines } #[fixture] @@ -129,12 +139,17 @@ fn multiple_tables() -> Vec { } #[rstest] -/// Tests that `reflow_table` correctly restructures a broken Markdown table into a well-formed table. +/// Tests that `reflow_table` correctly restructures a broken Markdown table into a well-formed +/// table. /// /// # Examples /// /// ``` -/// let broken = vec![String::from("| A | B |"), String::from("| 1 | 2 |"), String::from("| 3 | 4 |")]; +/// let broken = vec![ +/// String::from("| A | B |"), +/// String::from("| 1 | 2 |"), +/// String::from("| 3 | 4 |"), +/// ]; /// let expected = vec!["| A | B |", "| 1 | 2 |", "| 3 | 4 |"]; /// assert_eq!(reflow_table(&broken), expected); /// ``` @@ -144,9 +159,11 @@ fn test_reflow_basic(broken_table: Vec) { } #[rstest] -/// Tests that `reflow_table` returns the original input unchanged when given a malformed Markdown table. +/// Tests that `reflow_table` returns the original input unchanged when given a malformed Markdown +/// table. /// -/// This ensures that the function does not attempt to modify tables with inconsistent columns or structure. +/// This ensures that the function does not attempt to modify tables with inconsistent columns or +/// structure. fn test_reflow_malformed_returns_original(malformed_table: Vec) { assert_eq!(reflow_table(&malformed_table), malformed_table); } @@ -211,7 +228,8 @@ fn test_process_stream_multiple_tables(multiple_tables: Vec) { /// Tests that `process_stream` leaves lines inside code fences unchanged. /// -/// Verifies that both backtick (```) and tilde (~~~) fenced code blocks are ignored by the table processing logic, ensuring their contents are not altered. +/// Verifies that both backtick (```) and tilde (~~~) fenced code blocks are ignored by the table +/// processing logic, ensuring their contents are not altered. #[rstest] fn test_process_stream_ignores_code_fences() { let lines = lines_vec!("```rust", "| not | a | table |", "```"); @@ -225,7 +243,8 @@ fn test_process_stream_ignores_code_fences() { #[rstest] /// Verifies that the CLI fails when the `--in-place` flag is used without specifying a file. /// -/// This test ensures that running `mdtablefix --in-place` without a file argument results in a command failure. +/// This test ensures that running `mdtablefix --in-place` without a file argument results in a +/// command failure. /// /// # Examples /// @@ -242,9 +261,11 @@ fn test_cli_in_place_requires_file() { } #[rstest] -/// Tests that the CLI processes a file containing a broken Markdown table and outputs the corrected table to stdout. +/// Tests that the CLI processes a file containing a broken Markdown table and outputs the corrected +/// table to stdout. /// -/// This test creates a temporary file with a malformed table, runs the `mdtablefix` binary on it, and asserts that the output is the expected fixed table. +/// This test creates a temporary file with a malformed table, runs the `mdtablefix` binary on it, +/// and asserts that the output is the expected fixed table. /// /// # Examples /// @@ -275,9 +296,9 @@ fn test_cli_process_file(broken_table: Vec) { #[test] fn test_cli_wrap_option() { - let input = "This line is deliberately made much longer than eighty columns so that \ - the wrapping algorithm is forced to insert a soft line-break somewhere \ - in the middle of the paragraph when the --wrap flag is supplied."; + let input = "This line is deliberately made much longer than eighty columns so that the \ + wrapping algorithm is forced to insert a soft line-break somewhere in the middle \ + of the paragraph when the --wrap flag is supplied."; let output = Command::cargo_bin("mdtablefix") .unwrap() .arg("--wrap") @@ -521,7 +542,8 @@ fn test_offset_table_output_matches() { } #[test] -/// Tests that `process_stream` correctly processes a complex Markdown table representing logical types by comparing its output to expected results loaded from a file. +/// Tests that `process_stream` correctly processes a complex Markdown table representing logical +/// types by comparing its output to expected results loaded from a file. fn test_process_stream_logical_type_table() { let input: Vec = include_str!("data/logical_type_input.txt") .lines() @@ -535,14 +557,16 @@ fn test_process_stream_logical_type_table() { } #[test] -/// Tests that `process_stream` correctly processes a Markdown table with options, producing the expected output. +/// Tests that `process_stream` correctly processes a Markdown table with options, producing the +/// expected output. /// -/// Loads input and expected output from test data files, runs `process_stream` on the input, and asserts equality. +/// Loads input and expected output from test data files, runs `process_stream` on the input, and +/// asserts equality. /// /// # Examples /// /// ``` -/// test_process_stream_option_table(); +/// test_process_stream_option_table(); /// ``` fn test_process_stream_option_table() { let input: Vec = include_str!("data/option_table_input.txt") @@ -559,11 +583,12 @@ fn test_process_stream_option_table() { #[test] /// Tests that long paragraphs are wrapped at 80 columns by `process_stream`. /// -/// Ensures that a single long paragraph is split into multiple lines, each not exceeding 80 characters. +/// Ensures that a single long paragraph is split into multiple lines, each not exceeding 80 +/// characters. fn test_wrap_paragraph() { let input = vec![ - "This is a very long paragraph that should be wrapped at eighty columns \ - so it needs to contain enough words to exceed that limit." + "This is a very long paragraph that should be wrapped at eighty columns so it needs to \ + contain enough words to exceed that limit." .to_string(), ]; let output = process_stream(&input); @@ -609,7 +634,8 @@ fn test_wrap_short_list_item() { #[test] /// Tests that lines with hard line breaks (trailing spaces) are preserved after processing. /// -/// Ensures that the `process_stream` function does not remove or alter lines ending with Markdown hard line breaks. +/// Ensures that the `process_stream` function does not remove or alter lines ending with Markdown +/// hard line breaks. fn test_preserve_hard_line_breaks() { let input = vec![ "Line one with break. ".to_string(),
1