fillable-pdf 1.1.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3105d6a8fe53b1a6e31ba6c13742fcf1084e9a37e54e6163545962e0afad39c9
4
- data.tar.gz: be445e7766b56bf10b87a08683909932039e3bdd6ed99d2f743635f24f650867
3
+ metadata.gz: 2cdd748940498c34c3e4f19f91f83cfc47fcf34dda1d10eb07e05f7aef9c7d57
4
+ data.tar.gz: a98954a86876c759716a8919a24f54c175ec97eb0eddd19bc2b9aaa844bdd6cb
5
5
  SHA512:
6
- metadata.gz: 7bc9900f789332db17d1b754a911139fd99e14b2410bcaab167311b0d29404fffe0131ea450963fee265c9db0daaa50852371b5ca63f2eadc39c636c3ce62126
7
- data.tar.gz: 412662633f9de92c60cecceaea7bee5afda28c7b55edb5f76d8a424ab9b096a4f598bca4e7ef99adcbe41da090e84a9b1247c99301e25746dd0b5140ad024d51
6
+ metadata.gz: bb4104898a7feb6a16338aae323b3d1285f8fb5dd2458e48d5e936ca17ed27fc407289c68db0a466105bbe06fc1100cfd5a8cfa92873f6f6b731692ee385bfaf
7
+ data.tar.gz: 07430fe63ccbbec3e4c7c5191d6831b767320b87ed6ea0bd0542c11d41e10fe8c7883ce7d396fe7cc31f029d425fb87e055e3af01bd44358cf8d3b99010e17ca
data/README.md CHANGED
@@ -1,14 +1,16 @@
1
1
 
2
2
  # FillablePDF
3
3
 
4
- [![Gem Version](https://img.shields.io/gem/v/fillable-pdf.svg)](https://rubygems.org/gems/fillable-pdf)
5
- [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
- [![Lint Status](https://github.com/vkononov/fillable-pdf/actions/workflows/lint.yml/badge.svg)](https://github.com/vkononov/fillable-pdf/actions/workflows/lint.yml)
7
- [![Test Status](https://github.com/vkononov/fillable-pdf/actions/workflows/test.yml/badge.svg)](https://github.com/vkononov/fillable-pdf/actions/workflows/test.yml)
4
+ [![Gem Version](https://img.shields.io/gem/v/fillable-pdf.svg?label=Gem&logo=rubygems&logoColor=white)](https://rubygems.org/gems/fillable-pdf)
5
+ [![Ruby](https://img.shields.io/badge/Ruby-2.4%20to%204.0-CC342D?logo=ruby&logoColor=white)](https://github.com/vkononov/fillable-pdf/blob/main/.github/workflows/test.yml)
6
+ [![JDK](https://img.shields.io/badge/JDK-8%20to%2026-007396?logo=openjdk&logoColor=white)](https://github.com/vkononov/fillable-pdf/blob/main/.github/workflows/test.yml)
7
+ [![Test Matrix](https://img.shields.io/github/actions/workflow/status/vkononov/fillable-pdf/test.yml?branch=main&label=Test%20Matrix&logo=github)](https://github.com/vkononov/fillable-pdf/actions/workflows/test.yml)
8
+ [![Lint](https://img.shields.io/github/actions/workflow/status/vkononov/fillable-pdf/lint.yml?branch=main&label=Lint&logo=github)](https://github.com/vkononov/fillable-pdf/actions/workflows/lint.yml)
9
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/license/MIT)
8
10
 
9
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.
10
12
 
11
- Supports `Ruby >= 2.4.0` with `JDK >= 8`
13
+ Supports **Ruby 2.4 → latest** and **JDK 8 → latest**, with the full Ruby/Java matrix tested daily in CI.
12
14
 
13
15
  [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/vkononov)
14
16
 
@@ -16,7 +18,7 @@ Supports `Ruby >= 2.4.0` with `JDK >= 8`
16
18
 
17
19
  1. Phusion Passenger's [smart spawning](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#the-smart-spawning-method) is not supported. Please see [Deployment with Phusion Passenger + Nginx](#deployment-with-phusion-passenger--nginx) for more information.
18
20
 
19
- 2. Puma workers (process forking) is not supposed due to an [issue](https://github.com/arton/rjb/issues/88) with the [rjb](https://github.com/arton/rjb) gem dependency.
21
+ 2. Puma workers (process forking) is not supported due to an [issue](https://github.com/arton/rjb/issues/88) with the [rjb](https://github.com/arton/rjb) gem dependency.
20
22
 
21
23
  3. If the gem hangs in `development`, removing the following gems may fix the issue:
22
24
 
@@ -229,7 +231,7 @@ An instance of `FillablePDF` has the following methods at its disposal:
229
231
  pdf.set_field('first_name', 'Richard', generate_appearance: false)
230
232
  ```
231
233
 
232
- * `def set_fields(fields, generate_appearance: nil)`
234
+ * `set_fields(fields, generate_appearance: nil)`
233
235
  *Sets the values of multiple fields given a set of unique field names and values, with an optional `generate_appearance` directive.*
234
236
 
235
237
  ```ruby
@@ -317,7 +319,7 @@ An instance of `FillablePDF` has the following methods at its disposal:
317
319
  # result: document is saved in a given path with flattening
318
320
  ```
319
321
 
320
- **NOTE:** Saving the file automatically closes the input file, so you would need to reinitialize the `FillabePDF` class before making any more changes or saving another copy.
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.
321
323
 
322
324
  * `save_as!(file_path, flatten: false)`
323
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).*
@@ -452,15 +454,18 @@ Naturally, there are many downsides (in terms of efficiency, scalability, securi
452
454
 
453
455
  ## Example
454
456
 
455
- The following [example.rb](example/run.rb) with [input.pdf](example/input.pdf) is located in the [example](example) directory. It uses all 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).
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).
456
458
 
457
459
  ```ruby
458
460
  require_relative '../lib/fillable-pdf'
459
461
 
462
+ # Get the directory where this script is located
463
+ EXAMPLE_DIR = __dir__
464
+
460
465
  BASE64_PHOTO = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' # rubocop:disable Layout/LineLength
461
466
 
462
467
  # opening a fillable PDF
463
- pdf = FillablePDF.new('input.pdf')
468
+ pdf = FillablePDF.new(File.join(EXAMPLE_DIR, 'input.pdf'))
464
469
 
465
470
  # total number of fields
466
471
  if pdf.any_fields?
@@ -473,12 +478,15 @@ puts
473
478
 
474
479
  # setting form fields
475
480
  pdf.set_fields({first_name: 'Richard', last_name: 'Rahl'})
476
- pdf.set_fields({football: 'Yes', baseball: 'Yes', basketball: 'Yes', nascar: 'Yes', hockey: 'Yes', rugby: 'Yes'}, generate_appearance: false)
481
+ pdf.set_fields(
482
+ {football: 'Yes', baseball: 'Yes', basketball: 'Yes', nascar: 'Yes', hockey: 'Yes', rugby: 'Yes'},
483
+ generate_appearance: false
484
+ )
477
485
  pdf.set_field(:date, Time.now.strftime('%B %e, %Y'))
478
486
  pdf.set_field(:newsletter, 'Off') # uncheck the checkbox
479
487
  pdf.set_field(:language, 'dart') # select a radio button option
480
488
  pdf.set_image_base64(:photo, BASE64_PHOTO)
481
- pdf.set_image(:signature, 'signature.png')
489
+ pdf.set_image(:signature, File.join(EXAMPLE_DIR, 'signature.png'))
482
490
 
483
491
  # list of fields
484
492
  puts "Fields hash: #{pdf.fields}"
@@ -515,11 +523,11 @@ pdf.remove_field :marketing
515
523
  puts "Removed field 'marketing'"
516
524
 
517
525
  # saving the filled out PDF in another file
518
- pdf.save_as('output.pdf')
526
+ pdf.save_as(File.join(EXAMPLE_DIR, 'output.pdf'))
519
527
 
520
528
  # saving another copy of the filled out PDF in another file and making it non-editable
521
- pdf = FillablePDF.new('output.pdf')
522
- 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
523
531
 
524
532
  # closing the document
525
533
  pdf.close
@@ -528,19 +536,19 @@ pdf.close
528
536
  The example above produces the following output and also generates the output file [output.pdf](example/output.pdf).
529
537
 
530
538
  ```text
531
- The form has a total of 16 fields.
539
+ The form has a total of 14 fields.
532
540
 
533
- Fields hash: {:last_name=>"Rahl", :first_name=>"Richard", :football=>"Yes", :baseball=>"Yes", :basketball=>"Yes", :hockey=>"Yes", :date=>"November 16, 2021", :newsletter=>"Off", :nascar=>"Yes", :language=>"dart", :"language.1"=>"dart", :"language.2"=>"dart", :"language.3"=>"dart", :"language.4"=>"dart", :signature=>"", :photo=>""}
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: ""}
534
542
 
535
- Keys: [:last_name, :first_name, :football, :baseball, :basketball, :hockey, :date, :newsletter, :nascar, :language, :"language.1", :"language.2", :"language.3", :"language.4", :signature, :photo]
543
+ Keys: [:last_name, :first_name, :football, :baseball, :basketball, :date, :newsletter, :nascar, :language, :signature, :photo, :rugby, :hockey, :marketing]
536
544
 
537
- Values: ["Rahl", "Richard", "Yes", "Yes", "Yes", "Yes", "November 16, 2021", "Off", "Yes", "dart", "dart", "dart", "dart", "dart", "", ""]
545
+ Values: ["Rahl", "Richard", "Yes", "Yes", "Yes", "August 12, 2026", "Off", "Yes", "dart", "", "", "Yes", "Yes", ""]
538
546
 
539
547
  Field 'football' is of type BUTTON
540
548
 
541
549
  Renamed field 'last_name' to 'surname'
542
550
 
543
- Removed field 'nascar'
551
+ Removed field 'marketing'
544
552
  ```
545
553
 
546
554
  ## Contributing
@@ -554,6 +562,6 @@ Removed field 'nascar'
554
562
 
555
563
  ## License
556
564
 
557
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
565
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/license/MIT).
558
566
 
559
- However, you must also adhere to the [iText License](https://github.com/itext/itext7) when using this gem in your project.
567
+ However, you must also adhere to the [iText License](https://github.com/itext/itext-java) when using this gem in your project.
Binary file
@@ -1,3 +1,3 @@
1
1
  class FillablePDF
2
- VERSION = '1.1.1'
2
+ VERSION = '1.1.3'
3
3
  end
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
- field = pdf_field(key)
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.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: FillablePDF is an extremely simple and lightweight utility that bridges
55
- iText and Ruby in order to fill out fillable PDF forms or extract field values from
56
- previously filled out PDF forms.
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: []
@@ -62,12 +62,12 @@ extra_rdoc_files: []
62
62
  files:
63
63
  - LICENSE.md
64
64
  - README.md
65
- - ext/commons-9.7.0.jar
66
- - ext/font-asian-9.7.0.jar
67
- - ext/forms-9.7.0.jar
68
- - ext/io-9.7.0.jar
69
- - ext/kernel-9.7.0.jar
70
- - ext/layout-9.7.0.jar
65
+ - ext/commons-9.7.1.jar
66
+ - ext/font-asian-9.7.1.jar
67
+ - ext/forms-9.7.1.jar
68
+ - ext/io-9.7.1.jar
69
+ - ext/kernel-9.7.1.jar
70
+ - ext/layout-9.7.1.jar
71
71
  - ext/slf4j-api-2.0.18.jar
72
72
  - ext/slf4j-simple-2.0.18.jar
73
73
  - lib/fillable-pdf.rb
@@ -98,5 +98,5 @@ requirements:
98
98
  - JDK >= 8
99
99
  rubygems_version: 4.0.10
100
100
  specification_version: 4
101
- summary: Fill out or extract field values from simple fillable PDF forms using iText.
101
+ summary: Fill, read, flatten and edit PDF form fields in Ruby with the iText engine
102
102
  test_files: []