Repository navigation
A form can be added to a document - #56
Merged
Merged
Conversation
Doc.AddFields and the addfields verb: the other half of Fill, which can only change a field the document already has. This is what BentoPDF's form-creator needs, and the fleet had every other piece already. Fields are held until the write, because a widget names the page OBJECT it sits on and the pages have no object numbers until then. A field showing in one place is one object, which is what nearly every producer writes; a field showing on several pages becomes a parent with one Kid per place. Two details the format makes easy to get wrong, both held by tests: A checkbox's drawing is not generated by the viewer. NeedAppearances covers text and choice fields, but a button shows whatever its own appearance dictionary holds for the state it is in, so one written without them is a box that never looks ticked however often it is clicked. One is drawn per state with the path operators rather than with a font, so the document needs no ZapfDingbats to show a tick. A widget is marked Print. Without it the field is on screen and gone from the paper, which is where a filled form is most often looked at. A document that already has a form is joined rather than replaced: replacing it would drop every field the file came with, and the file would still open. A document assembled from several files can still be given a form, because fields the caller asked for come from neither source and so are in no conflict. The description the verb reads is JSON, since the thing being described is a layout and a command line is a poor place to put one. Unknown keys are refused: "mutliline" is a form missing the thing it was written to ask for, and a parser that ignores what it does not know says nothing about it. The list lengths are bounded, because a small file otherwise asks for an enormous document and all the memory to build it. The oracle throughout is the reading half -- forms.Read and the fields verb -- rather than these tests' own expectations. Measured: 100% of statements and 0 uncovered blocks in both packages, counted on the profile rather than the rounded percentage. Three mutations caught (the checkbox appearance never written; NeedAppearances not set; the existing form replaced instead of joined). runAddFields uses the c.open and save helpers every other verb uses rather than its own copy of the password, the write and their error paths. 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.AddFieldsand theaddfieldsverb: the other half ofFill, which can only change a field the document already has.This is what BentoPDF's
form-creatorneeds. The fleet had every other piece already —formsreads and draws them,opsfills them,renderdraws widgets — and only the direction that creates one was missing. The field vocabulary comes fromformsv0.6.0, so the writer and the reader cannot disagree on what a field is.Fields are held until the write, because a widget names the page object it sits on and the pages have no object numbers until then. A field showing in one place is one object, which is what nearly every producer writes; a field showing on several pages becomes a parent with one
Kidper place.Two details the format makes easy to get wrong
A checkbox's drawing is not generated by the viewer.
NeedAppearancescovers text and choice fields, but a button shows whatever its own appearance dictionary holds for the state it is in — so one written without them is a box that never looks ticked however often it is clicked. One is drawn per state with the path operators rather than with a font, so the document needs no ZapfDingbats to show a tick.A widget is marked
Print. Without it the field is on screen and gone from the paper, which is where a filled form is most often looked at.Joining rather than replacing
A document that already has a form is joined. Replacing it would drop every field the file came with, and the file would still open — the old fields simply gone.
A document assembled from several files can still be given a form: two sources' forms cannot be merged, since their fields may be named the same, but fields the caller asked for come from neither source and so are in no conflict.
The description is a file
JSON, because the thing being described is a layout and a command line is a poor place to put one. The kinds are the names
pdfops fieldsprints, so a description can be written from a listing.Unknown keys are refused:
"mutliline"is a form missing the thing it was written to ask for, and a parser that ignores what it does not know says nothing about it. The list lengths are bounded (10 000 fields, 10 000 options, 1 000 widgets) because a small file otherwise asks for an enormous document and all the memory to build it.It refuses before it writes, for everything that makes a file which opens and is broken: a field with no name, a choice with no rows, a checkbox whose on-state is the reserved
Off, two widgets of one radio group in the same state, a comb with nomaxLen, an empty rectangle, a page the document does not have, and two fields of one name — which the reader would silently shadow.Controls
The oracle throughout is the reading half —
forms.Readand thefieldsverb — rather than these tests' own expectations.NeedAppearancesnot set; the existing form replaced instead of joinedrunAddFieldsuses thec.openandsavehelpers every other verb uses rather than its own copy of the password, the write and their error paths — which is also how the last uncovered block went away.Not in this change
pdfopsuses the standardflagpackage across all 54 verbs rather than cobra. I matched the siblings rather than make one verb the odd one out; converting the command is its own piece of work.🤖 Generated with Claude Code