Conversation
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.
From Tapio:
Fix line-break handling for hand-formatted blocks in plain text sources
Five related fixes to
GutenbergTextParser, all concerning blocks whose linebreaks were put there deliberately by the transcriber. Each is independent and
can be reverted on its own.
1. Verse in languages that do not capitalize every line
Problem
Whether a paragraph is verse or prose is decided by a fuzzy score. One of the
strongest inputs is how many lines begin with a capital letter:
Since
c <= len(self.lines), the exponent is never positive: the term is apure penalty, and it grows with the length of the paragraph.
The threshold is
scores.verse > 1.0, so a stanza whose lines are notcapitalized loses — and the longer the stanza, the more certainly it loses. It
is then rendered as a reflowed block quote and the browser rewraps the verse
at whatever width the reader's window happens to be.
Capitalizing every verse line is an English convention. Finnish, Swedish,
German and many other languages do not follow it, so poems embedded in novels
in those languages are reflowed essentially every time. Single-line verse is
affected too: it never reaches
white-space: pre, so its indentation isdropped and the line moves flush left.
Transcribers have been working around this by hand. For a six-line stanza,
adding one extra space to lines 2 and 6 makes the block pass a different test:
some()requires 25%, the first line is excluded, so 2 of the remaining 5lines (40%) is enough while 1 of 5 (20%) is not. Needing to know that in order
to typeset a poem is not reasonable.
Fix
If every line of a paragraph starts with at least
VERSE_INDENT(default 4)spaces, the transcriber indented and broke those lines deliberately.
Par.analyze()setspar.force_verse, unlessp_smells()matches, and thestyle pass honours the flag.
EBOOKMAKER_VERSE_INDENT=0restores the previous behaviour exactly.Why a flag and not a score
Boosting
scores.verseinstead leaks into neighbouring paragraphs through thefollows verse/precedes verserules inanalyze_multi(). In testing, athree-space prose block quote next to a poem was promoted to
white-space: prebecause its score was nudged from 0.833 to 1.0000000000000002. A flag
consulted only in the style pass leaves all existing scores untouched.
2. Numbered lists behave differently from roman-numbered ones
_istitlelooks at the first word character of a line and asksisupper().I.is a letter and passes;1.is a digit and fails. A table of contentsnumbered with roman numerals keeps its line breaks, while the same table
numbered
1. 2. ... 10.is reflowed into one paragraph.A new metric
numbersrecords which lines start with a digit. When mostlines are numbered, they count as titles:
The
most()guard matters. Counting digits per line unconditionally breaksprose whose continuation line happens to start with a number — this occurs in
the existing test book 69030:
At 75%, one numbered line out of two does not qualify, while five out of five
in a table of contents does.
3. Block indentation as hard spaces
preformat()converts leading spaces to , so a preformatted blockstarts with hard spaces that cannot adapt to the reader's screen. A title page
line centered in the source with 22 spaces becomes 22 hard spaces.
The block's common minimum indentation is now stripped and expressed as
margin-leftinstead. Indentation relative to that minimum is preserved,which is what actually carries meaning inside a stanza.
Note in passing that
centered_lines()andflush_right_lines()exist andscores.center/scores.rightare read in the style pass, but nothing everraises those scores, so
text-alignis effectively never emitted. Hard spacesare currently the only positioning mechanism these blocks have.
4. Hand-broken blocks that are not indented
A publisher's imprint is reflowed into a single line:
The block is not indented, and only two of its three lines start with a
capital, which falls below the 75% that
most()requires. The same happens tocasts of characters, addresses and signatures.
Fix
A signal that does not depend on indentation at all: reflowed prose always
fills its lines nearly to the margin, so a block whose longest line does not
come close was typed one line at a time.
The fill width is measured from the book itself rather than hard-coded, so the
rule works for transcriptions wrapped at 60, 70 or 80 columns. A high
percentile rather than the maximum, so one stray long line does not set the
standard for the whole book.
The rule does not apply to single-line paragraphs or to PG boilerplate.
5. Blocks start at a uniform level
Two adjustments, both about where a preformatted block begins.
The margin is the same for every block (
VERSE_MARGIN, 5%). It used to bederived from the source indentation, so a poem whose stanzas were indented by
4 and 6 spaces got 5% and 8% and drifted apart; a title page indented 23 spaces
got 31% and was pushed a third of the way across the screen.
Extra indentation on the first line is removed. A block never starts
indented relative to its own body — the blank line above it is what separates
it from the previous paragraph. Indentation on later lines is meaningful and
is kept:
6. First-line indent on hand-broken blocks
Problem
The stylesheet gives every body-level paragraph a first-line indent
(
body > p { text-indent: 1em }) and suppresses it only after a heading(
h2 + p { text-indent: 0 }). That is right for prose, but a hand-brokenblock is not prose: its first line is a verse line, a publisher's town, or a
table-of-contents entry, and the transcription does not indent it.
The result was visible in every text with verse or front matter: the first
stanza of a poem started flush left because it follows the poem's heading,
while every stanza after it started one em in. The same stray indent appeared
on title pages and tables of contents.
Fix
Any paragraph shipped as a hand-broken block (
force_verse, orscores.quote > THRESHOLD) gets an explicittext-indent: 0.A single-line paragraph is ambiguous: in a novel it is a one-line prose
paragraph and must keep its indent. It is treated as front matter — and loses
the indent — only when neither neighbour is flowed prose, which is the case
for a byline, an imprint, a section title or a numbered subtitle sitting
between headings and blocks.
Par.nextis now initialized in__init__; it was only ever assigned forparagraphs that have a successor.
Test plan
Verified with constructed Finnish samples and with the existing test book:
<br />per line. Verified for 4-, 6- and 8-line stanzas and for a single-line
stanza (previously flush left).
is exactly 4.
1. 2. 3. 10. 11.keeps its line breaks,matching the existing behaviour for
I. II. III. X. XI..line aligned with the body; a deeper line further down keeps its indent.
tests/files/69030/69030-0.txtdiffers from the pre-patch output in exactlytwo paragraphs out of 162, both on the title page, where hard spaces became
a margin.
Kaukainen puutarha) now carries
text-indent: 0; the stanzas of a poemstart at the same level, and so do the lines of the title page and the
table of contents.
keep the stylesheet's first-line indent.
tests/test_html.pypasses.tests/test_txt.pyandtests/test_job.pyfail identically before and after (missing dependencies in the test
environment).
Compatibility note
Texts that indent prose block quotes by 4 or more spaces will now have those
quotes preformatted as well. Transcribers who want such a quote reflowed can
indent it by 2–3 spaces, or lower
VERSE_INDENTfor that build.