Skip to content

fix(documents.js): read text set in columns one column at a time - #1700

Merged
Mearman merged 2 commits into
mainfrom
fix/column-aware-line-reconstruction
Oct 25, 2026
Merged

Mearman merged 2 commits into
mainfrom
fix/column-aware-line-reconstruction

Conversation

@Mearman

@Mearman Mearman commented Oct 25, 2026

Copy link
Copy Markdown
Member

PDF reconstruction read two-column pages interleaved. clusterIntoLines merges every item sharing a baseline into one line across the full page width, so when two prose columns have the same leading (HSE's HSG141 guidance is an example: 12pt on 15pt leading, columns at x 56.7 and 303, baselines a twentieth of a point apart) every line came out as "left-column line, right-column line", and a sentence's subject and predicate ended up separated by text from the other column. The presentation direction had the same problem, and on pages whose column baselines do not line up the y sort interleaved the columns line by line instead.

The page's text is now split into reading-order flows before any line or paragraph clustering (src/layout/reading-order.ts). A gutter is a vertical strip that no item touches over a run of consecutive lines, wider than the natural word space of those lines, with text on both sides. It splits only when the text on each side reads as running prose: at least three lines, a measure of at least twenty of its own average character advances (half the lower end of Bringhurst's 40 to 50 characters for multi-column work), word gaps narrower than the strip, and a majority of lines that wrap, meaning each stops short of the column's right edge by less than the next line's first word plus a space. Lines crossing the strip (a full-width heading, a boxed passage spanning both columns) end the band and are read in page order before or after it, and each side and each remaining band is split again, so three columns work too. Images, recovered tables and the page's drawing are placed by the band and column their position falls in, then by height.

Tables keep their rows. A table's columns also leave empty strips with shared baselines, but a column of codes or figures is a few characters wide, and a column of short cells is ragged by far more than a word, so neither passes as prose and the page keeps its full-width lines. A page with no gutter, or with an item whose horizontal extent the reader did not report (no width, vertical writing, rotation), is one flow holding exactly the items it was given, so its output is unchanged.

The new tests build pages from plain LayoutText data: two prose columns (one item per line and one per word), a full-width heading above two columns, a spanning passage between two column bands, uneven column lengths, an image in the right column, the presentation direction, a single column, and three table shapes (an equal-width grid of figures, wide columns of short ragged cells, short codes beside long descriptions). On the code before this change the seven column tests fail with the interleaved text and the four single-column and table tests pass; with the prose test disabled the three table tests fail, and with only the wrap test disabled the ragged-cell table fails. The README's PDF reconstruction paragraph describes the behaviour.

Line clustering merged every item sharing a baseline into one line
across the full page width, so two prose columns whose baselines line up
read as "left line, right line" for every line, interleaving the page.

Split a page's text at the column gutters its own geometry states before
clustering lines: a strip no item touches over a run of consecutive
lines, with text on both sides that reads as running prose (a measure of
at least twenty characters, lines that wrap, word gaps narrower than the
strip). Lines crossing the strip, such as a full-width heading, form
their own bands read in page order. Each side is split again, so three
columns read correctly too.

Tables keep their rows: their columns fail the prose test, being a few
characters wide or holding cells ragged by more than a word. A page with
no gutter is one flow holding exactly the items it was given.

Images, recovered tables and drawings are placed by the band and column
their position falls in, then by height, in both the wordprocessing and
the presentation directions.
…n both sides

Its label column was narrower than the prose measure, so the measure alone kept it
whole and the line-wrap test it was meant to exercise never decided anything.
@Mearman
Mearman marked this pull request as ready for review October 25, 2026 23:01
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ⚠️ Failed 2026-10-25T23:01:36.300077Z
We couldn’t complete this review. Comment @codex security review to try again.
f93576a Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins.

@Mearman
Mearman added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit b9174f8 Oct 25, 2026
34 checks passed
@Mearman
Mearman deleted the fix/column-aware-line-reconstruction branch October 25, 2026 23:07
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 14.6.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

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