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 +4 -4
- data/.rubocop.yml +21 -3
- data/.travis.yml +2 -2
- data/{LICENSE.txt → LICENSE.md} +4 -0
- data/README.md +239 -79
- data/Rakefile +4 -1
- data/ext/font-asian-7.1.17.jar +0 -0
- data/ext/forms-7.1.17.jar +0 -0
- data/ext/io-7.1.17.jar +0 -0
- data/ext/kernel-7.1.17.jar +0 -0
- data/ext/layout-7.1.17.jar +0 -0
- data/ext/slf4j-api-1.7.32.jar +0 -0
- data/ext/slf4j-simple-1.7.32.jar +0 -0
- data/fillable-pdf.gemspec +14 -4
- data/lib/field.rb +6 -1
- data/lib/fillable-pdf/version.rb +1 -1
- data/lib/fillable-pdf.rb +31 -12
- data/lib/kernel.rb +9 -0
- metadata +104 -31
- data/ext/forms-7.1.9.jar +0 -0
- data/ext/io-7.1.9.jar +0 -0
- data/ext/kernel-7.1.9.jar +0 -0
- data/ext/layout-7.1.9.jar +0 -0
- data/ext/slf4j-api-1.7.29.jar +0 -0
- data/ext/slf4j-simple-1.7.29.jar +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 389bff629090f3998b0981c03d347801d3dde03b7a1e829634980a38524cc7c4
|
4
|
+
data.tar.gz: c23c74c352cd65c434cca51056276757c6e7d0f217119d9a2de42bc76203db92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
12
|
+
Gemspec/RequiredRubyVersion:
|
9
13
|
Enabled: false
|
10
14
|
|
11
|
-
Layout/
|
15
|
+
Layout/EmptyLineAfterGuardClause:
|
12
16
|
Enabled: false
|
13
17
|
|
14
|
-
|
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
data/{LICENSE.txt → LICENSE.md}
RENAMED
@@ -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
|
-
|
91
|
+
```ruby
|
92
|
+
gem 'fillable-pdf'
|
93
|
+
```
|
18
94
|
|
19
95
|
And then execute:
|
20
96
|
|
21
|
-
|
97
|
+
```bash
|
98
|
+
bundle
|
99
|
+
```
|
22
100
|
|
23
101
|
Or install it yourself as:
|
24
102
|
|
25
|
-
|
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
|
-
|
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
|
-
|
45
|
-
# output example: true
|
46
|
-
pdf.any_fields?
|
124
|
+
pdf.close
|
47
125
|
```
|
48
126
|
|
49
|
-
|
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
|
-
|
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
|
-
|
63
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
```
|
140
|
+
- Ruby (`ruby`)
|
141
|
+
- Python (`python`)
|
142
|
+
- Dart (`dart`)
|
143
|
+
- Other (`other`)
|
91
144
|
|
92
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
113
|
-
# output example: ["Rahl", "Richard"]
|
114
|
-
pdf.values
|
154
|
+
pdf.set_field(:language, 'Off')
|
115
155
|
```
|
116
156
|
|
117
|
-
|
157
|
+
### Instance Methods
|
118
158
|
|
119
|
-
|
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
|
-
|
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
|
-
|
127
|
-
|
128
|
-
|
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
|
-
|
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
|
-
|
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
|
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", :
|
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, :
|
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", "
|
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
|
-
|
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'
|
24
|
-
spec.add_development_dependency 'minitest'
|
25
|
-
spec.add_development_dependency 'rake'
|
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', '
|
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
|
-
|
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
|
data/lib/fillable-pdf/version.rb
CHANGED
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
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
|
-
|
162
|
+
FileUtils.mv tmp_file, @file_path
|
158
163
|
end
|
159
164
|
|
160
165
|
##
|
161
|
-
# Saves the filled out PDF
|
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
|
-
|
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
|
-
|
198
|
+
close
|
180
199
|
@byte_stream.toByteArray
|
181
200
|
end
|
182
201
|
|
data/lib/kernel.rb
ADDED
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.
|
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:
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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:
|
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:
|
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.
|
152
|
+
- LICENSE.md
|
83
153
|
- README.md
|
84
154
|
- Rakefile
|
85
155
|
- bin/console
|
86
156
|
- bin/setup
|
87
|
-
- ext/
|
88
|
-
- ext/
|
89
|
-
- ext/
|
90
|
-
- ext/
|
91
|
-
- ext/
|
92
|
-
- ext/slf4j-
|
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
|
-
|
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:
|
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.
|
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
|
data/ext/slf4j-api-1.7.29.jar
DELETED
Binary file
|
data/ext/slf4j-simple-1.7.29.jar
DELETED
Binary file
|