fillable-pdf 0.7.2 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7dc484831ca2d2e181d269d0a3edd8e267b13baf970b43edc367274a6cd8629
4
- data.tar.gz: 82a788e368997808f8c08824dbc130a0d95bfc5a1c72e439a83bb474508de82d
3
+ metadata.gz: 389bff629090f3998b0981c03d347801d3dde03b7a1e829634980a38524cc7c4
4
+ data.tar.gz: c23c74c352cd65c434cca51056276757c6e7d0f217119d9a2de42bc76203db92
5
5
  SHA512:
6
- metadata.gz: e21037070edbe7b10143798a27a0e312890c45cc82e3fda731df4657bc3b8d6b4f8d87caca17acce484e6c9b6f5e33d1da05fac6b34679c71a3b254d3d344eb5
7
- data.tar.gz: 6814dbe8c682a026fce96ffa8dc99c7f6363983d2b5667a460abab047249b65a9a7f9ad0165298b91bf38b010489e3fbea8460f84e1ca2e7ae595f8858dcd176
6
+ metadata.gz: dfb50d0139200dce237e1074496acbc3b24cb0b0b89884a233763c988892b8700cd597433989666ba68e3edb1dd20afb4d451b56644002f19115e18359f9314f
7
+ data.tar.gz: 5a9e3d9341305c82a8df63215e02d4e9c590a4e0ef405a0c5a5748ec49f7a9c46284b8dace44907c3adbc2792f516e61e67f5a6c07b91375979ecb3f0b6d362f
data/.rubocop.yml CHANGED
@@ -1,21 +1,39 @@
1
1
  require:
2
+ - rubocop-md
3
+ - rubocop-minitest
2
4
  - rubocop-performance
5
+ - rubocop-rake
3
6
 
4
7
  AllCops:
8
+ NewCops: enable
5
9
  Exclude:
6
10
  - .git/**/*
7
11
 
8
- Layout/EmptyLineAfterGuardClause:
12
+ Gemspec/RequiredRubyVersion:
9
13
  Enabled: false
10
14
 
11
- Layout/SpaceInsideHashLiteralBraces:
15
+ Layout/EmptyLineAfterGuardClause:
12
16
  Enabled: false
13
17
 
14
- Metrics/LineLength:
18
+ Layout/IndentationConsistency:
19
+ Exclude:
20
+ - README.md
21
+
22
+ Layout/InitialIndentation:
23
+ Exclude:
24
+ - README.md
25
+
26
+ Layout/LineLength:
15
27
  Exclude:
16
28
  - fillable-pdf.gemspec
17
29
  Max: 120
18
30
 
31
+ Layout/SpaceInsideHashLiteralBraces:
32
+ Enabled: false
33
+
34
+ Metrics/MethodLength:
35
+ Max: 12
36
+
19
37
  Naming/AccessorMethodName:
20
38
  Enabled: false
21
39
 
data/.travis.yml CHANGED
@@ -3,8 +3,8 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.6.4
6
+ - 3.0.2
7
7
  jdk:
8
8
  - openjdk8
9
9
  before_install:
10
- - gem install bundler -v 2.0.2
10
+ - gem install bundler
@@ -1,3 +1,7 @@
1
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
2
+
3
+ However, you must also adhere to the [iText License](https://github.com/itext/itext7) when using this gem in your project.
4
+
1
5
  The MIT License (MIT)
2
6
 
3
7
  Copyright (c) 2016 Vadim Kononov
data/README.md CHANGED
@@ -1,28 +1,108 @@
1
+
1
2
  # FillablePDF
2
3
 
3
4
  [![Gem Version](https://badge.fury.io/rb/fillable-pdf.svg)](https://rubygems.org/gems/fillable-pdf)
4
5
  [![Build Status](https://api.travis-ci.org/vkononov/fillable-pdf.svg?branch=master)](http://travis-ci.org/vkononov/fillable-pdf)
5
6
 
6
- 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.
7
+ 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.
8
+
9
+
10
+ ## Known Issues
11
+
12
+ 1. This gem currently does not work with Phusion Passenger's [smart spawning](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#the-smart-spawning-method). Please see [Deployment with Phusion Passenger + Nginx](#deployment-with-phusion-passenger--nginx) for more information.
13
+
14
+ 2. If the gem hangs in `development`, removing the following gems may fix the issue:
15
+
16
+ ```ruby
17
+ gem 'spring'
18
+ gem 'spring-watcher-listen'
19
+ ```
20
+
21
+
22
+ ## Deployment with Heroku
23
+
24
+ When deploying to Heroku, be sure to install the following build packs (in this order):
25
+
26
+ ```bash
27
+ heroku buildpacks:add heroku/jvm
28
+ heroku buildpacks:add heroku/ruby
29
+ ```
30
+
31
+ ## Deployment with Phusion Passenger + Nginx
32
+
33
+ The way the gem is currently built makes it [fundamentally incompatible](https://github.com/phusion/passenger/issues/223#issuecomment-44504029) with Phusion Passenger's [smart spawning](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#the-smart-spawning-method). You must turn off smart spawning, or else your application will freeze as soon Ruby tries to access the Java bridge.
34
+
35
+ Below is an example of a simple Nginx virtual host configuration (note the use of `passenger_spawn_method`):
36
+
37
+ ```nginx
38
+ server {
39
+ server_name my-rails-app.com;
40
+ listen 443 ssl http2;
41
+ listen [::]:443 ssl http2;
42
+ passenger_enabled on;
43
+ passenger_spawn_method direct;
44
+ root /home/system/my-rails-app/public;
45
+ }
46
+ ```
47
+
48
+ If you absolutely must have smart spawning, I recommend using `fillable-pdf` as a service that runs independently of your Rails application.
49
+
50
+
51
+ ## Deployment with Puma + Nginx
52
+
53
+ In order to use Puma in production, you need to configure a reverse proxy in your Nginx virtual host. Here is simple naive example:
54
+
55
+ ```nginx
56
+ server {
57
+ server_name my-rails-app.com;
58
+ listen 443 ssl http2;
59
+ listen [::]:443 ssl http2;
60
+ location / {
61
+ proxy_pass http://127.0.0.1:8888;
62
+ proxy_redirect off;
63
+ proxy_set_header Connection "upgrade";
64
+ proxy_set_header Host $http_host;
65
+ proxy_set_header Upgrade $http_upgrade;
66
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
67
+ proxy_set_header X-Forwarded-Proto https;
68
+ proxy_set_header X-Real-IP $remote_addr;
69
+ }
70
+ }
71
+ ```
72
+
73
+ Then you'll have to start Puma in production daemon mode as follows:
74
+
75
+ ```bash
76
+ RAILS_ENV=production bin/rails server -p 8888 --daemon
77
+ ```
78
+
79
+ Naturally, there are many downsides (in terms of efficiency, scalability, security, etc) to running your application in production in this manner, so please use the above as an example only.
80
+
7
81
 
8
82
  ## Installation
9
83
 
10
84
  **Ensure that your `JAVA_HOME` variable is set before installing this gem (see examples below).**
11
-
12
- * OSX: `/Library/Java/JavaVirtualMachines/jdk-12.0.2.jdk/Contents/Home`
85
+
86
+ * OSX: `/Library/Java/JavaVirtualMachines/jdk-12.0.2.jdk/Contents/Home`
13
87
  * Ubuntu/CentOS: `/usr/lib/jvm/java-1.8.0-openjdk`
14
88
 
15
89
  Add this line to your application's Gemfile:
16
90
 
17
- gem 'fillable-pdf'
91
+ ```ruby
92
+ gem 'fillable-pdf'
93
+ ```
18
94
 
19
95
  And then execute:
20
96
 
21
- bundle
97
+ ```bash
98
+ bundle
99
+ ```
22
100
 
23
101
  Or install it yourself as:
24
102
 
25
- gem install fillable-pdf
103
+ ```bash
104
+ gem install fillable-pdf
105
+ ```
26
106
 
27
107
  If you are using this gem in a script, you need to require it manually:
28
108
 
@@ -38,104 +118,177 @@ First of all, you should open a fillable PDF file:
38
118
  pdf = FillablePDF.new 'input.pdf'
39
119
  ```
40
120
 
41
- An instance of `FillablePDF` has the following methods at its disposal:
121
+ > **Always remember to close your document once you're finished working with it in order to avoid memory leaks:**
42
122
 
43
123
  ```ruby
44
- fillable-pdf
45
- # output example: true
46
- pdf.any_fields?
124
+ pdf.close
47
125
  ```
48
126
 
49
- ```ruby
50
- # get the total number of fillable form fields
51
- # output example: 10
52
- pdf.num_fields
53
- ```
127
+ ### Checking / Unchecking Checkboxes
54
128
 
55
- ```ruby
56
- # retrieve a single field value by field name
57
- # output example: 'Richard'
58
- pdf.field(:full_name)
59
- ```
129
+ Use the values `'Yes'` and `'Off'` to check and uncheck checkboxes, respectively. For example:
60
130
 
61
131
  ```ruby
62
- # retrieve a field type by field name
63
- # numeric types should
64
- # output example: 4
65
- pdf.field_type(:football)
66
-
67
- # list of all field types
68
- Field::BUTTON
69
- Field::CHOICE
70
- Field::SIGNATURE
71
- Field::TEXT
132
+ pdf.set_field(:newsletter, 'Yes')
133
+ pdf.set_field(:newsletter, 'Off')
72
134
  ```
73
135
 
74
- ```ruby
75
- # retrieve a hash of field name and values
76
- # output example: {:last_name=>"Rahl", :first_name=>"Richard"}
77
- pdf.fields
78
- ```
136
+ ### Checking / Unchecking Radio Buttons
79
137
 
80
- ```ruby
81
- # set the value of a single field by field name
82
- # result: changes the value of 'first_name' to 'Richard'
83
- pdf.set_field(:first_name, 'Richard')
84
- ```
138
+ Suppose you have the following a radio button field name `language` with the following options:
85
139
 
86
- ```ruby
87
- # set the values of multiple fields by field names
88
- # result: changes the values of 'first_name' and 'last_name'
89
- pdf.set_fields(first_name: 'Richard', last_name: 'Rahl')
90
- ```
140
+ - Ruby (`ruby`)
141
+ - Python (`python`)
142
+ - Dart (`dart`)
143
+ - Other (`other`)
91
144
 
92
- ```ruby
93
- # rename field (i.e. change the name of the field)
94
- # result: renames field name 'last_name' to 'surname'
95
- # NOTE: this action does not take effect until the document is saved
96
- pdf.rename_field(:last_name, :surname)
97
- ```
145
+ To select one of these options (or change the current option) use:
98
146
 
99
147
  ```ruby
100
- # remove field (i.e. delete field and its value)
101
- # result: physically removes field 'last_name' from document
102
- pdf.remove_field(:last_name)
148
+ pdf.set_field(:language, 'dart')
103
149
  ```
104
150
 
105
- ```ruby
106
- # get an array of all field names in the document
107
- # output example: [:first_name, :last_name]
108
- pdf.names
109
- ```
151
+ To unset the radio button use the `'Off'` string:
110
152
 
111
153
  ```ruby
112
- # get an array of all field values in the document
113
- # output example: ["Rahl", "Richard"]
114
- pdf.values
154
+ pdf.set_field(:language, 'Off')
115
155
  ```
116
156
 
117
- Once the PDF is filled out you can either overwrite it or save it as another file:
157
+ ### Instance Methods
118
158
 
119
- ```ruby
120
- pdf.save
121
- pdf.save_as('output.pdf')
122
- ```
159
+ An instance of `FillablePDF` has the following methods at its disposal:
123
160
 
124
- Or if you prefer to flatten the file (i.e. make it non-editable), you can instead use:
161
+ * `any_fields?`
162
+ *Determines whether the form has any fields.*
163
+
164
+ ```ruby
165
+ pdf.any_fields?
166
+ # output example: true
167
+ ```
125
168
 
126
- ```ruby
127
- pdf.save(flatten: true)
128
- pdf.save_as('output.pdf', flatten: true)
129
- ```
169
+ * `num_fields`
170
+ *Returns the total number of fillable form fields.*
171
+
172
+ ```ruby
173
+ # output example: 10
174
+ pdf.num_fields
175
+ ```
176
+
177
+ * `field`
178
+ *Retrieves the value of a field given its unique field name.*
179
+
180
+ ```ruby
181
+ pdf.field(:full_name)
182
+ # output example: 'Richard'
183
+ ```
184
+
185
+ * `field_type`
186
+ *Retrieves the numeric type of a field given its unique field name.*
187
+
188
+ ```ruby
189
+ pdf.field_type(:football)
190
+ # output example: '/Btn'
191
+
192
+ # list of all field types
193
+ Field::BUTTON ('/Btn')
194
+ Field::CHOICE ('/Ch')
195
+ Field::SIGNATURE ('/Sig')
196
+ Field::TEXT ('/Tx')
197
+ ```
198
+
199
+ * `fields`
200
+ *Retrieves a hash of all fields and their values.*
201
+
202
+ ```ruby
203
+ pdf.fields
204
+ # output example: {first_name: "Richard", last_name: "Rahl"}
205
+ ```
206
+
207
+ * `set_field`
208
+ *Sets the value of a field given its unique field name and value.*
130
209
 
131
- **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.
210
+ ```ruby
211
+ pdf.set_field(:first_name, 'Richard')
212
+ # result: changes the value of 'first_name' to 'Richard'
213
+ ```
214
+
215
+ * `set_fields`
216
+ *Sets the values of multiple fields given a set of unique field names and values.*
217
+
218
+ ```ruby
219
+ pdf.set_fields(first_name: 'Richard', last_name: 'Rahl')
220
+ # result: changes the values of 'first_name' and 'last_name'
221
+ ```
222
+
223
+ * `rename_field`
224
+ *Renames a field given its unique field name and the new field name.*
225
+
226
+ ```ruby
227
+ pdf.rename_field(:last_name, :surname)
228
+ # result: renames field name 'last_name' to 'surname'
229
+ # NOTE: this action does not take effect until the document is saved
230
+ ```
231
+
232
+ * `remove_field`
233
+ *Removes a field from the document given its unique field name.*
234
+
235
+ ```ruby
236
+ pdf.remove_field(:last_name)
237
+ # result: physically removes field 'last_name' from document
238
+ ```
239
+
240
+ * `names`
241
+ *Returns a list of all field keys used in the document.*
242
+
243
+ ```ruby
244
+ pdf.names
245
+ # output example: [:first_name, :last_name]
246
+ ```
247
+
248
+ * `values`
249
+ *Returns a list of all field values used in the document.*
250
+
251
+ ```ruby
252
+ pdf.values
253
+ # output example: ["Rahl", "Richard"]
254
+ ```
255
+
256
+ * `save`
257
+ *Overwrites the previously opened PDF document and flattens it if requested.*
258
+
259
+ ```ruby
260
+ pdf.save
261
+ # result: document is saved without flattening
262
+ pdf.save_as(flatten: true)
263
+ # result: document is saved with flattening
264
+ ```
265
+
266
+ * `save_as`
267
+ *Saves the filled out PDF document in a given path and flattens it if requested.*
268
+
269
+ ```ruby
270
+ pdf.save_as('output.pdf')
271
+ # result: document is saved in a given path without flattening
272
+ pdf.save_as('output.pdf', flatten: true)
273
+ # result: document is saved in a given path with flattening
274
+ ```
275
+
276
+ **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.
277
+
278
+ * `close`
279
+ *Closes the PDF document discarding all unsaved changes.*
280
+
281
+ ```ruby
282
+ pdf.close
283
+ # result: document is closed
284
+ ```
132
285
 
133
286
  ## Example
134
287
 
135
288
  The following example [example.rb](example/run.rb) and the input file [input.pdf](example/input.pdf) are located in the `test` 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).
136
289
 
137
290
  ```ruby
138
- require 'fillable-pdf'
291
+ require_relative '../lib/fillable-pdf'
139
292
 
140
293
  # opening a fillable PDF
141
294
  pdf = FillablePDF.new('input.pdf')
@@ -154,6 +307,8 @@ pdf.set_fields(first_name: 'Richard', last_name: 'Rahl')
154
307
  pdf.set_fields(football: 'Yes', baseball: 'Yes',
155
308
  basketball: 'Yes', nascar: 'Yes', hockey: 'Yes')
156
309
  pdf.set_field(:date, Time.now.strftime('%B %e, %Y'))
310
+ pdf.set_field(:newsletter, 'Off') # uncheck the checkbox
311
+ pdf.set_field(:language, 'dart') # select a radio button option
157
312
 
158
313
  # list of fields
159
314
  puts "Fields hash: #{pdf.fields}"
@@ -199,18 +354,21 @@ pdf.save_as('output.pdf')
199
354
  # saving another copy of the filled out PDF in another file and making it non-editable
200
355
  pdf = FillablePDF.new('output.pdf')
201
356
  pdf.save_as 'output.flat.pdf', flatten: true
357
+
358
+ # closing the document
359
+ pdf.close
202
360
  ```
203
361
 
204
362
  The example above produces the following output and also generates the output file [output.pdf](example/output.pdf).
205
363
 
206
- ```
207
- The form has a total of 8 fields.
364
+ ```text
365
+ The form has a total of 14 fields.
208
366
 
209
- Fields hash: {:last_name=>"Rahl", :first_name=>"Richard", :football=>"Yes", :baseball=>"Yes", :basketball=>"Yes", :nascar=>"Yes", :hockey=>"Yes", :date=>"August 30, 2019"}
367
+ Fields hash: {:last_name=>"Rahl", :first_name=>"Richard", :football=>"Yes", :baseball=>"Yes", :basketball=>"Yes", :hockey=>"Yes", :date=>"November 15, 2021", :newsletter=>"Off", :nascar=>"Yes", :language=>"dart", :"language.1"=>"dart", :"language.2"=>"dart", :"language.3"=>"dart", :"language.4"=>"dart"}
210
368
 
211
- Keys: [:last_name, :first_name, :football, :baseball, :basketball, :nascar, :hockey, :date]
369
+ Keys: [:last_name, :first_name, :football, :baseball, :basketball, :hockey, :date, :newsletter, :nascar, :language, :"language.1", :"language.2", :"language.3", :"language.4"]
212
370
 
213
- Values: ["Rahl", "Richard", "Yes", "Yes", "Yes", "Yes", "Yes", "August 30, 2019"]
371
+ Values: ["Rahl", "Richard", "Yes", "Yes", "Yes", "Yes", "November 15, 2021", "Off", "Yes", "dart", "dart", "dart", "dart", "dart"]
214
372
 
215
373
  Field 'football' is of type BUTTON
216
374
 
@@ -233,3 +391,5 @@ Signatory: Richard Rahl
233
391
  ## License
234
392
 
235
393
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
394
+
395
+ However, you must also adhere to the [iText License](https://github.com/itext/itext7) when using this gem in your project.
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
+ require 'rubocop/rake_task'
3
4
 
4
5
  Rake::TestTask.new(:test) do |t|
5
6
  t.libs << 'test'
@@ -7,4 +8,6 @@ Rake::TestTask.new(:test) do |t|
7
8
  t.test_files = FileList['test/**/*_test.rb']
8
9
  end
9
10
 
10
- task default: :test
11
+ RuboCop::RakeTask.new
12
+
13
+ task default: %i[test rubocop]
Binary file
Binary file
data/ext/io-7.1.17.jar ADDED
Binary file
Binary file
Binary file
Binary file
Binary file
data/fillable-pdf.gemspec CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = '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.'
13
13
  spec.homepage = 'https://github.com/vkononov/fillable-pdf'
14
14
  spec.license = 'MIT'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
15
16
 
16
17
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
17
18
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(example|test|spec|features)/}) }
@@ -20,9 +21,18 @@ Gem::Specification.new do |spec|
20
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
22
  spec.require_paths = %w[ext lib]
22
23
 
23
- spec.add_development_dependency 'bundler', '~> 2.0'
24
- spec.add_development_dependency 'minitest', '~> 5.0'
25
- spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'bundler'
25
+ spec.add_development_dependency 'minitest'
26
+ spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'rubocop'
28
+ spec.add_development_dependency 'rubocop-md'
29
+ spec.add_development_dependency 'rubocop-minitest'
30
+ spec.add_development_dependency 'rubocop-performance'
31
+ spec.add_development_dependency 'rubocop-rake'
26
32
 
27
- spec.add_runtime_dependency 'rjb', '~> 1.6'
33
+ spec.add_runtime_dependency 'rjb', '1.6.2'
34
+
35
+ spec.metadata = {
36
+ 'rubygems_mfa_required' => 'true'
37
+ }
28
38
  end
data/lib/field.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  require_relative 'fillable-pdf/itext'
2
+ require_relative 'kernel'
2
3
 
3
4
  class Field
4
- PDF_NAME = Rjb.import('com.itextpdf.kernel.pdf.PdfName')
5
+ # PdfName has a constant "A" and a constant "a". Unfortunately, RJB does not differentiate
6
+ # between these constants and tries to create the same constant ("A") for both, which causes
7
+ # an annoying warning "already initialized constant Rjb::Com_itextpdf_kernel_pdf_PdfName::A".
8
+ # As long as RJB has not fixed this issue, this warning will remain suppressed.
9
+ suppress_warnings { PDF_NAME = Rjb.import('com.itextpdf.kernel.pdf.PdfName') } # rubocop:disable Lint/ConstantDefinitionInBlock
5
10
 
6
11
  BUTTON = PDF_NAME.Btn.toString
7
12
  CHOICE = PDF_NAME.Ch.toString
@@ -1,3 +1,3 @@
1
1
  class FillablePDF
2
- VERSION = '0.7.2'
2
+ VERSION = '0.9.2'
3
3
  end
data/lib/fillable-pdf.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require_relative 'fillable-pdf/itext'
2
2
  require_relative 'field'
3
+ require 'fileutils'
3
4
  require 'securerandom'
4
5
 
5
6
  class FillablePDF
@@ -19,12 +20,16 @@ class FillablePDF
19
20
  def initialize(file_path)
20
21
  raise IOError, "File at `#{file_path}' is not found" unless File.exist?(file_path)
21
22
  @file_path = file_path
22
- @byte_stream = BYTE_STREAM.new
23
- @pdf_reader = PDF_READER.new @file_path
24
- @pdf_writer = PDF_WRITER.new @byte_stream
25
- @pdf_doc = PDF_DOCUMENT.new @pdf_reader, @pdf_writer
26
- @pdf_form = PDF_ACRO_FORM.getAcroForm(@pdf_doc, true)
27
- @form_fields = @pdf_form.getFormFields
23
+ begin
24
+ @byte_stream = BYTE_STREAM.new
25
+ @pdf_reader = PDF_READER.new @file_path.to_s
26
+ @pdf_writer = PDF_WRITER.new @byte_stream
27
+ @pdf_doc = PDF_DOCUMENT.new @pdf_reader, @pdf_writer
28
+ @pdf_form = PDF_ACRO_FORM.getAcroForm(@pdf_doc, true)
29
+ @form_fields = @pdf_form.getFormFields
30
+ rescue StandardError => e
31
+ raise "#{e.message} (input file may be corrupt, incompatible, or may not have any forms)"
32
+ end
28
33
  end
29
34
 
30
35
  ##
@@ -37,7 +42,7 @@ class FillablePDF
37
42
  end
38
43
 
39
44
  ##
40
- # Returns the total number of form fields.
45
+ # Returns the total number of fillable form fields.
41
46
  #
42
47
  # @return the number of fields
43
48
  #
@@ -147,24 +152,38 @@ class FillablePDF
147
152
  end
148
153
 
149
154
  ##
150
- # Overwrites the previously opened PDF file and flattens it if requested.
155
+ # Overwrites the previously opened PDF document and flattens it if requested.
151
156
  #
152
157
  # @param [bool] flatten true if PDF should be flattened, false otherwise
153
158
  #
154
159
  def save(flatten: false)
155
160
  tmp_file = SecureRandom.uuid
156
161
  save_as(tmp_file, flatten: flatten)
157
- File.rename tmp_file, @file_path
162
+ FileUtils.mv tmp_file, @file_path
158
163
  end
159
164
 
160
165
  ##
161
- # Saves the filled out PDF file with a given file and flattens it if requested.
166
+ # Saves the filled out PDF document in a given path and flattens it if requested.
162
167
  #
163
168
  # @param [String] file_path the name of the PDF file or file path
164
169
  # @param [Hash] flatten: true if PDF should be flattened, false otherwise
165
170
  #
166
171
  def save_as(file_path, flatten: false)
167
- File.open(file_path, 'wb') { |f| f.write(finalize(flatten: flatten)) && f.close }
172
+ if @file_path == file_path
173
+ save(flatten: flatten)
174
+ else
175
+ File.open(file_path, 'wb') { |f| f.write(finalize(flatten: flatten)) && f.close }
176
+ end
177
+ end
178
+
179
+ ##
180
+ # Closes the PDF document discarding all unsaved changes.
181
+ #
182
+ # @return [Boolean] true if document is closed, false otherwise
183
+ #
184
+ def close
185
+ @pdf_doc.close
186
+ @pdf_doc.isClosed
168
187
  end
169
188
 
170
189
  private
@@ -176,7 +195,7 @@ class FillablePDF
176
195
  #
177
196
  def finalize(flatten: false)
178
197
  @pdf_form.flattenFields if flatten
179
- @pdf_doc.close
198
+ close
180
199
  @byte_stream.toByteArray
181
200
  end
182
201
 
data/lib/kernel.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Kernel
2
+ def suppress_warnings
3
+ original_verbosity = $VERBOSE
4
+ $VERBOSE = nil
5
+ result = yield
6
+ $VERBOSE = original_verbosity
7
+ result
8
+ end
9
+ end
metadata CHANGED
@@ -1,71 +1,141 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fillable-pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vadim Kononov
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-04 00:00:00.000000000 Z
11
+ date: 2021-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '5.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '5.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-md
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-performance
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
55
125
  - !ruby/object:Gem::Dependency
56
126
  name: rjb
57
127
  requirement: !ruby/object:Gem::Requirement
58
128
  requirements:
59
- - - "~>"
129
+ - - '='
60
130
  - !ruby/object:Gem::Version
61
- version: '1.6'
131
+ version: 1.6.2
62
132
  type: :runtime
63
133
  prerelease: false
64
134
  version_requirements: !ruby/object:Gem::Requirement
65
135
  requirements:
66
- - - "~>"
136
+ - - '='
67
137
  - !ruby/object:Gem::Version
68
- version: '1.6'
138
+ version: 1.6.2
69
139
  description: FillablePDF is an extremely simple and lightweight utility that bridges
70
140
  iText and Ruby in order to fill out fillable PDF forms or extract field values from
71
141
  previously filled out PDF forms.
@@ -79,27 +149,30 @@ files:
79
149
  - ".rubocop.yml"
80
150
  - ".travis.yml"
81
151
  - Gemfile
82
- - LICENSE.txt
152
+ - LICENSE.md
83
153
  - README.md
84
154
  - Rakefile
85
155
  - bin/console
86
156
  - bin/setup
87
- - ext/forms-7.1.9.jar
88
- - ext/io-7.1.9.jar
89
- - ext/kernel-7.1.9.jar
90
- - ext/layout-7.1.9.jar
91
- - ext/slf4j-api-1.7.29.jar
92
- - ext/slf4j-simple-1.7.29.jar
157
+ - ext/font-asian-7.1.17.jar
158
+ - ext/forms-7.1.17.jar
159
+ - ext/io-7.1.17.jar
160
+ - ext/kernel-7.1.17.jar
161
+ - ext/layout-7.1.17.jar
162
+ - ext/slf4j-api-1.7.32.jar
163
+ - ext/slf4j-simple-1.7.32.jar
93
164
  - fillable-pdf.gemspec
94
165
  - lib/field.rb
95
166
  - lib/fillable-pdf.rb
96
167
  - lib/fillable-pdf/itext.rb
97
168
  - lib/fillable-pdf/version.rb
169
+ - lib/kernel.rb
98
170
  homepage: https://github.com/vkononov/fillable-pdf
99
171
  licenses:
100
172
  - MIT
101
- metadata: {}
102
- post_install_message:
173
+ metadata:
174
+ rubygems_mfa_required: 'true'
175
+ post_install_message:
103
176
  rdoc_options: []
104
177
  require_paths:
105
178
  - ext
@@ -108,15 +181,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
181
  requirements:
109
182
  - - ">="
110
183
  - !ruby/object:Gem::Version
111
- version: '0'
184
+ version: 2.4.0
112
185
  required_rubygems_version: !ruby/object:Gem::Requirement
113
186
  requirements:
114
187
  - - ">="
115
188
  - !ruby/object:Gem::Version
116
189
  version: '0'
117
190
  requirements: []
118
- rubygems_version: 3.0.3
119
- signing_key:
191
+ rubygems_version: 3.2.22
192
+ signing_key:
120
193
  specification_version: 4
121
194
  summary: Fill out or extract field values from simple fillable PDF forms using iText.
122
195
  test_files: []
data/ext/forms-7.1.9.jar DELETED
Binary file
data/ext/io-7.1.9.jar DELETED
Binary file
data/ext/kernel-7.1.9.jar DELETED
Binary file
data/ext/layout-7.1.9.jar DELETED
Binary file
Binary file
Binary file