diff --git a/README.md b/README.md index 917a3d6..b1c82dc 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,7 @@ These boundaries are intentional and are used for issue triage. - Sparse indexes are compacted in first-seen order (`items[5]`, `items[8]` -> `items[0]`, `items[1]`). - Type inference is minimal by design; DOM extraction keeps native string values instead of coercing checkbox/radio fields. +- Unchecked indexed controls are omitted and therefore do not reserve compacted array slots; include another submitted field when row identity matters. - `formToObject` reads successful form control values, not option labels. Disabled controls (including disabled fieldset descendants) and button-like inputs are excluded unless you explicitly opt in to disabled values. - `extractPairs`/`formToObject` support `nodeCallback`; return `SKIP_NODE` to exclude a node entirely, or `{ name|key, value }` to inject a custom entry. - Parser inputs reject unsafe path segments by default. Use `allowUnsafePathSegments: true` only with trusted inputs. diff --git a/docs/api.md b/docs/api.md index 0d28074..57580eb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -227,6 +227,7 @@ export function form2js( - Checkbox and radio values follow native browser form submission semantics: - checked controls emit their string `value` - unchecked controls are omitted + - omitted indexed controls do not reserve compacted array slots; preserve row identity with another submitted field when it matters - Button-like inputs (`button`, `reset`, `submit`, `image`) are excluded from extraction. - Can merge multiple roots (`NodeList`, arrays, `HTMLCollection`) into one object. - If callback returns `SKIP_NODE`, that node is excluded from extraction entirely. diff --git a/packages/dom/test/dom.test.ts b/packages/dom/test/dom.test.ts index 6996b11..0333a69 100644 --- a/packages/dom/test/dom.test.ts +++ b/packages/dom/test/dom.test.ts @@ -155,6 +155,21 @@ describe("formToObject", () => { }); }); + it("compacts sparse indexed checkbox rows after omitting unchecked controls", () => { + document.body.innerHTML = ` +
+ + +
+ `; + + const form = document.getElementById("testForm") as HTMLFormElement; + + expect(formToObject(form)).toEqual({ + items: [{ selected: "true" }] + }); + }); + it("does not coerce an empty checked radio option to false when true and false siblings exist", () => { document.body.innerHTML = `