fix(txt): stop detecting measure-word prose as chapters in TXT import (#4658) - #4660
Merged
Conversation
…#4658) The Chinese chapter-detection regex treated certain measure words (the classifiers for "letter" and "book") as chapter units and let a title attach directly after the unit. As a result, ordinary prose such as "the first letter" or "the fourth book records..." was split out as bogus TOC entries when importing Chinese TXT novels. Split the unit characters into two explicit tiers that share the same number prefix and stay in one alternation (a single split pass, so a segment mixing chapter and volume headings is handled together): - Chapter units may carry a title attached directly, unchanged. - Volume/measure-word units only start a heading when the title is introduced by a separator (colon, comma, space, or parentheses) or the line ends, never a bare noun directly after the unit. Real volume and chapter headings still match. Adds regex-level and end-to-end tests covering both reported cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chrox
force-pushed
the
fix/txt-chapter-measure-word-4658
branch
from
June 19, 2026 08:07
b76fa80 to
4f48fae
Compare
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.
Problem
Closes #4658. When importing Chinese TXT novels, the chapter-detection regex promotes ordinary prose into the TOC. Two reported cases:
第一封信–第七封信("the Nth letter" — correspondence the character is reading) became chapters because the measure word封was a chapter unit.第四本书记载着锤法,来自孙家,可惜对秦铭用处不大了,他已经彻底掌握。— a full sentence starting with第四本书("the fourth book") became a chapter because本was a unit and a title could attach directly after it.Root cause
createChapterRegexps('zh')used a single unit class[章卷节回讲篇封本册部话]and allowed a title to attach directly after the unit. But封/本/部/册/卷are also 量词 (measure words) that precede a noun in prose (封信,本书), so those phrases matched as headings.Fix
Split the units into two explicit tiers, kept in one alternation (one split pass):
[章节回讲篇话]— real headings; a title may attach directly (第一章天地初开). Unchanged.[卷本册部封]— a title only counts when introduced by a separator (::、, space, parens) or the line ends — never a bare noun right after the unit.The trailing
(?!\S)boundary rejects第一封信/第四本书…by backtracking when a noun follows with no separator. Real headings still match:第一卷 起始篇,第二部 中篇,第一封 致读者, standalone第一本.The two tiers must stay in one regex: the
chapterRegexpsarray is a fallback chain (first "good" split wins andbreaks), so separate entries would recognize one tier and silently drop the other in books where a volume wraps chapters.Tests
Added regex-level and end-to-end cases for both reported patterns to
src/__tests__/utils/txt.test.ts(confirmed failing before the fix, passing after). Existing volume/heading tests unchanged.pnpm test— full suite green (5860 passed)pnpm lint(tsgo + Biome) — cleanpnpm format:check— clean🤖 Generated with Claude Code