Repository navigation
labels: what a viewer shows in its toolbar, and the labels every verb was losing - #44
Merged
Merged
Conversation
… was losing
Doc.SetPageLabels and Doc.PageLabels, with `pdfops labels` over them: the six
styles the format has, prefixes, start values, page ranges, and numbering that
carries across the pieces of a disjoint range. This closes BentoPDF's
add-page-labels.
⛔ AND IT FIXES A LOSS NOBODY HAD NOTICED. A /PageLabels tree is keyed by page
INDEX, so it cannot be carried across a rebuild the way the other document keys
are: after a select or a reverse every label would be on the wrong page. So
this package dropped it — and a document whose front matter was numbered
i, ii, iii came back from a WATERMARK numbered 1, 2, 3. The labels are now
asked for per page and rebuilt, which is right in both directions, and a
mutation removing the new write is caught by the watermark test.
Four things the format says that a reader has to be told:
- a page-label RANGE is contiguous. The file holds the first page of each run
and the viewer counts forward, so a rule over "1-9,30-40" is compiled into
two runs; "odd" over a hundred pages is fifty runs of one.
- a page-label TREE has no gaps. An entry labels from its own key until the
next, so "1, 2, then nothing" came back as 1, 2, 3, 4 until the stop was
said out loud with an entry carrying neither style nor prefix. The
round-trip through the file is what caught it.
- /St SHALL BE AT LEAST 1 (ISO 32000-1 table 159). A zero-based scheme is not
expressible as a numeric style, so a start below one is refused rather than
written out of specification. BentoPDF's tool offers "set to 0 for
zero-based numbering", and what that writes is a value the standard forbids.
- ⛔ THE LETTERS ARE NOT A SPREADSHEET'S COLUMNS. Table 159: "A to Z for the
first 26 pages, AA to ZZ for the next 26" — so 27 is AA and 28 is BB, where
a spreadsheet's 28 is AB. Borrowing the familiar rule relabels every
appendix past the twenty-sixth, and a mutation that does exactly that is
caught.
Roman numerals stop at 3999 and fall back to decimal past it, because 4000
needs a bar over the M that neither a PDF string nor a page number has. A
numeral is read only in its canonical spelling: "IIII" is four to a person and
is not what roman(4) writes, so reading it would build a run that renumbers the
page after it. A leading zero is not decimal for the same reason.
The runs are compressed on the way out: three hundred decimal pages are one
entry. A label no style can explain becomes a run of one with the whole label
as a literal prefix.
⛔ Four guards were REMOVED rather than tested, each one dead code a coverage
gap found: a bounds check on page numbers ParseRange has already validated, a
round-trip check on letters the parse loop has already made canonical, and two
error branches saying a second time what their nil answer already said. A guard
no test can reach is not a guard, and the invariant is now named where it is
established.
100% statement coverage with zero uncovered blocks, race-clean, go vet and
gofmt clean. Five mutations caught, including the state this package was in
before the change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Doc.SetPageLabelsandDoc.PageLabels, withpdfops labelsover them: thesix styles the format has, prefixes, start values, page ranges, and numbering
that carries across the pieces of a disjoint range. This closes BentoPDF's
add-page-labels.⛔ And it fixes a loss nobody had noticed
A
/PageLabelstree is keyed by page index, so it cannot be carried acrossa rebuild the way the other document keys are: after a
selector areverseevery label would be on the wrong page. So this package dropped it — and a
document whose front matter was numbered i, ii, iii came back from a
watermark numbered 1, 2, 3.
The labels are now asked for per page and rebuilt, which is right in both
directions:
watermark,stamp,metadatareverse,select,mergeA mutation that removes the new write is caught by the watermark test, so
the fix is held in place by a test that fails in the old state.
Four things the format says that a reader has to be told
run and the viewer counts forward, so a rule over
1-9,30-40is compiledinto two runs.
pages=oddover a hundred pages is fifty runs of one;the next one, so "1, 2, then nothing" came back as 1, 2, 3, 4 until the
stop was said out loud with an entry carrying neither style nor prefix. The
round-trip through the file is what caught it, not a reading of the standard;
/Stshall be at least 1 (ISO 32000-1 table 159). A zero-based schemeis not expressible as a numeric style, so a
startbelow one is refusedrather than written out of specification. BentoPDF's own tool offers "set to
0 for zero-based numbering", and what that writes is a value the standard
forbids;
the first 26 pages, AA to ZZ for the next 26" — so 27 is AA and 28 is
BB, where a spreadsheet's 28 is AB. Borrowing the familiar rule relabels
every appendix past the twenty-sixth, and a mutation that does exactly that
is caught.
Roman numerals stop at 3999 — 4000 needs a bar over the M that neither a PDF
string nor a page number has — and fall back to decimal past it, because a
label a viewer shows wrongly is worse than one in the wrong style. A numeral
is read only in its canonical spelling: "IIII" is four to a person and is
not what
roman(4)writes, so reading it would build a run that renumbers thepage after it. A leading zero is not decimal for the same reason.
⛔ Four guards removed rather than tested
Each was dead code a coverage gap found, and each is now an invariant named
where it is established:
ParseRangehas already validated — itrefuses a spec naming a page the document has not got rather than clipping it;
nilanswer already said(a dangling reference is the null object, per the format).
A guard no test can reach is not a guard.
Checks
100 % statement coverage with zero uncovered blocks, race-clean,
go vetand
gofmtclean. Five mutations caught, including the state this package wasin before the change.
🤖 Generated with Claude Code