Skip to content

Address review feedback for wrapping and footnotes - #266

Merged
leynos merged 23 commits into
mainfrom
feedback-following-code-fmt
Jun 1, 2026
Merged

Address review feedback for wrapping and footnotes#266
leynos merged 23 commits into
mainfrom
feedback-following-code-fmt

Conversation

@leynos

@leynos leynos commented Apr 18, 2026

Copy link
Copy Markdown
Owner

Centralize mutable state in the list, HTML-table, footnote, and paragraph-wrapping flows so the behaviour is easier to reason about from one place.

Fix the cargo-binstall Linux override, remove production expect usage from the reviewed paths, normalize whitespace-only wrapped lines, and add regression tests for mixed code-emphasis affixes, Unicode-width indentation, and indented multi-line HTML tables.

Summary by Sourcery

Centralize mutable state across paragraph wrapping, footnote renumbering, list renumbering, and HTML table conversion to simplify control flow and improve robustness.

Bug Fixes:

  • Fix cargo-binstall Linux override configuration to install binaries from the current directory.
  • Normalize whitespace-only wrapped lines to emit consistent empty lines.
  • Use Unicode display width when wrapping indented lines so full-width characters are handled correctly.
  • Ensure HTML table conversion correctly handles indented multi-line HTML tables.
  • Fix mixed code/emphasis affix handling so pending prefixes are cleared correctly in edge cases.

Enhancements:

  • Refactor paragraph wrapping to encapsulate buffer and indentation handling inside ParagraphWriter.
  • Refactor footnote renumbering to consolidate scan and numeric candidate state into a single DefinitionScanState struct.
  • Refactor list renumbering state management with helper methods for resetting and computing next list numbers.
  • Refactor HTML table parsing to manage buffer and depth via HtmlTableState and reuse it across conversion paths.
  • Introduce a SplitContext::new constructor to simplify split context creation in wrapping code and tests.

Build:

  • Adjust cargo-binstall Linux override to point bin-dir at the current directory instead of the binary path.

Tests:

  • Add regression tests for whitespace-only line normalization in wrapping.
  • Add regression tests for Unicode-width indentation handling in wrapping.
  • Add regression tests for mixed code/emphasis affix handling.
  • Add regression tests for indented multi-line HTML table conversion.

@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9f0b68ed-367c-4132-8f51-c206827aa4f3

📥 Commits

Reviewing files that changed from the base of the PR and between bb88c80 and 1874003.

📒 Files selected for processing (6)
  • src/footnotes/renumber/definitions.rs
  • src/footnotes/renumber/definitions/tests.rs
  • src/html.rs
  • src/html_tests.rs
  • src/lists.rs
  • src/wrap/paragraph.rs

Summary

This pull request implements reviewer feedback by centralising mutable state across wrapping, footnote renumbering, ordered-list renumbering and HTML-table conversion, hardening error handling, normalising corner-case whitespace, and adding broad test and documentation coverage.

Key changes

  • New and centralised stateful helpers

    • ParagraphWriter: paragraph buffering, wrap continuation handling and prefix repetition semantics.
    • HtmlTableState: buffers HTML …
      blocks, tracks nested depth, converts only at the outermost close, and flushes verbatim on incomplete input.
    • definitions (footnotes::renumber::definitions): DefinitionScanState-style helpers implemented in src/footnotes/renumber/definitions.rs to parse definition headers, collect numeric candidates, assign new numbers and reorder definition blocks.
    • ListState: indent stack and per-indent counters with pruning and ListState::next_number(indent) for centralised ordered-list renumbering.
    • Behavioural fixes and hardening

      • Normalise whitespace-only wrapped lines to empty strings so they act as paragraph boundaries rather than producing whitespace artefacts.
      • Compute continuation-line indentation using Unicode display width (UnicodeWidthStr::width) so full‑width prefix characters align visually.
      • Correctly convert indented, multi-line HTML tables while leaving surrounding indented non-table content unchanged; support nested tables by depth-tracking to avoid premature flush.
      • Fix mixed code/emphasis affix handling so pending-prefix state is cleared correctly; remove production panics (expect/unwrap) in reviewed paths and return fallible results where captures may be missing.
      • Add bounds guards (saturating arithmetic and range checks) and avoid unsafe indexing in numeric-candidate extraction; numeric capture helpers return Option rather than panicking.
      • Emit tracing::warn when definition-block reordering is skipped due to segment-count mismatch.
      • Fix Cargo bin-dir override for Linux in package.metadata.binstall to use "." (archive current directory) for GNU x86_64/aarch64.
    • Refactor and API surface

      • Move the footnote-definition pipeline into a new submodule (src/footnotes/renumber/definitions.rs) exposing explicit internal types and helpers: DefinitionLine, NumericCandidate, DefinitionUpdates, numeric_candidate_from_line, collect_definition_updates, rewrite_definition_headers, reorder_definition_block.
      • Replace ad‑hoc in_html boolean with HtmlTableState { buf, depth } and provide flush_raw for deterministic buffering/flush semantics.
      • Keep PrefixLine.prefix as Cow<'a, str'> (intentional design decision) to avoid added complexity.
    • Tests, property tests and docs

      • Extensive new unit, regression and proptest coverage: paragraph wrapping (ParagraphWriter), ListState, HtmlTableState, footnote renumbering and inline postprocess helpers.
      • New tests for whitespace-only normalisation, Unicode-width indentation, mixed code/emphasis affixes, indented multi-line and nested HTML tables, numeric-candidate edge cases, and footnote renumbering behaviour (including fenced-code escape cases).
      • Split large test modules into focused files under tests/wrap_unit/ to keep source files under size limits.
      • Update CHANGELOG.md and documentation (docs/architecture.md, docs/developers-guide.md, docs/users-guide.md) describing the new stateful helpers and the wrapping/HTML-table conversion rules.
    • Compatibility

      • No public API/signature changes; all changes are internal implementation, configuration and test/documentation updates.

      Notes

      • Reviewer suggestions that would increase cyclomatic complexity without improving correctness (notably avoiding Cow allocations) were intentionally declined and are documented in the PR.
      • No new execplan document was added or referenced by this PR.

      Walkthrough

      Refactor footnote-definition processing into a renumber/definitions submodule; centralise HTML-table and list numbering state; harden wrap prefix capture handling and normalise whitespace-only passthroughs; expand unit/property tests; update docs, changelog and cargo-binstall metadata.

      Changes

      Footnote Definition Submodule Extraction

      Layer / File(s) Summary
      Definitions module types and core helpers
      src/footnotes/renumber/definitions.rs
      Add DefinitionLine, NumericCandidate, DefinitionUpdates, DefinitionScanState, scanning, candidate finalisation, numbering and header construction helpers.
      Reorder & apply changes
      src/footnotes/renumber/definitions.rs
      Build definition segments, compose reordered block, migrate leading blank-lines, and apply rewritten headers with row-count safety checks and warning on mismatch.
      Definitions unit & property tests
      src/footnotes/renumber/definitions/tests.rs, src/footnotes/renumber/tests.rs
      Add unit and proptest coverage for numeric-candidate parsing, segment detection, collect_definition_updates, rewrite_definition_headers, reorder_definition_block, and end-to-end renumbering behaviour.
      Parent renumber integration and cleanup
      src/footnotes/renumber.rs
      Import definitions, remove prior in-file parsing/rewrite machinery, handle missing regex captures safely in footnote-ref replacement, and add test module wiring.

      HTML Table and List State Consolidation

      Layer / File(s) Summary
      HTML table state consolidation
      src/html.rs
      Introduce HtmlTableState { buf, depth }, derive buffering state from buf, implement push_html_line/flush_raw, count nested <table> tags, and auto-flush when depth returns to zero.
      HTML buffering integration & tests
      src/html.rs, src/html_tests.rs, tests/table/convert_html.rs
      Route table detection and buffering through HtmlTableState; flush on fenced-code boundaries and at scan end; add unit/proptest and conversion tests for indented and nested tables.
      List numbering state encapsulation
      src/lists.rs
      Derive Default for ListState; add reset() and next_number(indent) to centralise prune/push/increment logic; update renumber_lists and add unit/proptest coverage.

      Wrapping Robustness and Whitespace Handling

      Layer / File(s) Summary
      Regex capture safety in wrapping
      src/wrap.rs
      Change prefix_line to use optional capture extraction for bullet/footnote/blockquote branches so missing groups return None instead of panicking; remove doc panics claim.
      Whitespace normalisation in passthrough blocks
      src/wrap.rs, src/wrap/inline/postprocess.rs
      Normalise whitespace-only passthrough lines to "" before push_verbatim; add tracing::trace logging when normalising or when merging whitespace-only lines in postprocess.
      Wrapping test expansion and split
      tests/wrap_unit.rs, tests/wrap_unit/*, src/wrap/tests/prefix.rs
      Split monolithic wrap tests into focused submodules and add tests for prefix parsing, code-span wrapping, footnote-reference handling, shell-block preservation, prefixed wrapping behaviours, and stream-level invariants.
      Paragraph continuation repeat test
      src/wrap/paragraph.rs
      Add test verifying repeat_prefix = true repeats the full PrefixLine prefix on every continuation line.
      Inline postprocess tracing & tests
      src/wrap/inline/postprocess.rs, src/wrap/inline/postprocess_tests.rs
      Emit trace events when merging whitespace-only lines and move tests into a dedicated test file covering merging and rebalance behaviours.
      Code-emphasis unit test
      src/code_emphasis.rs
      Add unit test verifying consume_code_affixes clears mismatched pending affixes, marks modified, and advances the token iterator.

      Testing, Documentation, and Configuration Polish

      Layer / File(s) Summary
      Architecture & developer docs
      docs/architecture.md, docs/developers-guide.md
      Document new "Stateful helpers": ParagraphWriter, HtmlTableState, DefinitionScanState, and ListState.
      Users guide updates
      docs/users-guide.md
      Document whitespace-only normalisation, Unicode display-width continuation indentation, and indented HTML-table conversion behaviour.
      Changelog and Cargo metadata
      CHANGELOG.md, Cargo.toml
      Add Fixed changelog bullets for whitespace normalisation, Unicode indentation, indented HTML-table conversion; set cargo-binstall Linux bin-dir override to ".".
      Test reorganisation wiring
      tests/wrap_unit.rs, tests/wrap_unit/*
      Refactor test wiring to submodules and add many focused unit/property tests across wrapping, tables, footnotes, and stream processing.

      Possibly related issues

      Possibly related PRs

      "Move definitions to their special room,
      Buffer tables till the outer bloom,
      Let lists count tidy, shallow then deep,
      Trim stray whitespace, keep flows neat —
      Tests chant true and docs now show."

      ✨ Finishing Touches
      📝 Generate docstrings
      • Create stacked PR
      • Commit on current branch
      🧪 Generate unit tests (beta)
      • Create PR with unit tests
      • Commit unit tests in branch feedback-following-code-fmt

@sourcery-ai

sourcery-ai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Refactors wrapping, list renumbering, footnote renumbering, and HTML table conversion to centralize mutable state and remove panicking expectations, while tightening wrapping behavior (Unicode-aware indentation, whitespace-only lines) and adding regression tests, plus a small cargo-binstall override fix.

Sequence diagram for updated wrap_text paragraph processing

sequenceDiagram
    participant WT as wrap_text
    participant FT as FenceTracker
    participant PW as ParagraphWriter

    loop for each line in lines
        WT->>FT: observe(line)
        alt fence line toggled
            FT-->>WT: true
            WT->>PW: push_verbatim(line)
            WT->>WT: continue
        else not fence
            FT-->>WT: false
            alt FT.in_fence()
                WT->>PW: push_verbatim(line)
                WT->>WT: continue
            else not in fence
                alt line.trim().is_empty()
                    WT->>PW: push_blank_line()
                    WT->>WT: continue
                else
                    alt passthrough block
                        WT->>PW: push_verbatim(line)
                        WT->>WT: continue
                    else prefix_line found
                        WT->>PW: handle_prefix_line(prefix_line)
                        WT->>WT: continue
                    else plain paragraph text
                        WT->>PW: note_indent(line)
                        WT->>WT: (text, hard_break) = line_break_parts(line)
                        WT->>PW: push_wrapped(text, hard_break)
                    end
                end
            end
        end
    end
    WT->>PW: flush_paragraph()
Loading

Class diagram for updated wrapping, list, footnote, and HTML table state structs

classDiagram
    class ParagraphWriter {
        - out : &mut Vec~String~
        - width : usize
        - buf : Vec~(String, bool)~
        - indent : String
        + new(out : &mut Vec~String~, width : usize) ParagraphWriter
        + note_indent(line : &str) void
        + push_wrapped(text : String, hard_break : bool) void
        + flush_paragraph() void
        + push_verbatim(line : &str) void
        + push_blank_line() void
        + handle_prefix_line(prefix_line : &PrefixLine) void
        - push_wrapped_segment(indent : &str, segment : &str) void
    }

    class PrefixLine {
        + prefix : String
        + rest : &str
        + repeat_prefix : bool
    }

    class SplitContext {
        + lines : &mut Vec~String~
        + width : usize
        + new(lines : &mut Vec~String~, width : usize) SplitContext
    }

    class HtmlTableState {
        + buf : Vec~String~
        + depth : usize
        + in_html() bool
        + flush_raw(out : &mut Vec~String~) void
        + push_html_line(line : &str, out : &mut Vec~String~) void
    }

    class ListState {
        + indent_stack : Vec~usize~
        + counters : HashMap~usize, usize~
        + reset() void
        + prune_deeper(indent : usize, inclusive : bool) void
        + next_number(indent : usize) usize
        + handle_paragraph_restart(indent : usize, line : &str, prev_blank : bool) bool
    }

    class DefinitionScanState {
        + mapping : &mut HashMap~usize, usize~
        + next_number : &mut usize
        + numeric_list_range : Option~(usize, usize)~
        + skip_numeric_conversion : bool
        + definitions : Vec~DefinitionLine~
        + is_definition_line : Vec~bool~
        + numeric_candidates : Vec~NumericCandidate~
    }

    class FenceTracker {
        + observe(line : &str) bool
        + in_fence() bool
    }

    ParagraphWriter --> PrefixLine : handles
    ParagraphWriter --> SplitContext : uses via wrap_preserving_code
    ParagraphWriter --> FenceTracker : used in wrap_text
    HtmlTableState ..> table_lines_to_markdown : calls
    ListState ..> FenceTracker : used in renumber_lists
    DefinitionScanState ..> DefinitionLine : owns
    DefinitionScanState ..> NumericCandidate : owns
Loading

File-Level Changes

Change Details Files
Centralize paragraph wrapping logic into a stateful writer and adjust wrap_text behavior, including whitespace-only lines and Unicode-width indentation.
  • Replace ParagraphState + ParagraphWriter split with a single ParagraphWriter that owns the paragraph buffer and indentation state.
  • Ensure wrap_text treats empty/whitespace-only lines as blank lines and does not wrap them.
  • Use UnicodeWidthStr to compute available width for indentation and prefix handling, including full-width spaces.
  • Refactor fence handling to no longer depend on an external ParagraphState and to write verbatim lines directly via ParagraphWriter.
  • Introduce ParagraphWriter::push_blank_line and push_verbatim to manage paragraph flushing before emitting structural lines.
src/wrap/paragraph.rs
src/wrap.rs
src/wrap/fence.rs
src/wrap/inline.rs
src/wrap/line_buffer.rs
src/wrap/tests.rs
Make footnote renumbering scan stateful and remove panicking regex/write! assumptions.
  • Merge DefinitionScanContext and DefinitionAccumulator into a single DefinitionScanState struct that carries mapping, counters, collected definitions, and numeric candidates.
  • Change numeric_candidate_from_line and prefix extraction to use optional regex captures instead of expect panics.
  • Replace write!(...).expect(...) when building footnote definition lines with ignored write! results, avoiding panics on string write.
  • Inline numeric candidate accumulation into DefinitionScanState and finalize them in-place when computing DefinitionUpdates.
src/footnotes/renumber.rs
Refine passthrough/wrapping classification and prefix handling in wrap.rs to avoid panics on missing captures.
  • Simplify is_passthrough_block to treat only tables, headings, markdownlint directives, and indented code as passthrough, and handle blank lines separately in wrap_text.
  • Update prefix_line to return None on missing regex groups instead of panicking via expect, and to store prefixes as owned Strings in PrefixLine.
  • Adjust fenced-block handling to push verbatim lines and continue without involving paragraph state.
src/wrap.rs
Refactor HTML table conversion to use an explicit HtmlTableState that properly supports indented multi-line tables.
  • Add HtmlTableState::in_html helper and move html/in-table tracking into the state struct based on buffer emptiness and depth.
  • Reimplement push_html_line to trim leading indentation for tag depth counting while preserving original lines in the buffer, and to flush when depth returns to zero.
  • Update html_table_to_markdown and convert_html_tables to drive conversion via HtmlTableState instead of separate buf/depth/in_html variables.
  • Ensure flush_raw is called at the end of processing to emit any unterminated HTML table lines verbatim.
src/html.rs
tests/table/convert_html.rs
Encapsulate list renumbering mutable state and add helpers for nesting and counter tracking.
  • Mark ListState as Default and add a reset method to clear indent stack and counters when encountering headings or thematic breaks.
  • Introduce ListState::next_number to encapsulate pruning deeper levels, managing the indent stack, and incrementing counters.
  • Update renumber_lists to use ListState::default and next_number, simplifying numbered-list handling logic.
src/lists.rs
Tighten inline wrapping and code/emphasis handling helpers and tests.
  • Introduce SplitContext::new constructor and use it in inline wrapping and line buffer tests to simplify call sites.
  • Add regression test to ensure consume_code_affixes clears mixed pending prefix state and rewrites the token stream as expected.
src/wrap/inline.rs
src/wrap/line_buffer.rs
src/wrap/tests.rs
src/code_emphasis.rs
Adjust cargo-binstall Linux override to install binaries from the current directory.
  • Change Cargo.toml bin-dir override for Linux GNU targets from a nested bin path to "." so installed binaries are found correctly.
Cargo.toml

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@leynos
leynos marked this pull request as ready for review April 18, 2026 15:55
sourcery-ai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/footnotes/renumber.rs (1)

337-344: ⚠️ Potential issue | 🟠 Major

Remove the panic path in numeric_candidate_from_line.

Parse from num_match.as_str() directly. Line 339 still indexes caps["num"], which panics when the named group is absent and defeats the Option-based fallback.

🔧 Proposed fix
 fn numeric_candidate_from_line(line: &str, index: usize) -> Option<NumericCandidate> {
     let caps = FOOTNOTE_LINE_RE.captures(line)?;
-    let number = caps["num"].parse::<usize>().ok()?;
+    let num_match = caps.name("num")?;
+    let number = num_match.as_str().parse::<usize>().ok()?;
     let indent = caps.name("indent").map_or("", |m| m.as_str()).to_string();
-    let rest = caps.name("rest").map_or("", |m| m.as_str()).to_string();
-    let num_match = caps.name("num")?;
-    let rest_match = caps.name("rest")?;
+    let rest_match = caps.name("rest")?;
+    let rest = rest_match.as_str().to_string();
     let whitespace = line[num_match.end() + 1..rest_match.start()].to_string();
     Some(NumericCandidate {
         index,
         number,
         indent,

As per coding guidelines: ".expect() and .unwrap() are forbidden outside of tests. Errors must be propagated."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/footnotes/renumber.rs` around lines 337 - 344, The function
numeric_candidate_from_line currently uses caps["num"] which can panic if the
named capture is absent; instead use the already-obtained num_match (from
caps.name("num")) and parse num_match.as_str() to get the usize (e.g., replace
the caps["num"].parse::<usize>() call with parsing num_match.as_str()), keeping
the .ok()? propagation so the function returns None on parse failure; also
remove any other direct indexing into caps[...] that can panic and rely on the
existing num_match/rest_match variables and safe slicing using their
start()/end() positions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/footnotes/renumber.rs`:
- Around line 328-329: The code currently discards the Result from write! when
building the definition header (e.g., the line using write!(&mut line,
"[^{new_number}]:") before pushing rewritten_rest), creating a silent failure
path; replace those write! calls (both occurrences around the build of the
header) with infallible string assembly such as let header =
format!("[^{new_number}]:"); line.push_str(&header); (or build the header with
String::from and push_str) so you don't ignore errors and avoid using a fallible
fmt write into the mutable string; apply the same replacement for the second
occurrence near lines 401–402.

In `@src/wrap/tests.rs`:
- Around line 309-314: The test wrap_text_uses_display_width_for_unicode_indent
is too weak: it uses " a" with width 2 which doesn't fail even if indent width
is computed incorrectly; update the test to exercise display-width by using an
input like " a b" and call wrap_text(&input, 4) so the ideographic space (width
2) causes a wrap, and assert that the result equals vec![" a".to_string(),
" b".to_string()]—modify the test body in
wrap_text_uses_display_width_for_unicode_indent to use that input, width, and
expected assertion.
- Around line 302-314: The new regression tests
wrap_text_normalizes_whitespace_only_lines and
wrap_text_uses_display_width_for_unicode_indent should be moved out of the
already-large src/wrap/tests.rs into a dedicated test module file to keep files
under the 400-line limit; create a new test file (for example
tests/wrap_regressions.rs or src/wrap/regressions_tests.rs), copy those two
#[test] functions (which call wrap_text) into it, preserve any necessary
use/imports for wrap_text, and remove them from src/wrap/tests.rs so the
original file stays below the line limit.

---

Outside diff comments:
In `@src/footnotes/renumber.rs`:
- Around line 337-344: The function numeric_candidate_from_line currently uses
caps["num"] which can panic if the named capture is absent; instead use the
already-obtained num_match (from caps.name("num")) and parse num_match.as_str()
to get the usize (e.g., replace the caps["num"].parse::<usize>() call with
parsing num_match.as_str()), keeping the .ok()? propagation so the function
returns None on parse failure; also remove any other direct indexing into
caps[...] that can panic and rely on the existing num_match/rest_match variables
and safe slicing using their start()/end() positions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d67b626d-6713-4149-8d79-2492c7423851

📥 Commits

Reviewing files that changed from the base of the PR and between b8962c0 and 55b5a15.

📒 Files selected for processing (12)
  • Cargo.toml
  • src/code_emphasis.rs
  • src/footnotes/renumber.rs
  • src/html.rs
  • src/lists.rs
  • src/wrap.rs
  • src/wrap/fence.rs
  • src/wrap/inline.rs
  • src/wrap/line_buffer.rs
  • src/wrap/paragraph.rs
  • src/wrap/tests.rs
  • tests/table/convert_html.rs

Comment thread src/footnotes/renumber.rs Outdated
Comment thread src/wrap/tests.rs Outdated
Comment thread src/wrap/tests.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/wrap/tests.rs (2)

302-324: 🛠️ Refactor suggestion | 🟠 Major

Move these regressions into a dedicated test module.

Lines 302-324 keep src/wrap/tests.rs at 489 lines, so this PR still breaches the repository cap. Move the new wrapping regressions out of this module and keep the file below the limit.

As per coding guidelines, "Files must not exceed 400 lines in length".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/wrap/tests.rs` around lines 302 - 324, The three new regression tests
(wrap_text_normalizes_whitespace_only_lines,
wrap_text_treats_whitespace_only_lines_as_paragraph_breaks,
wrap_text_uses_display_width_for_unicode_indent) should be moved out of the
oversized tests.rs into a dedicated test module/file (e.g., a new module named
wrap_regressions or regressions) so the original file stays under the 400-line
limit; extract those #[test] functions into the new module, ensure the new
file/module is compiled as part of the test suite (keeping the same function
names and signatures and any necessary use/imports such as wrap_text), and
remove the original copies from the large tests.rs.

320-324: ⚠️ Potential issue | 🟡 Minor

Strengthen the Unicode-width regression.

Lines 320-324 still pass when the ideographic space is mismeasured as one column, so the test does not prove the fix. Use an input that only wraps when that indent consumes two columns, such as " a b" at width 4, and assert the split output.

Patch
 fn wrap_text_uses_display_width_for_unicode_indent() {
-    let input = vec![" a".to_string()];
-    let wrapped = wrap_text(&input, 2);
-    assert_eq!(wrapped, vec![" a".to_string()]);
+    let input = vec![" a b".to_string()];
+    let wrapped = wrap_text(&input, 4);
+    assert_eq!(wrapped, vec![" a".to_string(), " b".to_string()]);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/wrap/tests.rs` around lines 320 - 324, The test
wrap_text_uses_display_width_for_unicode_indent currently uses " a" which still
passes if the ideographic space is mismeasured; change it to exercise the wrap
threshold by using input " a b" and width 4 so the indent (ideographic space = 2
columns) forces a wrap; update the test (function
wrap_text_uses_display_width_for_unicode_indent) to call wrap_text(&vec![" a
b".to_string()], 4) and assert the expected split output (e.g.
assert_eq!(wrapped, vec![" a".to_string(), "b".to_string()])).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/footnotes/renumber.rs`:
- Around line 490-528: This file is over the 400-line limit because the
#[cfg(test)] mod tests block is large; move the entire test module into a new
test file (either src/footnotes/renumber/tests.rs or
tests/footnotes_renumber.rs) preserving the imported functions
numeric_candidate_from_line and renumber_footnotes, and update module imports
accordingly; also replace the duplicated assertions in the
malformed_numeric_candidate_line_is_ignored test with a parameterised rstest
(use #[rstest] with two cases like "7." and "7:") to consolidate into a single
parameterised test function while keeping the existing test names for clarity.

In `@tests/table/convert_html.rs`:
- Around line 81-115: Collapse the two nearly-identical tests into a single
parameterised rstest: remove the functions
converts_indented_multiline_html_table and
converts_indented_table_without_touching_surrounding_content and replace them
with one #[rstest(...)] that supplies the two cases and a single test function
(e.g. converts_indented_html_table_cases) which takes input: Vec<String>,
expected: Vec<String> and asserts assert_eq!(convert_html_tables(&input),
expected); ensure the rstest attribute lists both case::... entries and the test
helper convert_html_tables is used unchanged.

---

Duplicate comments:
In `@src/wrap/tests.rs`:
- Around line 302-324: The three new regression tests
(wrap_text_normalizes_whitespace_only_lines,
wrap_text_treats_whitespace_only_lines_as_paragraph_breaks,
wrap_text_uses_display_width_for_unicode_indent) should be moved out of the
oversized tests.rs into a dedicated test module/file (e.g., a new module named
wrap_regressions or regressions) so the original file stays under the 400-line
limit; extract those #[test] functions into the new module, ensure the new
file/module is compiled as part of the test suite (keeping the same function
names and signatures and any necessary use/imports such as wrap_text), and
remove the original copies from the large tests.rs.
- Around line 320-324: The test wrap_text_uses_display_width_for_unicode_indent
currently uses " a" which still passes if the ideographic space is mismeasured;
change it to exercise the wrap threshold by using input " a b" and width 4 so
the indent (ideographic space = 2 columns) forces a wrap; update the test
(function wrap_text_uses_display_width_for_unicode_indent) to call
wrap_text(&vec![" a b".to_string()], 4) and assert the expected split output
(e.g. assert_eq!(wrapped, vec![" a".to_string(), "b".to_string()])).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4e0b8687-eb63-4e39-946c-a8b476a89d3d

📥 Commits

Reviewing files that changed from the base of the PR and between 55b5a15 and 58f905a.

📒 Files selected for processing (6)
  • src/footnotes/renumber.rs
  • src/html.rs
  • src/wrap.rs
  • src/wrap/paragraph.rs
  • src/wrap/tests.rs
  • tests/table/convert_html.rs

Comment thread src/footnotes/renumber.rs Outdated
Comment thread tests/table/convert_html.rs Outdated
@leynos

leynos commented Apr 18, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

Annul any requirements that violate the en-GB-oxendict spelling (-ize / -yse / -our) conventions (for example a request to replace "normalize" with "normalise" or "artefact" with "artifact"), or where the requirement unnecessarily increases cyclomatic complexity.

Please address the comments from this code review:

## Overall Comments
- In `HtmlTableState::push_html_line` you increment `depth` using `TABLE_START_RE` on `trimmed` but decrement using `TABLE_END_RE` on the original `line`; consider applying both start and end regexes consistently on the same representation (trimmed or original) to avoid subtle mismatches with indented or oddly spaced tags.
- Now that `PrefixLine.prefix` is always a `String`, `prefix_line` unconditionally allocates even for simple matches; if performance on large files is a concern, you might consider retaining a borrowing representation for the common bullet/blockquote cases and only allocating when the prefix needs to be synthesized (e.g., footnotes).

## Individual Comments

### Comment 1
<location path="src/footnotes/renumber.rs" line_range="393-394" />
<code_context>
-        let new_number = assign_new_number(ctx.mapping, candidate.number, ctx.next_number);
-        let rewritten_rest = rewrite_tokens(&candidate.rest, ctx.mapping);
+fn finalize_numeric_candidates(state: &mut DefinitionScanState<'_>) {
+    for candidate in state.numeric_candidates.drain(..).rev() {
+        let new_number = assign_new_number(state.mapping, candidate.number, state.next_number);
+        let rewritten_rest = rewrite_tokens(&candidate.rest, state.mapping);
</code_context>
<issue_to_address>
**suggestion:** Consider draining numeric candidates in-place without reversing if ordering is not semantically required.

This now drains `numeric_candidates` in reverse, preserving the previous `into_iter().rev()` behavior. If that ordering isn’t required for correctness, consider iterating in insertion order and dropping the `.rev()`. If it *is* required (e.g., to avoid index churn while mutating), please add a short comment explaining the dependency on reverse order where this iteration is defined.

```suggestion
fn finalize_numeric_candidates(state: &mut DefinitionScanState<'_>) {
    for candidate in state.numeric_candidates.drain(..) {
```
</issue_to_address>

### Comment 2
<location path="src/wrap/tests.rs" line_range="303-306" />
<code_context>
 }

+#[test]
+fn wrap_text_normalizes_whitespace_only_lines() {
+    let input = vec![String::new(), "   ".to_string(), "\t\t".to_string()];
+    let wrapped = wrap_text(&input, 80);
+    assert_eq!(wrapped, vec![String::new(), String::new(), String::new()]);
+}
+
</code_context>
<issue_to_address>
**suggestion (testing):** Add a case with whitespace-only lines inside a paragraph to prove paragraph-splitting behavior.

Since `wrap_text` now treats `trim().is_empty()` as a paragraph break, it’d be helpful to cover a mixed case like `["foo", "   ", "bar"]`, asserting that the middle line normalizes to an empty string and that `foo` and `bar` end up in separate wrapped paragraphs. That directly exercises the paragraph-boundary behavior of `push_blank_line` and guards against whitespace normalization merging or dropping paragraphs.

Suggested implementation:

```rust
 }

 #[test]
 fn wrap_text_normalizes_whitespace_only_lines() {
     let input = vec![String::new(), "   ".to_string(), "\t\t".to_string()];
     let wrapped = wrap_text(&input, 80);
     assert_eq!(wrapped, vec![String::new(), String::new(), String::new()]);
 }

 #[test]
 fn wrap_text_treats_whitespace_only_lines_as_paragraph_breaks() {
     let input = vec![
         "foo".to_string(),
         "   ".to_string(),
         "bar".to_string(),
     ];
     let wrapped = wrap_text(&input, 80);

     // The whitespace-only line should normalize to an empty string and act as
     // a paragraph separator, so "foo" and "bar" remain in separate paragraphs.
     assert_eq!(
         wrapped,
         vec![
             "foo".to_string(),
             String::new(),
             "bar".to_string(),
         ]
     );
 }


```

If `wrap_text` is not already imported into this test module, ensure there is a `use` bringing it into scope (for example, `use crate::wrap::wrap_text;` or similar based on the existing conventions in `src/wrap/tests.rs`).
</issue_to_address>

### Comment 3
<location path="tests/table/convert_html.rs" line_range="82-78" />
<code_context>
 }
+
+#[test]
+fn converts_indented_multiline_html_table() {
+    let input = lines_vec![
+        "  <table>",
+        "    <tr><th>A</th><th>B</th></tr>",
+        "    <tr><td>1</td><td>2</td></tr>",
+        "  </table>",
+    ];
+    let expected = lines_vec![
+        "  | A | B |",
+        "  | --- | --- |",
+        "  | 1 | 2 |",
+    ];
+    assert_eq!(convert_html_tables(&input), expected);
+}
</code_context>
<issue_to_address>
**suggestion (testing):** Consider adding a test where an indented HTML table is followed by non-table HTML/content at the same indentation.

This test covers the core regression for indented multi-line tables and the refactored `HtmlTableState`. To better exercise the `buf`/`depth` state and `flush_raw`, please also add a case with:

- indented non-table content
- an indented `<table>…</table>` block
- more indented non-table content at the same indentation

and assert that only the table is converted and the surrounding lines pass through unchanged, verifying the `in_html()`/`flush_raw` transitions into and out of indented tables.
</issue_to_address>

### Comment 4
<location path="src/footnotes/renumber.rs" line_range="328" />
<code_context>
     let mut line = String::with_capacity(parts.prefix.len() + rewritten_rest.len() + 8);
     line.push_str(parts.prefix);
-    write!(&mut line, "[^{new_number}]:").expect("write to string cannot fail");
+    let _ = write!(&mut line, "[^{new_number}]:");
     line.push_str(&rewritten_rest);
     DefinitionLine {
</code_context>
<issue_to_address>
**issue (review_instructions):** Add tests demonstrating the bug this change addresses (ignoring write! errors instead of panicking) and verifying that renumbering behaves correctly when formatting succeeds.

Previously this code used expect("write to string cannot fail"), which would panic if formatting failed; now it ignores the Result from write!. This is a behavioural change intended to avoid panics and is effectively a bug fix. Add targeted tests that:
- Exercise renumbering of footnotes and numeric candidates to confirm no panics occur and the output lines are correctly formatted.
- If applicable, cover edge cases that could previously trigger the panic, to show the bug is fixed and behaviour remains correct.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*`

**Instructions:**
Bug fixes must be demonstrated by a test.

</details>
</issue_to_address>

### Comment 5
<location path="src/footnotes/renumber.rs" line_range="342" />
<code_context>
-    let rest_match = caps
-        .name("rest")
-        .expect("numeric list capture missing rest");
+    let num_match = caps.name("num")?;
+    let rest_match = caps.name("rest")?;
     let whitespace = line[num_match.end() + 1..rest_match.start()].to_string();
</code_context>
<issue_to_address>
**issue (review_instructions):** Add a regression test showing that malformed numeric list lines no longer panic due to missing regex captures.

numeric_candidate_from_line previously called expect on the "num" and "rest" captures, which would panic on malformed or unexpected input; now it returns None when captures are missing. This is a bug fix in error handling. Add a test that feeds a line matching NUMERIC_LIST_RE partially or unexpectedly (e.g., missing rest or number group) and assert that renumbering completes without panic and with the expected behaviour (either ignoring the line or handling it in a defined way).

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*`

**Instructions:**
Bug fixes must be demonstrated by a test.

</details>
</issue_to_address>

@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== src/footnotes/renumber.rs (lines 320-360, 385-410) ==="
sed -n '310,420p' src/footnotes/renumber.rs

echo ""
echo "=== src/wrap/tests.rs (last 80 lines) ==="
tail -100 src/wrap/tests.rs

echo ""
echo "=== tests/table/convert_html.rs ==="
cat tests/table/convert_html.rs

echo ""
echo "=== src/html.rs (push_html_line) ==="
grep -n "push_html_line\|TABLE_START_RE\|TABLE_END_RE\|trimmed\|depth\|trim_start" src/html.rs | head -60

echo ""
echo "=== src/wrap/paragraph.rs (PrefixLine prefix field) ==="
grep -n "prefix\|Cow\|String\|alloc\|borrow" src/wrap/paragraph.rs | head -40

Length of output: 12108


🏁 Script executed:

#!/bin/bash
echo "=== tests/wrap_unit.rs ==="
cat tests/wrap_unit.rs

echo ""
echo "=== src/footnotes/renumber.rs (test section) ==="
grep -n "#\[cfg(test\|#\[test\|mod tests\|fn test_\|fn renumber\|fn ignor\|fn malform\|fn numeric" src/footnotes/renumber.rs
sed -n '420,600p' src/footnotes/renumber.rs

Length of output: 7747


@leynos: Here is the status of each point.


Overall Comments

# Issue Status
1 TABLE_START_RE/TABLE_END_RE applied inconsistently (trimmed vs. original line) Resolvedpush_html_line now applies both regexes to trimmed (line.trim_start()).
2 PrefixLine.prefix unconditionally allocates; consider retaining a borrowing representation Annulledprefix remains Cow<'a, str>, which already permits borrowing. Converting common paths to avoid allocation would increase cyclomatic complexity without fixing a defect, so this requirement is annulled per your instruction.

Individual Comments

# Location Issue Status
1 src/footnotes/renumber.rsfinalize_numeric_candidates .rev() kept without explanation Resolved — a prose comment ("Drain from the bottom so wrapped continuation lines stay attached…") explains the semantic dependency on reverse order.
2 src/wrap/tests.rs Add a mixed ["foo", " ", "bar"] case proving paragraph-splitting behaviour Resolvedwrap_text_treats_whitespace_only_lines_as_paragraph_breaks was added to tests/wrap_unit.rs and asserts the expected ["foo", "", "bar"] output.
3 tests/table/convert_html.rs Add a test with indented non-table content surrounding an indented table Resolvedconverts_indented_table_without_touching_surrounding_content covers exactly this case.
4 src/footnotes/renumber.rs line 328 Tests required for the write!format! bug fix Resolvedrenumber_footnotes_rewrites_existing_definition_headers and renumber_footnotes_rewrites_numeric_candidates both exercise the format! path end-to-end and confirm correct output.
5 src/footnotes/renumber.rs line 342 Regression test for the expect? fix on missing regex captures Resolvedmalformed_numeric_candidate_line_is_ignored asserts numeric_candidate_from_line returns None for "7." and "7:", confirming no panic occurs on malformed input.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/footnotes/renumber/definitions.rs`:
- Line 100: Replace the odd double-super path by re-exporting or importing
DefinitionParts from the immediate parent: in renumber.rs add a re-export/import
for parsing::DefinitionParts (e.g., make DefinitionParts available as
super::parsing::DefinitionParts) and then update the type in definitions.rs to
use the simpler super::parsing::DefinitionParts<'_> (replace
super::super::parsing::DefinitionParts<'_> occurrences). This keeps the module
path clear and locates the change around the DefinitionParts type usage in
definitions.rs and the renumber.rs parent module.

In `@src/footnotes/renumber/tests.rs`:
- Around line 13-18: The test malformed_numeric_candidate_line_is_ignored uses
assert! without a diagnostic message; update the assertion to include a clear
failure message that shows the input, e.g. change the assertion around
numeric_candidate_from_line(line, 0).is_none() to include a message like
"expected None for malformed numeric candidate line: {line}" so failures surface
the offending case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3caf340c-8cb1-447f-8018-395c17e6be97

📥 Commits

Reviewing files that changed from the base of the PR and between 088948a and 6536e7a.

📒 Files selected for processing (4)
  • src/footnotes/renumber.rs
  • src/footnotes/renumber/definitions.rs
  • src/footnotes/renumber/tests.rs
  • tests/table/convert_html.rs

Comment thread src/footnotes/renumber/definitions.rs Outdated
Comment thread src/footnotes/renumber/tests.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/footnotes/renumber.rs (1)

70-87: ⚠️ Potential issue | 🟠 Major

Replace expect with fallible handling in production code.

Line 73 uses expect in production code, which violates the guideline forbidding .expect() outside tests. Return early when the capture is missing instead of panicking.

🔧 Proposed fix
 fn rewrite_refs_in_segment(text: &str, mapping: &HashMap<usize, usize>) -> String {
     FOOTNOTE_REF_RE
         .replace_all(text, |caps: &Captures| {
-            let mat = caps.get(0).expect("regex matched without capture");
+            let Some(mat) = caps.get(0) else {
+                return caps[0].to_string();
+            };
             if is_definition_like(text, &mat) {
                 return caps[0].to_string();
             }

As per coding guidelines: ".expect() and .unwrap() are forbidden outside of tests. Errors must be propagated."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/footnotes/renumber.rs` around lines 70 - 87, The closure in
rewrite_refs_in_segment currently calls caps.get(0).expect(...), which can
panic; replace that with fallible handling: match or if-let on caps.get(0)
(e.g., if let Some(mat) = caps.get(0) { ... } else { ... }), and in the None
branch return an appropriate safe fallback (the original matched text or
String::new()) instead of panicking; keep the rest of the logic (calling
is_definition_like(text, &mat), parsing caps["num"], and using mapping)
unchanged so the closure never uses .expect() or .unwrap().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/footnotes/renumber.rs`:
- Around line 70-87: The closure in rewrite_refs_in_segment currently calls
caps.get(0).expect(...), which can panic; replace that with fallible handling:
match or if-let on caps.get(0) (e.g., if let Some(mat) = caps.get(0) { ... }
else { ... }), and in the None branch return an appropriate safe fallback (the
original matched text or String::new()) instead of panicking; keep the rest of
the logic (calling is_definition_like(text, &mat), parsing caps["num"], and
using mapping) unchanged so the closure never uses .expect() or .unwrap().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 63e834dd-352d-4c55-b0ab-ef615c11d4b0

📥 Commits

Reviewing files that changed from the base of the PR and between 6536e7a and 8c1c7a7.

📒 Files selected for processing (2)
  • src/footnotes/renumber.rs
  • src/footnotes/renumber/definitions.rs

@leynos

leynos commented Apr 18, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai pause

@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Reviews paused.

@lodyai
lodyai Bot force-pushed the feedback-following-code-fmt branch from 766c589 to 7d4a095 Compare May 25, 2026 19:25

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 12-13: Update the CHANGELOG entry that currently reads "Normalise
whitespace-only artefacts during wrapping by rebalancing atomic tails." to use
en-GB-oxendict spelling by replacing "Normalise" with "Normalize" so the line
becomes "Normalize whitespace-only artefacts during wrapping by rebalancing
atomic tails."; keep the rest of the entry unchanged and add the triage tags
`[type:spelling]` `[type:docstyle]` if not already present.

In `@src/footnotes/renumber.rs`:
- Around line 8-10: Add module-level documentation for the new module boundary
by adding a leading `//!` comment above `mod parsing` that succinctly explains
the module's purpose and how its re-export of `DefinitionParts` is intended to
be used; also add a Rustdoc `///` comment on the `renumber_footnotes` function
that documents its public API: state that it mutates its input in-place,
describe the exact renumbering rules it applies (e.g., how it maps original
footnote identifiers to new sequential numbers, what it does with references and
definitions, and any invariants preserved), and note any side-effects or
preconditions/postconditions for callers so cargo doc will surface this
behavior.

In `@src/footnotes/renumber/definitions.rs`:
- Around line 19-37: Add Rustdoc comments for the module-visible types and their
fields to document their contracts and mutation semantics: annotate
DefinitionLine, NumericCandidate, and DefinitionUpdates (and their public fields
like index, new_number, line, indent, whitespace, rest, definitions,
is_definition_line) with /// comments describing what each struct represents,
which fields are mutated or read-only after construction, expected
units/constraints (e.g. zero-based index, new_number meaning), and what outputs
or invariants callers can rely on; apply the same documentation pattern to the
other affected regions (lines referenced 118-133 and 198-235) so all pub(super)
APIs in this submodule have concise Rustdoc describing purpose, mutation
behaviour, and visible outputs.
- Around line 315-460: Remove the inline #[cfg(test)] mod tests { ... } block
from definitions.rs and instead add a new test module file named tests.rs
alongside definitions.rs that contains the same test code (keeping the
#[cfg(test)] and use super::{DefinitionLine, assign_new_number,
collect_definition_updates, definition_segment_end, reorder_definition_block,
rewrite_definition_headers, should_convert_numeric_line} line). In the original
definitions.rs replace the removed block with a single declaration #[cfg(test)]
mod tests; so the compiler will include the external tests.rs; ensure the new
tests.rs uses super::* imports as needed and keeps all test functions and helper
fn strings unchanged.

In `@src/wrap/paragraph.rs`:
- Around line 205-216: The test
handle_prefix_line_can_repeat_or_change_the_continuation_prefix only covers the
non-repeating (space-aligned) path; add a second assertion exercising
repeat_prefix = true so blockquote-style continuations are validated. Update the
test body that constructs ParagraphWriter::new and calls handle_prefix_line with
a PrefixLine where prefix is a blockquote-like value (e.g., starting with "> ")
and set repeat_prefix: true, then assert that out contains the wrapped lines
that repeat the prefix on continuation (matching the expected vector for
repeated-prefix wrapping). Ensure you reference the same test function name and
PrefixLine fields (prefix, rest, repeat_prefix) and keep the existing
non-repeating assertion intact.

In `@tests/wrap_unit.rs`:
- Around line 62-88: Add a content-preservation assertion after calling
wrap_text: verify that replacing the inserted line breaks with spaces
reconstructs the original input by asserting wrapped.join(" ") == input[0]; this
uses the existing wrap_text function and the wrapped/local input variables to
ensure no characters are dropped or rewritten during wrapping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6c6c762b-6000-428e-ae49-eb3e3b9114f6

📥 Commits

Reviewing files that changed from the base of the PR and between 8c1c7a7 and 1b0ce55.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • Cargo.toml
  • docs/architecture.md
  • src/code_emphasis.rs
  • src/footnotes/renumber.rs
  • src/footnotes/renumber/definitions.rs
  • src/footnotes/renumber/tests.rs
  • src/html.rs
  • src/lists.rs
  • src/wrap.rs
  • src/wrap/fence.rs
  • src/wrap/paragraph.rs
  • src/wrap/tests.rs
  • tests/table/convert_html.rs
  • tests/wrap_unit.rs

Comment thread CHANGELOG.md Outdated
Comment thread src/footnotes/renumber.rs
Comment thread src/footnotes/renumber/definitions.rs
Comment thread src/footnotes/renumber/definitions.rs Outdated
Comment thread src/wrap/paragraph.rs
Comment thread tests/wrap_unit.rs Outdated
@lodyai
lodyai Bot force-pushed the feedback-following-code-fmt branch from 1b0ce55 to f7b07ed Compare May 30, 2026 00:37
@leynos

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

@leynos

leynos commented May 31, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

This comment was marked as resolved.

@coderabbitai coderabbitai Bot added the Issue label May 31, 2026
@leynos

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

lodyai Bot pushed a commit that referenced this pull request May 31, 2026
CHANGELOG: add three Fixed entries for PR #266 (Unicode display-width
indentation, indented multi-line HTML table conversion, and the
cargo-binstall Linux `bin-dir` correction).

renumber.rs: document the `definitions` submodule boundary so cargo doc
explains why the parsing and reordering machinery is delegated.

definitions.rs: replace the inaccurate "in scan order" doc on
`DefinitionUpdates::definitions` with the actual ordering (explicit
definitions in scan order; promoted numeric candidates in reverse scan
order).

renumber/tests.rs: collapse the two `renumber_footnotes_rewrites_*`
`#[test]` functions into a single parameterised `#[rstest]`, and add a
`proptest` module that verifies sequential numbering, reference
consistency, and fenced-region preservation across generated inputs.

lists.rs: add unit tests for `ListState::reset` and the indent-pruning
behaviour of `ListState::next_number`.

tests/table/convert_html.rs: add a regression test that a nested
`<table>` inside an outer `<table>` does not flush prematurely and is
converted as one contiguous block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== CHANGELOG.md [Unreleased] section ==="
awk '/^## \[Unreleased\]/{p=1} p && /^## \[/ && !/Unreleased/{p=0} p' CHANGELOG.md

echo ""
echo "=== mod definitions doc comment in renumber.rs ==="
sed -n '1,15p' src/footnotes/renumber.rs

echo ""
echo "=== DefinitionUpdates struct doc in definitions.rs ==="
grep -n -B5 -A10 "struct DefinitionUpdates" src/footnotes/renumber/definitions.rs

echo ""
echo "=== renumber/tests.rs full content ==="
cat src/footnotes/renumber/tests.rs 2>/dev/null || echo "NOT FOUND"

echo ""
echo "=== proptest usage in tests ==="
rg -n "proptest" src/ tests/ --include="*.rs" | head -30

echo ""
echo "=== ListState tests in lists.rs ==="
grep -n -A5 "#\[cfg(test\|#\[test\]\|mod tests" src/lists.rs | head -40

echo ""
echo "=== tests/table/convert_html.rs full content ==="
cat tests/table/convert_html.rs

echo ""
echo "=== Cargo.toml dev-dependencies ==="
grep -n -A2 "\[dev-dependencies\]" Cargo.toml | head -20

echo ""
echo "=== open GitHub issues ==="
gh issue list --repo leynos/mdtablefix --state open --limit 30

Length of output: 17127



@leynos: All eight checks are now resolved.

Check Status Evidence
User-Facing Documentation ✅ Resolved CHANGELOG.md contains three new Fixed bullets: Unicode display-width indentation, indented multi-line HTML table conversion, and cargo-binstall Linux bin-dir fix.
Developer Documentation ✅ Resolved Same three CHANGELOG entries satisfy this requirement.
Module-Level Documentation ✅ Resolved A /// doc comment explaining delegation responsibility sits immediately above mod definitions; in src/footnotes/renumber.rs.
Unit Architecture / Domain Architecture ✅ Resolved DefinitionUpdates::definitions Rustdoc now documents the actual ordering: explicit [^n]: definitions in scan order, promoted numeric candidates in reverse scan order as required by finalize_numeric_candidates.
Testing (Unit And Behavioural) ✅ Resolved Two renumber_footnotes tests are merged into a single #[rstest] function with #[case::existing_definition] and #[case::numeric_candidate]; mod proptest_tests is present.
Testing (Property / Proof) ✅ Resolved proptest_tests::renumber_footnotes_assigns_sequential_numbers_and_preserves_fenced_refs generates arbitrary footnote numbers, asserts dense sequential renumbering, and verifies fenced-block lines are untouched.
Testing (Overall) ✅ Resolved list_state_reset_clears_indent_stack_and_counters and list_state_next_number_increments_and_prunes_deeper_indents cover ListState methods; nested_html_table_does_not_trigger_premature_flush covers nested HTML table depth tracking; footnote tests are parameterised.

@leynos

leynos commented May 31, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos

leynos commented May 31, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following failed checks now been resolved?

If further work is required, please provide an AI agent prompt for the remaining work to be done to address these failures.

Do not treat warnings as optional or aspirational. Where a change is out of scope for this PR, propose a GitHub issue unless one exists already.

❌ Failed checks (3 errors, 5 warnings)

Check name Status Explanation Resolution
Testing (Overall) ❌ Error Footnote tests not parameterised, property tests missing, HTML depth test incomplete, ListState methods untested. Parameterise footnote tests with rstest; add proptest for renumbering invariants; test nested table depth tracking; add unit tests for ListState methods.
Module-Level Documentation ❌ Error Module definitions declared in src/footnotes/renumber.rs (line 7) lacks a module-level docstring explaining its purpose and relationship to other components. Add a documentation comment above mod definitions; explaining that it owns definition parsing/reordering machinery, delegated from the parent module to keep files readable.
Unit Architecture ❌ Error DefinitionUpdates::definitions doc claims "in scan order" but finalize_numeric_candidates drains in reverse order, violating stated architectural contract. Sort DefinitionUpdates::definitions by DefinitionLine::index before returning from collect_definition_updates, or revise Rustdoc to document actual reverse-drain ordering.
User-Facing Documentation ⚠️ Warning Three user-facing fixes lack CHANGELOG.md entries: Unicode display-width wrapping, indented multi-line HTML table conversion, and cargo-binstall Linux bin-dir fix. Add three Fixed bullets to CHANGELOG.md documenting Unicode display-width indentation handling, indented HTML table conversion, and cargo-binstall Linux binary installation directory.
Developer Documentation ⚠️ Warning CHANGELOG.md lacks three required user-facing fixes: Unicode display-width wrapping, indented multi-line HTML table conversion, and cargo-binstall Linux binary-directory fix. Add three Fixed bullets to CHANGELOG.md documenting Unicode display-width wrapping, indented multi-line HTML table conversion, and cargo-binstall Linux fix.
Testing (Unit And Behavioural) ⚠️ Warning Property-based testing for renumbering invariants was requested but not implemented. Two renumber_footnotes tests remain separate instead of parameterised with #[rstest]. Add proptest for renumbering invariants. Parameterise renumber_footnotes tests into single #[rstest] function with two #[case] attributes.
Testing (Property / Proof) ⚠️ Warning PR introduces stateful renumbering with invariants across mixed orderings but lacks proptest; review explicitly requested property tests for dense sequential numbering—unaddressed. Add proptest generating mixed footnote references, repeated references, numeric candidates, and fenced blocks; assert dense sequential renumbering and untouched fenced content.
Domain Architecture ⚠️ Warning Domain command collect_definition_updates claims "in scan order" but finalize_numeric_candidates reverses candidate order, violating documented invariant contract. Sort DefinitionUpdates::definitions by index before return, or rewrite Rustdoc to match actual reverse-order numeric candidate appending behaviour.

leynos and others added 14 commits June 1, 2026 22:56
Add the missing changelog note for wrapping whitespace-only artefact
normalisation and atomic-tail rebalancing.

Expand the architecture document with concise responsibility notes for
`ParagraphWriter`, `HtmlTableState`, `DefinitionScanState`, and
`ListState` so the module-level overview reflects the current design
without listing private fields.
Exercise representative definition-scan, paragraph-writer, and prefix-line
behaviour directly so the refactored helper boundaries are covered without
widening private APIs.
Treat whitespace-only input lines as paragraph breaks and emit them as
empty strings so downstream consumers see a uniform separator.  This was
part of the original review-feedback intent on this branch but was lost
during the rebase onto main's evolved `wrap_text` flow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply Oxford spelling to the wrap CHANGELOG entry, document the
`renumber_footnotes` API and the `parsing` re-export shim, and add
rustdoc for the `pub(super)` types and functions in
`renumber::definitions` so cargo doc surfaces their contracts.

Extract the inline `mod tests` block from `definitions.rs` into a
sibling `definitions/tests.rs` so the implementation file stays focused.

Strengthen `handle_prefix_line_can_repeat_or_change_the_continuation_prefix`
with a `repeat_prefix = true` case, and add a join-roundtrip assertion to
`wrap_text_preserves_hyphenated_words` so accidental character loss is
caught directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CHANGELOG: add three Fixed entries for PR #266 (Unicode display-width
indentation, indented multi-line HTML table conversion, and the
cargo-binstall Linux `bin-dir` correction).

renumber.rs: document the `definitions` submodule boundary so cargo doc
explains why the parsing and reordering machinery is delegated.

definitions.rs: replace the inaccurate "in scan order" doc on
`DefinitionUpdates::definitions` with the actual ordering (explicit
definitions in scan order; promoted numeric candidates in reverse scan
order).

renumber/tests.rs: collapse the two `renumber_footnotes_rewrites_*`
`#[test]` functions into a single parameterised `#[rstest]`, and add a
`proptest` module that verifies sequential numbering, reference
consistency, and fenced-region preservation across generated inputs.

lists.rs: add unit tests for `ListState::reset` and the indent-pruning
behaviour of `ListState::next_number`.

tests/table/convert_html.rs: add a regression test that a nested
`<table>` inside an outer `<table>` does not flush prematurely and is
converted as one contiguous block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
wrap.rs: normalise whitespace-only lines in
`handle_pending_continuation` so the pending-prefix path matches the
main `wrap_text` loop and never re-emits original whitespace content.

footnotes/renumber/definitions.rs: emit a `tracing::warn!` when
`reorder_definition_block` skips because the segment count diverges
from the block width, and harden `numeric_candidate_from_line` against
panics by range-checking the regex-derived slice indices before the
byte slice.

docs/users-guide.md: document the whitespace-only normalisation,
Unicode display-width indentation handling, and indented HTML table
conversion under Paragraph wrapping and a new HTML table conversion
section.

docs/developers-guide.md: add a Stateful pipeline helpers section
describing `HtmlTableState`, `DefinitionScanState`, and `ListState`.

lists.rs, html.rs: add proptest properties for
`ListState::next_number` (newly seen or re-emerged indents always
return 1) and `HtmlTableState::push_html_line` (`in_html()` agrees
with `depth > 0` after every push, so `saturating_sub` and the flush
gate stay coherent).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
definitions.rs: spell "finalized" with the Oxford -ize ending so the
comment matches both the en-GB-oxendict convention used elsewhere in
the project and the existing `finalize_numeric_candidates` function
name.

tests/wrap_unit.rs: split the 430-line integration test into focused
submodules under `tests/wrap_unit/` so each file sits within the
400-line repository limit. The entry point now wires the
`code_spans`, `prefixed`, `footnotes`, `shell_blocks`, and `stream`
submodules with `#[path]`. Each submodule carries its own imports;
the `assert_footnote_reference_is_intact` helper moves into the
footnotes submodule (its sole caller). Insta snapshot files keep
their reviewed content; they are renamed without the `wrap_unit__`
prefix to match the path insta now picks for the relocated tests,
with `prepend_module_to_snapshot = false` pointing them back to
`tests/snapshots/`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Parameterize duplicated wrap regression tests, strengthen lossless wrapping
assertions, and split definition-block reordering into smaller helper
functions while preserving the existing writeback behaviour.
Update the `reorder_definition_block` Rustdoc so it matches the warning
emitted when row-count mismatches cause reordering to be skipped.
Add module-level documentation to the HTML and list test modules so
module docs remain complete for nested property-test coverage.

Emit tracing events for whitespace normalisation, HTML table conversion,
ordered-list state resets, and unsupported wrapping prefixes so these
behavioural decisions are visible during diagnostics.
Move HTML and inline postprocess tests into test-only child modules so the
production source files stay below the repository line limit while retaining
access to private helpers.

Lower the HTML table conversion event from `warn!` to `debug!` because normal
conversions should not be reported as warnings.
Make HTML table start-tag counting match end-tag counting so nested or compact
table markup adjusts parser depth consistently.

Keep `convert_html_tables` documentation contiguous before `#[must_use]`, and
collapse unchanged rebalance cases into one parameterised rstest.
Tighten the `convert_html_tables` Rustdoc so fenced-code behaviour is described
once while preserving the existing examples and attribute placement.
Require HTML table conversion to enter a block only when `<table>` starts the
trimmed Markdown line, so inline mentions are preserved as ordinary text.

Keep a separate unanchored table-tag regex for depth counting once a table
block is already active.
@lodyai
lodyai Bot force-pushed the feedback-following-code-fmt branch from 4f6baa1 to 650d4e8 Compare June 1, 2026 20:57
Remove extra blank lines in the developers and users guides, and restore the
required blank line before the test infrastructure heading.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/footnotes/renumber/definitions.rs (1)

1-450: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Decompose file to comply with 400-line limit.

This file contains 450 lines, exceeding the repository's 400-line maximum. Extract helper functions or split the implementation into focused submodules.

Potential decomposition strategies:

  • Extract segment-building helpers (lines 287-364) into a segments submodule
  • Extract scan state and collection logic (lines 74-274) into a scanning submodule
  • Move numeric candidate handling (lines 153-239) into a candidates submodule

As per coding guidelines, "Files must not exceed 400 lines in length".

♻️ Duplicate comments (2)
tests/wrap_unit/stream.rs (1)

41-48: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Assert opener coupling on every output line.

Update Line 42–47 to validate all lines, not only lines containing backticks. Prevent a false pass when the opener is stranded on a backtick-free line.

Proposed fix
-    for line in &output {
-        if line.contains('`') {
-            assert!(
-                !line.ends_with(opener),
-                "opening bracket must stay with inline code on line: {line:?}"
-            );
-        }
-    }
+    assert!(
+        output.iter().all(|line| !line.ends_with(opener)),
+        "opening bracket must stay with inline code: {output:?}"
+    );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/wrap_unit/stream.rs` around lines 41 - 48, The current loop in the
tests/wrap_unit/stream.rs that iterates "for line in &output" only performs the
"assert!(!line.ends_with(opener), ...)" when the line contains '`', which allows
a stranded opener on a backtick-free line to slip through; remove the
conditional "if line.contains('`')" so the assert executes for every line in the
"for line in &output" loop (keeping the same assertion message) to ensure opener
coupling is validated on all output lines.
src/footnotes/renumber/tests.rs (1)

16-18: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Surface the offending line in the assertion.

This assertion still fails without naming the input despite the earlier request to add a diagnostic message.

📝 Proposed enhancement
 fn malformed_numeric_candidate_line_is_ignored(#[case] line: &str) {
-    assert!(numeric_candidate_from_line(line, 0).is_none());
+    assert!(
+        numeric_candidate_from_line(line, 0).is_none(),
+        "expected None for malformed numeric candidate line: {line}"
+    );
 }

As per coding guidelines: "In Rust tests, prefer .expect(...) over .unwrap() to surface clearer failure diagnostics."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/footnotes/renumber/tests.rs` around lines 16 - 18, The test
malformed_numeric_candidate_line_is_ignored should include the input on failure
so diagnostics show the offending line; change the assertion to include a
message with the `line` value (e.g. use
assert!(numeric_candidate_from_line(line, 0).is_none(), "offending line: {:?}",
line) or assert_eq!(None, numeric_candidate_from_line(line, 0), "offending line:
{:?}", line)) so failures print the problematic input; locate this in the
malformed_numeric_candidate_line_is_ignored test and update the assert
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/architecture.md`:
- Line 390: Edit the sentence "Its depth counter tracks nested `<table>` blocks
so only the outermost table is converted at once" and insert a comma before "so"
so it reads: "Its depth counter tracks nested `<table>` blocks, so only the
outermost table is converted at once"; locate this exact fragment (mentioning
"depth counter" and `<table>`) in docs/architecture.md and update the
punctuation accordingly.

In `@docs/developers-guide.md`:
- Line 599: The sentence fragment "which drains the buffer in reverse so the
assigned numbers reflect" needs a comma before "so" to separate the independent
clauses; update the text (the phrase containing "which drains the buffer in
reverse so the assigned numbers reflect") to read "which drains the buffer in
reverse, so the assigned numbers reflect".
- Line 598: Replace the British spelling "finalised" with the
en-GB-oxendict-compliant "finalized" to match the existing function name
finalize_numeric_candidates and the project's spelling guidelines; update the
occurrence in the docs (the phrase "finalised at the end via
`finalize_numeric_candidates`") so the word and the referenced function name use
the same "-ize" form for consistency.
- Line 573: The sentence fragment "Each owns one slice of pipeline behaviour so
the surrounding" needs a comma before "so" to separate the two independent
clauses; update the sentence in docs/developers-guide.md (the line containing
"Each owns one slice of pipeline behaviour so the surrounding") to read "Each
owns one slice of pipeline behaviour, so the surrounding" ensuring punctuation
is corrected.
- Line 609: Edit the sentence fragment "next sequential number for that level —
incrementing the counter so the next" in docs/developers-guide.md and insert a
comma before "so" so it reads "...incrementing the counter, so the next" to
separate the independent clauses properly.

In `@src/footnotes/renumber/tests.rs`:
- Around line 37-41: Add a module-level doc comment at the top of the
proptest_tests module: insert a //! docstring immediately above "mod
proptest_tests" that succinctly explains the module's purpose (property tests
for renumbering footnotes using proptest and Regex) and how it is used,
mirroring the style of the sibling proptest_tests in src/lists.rs; ensure it
precedes the use/imports and the module declaration so the comment is
module-level.

---

Duplicate comments:
In `@src/footnotes/renumber/tests.rs`:
- Around line 16-18: The test malformed_numeric_candidate_line_is_ignored should
include the input on failure so diagnostics show the offending line; change the
assertion to include a message with the `line` value (e.g. use
assert!(numeric_candidate_from_line(line, 0).is_none(), "offending line: {:?}",
line) or assert_eq!(None, numeric_candidate_from_line(line, 0), "offending line:
{:?}", line)) so failures print the problematic input; locate this in the
malformed_numeric_candidate_line_is_ignored test and update the assert
accordingly.

In `@tests/wrap_unit/stream.rs`:
- Around line 41-48: The current loop in the tests/wrap_unit/stream.rs that
iterates "for line in &output" only performs the
"assert!(!line.ends_with(opener), ...)" when the line contains '`', which allows
a stranded opener on a backtick-free line to slip through; remove the
conditional "if line.contains('`')" so the assert executes for every line in the
"for line in &output" loop (keeping the same assertion message) to ensure opener
coupling is validated on all output lines.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f507f378-a5f9-4cee-93c7-d39a073395cf

📥 Commits

Reviewing files that changed from the base of the PR and between 2559d49 and 1d362fc.

⛔ Files ignored due to path filters (3)
  • tests/snapshots/inline_footnote_reference_after_code_wrap.snap is excluded by !**/*.snap
  • tests/snapshots/inline_footnote_reference_after_opener_coupled_code_wrap.snap is excluded by !**/*.snap
  • tests/snapshots/inline_footnote_reference_wrap.snap is excluded by !**/*.snap
📒 Files selected for processing (25)
  • CHANGELOG.md
  • Cargo.toml
  • docs/architecture.md
  • docs/developers-guide.md
  • docs/users-guide.md
  • src/code_emphasis.rs
  • src/footnotes/renumber.rs
  • src/footnotes/renumber/definitions.rs
  • src/footnotes/renumber/definitions/tests.rs
  • src/footnotes/renumber/tests.rs
  • src/html.rs
  • src/html_tests.rs
  • src/lists.rs
  • src/wrap.rs
  • src/wrap/inline/postprocess.rs
  • src/wrap/inline/postprocess_tests.rs
  • src/wrap/paragraph.rs
  • src/wrap/tests/prefix.rs
  • tests/table/convert_html.rs
  • tests/wrap_unit.rs
  • tests/wrap_unit/code_spans.rs
  • tests/wrap_unit/footnotes.rs
  • tests/wrap_unit/prefixed.rs
  • tests/wrap_unit/shell_blocks.rs
  • tests/wrap_unit/stream.rs

Comment thread docs/architecture.md Outdated
Comment thread docs/developers-guide.md Outdated
Comment thread docs/developers-guide.md Outdated
Comment thread docs/developers-guide.md Outdated
Comment thread docs/developers-guide.md Outdated
Comment thread src/footnotes/renumber/tests.rs
@leynos

leynos commented Jun 1, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Fix punctuation and Oxford spelling in the architecture and developer docs.

Improve footnote renumbering test diagnostics and document the property-test
module while broadening stream opener assertions to every output line.
Add property coverage for paragraph wrapping prefixes, definition block
ordering, list pruning, and HTML table buffering.

Emit trace and debug events for numeric candidate skip decisions,
definition-block reorder exits, and HTML table buffer depth transitions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant