Skip to content

feat(pdf): join CJK text lines without a space - #4810

Open
kevin9327 wants to merge 2 commits into
docling-project:mainfrom
kevin9327:feat/cjk-line-join
Open

kevin9327 wants to merge 2 commits into
docling-project:mainfrom
kevin9327:feat/cjk-line-join

Conversation

@kevin9327

Copy link
Copy Markdown
Contributor

Part B of #4672 (the docling-side change; part A in docling-parse is independent).

Problem

PageAssembleModel.sanitize_text joins every line break of a cluster with " ". Chinese and Japanese put no spaces between words, so every wrapped line of a horizontal CJK paragraph gets a spurious space in the middle of a word or sentence (地方公共団 体, 准确识别版面结构并保留表格、公式和阅读顺序, 从而…).

Change

  • A break is closed up when the last character of the previous line and the first character of the next line are both Han, kana, or CJK / full-width punctuation (_CJK_NO_SPACE_RE; covers Extensions A–H, compatibility ideographs, half-width katakana, vertical punctuation forms).
  • Hangul is excluded, and a cluster that contains any Hangul keeps every space: Korean separates words with spaces, and Hanja inside Korean text (대한민국 憲法 第一條) are space-separated words too. This also leaves the Korean ground truth (normal_4pages) untouched.
  • Mixed breaks (docling は / PDF, 令和元年 / 10月) still get a space; hyphenation handling is unchanged.
  • The Hangul scan only runs once a CJK/CJK break is found, and a single code-point comparison skips the regex for Latin text.

Verification

  • tests/test_page_assemble_model.py: 17 new cases (Japanese, Chinese, full-width punctuation, half-width katakana, Ext-B ideograph, multi-line, mixed Latin/CJK, digits, Korean, Korean+Hanja, hyphenation, empty line). 6 of them fail on main; all 56 pass with this change.

  • End to end, standard PDF pipeline (no OCR) on a horizontal PDF rendered with Noto Serif CJK, counting spaces between two CJK characters in the output:

    paragraph main this PR
    Japanese (4 wrapped lines) 4 0
    Chinese (3 wrapped lines) 3 0
    Korean unchanged unchanged
  • Cost of sanitize_text on an 8-line cluster (best of 5 × 20k): Latin 2.75 → ~3.1–3.5 µs, Japanese 2.5 → 7.0 µs (that path now does the real work). Negligible next to the layout model per page.

  • ruff format/ruff check clean; mypy reports only the pre-existing FigureElement error on main.

Vertical text (part A) and vertical reading order remain out of scope.

A line break between two Han, kana or CJK/full-width punctuation
characters is not a word boundary, so sanitize_text no longer inserts a
space there. Clusters that contain Hangul keep the space, since Korean
separates words with spaces.

Part B of docling-project#4672.

Signed-off-by: kevin9327 <5299031+kevin9327@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ DCO Check Passed

Thanks @kevin9327, all your commits are properly signed off. 🎉

@mergify

mergify Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🟢 Merge protection satisfied — ready to merge.

Show 1 satisfied protection

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\(.+\))?(!)?:

@github-actions github-actions Bot added ai:ci-safe AI triage found no CI-safety concern (advisory) enhancement New feature or request language support pdf PDF issue (except docling-parse) labels Oct 14, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

AI triage (advisory)

Checked commit 130bb27ffc. The analysis read the diff only. It did not run code from this pull request.

The PR changes PageAssembleModel.sanitize_text to join wrapped lines without a space when both sides of the break are Han, kana, or CJK/full-width punctuation. Clusters that contain Hangul keep every space. The PR adds tests for this.

CI safety: no concern found. A maintainer must still approve CI.

1 related pull request(s) in the same code
PR State Signal Assessment
#4387 open changes the same code related: Both PRs change sanitize_text in page_assemble_model.py. This PR adds CJK line joining. Candidate 4387 changes which line-final hyphens are kept. The fixes are different, but the edits are close and may need a merge.

The ai:* labels are advisory. They do not approve CI and they do not add tests:full. A new push runs this check again.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI first review (advisory): no blocker found

This review covers the full diff at 1a902ea5c8. It read the code and did not run it.

The CJK join logic in sanitize_text is correct for the cases I traced, and the tests cover it. The main problem is scope: the PR also reformats Markdown code blocks in four usage-skill files, and none of that is mentioned in the description. Ask the author to remove those changes.

A maintainer makes the merge decision. This review never approves the pull request.

# 1. JSON-ish string
result = extractor.extract(source="invoice.pdf",
template='{"bill_no": "string", "total": "float"}')
result = extractor.extract(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion: Unrelated reformatting of four usage-skill files

The PR changes only code-block formatting in extraction.md, python-sdk.md, rag.md and service-client.md. It re-wraps lines, changes comment spacing and adds blank lines. None of this relates to CJK line joining, and the description does not mention it. These files are shipped in the wheel. They also overlap with open PRs #4218, #4496 and #4752, so the churn will cause merge conflicts for those PRs. Revert these four files and keep the PR to page_assemble_model.py and its test. If a formatter hook caused the changes, open a separate PR for them.

@github-actions github-actions Bot added the ai:review-lgtm AI first review found no blocker or major issue (advisory) label Oct 14, 2026
@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Keep this PR to the CJK line-join change in sanitize_text.

Signed-off-by: kevin9327 <5299031+kevin9327@users.noreply.github.com>
@github-actions github-actions Bot added ai:ci-safe AI triage found no CI-safety concern (advisory) and removed ai:ci-safe AI triage found no CI-safety concern (advisory) ai:review-lgtm AI first review found no blocker or major issue (advisory) labels Oct 18, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI first review (advisory): no blocker found

This review covers the changes since 1a902ea5c8 at 130bb27ffc. It read the code and did not run it.

The new commit only reverts the Markdown formatting changes in the four usage-skill files. The PR is now back to page_assemble_model.py and its test. I found no new defect in the incremental changes.

Earlier findings

  • fixed (suggestion): Unrelated reformatting of four usage-skill files

A maintainer makes the merge decision. This review never approves the pull request.

@github-actions github-actions Bot added the ai:review-lgtm AI first review found no blocker or major issue (advisory) label Oct 18, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:ci-safe AI triage found no CI-safety concern (advisory) ai:review-lgtm AI first review found no blocker or major issue (advisory) enhancement New feature or request language support pdf PDF issue (except docling-parse)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant