fillable-pdf 1.1.2 → 1.1.3
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 +4 -4
- data/README.md +23 -17
- data/lib/fillable-pdf/version.rb +1 -1
- data/lib/fillable-pdf.rb +18 -8
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2cdd748940498c34c3e4f19f91f83cfc47fcf34dda1d10eb07e05f7aef9c7d57
|
|
4
|
+
data.tar.gz: a98954a86876c759716a8919a24f54c175ec97eb0eddd19bc2b9aaa844bdd6cb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bb4104898a7feb6a16338aae323b3d1285f8fb5dd2458e48d5e936ca17ed27fc407289c68db0a466105bbe06fc1100cfd5a8cfa92873f6f6b731692ee385bfaf
|
|
7
|
+
data.tar.gz: 07430fe63ccbbec3e4c7c5191d6831b767320b87ed6ea0bd0542c11d41e10fe8c7883ce7d396fe7cc31f029d425fb87e055e3af01bd44358cf8d3b99010e17ca
|
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://github.com/vkononov/fillable-pdf/blob/main/.github/workflows/test.yml)
|
|
7
7
|
[](https://github.com/vkononov/fillable-pdf/actions/workflows/test.yml)
|
|
8
8
|
[](https://github.com/vkononov/fillable-pdf/actions/workflows/lint.yml)
|
|
9
|
-
[](https://opensource.org/
|
|
9
|
+
[](https://opensource.org/license/MIT)
|
|
10
10
|
|
|
11
11
|
FillablePDF is an extremely simple and lightweight utility that bridges iText and Ruby in order to fill out fillable PDF forms or extract field values from previously filled out PDF forms.
|
|
12
12
|
|
|
@@ -231,7 +231,7 @@ An instance of `FillablePDF` has the following methods at its disposal:
|
|
|
231
231
|
pdf.set_field('first_name', 'Richard', generate_appearance: false)
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
-
* `
|
|
234
|
+
* `set_fields(fields, generate_appearance: nil)`
|
|
235
235
|
*Sets the values of multiple fields given a set of unique field names and values, with an optional `generate_appearance` directive.*
|
|
236
236
|
|
|
237
237
|
```ruby
|
|
@@ -319,7 +319,7 @@ An instance of `FillablePDF` has the following methods at its disposal:
|
|
|
319
319
|
# result: document is saved in a given path with flattening
|
|
320
320
|
```
|
|
321
321
|
|
|
322
|
-
**NOTE:** Saving the file automatically closes the input file, so you would need to reinitialize the `
|
|
322
|
+
**NOTE:** Saving the file automatically closes the input file, so you would need to reinitialize the `FillablePDF` class before making any more changes or saving another copy.
|
|
323
323
|
|
|
324
324
|
* `save_as!(file_path, flatten: false)`
|
|
325
325
|
*Saves the filled out PDF document in a given path and flattens it if requested. Raises an error if the path matches the current file (use save() instead).*
|
|
@@ -454,15 +454,18 @@ Naturally, there are many downsides (in terms of efficiency, scalability, securi
|
|
|
454
454
|
|
|
455
455
|
## Example
|
|
456
456
|
|
|
457
|
-
The following [
|
|
457
|
+
The following [run.rb](example/run.rb) with [input.pdf](example/input.pdf) is located in the [example](example) directory. It uses most of the methods that are described above and generates the output files [output.pdf](example/output.pdf) and [output.flat.pdf](example/output.flat.pdf).
|
|
458
458
|
|
|
459
459
|
```ruby
|
|
460
460
|
require_relative '../lib/fillable-pdf'
|
|
461
461
|
|
|
462
|
+
# Get the directory where this script is located
|
|
463
|
+
EXAMPLE_DIR = __dir__
|
|
464
|
+
|
|
462
465
|
BASE64_PHOTO = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' # rubocop:disable Layout/LineLength
|
|
463
466
|
|
|
464
467
|
# opening a fillable PDF
|
|
465
|
-
pdf = FillablePDF.new('input.pdf')
|
|
468
|
+
pdf = FillablePDF.new(File.join(EXAMPLE_DIR, 'input.pdf'))
|
|
466
469
|
|
|
467
470
|
# total number of fields
|
|
468
471
|
if pdf.any_fields?
|
|
@@ -475,12 +478,15 @@ puts
|
|
|
475
478
|
|
|
476
479
|
# setting form fields
|
|
477
480
|
pdf.set_fields({first_name: 'Richard', last_name: 'Rahl'})
|
|
478
|
-
pdf.set_fields(
|
|
481
|
+
pdf.set_fields(
|
|
482
|
+
{football: 'Yes', baseball: 'Yes', basketball: 'Yes', nascar: 'Yes', hockey: 'Yes', rugby: 'Yes'},
|
|
483
|
+
generate_appearance: false
|
|
484
|
+
)
|
|
479
485
|
pdf.set_field(:date, Time.now.strftime('%B %e, %Y'))
|
|
480
486
|
pdf.set_field(:newsletter, 'Off') # uncheck the checkbox
|
|
481
487
|
pdf.set_field(:language, 'dart') # select a radio button option
|
|
482
488
|
pdf.set_image_base64(:photo, BASE64_PHOTO)
|
|
483
|
-
pdf.set_image(:signature, 'signature.png')
|
|
489
|
+
pdf.set_image(:signature, File.join(EXAMPLE_DIR, 'signature.png'))
|
|
484
490
|
|
|
485
491
|
# list of fields
|
|
486
492
|
puts "Fields hash: #{pdf.fields}"
|
|
@@ -517,11 +523,11 @@ pdf.remove_field :marketing
|
|
|
517
523
|
puts "Removed field 'marketing'"
|
|
518
524
|
|
|
519
525
|
# saving the filled out PDF in another file
|
|
520
|
-
pdf.save_as('output.pdf')
|
|
526
|
+
pdf.save_as(File.join(EXAMPLE_DIR, 'output.pdf'))
|
|
521
527
|
|
|
522
528
|
# saving another copy of the filled out PDF in another file and making it non-editable
|
|
523
|
-
pdf = FillablePDF.new('output.pdf')
|
|
524
|
-
pdf.save_as 'output.flat.pdf', flatten: true
|
|
529
|
+
pdf = FillablePDF.new(File.join(EXAMPLE_DIR, 'output.pdf'))
|
|
530
|
+
pdf.save_as File.join(EXAMPLE_DIR, 'output.flat.pdf'), flatten: true
|
|
525
531
|
|
|
526
532
|
# closing the document
|
|
527
533
|
pdf.close
|
|
@@ -530,19 +536,19 @@ pdf.close
|
|
|
530
536
|
The example above produces the following output and also generates the output file [output.pdf](example/output.pdf).
|
|
531
537
|
|
|
532
538
|
```text
|
|
533
|
-
The form has a total of
|
|
539
|
+
The form has a total of 14 fields.
|
|
534
540
|
|
|
535
|
-
Fields hash: {:
|
|
541
|
+
Fields hash: {last_name: "Rahl", first_name: "Richard", football: "Yes", baseball: "Yes", basketball: "Yes", date: "August 12, 2026", newsletter: "Off", nascar: "Yes", language: "dart", signature: "", photo: "", rugby: "Yes", hockey: "Yes", marketing: ""}
|
|
536
542
|
|
|
537
|
-
Keys: [:last_name, :first_name, :football, :baseball, :basketball, :
|
|
543
|
+
Keys: [:last_name, :first_name, :football, :baseball, :basketball, :date, :newsletter, :nascar, :language, :signature, :photo, :rugby, :hockey, :marketing]
|
|
538
544
|
|
|
539
|
-
Values: ["Rahl", "Richard", "Yes", "Yes", "Yes", "
|
|
545
|
+
Values: ["Rahl", "Richard", "Yes", "Yes", "Yes", "August 12, 2026", "Off", "Yes", "dart", "", "", "Yes", "Yes", ""]
|
|
540
546
|
|
|
541
547
|
Field 'football' is of type BUTTON
|
|
542
548
|
|
|
543
549
|
Renamed field 'last_name' to 'surname'
|
|
544
550
|
|
|
545
|
-
Removed field '
|
|
551
|
+
Removed field 'marketing'
|
|
546
552
|
```
|
|
547
553
|
|
|
548
554
|
## Contributing
|
|
@@ -556,6 +562,6 @@ Removed field 'nascar'
|
|
|
556
562
|
|
|
557
563
|
## License
|
|
558
564
|
|
|
559
|
-
The gem is available as open source under the terms of the [MIT License](
|
|
565
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/license/MIT).
|
|
560
566
|
|
|
561
|
-
However, you must also adhere to the [iText License](https://github.com/itext/
|
|
567
|
+
However, you must also adhere to the [iText License](https://github.com/itext/itext-java) when using this gem in your project.
|
data/lib/fillable-pdf/version.rb
CHANGED
data/lib/fillable-pdf.rb
CHANGED
|
@@ -128,7 +128,7 @@ class FillablePDF # rubocop:disable Metrics/ClassLength
|
|
|
128
128
|
# @param [String|Symbol] key the field name
|
|
129
129
|
# @param [String|Symbol] file_path the name of the image file or image path
|
|
130
130
|
# @return [self] returns self for method chaining
|
|
131
|
-
# @raise [FileOperationError] if the image file is not found
|
|
131
|
+
# @raise [FileOperationError] if the image file is not found or the field has no visible area
|
|
132
132
|
# @raise [FieldNotFoundError] if the field does not exist
|
|
133
133
|
#
|
|
134
134
|
def set_image(key, file_path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
@@ -136,13 +136,7 @@ class FillablePDF # rubocop:disable Metrics/ClassLength
|
|
|
136
136
|
raise FileOperationError, "File <#{file_path}> is not found" unless File.exist?(file_path)
|
|
137
137
|
|
|
138
138
|
begin
|
|
139
|
-
|
|
140
|
-
widgets = field.getWidgets
|
|
141
|
-
widget_dict = suppress_warnings { widgets.isEmpty ? field.getPdfObject : widgets.get(0).getPdfObject }
|
|
142
|
-
orig_rect = widget_dict.getAsRectangle(ITEXT::PdfName.Rect)
|
|
143
|
-
|
|
144
|
-
border_style = field.getWidgets.get(0).getBorderStyle
|
|
145
|
-
border_width = border_style.nil? ? 0 : border_style.getWidth
|
|
139
|
+
widget_dict, orig_rect, border_width = image_placement(key)
|
|
146
140
|
|
|
147
141
|
bounding_rectangle = ITEXT::Rectangle.new(
|
|
148
142
|
orig_rect.getWidth - (border_width * 2),
|
|
@@ -165,6 +159,8 @@ class FillablePDF # rubocop:disable Metrics/ClassLength
|
|
|
165
159
|
widget_dict.put(ITEXT::PdfName.AP, pdf_dict)
|
|
166
160
|
pdf_dict.put(ITEXT::PdfName.N, pdf_form_x_object.getPdfObject)
|
|
167
161
|
widget_dict.setModified
|
|
162
|
+
rescue FileOperationError
|
|
163
|
+
raise
|
|
168
164
|
rescue StandardError => e
|
|
169
165
|
raise FileOperationError, "Failed to set image for field '#{key}': #{e.message}"
|
|
170
166
|
end
|
|
@@ -393,6 +389,20 @@ class FillablePDF # rubocop:disable Metrics/ClassLength
|
|
|
393
389
|
field
|
|
394
390
|
end
|
|
395
391
|
|
|
392
|
+
# Dictionary, rectangle and border width of the field's first widget, falling
|
|
393
|
+
# back to the field itself when it has no widget annotations.
|
|
394
|
+
def image_placement(key)
|
|
395
|
+
field = pdf_field(key)
|
|
396
|
+
widgets = field.getWidgets
|
|
397
|
+
widget = widgets.isEmpty ? nil : widgets.get(0)
|
|
398
|
+
widget_dict = suppress_warnings { (widget || field).getPdfObject }
|
|
399
|
+
rect = widget_dict.getAsRectangle(ITEXT::PdfName.Rect)
|
|
400
|
+
raise FileOperationError, "Field '#{key}' has no visible area to place an image in" if rect.nil?
|
|
401
|
+
|
|
402
|
+
border_style = widget&.getBorderStyle
|
|
403
|
+
[widget_dict, rect, border_style.nil? ? 0 : border_style.getWidth]
|
|
404
|
+
end
|
|
405
|
+
|
|
396
406
|
def validate_input(key, value)
|
|
397
407
|
validate_field_name(key)
|
|
398
408
|
raise InvalidArgumentError, 'Field value cannot be nil' if value.nil?
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fillable-pdf
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vadim Kononov
|
|
@@ -51,9 +51,9 @@ dependencies:
|
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '1.6'
|
|
54
|
-
description:
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
description: Ruby wrapper for iText to work with AcroForm PDFs. Fill and read text
|
|
55
|
+
fields, checkboxes and radio buttons, add images to fields, rename or remove fields,
|
|
56
|
+
and flatten forms.
|
|
57
57
|
email:
|
|
58
58
|
- vadim@konoson.com
|
|
59
59
|
executables: []
|
|
@@ -98,5 +98,5 @@ requirements:
|
|
|
98
98
|
- JDK >= 8
|
|
99
99
|
rubygems_version: 4.0.10
|
|
100
100
|
specification_version: 4
|
|
101
|
-
summary: Fill
|
|
101
|
+
summary: Fill, read, flatten and edit PDF form fields in Ruby with the iText engine
|
|
102
102
|
test_files: []
|