Repository navigation
Conversation
Each HTML control is placed on the blank beside its label, found in the rendered page: an underline, a box, a table cell (split at faint row lines), or a check box or radio circle. Scans, skewed ones too, use Tesseract's words. A control with no blank found is warned field_not_placed. The report lists the fields made under form.created, and --values fills them. Also gives table header cells ids unique across a page's tables. Closes #13 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Blocking
Re-tagging this tool's own output drops a created check box from the structure tree. src/form/create.ts:96:
obj.put("AP", { N: { Yes: this.stream(cross(w, h), w, h), Off: this.stream("", w, h) } });
...
f.value = undefined; // its on-state is Yes, whatever the HTML's valueThe on-state is forced to Yes, but on the next run (the output now has fields, so maker is off) emitField matches widgets with onStates(w.widget).includes(f.value) using the HTML's value. Reproduced: form-lines with <input type="checkbox" name="news" value="yes">, tag, then tag the output again with the same pages JSON → warnings field_on_other_page: news and field_not_in_html: news; the widget has no Form element. An untagged widget annotation fails PDF/UA and hides the control's label from a screen reader. value="yes"/"on" is ordinary HTML, and re-tagging is supported (retagged). Fix: use f.value || "Yes" as the on-state (and keep f.value), and add a retag test. The same mismatch hits names changed by unique() (a second name="date" becomes date-2, a dotted name gets -): on retag both HTML controls look for date and the second is field_not_in_pdf.
Non-blocking notes
src/form/create.ts:136const clean = base.replace(/\./g, "-")and the-2suffixes mean a field is not always named by its HTMLname, asREADME.md("A field is named by itsname") says.--values {"a.b": …}for<input name="a.b">is refusedno_acroform_field; onlyform.createdshows the real name. Say so in the README.src/form/create.ts:59radio groups are keyed perpage()call, so a group whose buttons sit on two pages becomes two fields (card,card-2). This is reachable only for a group that spans a page break.
Accessibility impact: flat forms become fillable, with each field tagged and named, but a created check box whose HTML has a value loses its Form tag when the output is tagged again.
… fields by their changed names Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Earlier blocking finding (a made check box's on-state forced to Yes, and names changed by unique(), dropped from the structure tree on retag): fixed in 0ad6a2e. src/form/create.ts:90 now uses f.value || "Yes" as the on-state, src/tag.ts:354-360 tries fieldNames() on retag, and test/forms.test.ts:189 checks this with 9 Form elements and state yes.
Non-blocking notes
- README naming (periods,
-2): fixed. src/form/create.ts:59a radio group whose buttons sit on two pages still becomes two fields (card,card-2). Unchanged since e26cdd3. Only a group that spans a page break reaches it.src/form/create.ts:90(f.value || "Yes").replace(/^Off$/, "off"): an HTMLvalue="Off"becomes on-stateoff, but on retagemitFieldstill matchesonStates(...).includes("Off"), so that check box loses its tag again. This is rare; matching on the same mapped value would close it.src/tag.ts:356thefieldNames()fallback also runs for source AcroForms (whenmakeris off). An HTML control nameddatecan bind to an existing PDF fielddate-2oncedateis used. This is usually right, but it is not limited to fields this tool made.
Accessibility impact: a flat form's created fields, check boxes with HTML values and renamed fields included, keep their Form tags and names when the output is tagged again.
Closes #13.
A PDF with no form fields (a flat or scanned form) now gets them from Iris's HTML. Each
<input>,<select>and<textarea>is placed on the blank next to its label. The blank is found in the rendered page: an underline, a box, a table cell (split at faint or dotted row lines), or a check box or radio circle. A field with no blank found is left out rather than put in the wrong place, and is warnedfield_not_placed. Fields made are listed inform.created, and--valuesfills them by name.Not PDF/UA: typed text uses base-14 Helvetica, which is not embedded. An output with created fields warns
font_not_embeddedand does not claim PDF/UA-1, the same as source AcroForms. I tried an embedded font in/DR, but mupdf's own appearance streams still use unembedded Helvetica, and viewers handle Type0 fonts in/DApoorly.Tests: new fixtures
form-lines(drawn),form-scanandform-scan-skewed(rendered at 300 dpi; the last rotated 1.5°). They check names, types and positions, filling,/TUnames,field_not_placed, and the approximate case. A real two-page application (kept local) gets 73 of 79 fields with none misplaced. Of the 6 missed, 3 have labels the OCR misread and 3 have HTML labels that are not printed on the page.🤖 Generated with Claude Code