fillable-pdf 0.7.2 → 0.8.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: b7dc484831ca2d2e181d269d0a3edd8e267b13baf970b43edc367274a6cd8629
4
- data.tar.gz: 82a788e368997808f8c08824dbc130a0d95bfc5a1c72e439a83bb474508de82d
3
+ metadata.gz: d5ab7087bc8f229f961c0da0082be323be426d8ec7ab4b2393f40bc802f4d43a
4
+ data.tar.gz: bb1470fd017ec78765c4fe4885ab946bd94167e01c28b7768d0fcca7e490729a
5
5
  SHA512:
6
- metadata.gz: e21037070edbe7b10143798a27a0e312890c45cc82e3fda731df4657bc3b8d6b4f8d87caca17acce484e6c9b6f5e33d1da05fac6b34679c71a3b254d3d344eb5
7
- data.tar.gz: 6814dbe8c682a026fce96ffa8dc99c7f6363983d2b5667a460abab047249b65a9a7f9ad0165298b91bf38b010489e3fbea8460f84e1ca2e7ae595f8858dcd176
6
+ metadata.gz: '0058f8ca36432a67568682669156536accd1da68bf345617289ac0b1defab458f6f47ab69ebc08ea872d60ad5573e8fab743904e8bbb71620eff25c4511a727a'
7
+ data.tar.gz: b77167e17b342c26e3e0003ab468016947e06567f042aef227175bfa368dc062728803347fc75565a81c871fde4a2a0807d1f3bf35e28a773477ea26022a893b
data/.rubocop.yml CHANGED
@@ -8,14 +8,14 @@ AllCops:
8
8
  Layout/EmptyLineAfterGuardClause:
9
9
  Enabled: false
10
10
 
11
- Layout/SpaceInsideHashLiteralBraces:
12
- Enabled: false
13
-
14
- Metrics/LineLength:
11
+ Layout/LineLength:
15
12
  Exclude:
16
13
  - fillable-pdf.gemspec
17
14
  Max: 120
18
15
 
16
+ Layout/SpaceInsideHashLiteralBraces:
17
+ Enabled: false
18
+
19
19
  Naming/AccessorMethodName:
20
20
  Enabled: false
21
21
 
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  # FillablePDF
2
3
 
3
4
  [![Gem Version](https://badge.fury.io/rb/fillable-pdf.svg)](https://rubygems.org/gems/fillable-pdf)
@@ -38,97 +39,126 @@ First of all, you should open a fillable PDF file:
38
39
  pdf = FillablePDF.new 'input.pdf'
39
40
  ```
40
41
 
41
- An instance of `FillablePDF` has the following methods at its disposal:
42
-
43
- ```ruby
44
- fillable-pdf
45
- # output example: true
46
- pdf.any_fields?
47
- ```
48
-
49
- ```ruby
50
- # get the total number of fillable form fields
51
- # output example: 10
52
- pdf.num_fields
53
- ```
54
-
55
- ```ruby
56
- # retrieve a single field value by field name
57
- # output example: 'Richard'
58
- pdf.field(:full_name)
59
- ```
60
-
61
- ```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
72
- ```
73
-
74
- ```ruby
75
- # retrieve a hash of field name and values
76
- # output example: {:last_name=>"Rahl", :first_name=>"Richard"}
77
- pdf.fields
78
- ```
79
-
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
- ```
85
-
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
- ```
91
-
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
- ```
42
+ > **Always remember to close your document once you're finished working with it in order to avoid memory leaks:**
98
43
 
99
44
  ```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)
45
+ pdf.close
103
46
  ```
104
47
 
105
- ```ruby
106
- # get an array of all field names in the document
107
- # output example: [:first_name, :last_name]
108
- pdf.names
109
- ```
110
-
111
- ```ruby
112
- # get an array of all field values in the document
113
- # output example: ["Rahl", "Richard"]
114
- pdf.values
115
- ```
48
+ ## Instance Methods
116
49
 
117
- Once the PDF is filled out you can either overwrite it or save it as another file:
118
-
119
- ```ruby
120
- pdf.save
121
- pdf.save_as('output.pdf')
122
- ```
123
-
124
- Or if you prefer to flatten the file (i.e. make it non-editable), you can instead use:
125
-
126
- ```ruby
127
- pdf.save(flatten: true)
128
- pdf.save_as('output.pdf', flatten: true)
129
- ```
50
+ An instance of `FillablePDF` has the following methods at its disposal:
130
51
 
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.
52
+ * `any_fields?`
53
+ *Determines whether the form has any fields.*
54
+ ```ruby
55
+ pdf.any_fields?
56
+ # output example: true
57
+ ```
58
+
59
+ * `num_fields`
60
+ *Returns the total number of fillable form fields.*
61
+ ```ruby
62
+ # output example: 10
63
+ pdf.num_fields
64
+ ```
65
+
66
+ * `field`
67
+ *Retrieves the value of a field given its unique field name.*
68
+ ```ruby
69
+ pdf.field(:full_name)
70
+ # output example: 'Richard'
71
+ ```
72
+
73
+ * `field_type`
74
+ *Retrieves the numeric type of a field given its unique field name.*
75
+ ```ruby
76
+ pdf.field_type(:football)
77
+ # output example: 4
78
+
79
+ # list of all field types
80
+ Field::BUTTON
81
+ Field::CHOICE
82
+ Field::SIGNATURE
83
+ Field::TEXT
84
+ ```
85
+
86
+ * `fields`
87
+ *Retrieves a hash of all fields and their values.*
88
+ ```ruby
89
+ pdf.fields
90
+ # output example: {first_name: "Richard", last_name: "Rahl"}
91
+ ```
92
+
93
+ * `set_field`
94
+ *Sets the value of a field given its unique field name and value.*
95
+ ```ruby
96
+ pdf.set_field(:first_name, 'Richard')
97
+ # result: changes the value of 'first_name' to 'Richard'
98
+ ```
99
+
100
+ * `set_fields`
101
+ *Sets the values of multiple fields given a set of unique field names and values.*
102
+ ```ruby
103
+ pdf.set_fields(first_name: 'Richard', last_name: 'Rahl')
104
+ # result: changes the values of 'first_name' and 'last_name'
105
+ ```
106
+
107
+ * `rename_field`
108
+ *Renames a field given its unique field name and the new field name.*
109
+ ```ruby
110
+ pdf.rename_field(:last_name, :surname)
111
+ # result: renames field name 'last_name' to 'surname'
112
+ # NOTE: this action does not take effect until the document is saved
113
+ ```
114
+
115
+ * `remove_field`
116
+ *Removes a field from the document given its unique field name.*
117
+ ```ruby
118
+ pdf.remove_field(:last_name)
119
+ # result: physically removes field 'last_name' from document
120
+ ```
121
+
122
+ * `names`
123
+ *Returns a list of all field keys used in the document.*
124
+ ```ruby
125
+ pdf.names
126
+ # output example: [:first_name, :last_name]
127
+ ```
128
+
129
+ * `values`
130
+ *Returns a list of all field values used in the document.*
131
+ ```ruby
132
+ pdf.values
133
+ # output example: ["Rahl", "Richard"]
134
+ ```
135
+
136
+ * `save`
137
+ *Overwrites the previously opened PDF document and flattens it if requested.*
138
+ ```ruby
139
+ pdf.save
140
+ # result: document is saved without flatenning
141
+ pdf.save_as(flatten: true)
142
+ # result: document is saved with flatenning
143
+ ```
144
+
145
+ * `save_as`
146
+ *Saves the filled out PDF document in a given path and flattens it if requested.*
147
+ ```ruby
148
+ pdf.save_as('output.pdf')
149
+ # result: document is saved in a given path without flatenning
150
+ pdf.save_as('output.pdf', flatten: true)
151
+ # result: document is saved in a given path with flatenning
152
+ ```
153
+
154
+ **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.
155
+
156
+ * `close`
157
+ *Closes the PDF document discarding all unsaved changes.*
158
+ ```ruby
159
+ pdf.close
160
+ # result: document is closed
161
+ ```
132
162
 
133
163
  ## Example
134
164
 
@@ -199,6 +229,9 @@ pdf.save_as('output.pdf')
199
229
  # saving another copy of the filled out PDF in another file and making it non-editable
200
230
  pdf = FillablePDF.new('output.pdf')
201
231
  pdf.save_as 'output.flat.pdf', flatten: true
232
+
233
+ # closing the document
234
+ pdf.close
202
235
  ```
203
236
 
204
237
  The example above produces the following output and also generates the output file [output.pdf](example/output.pdf).
Binary file
data/lib/field.rb CHANGED
@@ -1,10 +1,15 @@
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') }
5
10
 
6
11
  BUTTON = PDF_NAME.Btn.toString
7
12
  CHOICE = PDF_NAME.Ch.toString
8
13
  SIGNATURE = PDF_NAME.Sig.toString
9
14
  TEXT = PDF_NAME.Tx.toString
10
- end
15
+ end
data/lib/fillable-pdf.rb CHANGED
@@ -19,12 +19,16 @@ class FillablePDF
19
19
  def initialize(file_path)
20
20
  raise IOError, "File at `#{file_path}' is not found" unless File.exist?(file_path)
21
21
  @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
22
+ begin
23
+ @byte_stream = BYTE_STREAM.new
24
+ @pdf_reader = PDF_READER.new @file_path
25
+ @pdf_writer = PDF_WRITER.new @byte_stream
26
+ @pdf_doc = PDF_DOCUMENT.new @pdf_reader, @pdf_writer
27
+ @pdf_form = PDF_ACRO_FORM.getAcroForm(@pdf_doc, true)
28
+ @form_fields = @pdf_form.getFormFields
29
+ rescue StandardError => ex
30
+ raise "#{ex.message} (input file may be corrupt, incompatible, or may not have any forms)"
31
+ end
28
32
  end
29
33
 
30
34
  ##
@@ -37,7 +41,7 @@ class FillablePDF
37
41
  end
38
42
 
39
43
  ##
40
- # Returns the total number of form fields.
44
+ # Returns the total number of fillable form fields.
41
45
  #
42
46
  # @return the number of fields
43
47
  #
@@ -147,7 +151,7 @@ class FillablePDF
147
151
  end
148
152
 
149
153
  ##
150
- # Overwrites the previously opened PDF file and flattens it if requested.
154
+ # Overwrites the previously opened PDF document and flattens it if requested.
151
155
  #
152
156
  # @param [bool] flatten true if PDF should be flattened, false otherwise
153
157
  #
@@ -158,13 +162,27 @@ class FillablePDF
158
162
  end
159
163
 
160
164
  ##
161
- # Saves the filled out PDF file with a given file and flattens it if requested.
165
+ # Saves the filled out PDF document in a given path and flattens it if requested.
162
166
  #
163
167
  # @param [String] file_path the name of the PDF file or file path
164
168
  # @param [Hash] flatten: true if PDF should be flattened, false otherwise
165
169
  #
166
170
  def save_as(file_path, flatten: false)
167
- File.open(file_path, 'wb') { |f| f.write(finalize(flatten: flatten)) && f.close }
171
+ if @file_path == file_path
172
+ save(flatten: flatten)
173
+ else
174
+ File.open(file_path, 'wb') { |f| f.write(finalize(flatten: flatten)) && f.close }
175
+ end
176
+ end
177
+
178
+ ##
179
+ # Closes the PDF document discarding all unsaved changes.
180
+ #
181
+ # @return [Boolean] true if document is closed, false otherwise
182
+ #
183
+ def close
184
+ @pdf_doc.close
185
+ @pdf_doc.isClosed
168
186
  end
169
187
 
170
188
  private
@@ -176,7 +194,7 @@ class FillablePDF
176
194
  #
177
195
  def finalize(flatten: false)
178
196
  @pdf_form.flattenFields if flatten
179
- @pdf_doc.close
197
+ close
180
198
  @byte_stream.toByteArray
181
199
  end
182
200
 
@@ -1,3 +1,3 @@
1
1
  class FillablePDF
2
- VERSION = '0.7.2'
2
+ VERSION = '0.8.0'
3
3
  end
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,14 +1,14 @@
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.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vadim Kononov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-04 00:00:00.000000000 Z
11
+ date: 2020-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -84,6 +84,7 @@ files:
84
84
  - Rakefile
85
85
  - bin/console
86
86
  - bin/setup
87
+ - ext/font-asian-7.1.9.jar
87
88
  - ext/forms-7.1.9.jar
88
89
  - ext/io-7.1.9.jar
89
90
  - ext/kernel-7.1.9.jar
@@ -95,6 +96,7 @@ files:
95
96
  - lib/fillable-pdf.rb
96
97
  - lib/fillable-pdf/itext.rb
97
98
  - lib/fillable-pdf/version.rb
99
+ - lib/kernel.rb
98
100
  homepage: https://github.com/vkononov/fillable-pdf
99
101
  licenses:
100
102
  - MIT
@@ -115,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
117
  - !ruby/object:Gem::Version
116
118
  version: '0'
117
119
  requirements: []
118
- rubygems_version: 3.0.3
120
+ rubygems_version: 3.1.2
119
121
  signing_key:
120
122
  specification_version: 4
121
123
  summary: Fill out or extract field values from simple fillable PDF forms using iText.