render: correct output with post-render width - #83
Merged
Conversation
Two places sized layout from pre-render text instead of the visible width of what actually gets printed. format_table measured column widths on the raw markdown cell, so a link like `[ENG-396](https://linear.app/jellyfishco/issue/ENG-396)` counted as 55 columns even though it renders as just `ENG-396` (7). strip_ansi only removes escape sequences; it does not render markdown. The same overcount applied to `**bold**` and `` `code` ``. Now the header and rows are run through format_inline once up front, widths are measured on those rendered strings with display_width, and the formatted cells are reused when rendering (also avoids formatting every cell twice). wrap_text measured its indents with raw .width(). Most callers pass plain spaces, but format_callout passes a colored bar ("\e[34m | \e[0m"), so callouts believed their prefix was ~11 columns instead of 3 and wrapped ~8 columns early. Both indents now use display_width, which leaves display_width as the only caller of UnicodeWidthStr::width. table_inline_formatting.toml encoded the buggy widths (`**Alice**` as 9), so it is updated to the correct rendered widths.
llimllib
force-pushed
the
better-tables
branch
from
August 19, 2026 13:17
2b92459 to
179456d
Compare
The documented workflow said to publish the transcript as a public gist, but every recent PR commits an HTML export to transcripts/ instead, via the pr-transcript skill. Document what the repo actually does. Also note the commit-signing failure mode: commit.gpgsign is on with an SSH key, and sandboxed agents usually cannot read ~/.ssh, so git commit fails with 'Couldn't load public key' until you pass --no-gpg-sign.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two places sized layout from pre-render text rather than the visible width of what actually gets printed.
1. Table columns counted the markdown source
format_tablemeasured column widths on the raw cell:strip_ansionly removes escape sequences — it does not render markdown. So a link like[ENG-396](https://linear.app/company/issue/ENG-396)counted as 55 columns even though it renders as justENG-396(7). The same overcount applied to**bold**and`code`.Reported case, a table whose Ticket column is all links:
Before — Ticket column padded to 55:
After — 7:
The header and rows now go through
format_inlineonce up front, widths are measured on those rendered strings withdisplay_width, and the formatted cells are reused when rendering (which also stops every cell being formatted twice).2.
wrap_textmeasured its indents with raw.width()Most callers pass plain-space indents, but
format_calloutpasses a colored bar:The escape bytes were counted, so callouts believed their prefix was ~11 columns instead of 3 and wrapped ~8 columns early. At
--width 70(ANSI stripped, lengths shown):Both indents now use
display_width. As a side effectUnicodeWidthStr::widthis called from exactly one place (display_width), so all text measurement funnels through the ANSI-stripping path.Sites audited and found correct
format_paragraphformat_inlinebeforewrap_textformat_list— bullet / ordered / taskformat_blockquote" │ "prefix has no ANSIformat_calloutwrap_texttoken widthsdisplay_widthalign_celldisplay_width; now always receives rendered texttry_render_mermaid_asciidisplay_width; ASCII art is pre-rendered anywayformat_heading,format_horizontal_rule,format_code_blockprocess_imageimg.width()is image pixels, unrelatedapply_padding(main.rs)Tests
tests/fixtures/blocks/table_inline_formatting.toml— this fixture encoded the buggy widths (**Alice**measured as 9), updated to the correct rendered widths.tests/fixtures/blocks/table_link_width.toml— new, covers the link case.tests/fixtures/wrapping/callout_wrap.toml— new, covers the callout bar prefix.cargo fmt -- --check,cargo clippy --all-targets --all-features -- -D warnings, and all 171 tests pass.Docs
CLAUDE.mdtold agents to publish the transcript as a public gist, but every recent PR commits an HTML export totranscripts/via thepr-transcriptskill. Updated it to describe what the repo actually does, including how to guess the PR number for the filename before the PR exists.Also documented the commit-signing failure mode:
commit.gpgsignis on with an SSH key, and sandboxed agents usually cannot read~/.ssh, sogit commitdies withCouldn't load public keyuntil--no-gpg-signis passed.Note
The commits here are unsigned — the sandbox could not read
~/.sshto load the signing key. Amend withgit commit --amend -S --no-editif you want it signed.Session transcript
Pi session transcript (
transcripts/83-fix-table-and-wrap-widths.html)