Skip to content

fix(engine): contain long inline-code within its column#307

Merged
DemchaAV merged 3 commits into
developfrom
feat/auto-column-composed-width
Jul 6, 2026
Merged

fix(engine): contain long inline-code within its column#307
DemchaAV merged 3 commits into
developfrom
feat/auto-column-composed-width

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Why

A long inline-code token with no whitespace — a package coordinate, FQCN or URL
like org.junit.jupiter:junit-jupiter:5.10.2 — overflowed its paragraph or
table cell and drew over the neighbouring content, silently (no exception). It
surfaced through graph-compose-markdown rendering a Markdown table, where a
coordinate lands in a narrow fixed-width column. Prose wrapped fine; only long
unbreakable code tokens spilled. Two root causes: all three paragraph wrap paths
placed a lone over-wide token as-is (the first-token / empty-line branch skipped
any break), and a composed cell contributed zero natural width, so an auto()
column collapsed toward zero instead of sizing to its content.

What changed

  • TextFlowSupport — break over-wide tokens on all three wrap paths.
    wrapParagraph, wrapInlineParagraph and wrapMarkdownParagraph now route a
    lone over-wide token through a new breakLongToken helper instead of placing
    it raw. It prefers soft seams (. : / -) so coordinates and URLs break
    at readable boundaries, and char-splits any segment still too wide as the
    containment guarantee. A token that already fits takes the unchanged fast
    path, so existing prose and layout are byte-identical (no snapshot churn).
  • Highlight chips break too, fill intact per fragment. An over-wide chip
    word is split into pieces that keep the run's highlightGroup and
    background, with the outer padding on the first and last piece only and the
    break seams open — the existing per-line coalescer paints one rounded fill per
    fragment with no change. Links stay clickable on each fragment.
  • TableLayoutSupport.composedAutoCellNaturalWidthauto() columns size to
    composed content.
    A composed cell (DocumentTableCell.node(...)) in an
    auto() column now contributes its intrinsic content width, measured against
    the table's inner width so it self-clamps, reusing the same
    RowSlots.intrinsicColumnWidths prepare-to-measure pattern. fixed(...)
    columns are untouched, so a chip in a fixed column keeps its declared width
    and breaks inside it.

Verification

./mvnw -B -ntp clean verify -pl .BUILD SUCCESS, 1621 tests, no snapshot
drift. New coverage: over-wide break on plain / inline / markdown paths,
soft-seam breaking, per-fragment chip fill and one clickable rect per fragment,
narrow-cell containment (with a committed LayoutSnapshotAssertions baseline and
a target/visual-tests PDF), and auto() grows-to-one-fragment vs fixed()
breaks-to-many. GenerateAllExamplesSmokeTest green with a runnable
InlineCodeColumnWrapExample, its committed preview PDF and an examples/README
row.

Lane: shared-engine — paragraph wrap + table column sizing; no public API
change (all-private helpers). Behaviour documented in CHANGELOG ## v1.9.1 — Planned.

Notes

  • As with plain-text auto() columns, a table too narrow for the summed
    intrinsic width of its auto() columns now reports exceeds available width
    where it previously collapsed silently — consistent and intended.
  • Composed auto() cells are prepared twice (measure + final layout), bounded to
    that case only; this matches the existing RowSlots intrinsic-width idiom.
  • Char-split is the mandatory fallback (a dot-less 40-char identifier has no
    seam); soft-seam breaking is the readability layer on top of it.

DemchaAV added 3 commits July 6, 2026 00:40
Long code tokens with no whitespace — package coordinates, FQCNs, URLs
like org.junit.jupiter:junit-jupiter:5.10.2 — overflowed a paragraph or
table cell instead of wrapping, drawing over the neighbouring content.
All three paragraph wrap paths placed a lone over-wide token as-is, and
highlight-chip words were never broken at all.

Route an over-wide token through a new breakLongToken helper on the plain,
inline, and markdown wrap paths. It breaks at soft seams (. : / -) so
coordinates and URLs split at readable boundaries, and char-splits any
segment still too wide as a last resort. Highlight-chip words break the
same way while keeping one rounded fill per visual fragment: the split
pieces retain the run's highlight group and background, with the outer
padding on the first and last fragment only and the break seams open.

Tokens that already fit follow the unchanged fast path, so existing prose
and layouts are byte-identical (full suite green, no snapshot drift).
A composed table cell (DocumentTableCell.node(...)) contributed no natural
width, so an AUTO column holding only composed content collapsed toward zero
and its child — an inline-code chip, say — was laid out at a near-zero width.

Measure a composed cell's intrinsic content width in resolveNaturalColumnWidths
and feed it into the AUTO column's natural width, reusing the same
prepare-to-measure pattern as RowSlots.intrinsicColumnWidths. The child is
measured against the table's inner width, so one cell can never demand more
than the table can give. Only single-column composed cells in AUTO columns are
measured; plain-text cells, FIXED columns and spanning cells are unchanged, so
a chip in a FIXED column keeps its declared width and breaks inside it.

As with plain-text AUTO columns, a table too narrow for the summed intrinsic
width of its AUTO columns still reports "exceeds available width".
InlineCodeColumnWrapExample renders a long inlineCode(...) coordinate breaking
at its . : / - seams inside a narrow fixed column and fitting on one line in an
auto column, registered in GenerateAllExamples with a committed preview PDF and
a README quick-reference row. CHANGELOG v1.9.1 documents the chip-overflow fix
and the auto-column sizing.
@DemchaAV DemchaAV merged commit bf59fdc into develop Jul 6, 2026
11 checks passed
@DemchaAV DemchaAV deleted the feat/auto-column-composed-width branch July 6, 2026 07:05
@DemchaAV

DemchaAV commented Jul 6, 2026

Copy link
Copy Markdown
Owner Author

Perf smoke A/Bdevelop vs this branch (ab-bench.sh -p smoke -r 3, medians):

Normal scenarios are within laptop noise (±5–10%, mixed direction), so no general hot-path regression — consistent with the fit fast-path being byte-identical:

scenario avg p95 docs/s
cv-template −1.2% +7.7% +1.3%
engine-simple −7.4% −5.6% +7.9%
invoice-template −5.8% −8.0% +6.2%
proposal-template −5.5% −9.3% +5.8%
feature-rich +4.5% +14.3% −4.3%
vector-rich +3.9% +10.0% −3.9%
long-token +13.4% +13.6% −12.0%

The long-token worst-case scenario is ~13% slower across all three metrics (so real, not noise): breakLongToken does genuine seam-analysis + breaking on over-wide tokens that previously overflowed (placed raw). Bounded to the over-wide path; negligible on real documents, which the six normal scenarios confirm.

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.

1 participant