From e26cdd36499f4e9076d2ac15ce089daa08e9b15d Mon Sep 17 00:00:00 2001 From: Blake Bertuccelli-Booth <46652+bbertucc@users.noreply.github.com> Date: Tue, 6 Oct 2026 17:51:22 -0400 Subject: [PATCH 1/2] Make a flat form fillable: create its fields from Iris's HTML 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 --- README.md | 8 +- src/form/create.ts | 210 ++++++++++++++++ src/form/find.ts | 291 ++++++++++++++++++++++ src/html/build.ts | 59 ++++- src/pdf/widgets.ts | 14 +- src/report.ts | 5 +- src/tag.ts | 55 +++- test/document.test.ts | 2 +- test/fixtures/form-lines.pages.json | 10 + test/fixtures/form-lines.pdf | Bin 0 -> 1175 bytes test/fixtures/form-scan-skewed.pages.json | 10 + test/fixtures/form-scan-skewed.pdf | Bin 0 -> 51038 bytes test/fixtures/form-scan.pages.json | 10 + test/fixtures/form-scan.pdf | Bin 0 -> 44963 bytes test/fixtures/make.ts | 32 +++ test/forms.test.ts | 67 ++++- test/html.test.ts | 44 +++- 17 files changed, 772 insertions(+), 45 deletions(-) create mode 100644 src/form/create.ts create mode 100644 src/form/find.ts create mode 100644 test/fixtures/form-lines.pages.json create mode 100644 test/fixtures/form-lines.pdf create mode 100644 test/fixtures/form-scan-skewed.pages.json create mode 100644 test/fixtures/form-scan-skewed.pdf create mode 100644 test/fixtures/form-scan.pages.json create mode 100644 test/fixtures/form-scan.pdf diff --git a/README.md b/README.md index 1c35f15..420a8c8 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ Field name to value. Names are the ones `iris-pdf fields` prints. Text fields take strings, checkboxes `true`/`false`, radio groups and lists one of their options. A wrong type, an unknown option or a value over the field's length limit stops the run before anything is written. Read-only fields are skipped and counted. Unchecking always writes `/Off`, whatever the source used for "off". +### Flat forms + +A PDF with no form fields, such as a scanned form, gets them from the HTML: each ``, `', + ); + const [yes, no, city, notes] = formsOf(top); + assert.deepEqual([yes.group, no.group], ["Do you own a home?", "Do you own a home?"]); + assert.deepEqual(no.labelWords.map((w) => w.text), ["No"]); + assert.deepEqual(city.labelWords.map((w) => w.text), ["Your", "city:"]); + assert.deepEqual([city.type, city.options], ["combobox", ["a", "Boone"]]); + assert.equal(notes.type, "multiline"); }); +test("header ids are unique across a page's tables", () => { + const { top } = build("
A
1
B
2
"); + const ids: string[] = [], walk = (n: Node) => { if (n.id) ids.push(n.id); n.kids.forEach((k) => isRun(k) || walk(k)); }; + walk(top); + assert.deepEqual(ids, ["p1-th1", "p1-th2"]); +}); + +function formsOf(top: Node) { + const forms: FormRef[] = []; + const walk = (n: Node) => { if (n.form) forms.push(n.form); n.kids.forEach((k) => isRun(k) || walk(k)); }; + walk(top); + return forms; +} + test("tables: header ids, scope and each cell's headers", () => { const { top } = build( "" + From 0ad6a2e513760a17132456d3e7f09627548ab43a Mon Sep 17 00:00:00 2001 From: Blake Bertuccelli-Booth <46652+bbertucc@users.noreply.github.com> Date: Tue, 6 Oct 2026 17:59:18 -0400 Subject: [PATCH 2/2] A made check box's on-state is its HTML value, and a retag finds made fields by their changed names Co-Authored-By: Claude Opus 5.5 --- README.md | 2 +- src/form/create.ts | 20 ++++++++++++-------- src/tag.ts | 10 ++++++++-- test/forms.test.ts | 12 ++++++++++++ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 420a8c8..c9afbf2 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Text fields take strings, checkboxes `true`/`false`, radio groups and lists one ### Flat forms -A PDF with no form fields, such as a scanned form, gets them from the HTML: each ``, `
Q1Q2