acro_that 0.1.7 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5f98c3666d2a74883becbcb49e9c18fd4fc04a64f0e0dfd883b4c48056d64b8
4
- data.tar.gz: 13545403d27dcbbccc1474e88a8d97d45336c5afd292362692e8c50e2ef6c15a
3
+ metadata.gz: c25e9ad58be5a660ea6abb5a56896fef953d67578425b01a9de86f1cc1ae8a1d
4
+ data.tar.gz: 45133e292e45343903ee53b44f709149bea0353d9aa7e2a2a9f3c6fa676da1dd
5
5
  SHA512:
6
- metadata.gz: 55313e86d76491aae1ff68c78651d631ac0cfc8cf7feccd462f4ba3fbe37c3ba4c1f181102c9e849b0af837a817dd02681a97c468792a58e0fc8b93e9e486fb5
7
- data.tar.gz: 52d751681abc5e46db4e66721eaa8871cf2a7251d418b819a72fb6485f66263c8679cb7eb32bba74d478a8983fd1a194f92d3b490702546485d0b985b71c4b54
6
+ metadata.gz: 7762f8c137e7b29c6cdbc15c8ce3fd9387b96dfc4a22a64ee171fc0c9c8d7f67951b42fb491cb283e160aced6a37d0e6eaa30599fa63d0876a77a9be8506d493
7
+ data.tar.gz: 7a92be45bc9810a3e085c67fe0ee7b0a245925179ec345bbf0f3cb56cc4b2195bc6faca01f27a64c86646c7ef5c91dd1c6f732140905a6d208c4e8c476ff0458
data/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.8] - 2025-11-04
9
+
10
+ ### Fixed
11
+ - Fixed PDF parsing error when PDFs are wrapped in multipart form data. PDFs uploaded via web forms (with boundary markers like `------WebKitFormBoundary...`) are now automatically extracted before processing, ensuring correct offset calculations for xref tables and streams.
12
+
8
13
  ## [0.1.5] - 2025-11-01
9
14
 
10
15
  ### Fixed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acro_that (0.1.6)
4
+ acro_that (0.1.8)
5
5
  chunky_png (~> 1.4)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -175,6 +175,84 @@ doc.write("form_with_signature.pdf")
175
175
 
176
176
  **Note**: PNG image processing requires the `chunky_png` gem, which is included as a dependency. JPEG images can be processed without any additional dependencies.
177
177
 
178
+ #### Radio Buttons
179
+
180
+ Radio buttons allow users to select a single option from a group of mutually exclusive choices. Radio buttons in AcroThat are created using the `:radio` type and require a `group_id` to group related buttons together.
181
+
182
+ ```ruby
183
+ doc = AcroThat::Document.new("form.pdf")
184
+
185
+ # Create a radio button group with multiple options
186
+ # All buttons in the same group must share the same group_id
187
+
188
+ # First radio button in the group (creates the parent field)
189
+ doc.add_field("Option1",
190
+ type: :radio,
191
+ group_id: "my_radio_group",
192
+ value: "option1", # Export value for this button
193
+ x: 100,
194
+ y: 500,
195
+ width: 20,
196
+ height: 20,
197
+ page: 1,
198
+ selected: true # This button will be selected by default
199
+ )
200
+
201
+ # Second radio button in the same group
202
+ doc.add_field("Option2",
203
+ type: :radio,
204
+ group_id: "my_radio_group", # Same group_id as above
205
+ value: "option2",
206
+ x: 100,
207
+ y: 470,
208
+ width: 20,
209
+ height: 20,
210
+ page: 1
211
+ )
212
+
213
+ # Third radio button in the same group
214
+ doc.add_field("Option3",
215
+ type: :radio,
216
+ group_id: "my_radio_group", # Same group_id
217
+ value: "option3",
218
+ x: 100,
219
+ y: 440,
220
+ width: 20,
221
+ height: 20,
222
+ page: 1
223
+ )
224
+
225
+ # Write the PDF with radio buttons
226
+ doc.write("form_with_radio.pdf")
227
+ ```
228
+
229
+ **Key Points:**
230
+ - **`group_id`**: Required. All radio buttons that should be mutually exclusive must share the same `group_id`. This can be any string or identifier.
231
+ - **`type: :radio`**: Required. Specifies that this is a radio button field.
232
+ - **`value`**: The export value for this specific button. This is what gets returned when the button is selected. If not provided, a unique value will be generated automatically.
233
+ - **`selected`**: Optional boolean (`true` or `false`, or string `"true"`). If set to `true`, this button will be selected by default. Only one button in a group should have `selected: true`. If not specified, the button defaults to unselected.
234
+ - **Positioning**: Each radio button needs its own `x`, `y`, `width`, `height`, and `page` values to position it on the form.
235
+
236
+ **Example with multiple groups:**
237
+
238
+ ```ruby
239
+ doc = AcroThat::Document.new("form.pdf")
240
+
241
+ # First radio button group (e.g., "Gender")
242
+ doc.add_field("Male", type: :radio, group_id: "gender", value: "male", x: 100, y: 500, width: 20, height: 20, page: 1, selected: true)
243
+ doc.add_field("Female", type: :radio, group_id: "gender", value: "female", x: 100, y: 470, width: 20, height: 20, page: 1)
244
+ doc.add_field("Other", type: :radio, group_id: "gender", value: "other", x: 100, y: 440, width: 20, height: 20, page: 1)
245
+
246
+ # Second radio button group (e.g., "Age Range")
247
+ doc.add_field("18-25", type: :radio, group_id: "age", value: "18-25", x: 200, y: 500, width: 20, height: 20, page: 1)
248
+ doc.add_field("26-35", type: :radio, group_id: "age", value: "26-35", x: 200, y: 470, width: 20, height: 20, page: 1, selected: true)
249
+ doc.add_field("36+", type: :radio, group_id: "age", value: "36+", x: 200, y: 440, width: 20, height: 20, page: 1)
250
+
251
+ doc.write("form_with_multiple_groups.pdf")
252
+ ```
253
+
254
+ **Note:** Radio buttons are automatically configured with the correct PDF flags to enable mutual exclusivity within a group. When a user selects one radio button, all others in the same group are automatically deselected.
255
+
178
256
  #### Flattening PDFs
179
257
 
180
258
  ```ruby
@@ -269,8 +347,10 @@ Adds a new form field to the document. Options include:
269
347
  - `height`: Field height (Integer, default: 20)
270
348
  - `page`: Page number to add the field to (Integer, default: 1)
271
349
  - `type`: Field type (Symbol or String, default: `"/Tx"`). Options:
272
- - Symbol keys: `:text`, `:button`, `:choice`, `:signature`
350
+ - Symbol keys: `:text`, `:button`, `:choice`, `:signature`, `:radio`
273
351
  - PDF type strings: `"/Tx"`, `"/Btn"`, `"/Ch"`, `"/Sig"`
352
+ - `group_id`: Required for radio buttons. String or identifier to group radio buttons together. All radio buttons in the same group must share the same `group_id`.
353
+ - `selected`: Optional for radio buttons. Boolean (`true` or `false`, or string `"true"`). If set to `true`, this radio button will be selected by default.
274
354
 
275
355
  Returns a `Field` object if successful.
276
356
 
@@ -280,6 +360,9 @@ field = doc.add_field("NewField", value: "Value", x: 100, y: 500, width: 200, he
280
360
 
281
361
  # Using PDF type strings
282
362
  field = doc.add_field("ButtonField", type: "/Btn", x: 100, y: 500, width: 20, height: 20, page: 1)
363
+
364
+ # Radio button example
365
+ field = doc.add_field("Option1", type: :radio, group_id: "my_group", value: "option1", x: 100, y: 500, width: 20, height: 20, page: 1, selected: true)
283
366
  ```
284
367
 
285
368
  #### `#update_field(name, new_value, new_name: nil)`
@@ -351,8 +434,8 @@ doc.clear!(remove_pattern: /^text-/)
351
434
  # Keep only specific fields
352
435
  doc.clear!(keep_fields: ["Name", "Email"])
353
436
 
354
- # Use block to filter fields
355
- doc.clear! { |name| !name.match?(/^[a-f0-9-]{30,}/) }
437
+ # Use block to filter fields (return true to remove)
438
+ doc.clear! { |field| field.name.match?(/^[a-f0-9-]{30,}/) }
356
439
  ```
357
440
 
358
441
  **Note:** This completely rewrites the PDF (like `flatten`), so it's more efficient than using `remove_field` multiple times. See [Clearing Fields Documentation](docs/cleaning_fields.md) for detailed information.
data/docs/clear_fields.md CHANGED
@@ -75,11 +75,11 @@ doc.clear!(remove_fields: ["OldField1", "OldField2", "GeneratedField3"])
75
75
  ### Complex Selection with Block
76
76
 
77
77
  ```ruby
78
- # Remove all fields except those matching certain criteria
79
- doc.clear! do |field_name|
80
- # Keep fields that don't look generated
81
- !field_name.start_with?("text-") &&
82
- !field_name.match?(/^[a-f0-9]{20,}/)
78
+ # Remove fields matching certain criteria
79
+ doc.clear! do |field|
80
+ # Remove fields that look generated
81
+ field.name.start_with?("text-") ||
82
+ field.name.match?(/^[a-f0-9]{20,}/)
83
83
  end
84
84
  ```
85
85
 
@@ -179,11 +179,11 @@ require 'acro_that'
179
179
  doc = AcroThat::Document.new("messy_form.pdf")
180
180
 
181
181
  # Remove all generated/UUID-like fields
182
- doc.clear! { |name|
183
- # Keep only fields that look intentional
184
- !name.match?(/^[a-f0-9-]{30,}/) && # Not UUID-like
185
- !name.start_with?("temp_") && # Not temporary
186
- !name.empty? # Not empty
182
+ doc.clear! { |field|
183
+ # Remove fields that look generated or temporary
184
+ field.name.match?(/^[a-f0-9-]{30,}/) || # UUID-like
185
+ field.name.start_with?("temp_") || # Temporary
186
+ field.name.empty? # Empty name
187
187
  }
188
188
 
189
189
  # Add new fields