Skip to content

Conversation

@jlevy
Copy link
Owner

@jlevy jlevy commented Jan 15, 2026

Summary

This PR adds a new --list-spacing CLI option to control how tight vs loose list formatting is handled during Markdown normalization.

Feature Plan: plan-2026-01-14-list-spacing-control.md

New Feature

Mode Behavior
preserve Keep lists tight or loose as authored (NEW DEFAULT)
loose Convert all lists to loose format (previous behavior)
tight Convert lists to tight format where possible

BREAKING CHANGE

The default behavior has changed from always making lists loose to preserving the original tight/loose formatting. Use --list-spacing=loose to restore the previous behavior.

Files Changed

Core Implementation:

  • src/flowmark/formats/flowmark_markdown.py - Added ListSpacing enum and modified list rendering
  • src/flowmark/linewrapping/markdown_filling.py - Added list_spacing parameter
  • src/flowmark/reformat_api.py - Threaded parameter through API
  • src/flowmark/cli.py - Added --list-spacing CLI argument

Automated Testing

All 172 tests pass. The following test coverage was added in tests/test_list_spacing.py:

Preserve Mode Tests (default):

  • test_tight_list_preserved - Tight lists stay tight
  • test_loose_list_preserved - Loose lists stay loose
  • test_preserve_is_default - Confirm preserve is the default
  • test_numbered_list_preserve - Numbered lists preserve tightness

Loose Mode Tests:

  • test_tight_list_to_loose - Tight lists become loose
  • test_loose_list_stays_loose - Loose lists stay loose
  • test_numbered_list_to_loose - Numbered lists become loose

Tight Mode Tests:

  • test_loose_list_to_tight - Loose lists become tight
  • test_tight_list_stays_tight - Tight lists stay tight
  • test_multi_para_stays_loose_in_tight_mode - Multi-paragraph items force loose (CommonMark requirement)

Nested List Tests:

  • test_nested_lists_independent_preserve - Each nested list independently preserves tightness
  • test_nested_lists_loose_outer_tight_inner - Mixed outer/inner tightness preserved

Complex Content Tests:

  • test_list_items_with_code_blocks_preserve - Code blocks preserve tightness
  • test_list_items_with_code_blocks_loose - Code blocks with loose mode
  • test_list_items_with_quote_blocks - Quote blocks preserve tightness

Spacing Normalization Tests:

  • test_input_spacing_normalization_loose - Various input spacings normalize to loose
  • test_input_spacing_normalization_tight - Various input spacings normalize to tight

Other Updated Tests:

  • test_escape_handling.py - Updated for backward compatibility
  • test_filling.py - Updated for backward compatibility
  • test_heading_spacing.py - Updated for backward compatibility

Manual Validation

All core functionality is covered by automated tests. Manual review is only needed for:

  1. Help text clarity - Review flowmark --help to confirm the --list-spacing option description is clear
  2. Breaking change documentation - Confirm the breaking change is adequately documented

Test Results

  • All 172 unit tests pass
  • make lint passes
  • make test passes
  • CI passes

Add a new `--list-spacing` CLI option with three modes:
- `preserve` (NEW DEFAULT): Keep lists tight or loose as authored
- `loose`: Convert all lists to loose format (previous default behavior)
- `tight`: Convert lists to tight format where possible

BREAKING CHANGE: Default behavior changed from always making lists loose
to preserving the original tight/loose formatting. Use `--list-spacing=loose`
to restore the previous behavior.

Implementation:
- Add `ListSpacing` enum in flowmark_markdown.py
- Thread `list_spacing` parameter through the API stack:
  flowmark_markdown() → MarkdownNormalizer → render_list() → render_list_item()
- Add `_can_be_tight()` helper to check if lists can be tight
- Update CLI with `--list-spacing` argument

Test updates:
- Rewrite test_list_spacing.py with comprehensive tests for all modes
- Update tests that were testing other behavior (escape handling, etc.)
  to explicitly use `list_spacing="loose"` to maintain their expectations
- Regenerate testdoc.expected.*.md files for new default behavior
Create validation spec documenting:
- All automated unit tests for preserve/loose/tight modes
- Manual CLI validation steps for the user
- Breaking change awareness notes
All core functionality is covered by automated tests. Manual review
is only needed for help text clarity and breaking change documentation.
Use `str, Enum` instead of `StrEnum` which was added in Python 3.11.
Remove type annotations from enum members which pyright doesn't allow.
@jlevy
Copy link
Owner Author

jlevy commented Jan 15, 2026

Addresses part of #13

@jlevy jlevy merged commit 1753753 into main Jan 15, 2026
5 checks passed
@jlevy jlevy deleted the claude/setup-repo-gh-cli-LAeQo branch January 15, 2026 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants