Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix: prevent table rows from being broken by line wrapping (#36)#37

Open
jlevy wants to merge 5 commits intomainfrom
claude/review-issues-35-36-kjE3n
Open

fix: prevent table rows from being broken by line wrapping (#36)#37
jlevy wants to merge 5 commits intomainfrom
claude/review-issues-35-36-kjE3n

Conversation

@jlevy
Copy link
Owner

@jlevy jlevy commented Feb 17, 2026

Summary

Fixes #36. When a table directly follows paragraph text without a blank line, Marko's GFM parser doesn't recognize it as a Table element—the table rows are parsed as inline content within a Paragraph. The line wrapper then breaks wide rows at the wrap width (88 chars), producing invalid markdown like Geo:\nIntl % |. This PR makes the line wrapper always preserve table rows on single lines.

Additionally fixes table separator rendering to preserve original dash widths instead of normalizing everything to | --- |.

Changes

  • src/flowmark/linewrapping/tag_handling.py: Modified add_tag_newline_handling() to:
    • Always treat table rows (|-prefixed lines) as segment boundaries, regardless of whether template tags are present (previously only activated when tags were detected)
    • Pass table-row segments through verbatim instead of sending them to the base wrapper, preventing any width-based wrapping
    • Preserve existing behavior for list items (only segment boundaries when tags are present)
  • src/flowmark/formats/flowmark_markdown.py: Modified render_table() to preserve original table separator dash widths (ensuring a minimum of 3 dashes) instead of normalizing all separators to exactly ---
  • tests/test_wrapping.py: Added 4 new unit tests + updated 1 existing test:
    • test_table_rows_preserved_without_tags — table rows in paragraphs stay on own lines
    • test_wide_table_rows_not_wrapped — exact reproduction of issue Wide table header rows broken mid-cell by line wrapping #36
    • test_table_rows_with_semantic_wrapping — semantic mode also preserves rows
    • test_table_rows_only_no_surrounding_text — standalone table rows preserved
    • test_block_heuristics_only_with_tags_for_lists — updated regression guard (renamed from test_block_heuristics_only_with_tags)
  • tests/test_filling.py: Added 2 integration tests via fill_markdown():
  • tests/testdocs/: Added "Wide Table Adjacent to Paragraph" section to testdoc.orig.md and updated all 4 expected output files (plain, semantic, cleaned, auto) — now with preserved separator dash widths

Test Plan

  • All 287 tests pass (full suite: python -m pytest tests/ -v)
  • All 4 inline doctests pass (python -m pytest src/flowmark/linewrapping/block_heuristics.py)
  • All 4 golden reference doc tests pass (plain, semantic, cleaned, auto modes)
  • Table separator dashes are preserved (not normalized to minimum 3)
  • Manual testing: run flowmark --auto on a file containing a wide table directly after paragraph text (no blank line) — verify table rows are preserved on single lines
  • Manual testing: run flowmark --auto on a file with a standalone wide table (blank line before it) — verify separator dashes are preserved
  • Manual testing: verify normal paragraph text still gets reflowed at wrap width
  • Edge case: table rows inside template tags ({% field %}) — verify existing behavior preserved
  • Edge case: table rows inside blockquotes — verify no interference
  • Edge case: table with alignment markers (:---:, :---, ---:) — verify alignment preserved
  • Edge case: list items without tags — verify they are NOT treated as segment boundaries (regression guard)

Related Beads

  • fm-1422 (epic): Fix table rows broken by line wrapping when parsed as paragraph content (issue Wide table header rows broken mid-cell by line wrapping #36)
  • fm-625c: Core fix — remove has_tags guard for table row detection
  • fm-y6np: Unit tests in test_wrapping.py
  • fm-gt51: Integration tests in test_filling.py
  • fm-vzb9: Reference doc test updates
  • fm-ngl0: Regression guard verification
  • fm-3ahm: Full test suite run

https://claude.ai/code/session_01JESDwDj2UYgf9v5yttYyxr

Table rows (lines starting with |) are structural markdown elements that
must remain on a single line. When Marko's GFM parser doesn't recognize
a table (e.g. when it directly follows paragraph text without a blank
line), the rows were parsed as paragraph content and broken by the line
wrapper at the wrap width.

Fix: always treat table rows as segment boundaries in the tag handling
layer, and pass table-row segments through without wrapping. List items
retain the existing behavior (only segment boundaries when tags present).

https://claude.ai/code/session_01JESDwDj2UYgf9v5yttYyxr
Fixes ruff E741 (ambiguous variable name) and basedpyright
reportUnknownMemberType warning.

https://claude.ai/code/session_01JESDwDj2UYgf9v5yttYyxr
Copy link
Owner Author

@jlevy jlevy left a comment

Choose a reason for hiding this comment

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

.

table rows as paragraph content rather than a table element.
The line wrapper must still preserve each table row on its own line.
| Quarter | Revenue ($M) | YoY % | QoQ % | Segment A % | Segment B % | Geo: US % | Geo: Intl % |
|---------|-------------|-------|-------|-------------|-------------|-----------|-------------|
Copy link
Owner Author

Choose a reason for hiding this comment

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

Why is this removing the dashes? Shouldn't it be a minimum of 3 dashes ?

…zing to 3

Previously render_table() normalized all separator dashes to exactly
3 (e.g. `| --- | --- |`), discarding the original column alignment.
Now preserves the original dash widths from the source while ensuring
a minimum of 3 dashes per column.

https://claude.ai/code/session_01JESDwDj2UYgf9v5yttYyxr
Reverts the dash-preserving change. Normalizing separators to `| --- |`
is the cleaner approach. Updated expected test docs accordingly.

https://claude.ai/code/session_01JESDwDj2UYgf9v5yttYyxr
Tables adjacent to paragraph text bypass the Marko parser and pass through
the line wrapper verbatim. Added normalize_table_separator() to
block_heuristics.py so the line wrapper also normalizes separator rows
to `| --- |`, consistent with the Marko-parsed table rendering.

https://claude.ai/code/session_01JESDwDj2UYgf9v5yttYyxr
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.

Wide table header rows broken mid-cell by line wrapping

2 participants