Skip to content

Refactor list renumbering#69

Merged
leynos merged 3 commits intomainfrom
codex/refactor-list-renumbering-logic
Jul 15, 2025
Merged

Refactor list renumbering#69
leynos merged 3 commits intomainfrom
codex/refactor-list-renumbering-logic

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Jul 14, 2025

Summary

  • extract parse_numbered helper for numbered line parsing
  • simplify renumber_lists using a stack and map

Testing

  • make lint
  • make test

https://chatgpt.com/codex/tasks/task_e_687555d1e5308322a8e4f5878f0cd6cb

Summary by Sourcery

Refactor list renumbering by extracting parsing and indentation helpers, simplify the renumber_lists implementation with a stack-based counter, treat tabs as four spaces for indentation, update documentation, and add a test for tab-indented lists

Enhancements:

  • Extract parse_numbered, indent_len, and drop_deeper helper functions to modularise list renumbering
  • Simplify renumber_lists by leveraging the new helpers and a stack-based counter
  • Treat tabs as four spaces when measuring indentation for ordered lists

Documentation:

  • Update README to document tab-based indentation handling and fix line-wrapping formatting

Tests:

  • Add integration test for renumbering lists with tab-indented items

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Jul 14, 2025

Reviewer's Guide

Refactor and simplify Markdown list renumbering by extracting parsing and indentation helpers, streamlining counter stack logic, enhancing documentation, updating README formatting and instructions, and adding targeted tests.

Class diagram for refactored list renumbering helpers

classDiagram
    class parse_numbered {
        <<function>>
        +parse_numbered(line: &str) Option<(indent: &str, sep: &str, rest: &str)>
    }
    class indent_len {
        <<function>>
        +indent_len(indent: &str) usize
    }
    class drop_deeper {
        <<function>>
        +drop_deeper(indent: usize, counters: &mut Vec<(usize, usize)>)
    }
    class renumber_lists {
        +renumber_lists(lines: &[String]) Vec<String>
    }
    renumber_lists --> parse_numbered : uses
    renumber_lists --> indent_len : uses
    renumber_lists --> drop_deeper : uses
Loading

Class diagram for updated renumber_lists logic

classDiagram
    class renumber_lists {
        +renumber_lists(lines: &[String]) Vec<String>
        -counters: Vec<(usize, usize)>
        -out: Vec<String>
    }
    class parse_numbered {
        <<function>>
        +parse_numbered(line: &str) Option<(indent: &str, sep: &str, rest: &str)>
    }
    class indent_len {
        <<function>>
        +indent_len(indent: &str) usize
    }
    class drop_deeper {
        <<function>>
        +drop_deeper(indent: usize, counters: &mut Vec<(usize, usize)>)
    }
    renumber_lists --> parse_numbered : uses
    renumber_lists --> indent_len : uses
    renumber_lists --> drop_deeper : uses
Loading

File-Level Changes

Change Details Files
Introduce helper functions for parsing numbered list lines and measuring indentation
  • Extract parse_numbered to centralize regex capture
  • Implement indent_len to treat tabs as spaces
  • Add drop_deeper to trim deeper counters based on indent
src/lib.rs
Refactor renumber_lists logic to streamline counter management
  • Replace manual regex captures with parse_numbered
  • Leverage indent_len and drop_deeper for indentation handling
  • Merge list initialization and increment into a single match branch
src/lib.rs
Enrich renumber_lists documentation with examples
  • Add doc examples demonstrating expected renumbering behavior
  • Document panic condition for empty counter stack
src/lib.rs
Update README formatting and renumbering instructions
  • Reflow lines for consistent wrapping
  • Clarify that tabs count as four spaces for --renumber
README.md
Add integration test for tab-based indentation renumbering
  • Introduce test_renumber_tabs_in_indent in integration tests
tests/integration.rs

Possibly linked issues

  • #0: PR extracts parser, uses stack/map for counters, simplifies loops as suggested by the issue.

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 14, 2025

Summary by CodeRabbit

  • New Features
    • Improved handling of numbered lists with mixed indentation, treating tabs as four spaces for consistent renumbering.
  • Bug Fixes
    • Corrected renumbering of nested ordered list items when indentation uses tab characters.
  • Documentation
    • Enhanced documentation and examples for list renumbering, clarifying indentation rules and formatting for better readability.
  • Tests
    • Added an integration test to verify correct renumbering of lists with tab-indented items.

Summary by CodeRabbit

  • Documentation

    • Improved and expanded documentation with additional examples and notes for list renumbering functionality.
  • Refactor

    • Simplified and clarified the logic for handling numbered list indentation and counters, resulting in more consistent and reliable list renumbering.

Walkthrough

Refactor the renumber_lists function in src/lib.rs to use a new internal helper, parse_numbered, for extracting indentation and list details. Simplify the counter stack management logic for numbered lists, update variable naming for consistency, and expand documentation and examples for both functions.

Changes

File(s) Change Summary
src/lib.rs Add parse_numbered helper; refactor renumber_lists to use it; simplify stack logic; update docs and examples.
README.md Formatting and line-wrapping adjustments for improved readability; clarify tab indentation counts in --renumber option.
tests/integration.rs Add integration test for renumber_lists handling of tab-indented numbered lists.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant renumber_lists
    participant parse_numbered

    Caller->>renumber_lists: Provide lines (Vec<String>)
    loop For each line
        renumber_lists->>parse_numbered: Parse indentation, separator, remainder
        alt Line is numbered
            renumber_lists->>renumber_lists: Update counters stack
            renumber_lists->>renumber_lists: Format renumbered line
        else Line is not numbered
            renumber_lists->>renumber_lists: Output line unchanged
        end
    end
    renumber_lists-->>Caller: Return renumbered lines
Loading

Possibly related issues

Possibly related PRs

Poem

In code’s neat lines, a helper appears,
To parse the numbers, allaying old fears.
Stacks pop and push, indentation in tow,
Lists renumbered, in tidy new flow.
With logic refined and docs now bright,
Markdown lists march on, numbered just right!
📝✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/refactor-list-renumbering-logic

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes and found some issues that need to be addressed.

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/lib.rs:615` </location>
<code_context>
+
     let mut out = Vec::with_capacity(lines.len());
-    let mut counters: Vec<(usize, usize)> = Vec::new();
+    let mut stack = Vec::<usize>::new();
+    let mut counters = HashMap::<usize, usize>::new();
     let mut in_code = false;
</code_context>

<issue_to_address>
Consider reverting to a single Vec<(indent, count)> for tracking list numbering instead of using both a stack and a HashMap.

Here’s a way to keep the exact same behavior but collapse your two‐structure approach back into a single Vec<(indent, count)>, and even keep using your new `parse_numbered` helper if you like. This is essentially the old “counters” Vec with inline push/pop logic, but using your regex parser:

```rust
pub fn renumber_lists(lines: &[String]) -> Vec<String> {
    let mut out = Vec::with_capacity(lines.len());
    let mut counters: Vec<(usize, usize)> = Vec::new();
    let mut in_code = false;

    for line in lines {
        if FENCE_RE.is_match(line) {
            in_code = !in_code;
            out.push(line.clone());
            continue;
        }
        if in_code {
            out.push(line.clone());
            continue;
        }

        // Use your parse_numbered helper
        if let Some((indent, sep, rest)) = parse_numbered(line) {
            // pop any deeper levels
            while counters.last().map_or(false, |&(d, _)| d > indent) {
                counters.pop();
            }
            match counters.last_mut() {
                Some((d, cnt)) if *d == indent => {
                    *cnt += 1;
                }
                _ => {
                    // new nesting level
                    counters.push((indent, 1));
                }
            }
            let current = counters.last().unwrap().1;
            out.push(format!(
                "{}{}.{}{}",
                " ".repeat(indent),
                current,
                sep,
                rest
            ));
            continue;
        }

        // Reset deeper counters when we hit a non‐numbered line
        let indent = line.chars().take_while(|c| c.is_whitespace()).count();
        while counters.last().map_or(false, |&(d, _)| d > indent) {
            counters.pop();
        }
        out.push(line.clone());
    }

    out
}
```

Steps to apply:

1. Remove the separate `stack` Vec and the `HashMap`.
2. Replace them with a single `Vec<(usize, usize)> counters` as above.
3. Keep using `parse_numbered` (or inline your regex) for clarity.
4. Pop off deeper levels before deciding to bump or push a new counter.
5. This restores the original one‐structure flow but preserves all new tests and fence‐handling.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/lib.rs Outdated

let mut out = Vec::with_capacity(lines.len());
let mut counters: Vec<(usize, usize)> = Vec::new();
let mut stack = Vec::<usize>::new();
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.

issue (complexity): Consider reverting to a single Vec<(indent, count)> for tracking list numbering instead of using both a stack and a HashMap.

Here’s a way to keep the exact same behavior but collapse your two‐structure approach back into a single Vec<(indent, count)>, and even keep using your new parse_numbered helper if you like. This is essentially the old “counters” Vec with inline push/pop logic, but using your regex parser:

pub fn renumber_lists(lines: &[String]) -> Vec<String> {
    let mut out = Vec::with_capacity(lines.len());
    let mut counters: Vec<(usize, usize)> = Vec::new();
    let mut in_code = false;

    for line in lines {
        if FENCE_RE.is_match(line) {
            in_code = !in_code;
            out.push(line.clone());
            continue;
        }
        if in_code {
            out.push(line.clone());
            continue;
        }

        // Use your parse_numbered helper
        if let Some((indent, sep, rest)) = parse_numbered(line) {
            // pop any deeper levels
            while counters.last().map_or(false, |&(d, _)| d > indent) {
                counters.pop();
            }
            match counters.last_mut() {
                Some((d, cnt)) if *d == indent => {
                    *cnt += 1;
                }
                _ => {
                    // new nesting level
                    counters.push((indent, 1));
                }
            }
            let current = counters.last().unwrap().1;
            out.push(format!(
                "{}{}.{}{}",
                " ".repeat(indent),
                current,
                sep,
                rest
            ));
            continue;
        }

        // Reset deeper counters when we hit a non‐numbered line
        let indent = line.chars().take_while(|c| c.is_whitespace()).count();
        while counters.last().map_or(false, |&(d, _)| d > indent) {
            counters.pop();
        }
        out.push(line.clone());
    }

    out
}

Steps to apply:

  1. Remove the separate stack Vec and the HashMap.
  2. Replace them with a single Vec<(usize, usize)> counters as above.
  3. Keep using parse_numbered (or inline your regex) for clarity.
  4. Pop off deeper levels before deciding to bump or push a new counter.
  5. This restores the original one‐structure flow but preserves all new tests and fence‐handling.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 15, 2025

@coderabbitai resume

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 15, 2025

✅ Actions performed

Reviews resumed.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 15, 2025

@sourcery-ai review

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes and found some issues that need to be addressed.

  • parse_numbered could return the indent string slice instead of length to reuse the original whitespace prefix and avoid repeated allocations from " ".repeat.
  • There's duplicated logic popping counters in both branches—consider extracting that into a helper to reduce repetition and improve clarity.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- parse_numbered could return the indent string slice instead of length to reuse the original whitespace prefix and avoid repeated allocations from " ".repeat.
- There's duplicated logic popping counters in both branches—consider extracting that into a helper to reduce repetition and improve clarity.

## Individual Comments

### Comment 1
<location> `src/lib.rs:667` </location>
<code_context>

-        let indent_len = line.chars().take_while(|c| c.is_whitespace()).count();
-        while counters.last().is_some_and(|(i, _)| *i > indent_len) {
+        let indent = line.chars().take_while(|c| c.is_whitespace()).count();
+        while counters.last().is_some_and(|(d, _)| *d > indent) {
             counters.pop();
</code_context>

<issue_to_address>
Whitespace counting may not match tab/space semantics in all Markdown renderers.

Some Markdown renderers handle tabs and spaces differently. For full compatibility, consider normalizing tabs to spaces or clearly documenting the current approach.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        let indent = line.chars().take_while(|c| c.is_whitespace()).count();
        while counters.last().is_some_and(|(d, _)| *d > indent) {
            counters.pop();
=======
        // Normalize tabs to 4 spaces for consistent indentation counting
        let normalized_line = line.replace('\t', "    ");
        let indent = normalized_line.chars().take_while(|c| c.is_whitespace()).count();
        while counters.last().is_some_and(|(d, _)| *d > indent) {
            counters.pop();
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/lib.rs Outdated
Comment on lines 667 to 669
let indent = line.chars().take_while(|c| c.is_whitespace()).count();
while counters.last().is_some_and(|(d, _)| *d > indent) {
counters.pop();
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.

suggestion: Whitespace counting may not match tab/space semantics in all Markdown renderers.

Some Markdown renderers handle tabs and spaces differently. For full compatibility, consider normalizing tabs to spaces or clearly documenting the current approach.

Suggested change
let indent = line.chars().take_while(|c| c.is_whitespace()).count();
while counters.last().is_some_and(|(d, _)| *d > indent) {
counters.pop();
// Normalize tabs to 4 spaces for consistent indentation counting
let normalized_line = line.replace('\t', " ");
let indent = normalized_line.chars().take_while(|c| c.is_whitespace()).count();
while counters.last().is_some_and(|(d, _)| *d > indent) {
counters.pop();

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19e5168 and adfdd3c.

📒 Files selected for processing (3)
  • README.md (4 hunks)
  • src/lib.rs (3 hunks)
  • tests/integration.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.md

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • AGENTS.md

⚙️ CodeRabbit Configuration File

**/*.rs

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • AGENTS.md

⚙️ CodeRabbit Configuration File

🧠 Learnings (1)
README.md (1)
Learnt from: CR
PR: leynos/mdtablefix#0
File: docs/html-table-support.md:0-0
Timestamp: 2025-07-13T13:00:34.632Z
Learning: Applies to docs/**/*.md : `mdtablefix` can format simple HTML `<table>` elements embedded in Markdown by transforming them into Markdown tables before reflow, using the `convert_html_tables` function.
🧬 Code Graph Analysis (1)
tests/integration.rs (1)
src/lib.rs (1)
  • renumber_lists (647-688)
🪛 LanguageTool
README.md

[style] ~82-~82: Would you like to use the Oxford spelling “recognizes”? The spelling ‘recognises’ is also correct.
Context: ...k. ## HTML table support mdtablefix recognises simple <table> elements embedded in M...

(OXFORD_SPELLING_Z_NOT_S)


[uncategorized] ~83-~83: Possible missing comma found.
Context: ... Markdown. Before the main table reflow runs these HTML tables are converted to Mark...

(AI_HYDRA_LEO_MISSING_COMMA)


[style] ~87-~87: To elevate your writing, try using an alternative expression here.
Context: ... detected, and attributes or tag casing do not matter. After conversion the regular reflow lo...

(MATTERS_RELEVANT)


[uncategorized] ~87-~87: Possible missing comma found.
Context: ...utes or tag casing do not matter. After conversion the regular reflow logic aligns them al...

(AI_HYDRA_LEO_MISSING_COMMA)


[locale-violation] ~98-~98: license must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ... This project is licensed under the ISC license. See the LICENSE file for de...

(LICENCE_LICENSE_NOUN_SINGULAR)


[locale-violation] ~98-~98: LICENSE must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...icensed under the ISC license. See the LICENSE file for details.

(LICENCE_LICENSE_NOUN_SINGULAR)

🔇 Additional comments (8)
src/lib.rs (5)

229-240: Well-implemented parsing helper.

The parse_numbered function correctly extracts components from numbered list lines using regex capture groups. The explicit extraction of indent, separator, and remainder provides clear separation of concerns.


242-248: Correct tab-to-space conversion logic.

The indent_len function properly handles tab characters by treating them as four spaces, which aligns with the documented behaviour and resolves the whitespace counting concern from past reviews.


250-255: Efficient counter management.

The drop_deeper function uses is_some_and for concise conditional logic and correctly removes counters with deeper indentation levels. This addresses the stack management requirements cleanly.


626-646: Comprehensive documentation with examples.

The enhanced documentation includes a clear example and panic note, following Rust documentation best practices. The example demonstrates the expected renumbering behaviour effectively.


664-683: Simplified and robust renumbering logic.

The refactored implementation successfully uses the new helper functions to create cleaner, more readable code. The logic correctly handles indentation changes and counter management whilst preserving the original indentation string in the output.

Note: This implementation maintains the single Vec<(usize, usize)> structure as suggested in past reviews, avoiding the complexity of separate stack and HashMap structures.

tests/integration.rs (1)

842-855: Thorough test coverage for tab indentation.

The test correctly verifies that nested list items indented with tabs are renumbered properly whilst preserving the tab characters in the output. The test input and expected output clearly demonstrate the intended behaviour of treating tabs as four spaces for indentation calculation.

README.md (2)

31-32: Clear documentation of tab behaviour.

The clarification that tabs count as four spaces for indentation in --renumber aligns perfectly with the implementation changes and addresses potential user confusion about indentation handling.


82-89: Apply British English spelling corrections.

The coding guidelines specify en-GB-oxendict spelling. Apply these corrections to align with the project's language standards:

-`mdtablefix` recognises simple `<table>` elements embedded in Markdown. Before
-the main table reflow runs these HTML tables are converted to Markdown in a
+`mdtablefix` recognises simple `<table>` elements embedded in Markdown. Before
+the main table reflow runs, these HTML tables are converted to Markdown in a
 preprocessing stage handled by `convert_html_tables`.

 Only basic tables composed of `<tr>`, `<th>` and `<td>` tags are detected, and
-attributes or tag casing do not matter. After conversion the regular reflow
+attributes or tag casing are irrelevant. After conversion, the regular reflow
 logic aligns them alongside Markdown tables. See [`docs/html-table-support.md`]
 (docs/html-table-support.md) for details.
⛔ Skipped due to learnings
Learnt from: CR
PR: leynos/mdtablefix#0
File: docs/html-table-support.md:0-0
Timestamp: 2025-07-13T13:00:34.632Z
Learning: Applies to docs/**/*.md : `mdtablefix` can format simple HTML `<table>` elements embedded in Markdown by transforming them into Markdown tables before reflow, using the `convert_html_tables` function.

Comment thread README.md
Comment on lines +98 to +99
This project is licensed under the ISC license. See the [LICENSE](LICENSE) file
for details.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Jul 15, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Correct licence spelling for British English.

Apply the British English spelling correction:

-This project is licensed under the ISC license. See the [LICENSE](LICENSE) file
+This project is licensed under the ISC licence. See the [LICENCE](LICENCE) file
 for details.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
This project is licensed under the ISC license. See the [LICENSE](LICENSE) file
for details.
This project is licensed under the ISC licence. See the [LICENCE](LICENCE) file
for details.
🧰 Tools
🪛 LanguageTool

[locale-violation] ~98-~98: license must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ... This project is licensed under the ISC license. See the LICENSE file for de...

(LICENCE_LICENSE_NOUN_SINGULAR)


[locale-violation] ~98-~98: LICENSE must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...icensed under the ISC license. See the LICENSE file for details.

(LICENCE_LICENSE_NOUN_SINGULAR)

🤖 Prompt for AI Agents
In README.md around lines 98 to 99, the word "license" should be corrected to
the British English spelling "licence". Update the text to use "licence" instead
of "license" to reflect the correct British English spelling.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

"LICENSE" is used here for community consistency

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.

@leynos, understood. The LICENSE filename is indeed a standard convention in the open source community, and maintaining this consistency makes perfect sense. I'll keep that in mind for future reviews.


✏️ Learnings added
Learnt from: leynos
PR: leynos/mdtablefix#69
File: README.md:98-99
Timestamp: 2025-07-15T07:15:47.096Z
Learning: The LICENSE filename should be kept as-is for community consistency in open source projects, even when using British English spelling elsewhere in documentation.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 15, 2025

@sourcery-ai review

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/lib.rs:681` </location>
<code_context>
-        while counters.last().is_some_and(|(i, _)| *i > indent_len) {
-            counters.pop();
-        }
+        let indent_part: String = line.chars().take_while(|c| c.is_whitespace()).collect();
+        let indent = indent_len(&indent_part);
+        drop_deeper(indent, &mut counters);
</code_context>

<issue_to_address>
Consider avoiding allocation by slicing the leading whitespace as a &str instead of collecting it into a String before measuring indentation.

Here’s a quick win: you don’t need to allocate a `String` just to measure the indent on non-numbered lines. Instead, slice off the leading whitespace and pass that `&str` to `indent_len`. This keeps one allocation out of the hot path and makes the non-numbered branch as straightforward as the numbered one.

```rust
// before
let indent_part: String = line.chars().take_while(|c| c.is_whitespace()).collect();
let indent = indent_len(&indent_part);
drop_deeper(indent, &mut counters);

// after
let indent_end = line
    .char_indices()
    .find(|&(_, c)| !c.is_whitespace())
    .map_or(line.len(), |(i, _)| i);
let indent_str = &line[..indent_end];
let indent = indent_len(indent_str);
drop_deeper(indent, &mut counters);
```

This preserves all existing behavior but avoids the intermediate allocation.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/lib.rs
while counters.last().is_some_and(|(i, _)| *i > indent_len) {
counters.pop();
}
let indent_part: String = line.chars().take_while(|c| c.is_whitespace()).collect();
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.

issue (complexity): Consider avoiding allocation by slicing the leading whitespace as a &str instead of collecting it into a String before measuring indentation.

Here’s a quick win: you don’t need to allocate a String just to measure the indent on non-numbered lines. Instead, slice off the leading whitespace and pass that &str to indent_len. This keeps one allocation out of the hot path and makes the non-numbered branch as straightforward as the numbered one.

// before
let indent_part: String = line.chars().take_while(|c| c.is_whitespace()).collect();
let indent = indent_len(&indent_part);
drop_deeper(indent, &mut counters);

// after
let indent_end = line
    .char_indices()
    .find(|&(_, c)| !c.is_whitespace())
    .map_or(line.len(), |(i, _)| i);
let indent_str = &line[..indent_end];
let indent = indent_len(indent_str);
drop_deeper(indent, &mut counters);

This preserves all existing behavior but avoids the intermediate allocation.

@leynos leynos merged commit 2e649bf into main Jul 15, 2025
2 checks passed
@leynos leynos deleted the codex/refactor-list-renumbering-logic branch July 15, 2025 11:16
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