pdf_tempura 0.0.2

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.
Files changed (80) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +342 -0
  8. data/Rakefile +1 -0
  9. data/example/my_pdf.rb +37 -0
  10. data/lib/pdf_tempura.rb +8 -0
  11. data/lib/pdf_tempura/document.rb +121 -0
  12. data/lib/pdf_tempura/document/boxed_characters.rb +70 -0
  13. data/lib/pdf_tempura/document/boxed_characters/groups.rb +53 -0
  14. data/lib/pdf_tempura/document/character_field.rb +37 -0
  15. data/lib/pdf_tempura/document/checkbox_field.rb +15 -0
  16. data/lib/pdf_tempura/document/default_commands.rb +40 -0
  17. data/lib/pdf_tempura/document/field/base.rb +55 -0
  18. data/lib/pdf_tempura/document/field_set.rb +51 -0
  19. data/lib/pdf_tempura/document/page.rb +33 -0
  20. data/lib/pdf_tempura/document/table.rb +95 -0
  21. data/lib/pdf_tempura/document/table/boxed_character_column.rb +20 -0
  22. data/lib/pdf_tempura/document/table/checkbox_column.rb +9 -0
  23. data/lib/pdf_tempura/document/table/column.rb +18 -0
  24. data/lib/pdf_tempura/document/table/spacer.rb +13 -0
  25. data/lib/pdf_tempura/document/table/text_column.rb +9 -0
  26. data/lib/pdf_tempura/document/text_field.rb +18 -0
  27. data/lib/pdf_tempura/document/validation.rb +79 -0
  28. data/lib/pdf_tempura/extensions/hash/stringify_keys.rb +35 -0
  29. data/lib/pdf_tempura/render.rb +18 -0
  30. data/lib/pdf_tempura/render/boxed_characters.rb +42 -0
  31. data/lib/pdf_tempura/render/character_field.rb +49 -0
  32. data/lib/pdf_tempura/render/checkbox_field.rb +35 -0
  33. data/lib/pdf_tempura/render/debug.rb +16 -0
  34. data/lib/pdf_tempura/render/debug/annotation/base.rb +83 -0
  35. data/lib/pdf_tempura/render/debug/character_field_annotation.rb +13 -0
  36. data/lib/pdf_tempura/render/debug/checkbox_field_annotation.rb +24 -0
  37. data/lib/pdf_tempura/render/debug/field_set_annotation.rb +23 -0
  38. data/lib/pdf_tempura/render/debug/grid.rb +59 -0
  39. data/lib/pdf_tempura/render/debug/outside_annotation.rb +42 -0
  40. data/lib/pdf_tempura/render/debug/table_annotation.rb +19 -0
  41. data/lib/pdf_tempura/render/debug/text_field_annotation.rb +42 -0
  42. data/lib/pdf_tempura/render/field.rb +40 -0
  43. data/lib/pdf_tempura/render/field_bounds.rb +26 -0
  44. data/lib/pdf_tempura/render/field_data_mapper.rb +15 -0
  45. data/lib/pdf_tempura/render/field_set.rb +31 -0
  46. data/lib/pdf_tempura/render/option_access.rb +21 -0
  47. data/lib/pdf_tempura/render/page.rb +23 -0
  48. data/lib/pdf_tempura/render/table.rb +35 -0
  49. data/lib/pdf_tempura/render/text_field.rb +13 -0
  50. data/lib/pdf_tempura/renderer.rb +39 -0
  51. data/lib/pdf_tempura/version.rb +3 -0
  52. data/pdf_tempura.gemspec +27 -0
  53. data/spec/assets/sample_pdf_form.odg +0 -0
  54. data/spec/assets/sample_pdf_form.pdf +0 -0
  55. data/spec/integration_spec.rb +88 -0
  56. data/spec/lib/pdf_tempura/document/boxed_characters_spec.rb +125 -0
  57. data/spec/lib/pdf_tempura/document/checkbox_field_spec.rb +54 -0
  58. data/spec/lib/pdf_tempura/document/field_common.rb +12 -0
  59. data/spec/lib/pdf_tempura/document/field_set_spec.rb +38 -0
  60. data/spec/lib/pdf_tempura/document/page_spec.rb +57 -0
  61. data/spec/lib/pdf_tempura/document/table_spec.rb +161 -0
  62. data/spec/lib/pdf_tempura/document/text_field_spec.rb +195 -0
  63. data/spec/lib/pdf_tempura/document_spec.rb +131 -0
  64. data/spec/lib/pdf_tempura/extensions/hash/stringify_keys_spec.rb +42 -0
  65. data/spec/lib/pdf_tempura/render/boxed_characters_spec.rb +68 -0
  66. data/spec/lib/pdf_tempura/render/checkbox_field_spec.rb +39 -0
  67. data/spec/lib/pdf_tempura/render/debug/annotation_renderer/base_spec.rb +45 -0
  68. data/spec/lib/pdf_tempura/render/debug/checkbox_field_annotation_spec.rb +45 -0
  69. data/spec/lib/pdf_tempura/render/debug/grid_spec.rb +15 -0
  70. data/spec/lib/pdf_tempura/render/debug/text_field_annotation_spec.rb +46 -0
  71. data/spec/lib/pdf_tempura/render/field_data_mapper_spec.rb +31 -0
  72. data/spec/lib/pdf_tempura/render/field_set_spec.rb +41 -0
  73. data/spec/lib/pdf_tempura/render/field_spec.rb +37 -0
  74. data/spec/lib/pdf_tempura/render/page_spec.rb +77 -0
  75. data/spec/lib/pdf_tempura/render/table_spec.rb +44 -0
  76. data/spec/lib/pdf_tempura/render/text_field_spec.rb +39 -0
  77. data/spec/lib/pdf_tempura/renderer_spec.rb +79 -0
  78. data/spec/spec_helper.rb +29 -0
  79. data/spec/support/shared_examples/field_examples.rb +265 -0
  80. metadata +219 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OTExNjA1ZWY2NjkwZDA5YmY4Y2NhODhiMmRjMzZhZTJiY2IzN2M0OQ==
5
+ data.tar.gz: !binary |-
6
+ MDczNGQ5NzJkYmNjODA3YThkZWZlYTExNzU1OWI3NTU1ZGM0YTc4ZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZGI2ZWZiNGJiMjNmMjUxOTJkOGYyOTBjYTkyMjFiYmVjOTM4Mjk1NzVlOWE2
10
+ MjdhNTg4MTQwZDcxNmQ4MjE3NDIxZDZkMDE1ZjI3MDNmYWRlZmU2NDZkM2Iy
11
+ ZjFjMTFjYTM5Zjk3ZWIwMGI5ZjNiZTA0YmRkYzZiZjMwYzYwYzc=
12
+ data.tar.gz: !binary |-
13
+ MzY4YjU3ZjFiMWU0ODBmYTA3NDNhZjc3N2NjMTVkYWIyODkwYjFhZjk3ZjM0
14
+ NWFjY2JiODI4ODA2ZDMwYTk2ZTYyM2ViYjY1ODhlOWUwZmU3MzUyYTg0ZDE1
15
+ Y2Q2N2NjMDdjMzhjZmFhYzBlNTlkNGE0YWEwN2Q5NjdkOGM5YzQ=
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .ruby-*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ script: "bundle exec rspec"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pdf_tempura.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 PayrollHero
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,342 @@
1
+ # PdfTempura
2
+
3
+ [![Code Climate](https://codeclimate.com/github/payrollhero/pdf_tempura.png)](https://codeclimate.com/github/payrollhero/pdf_tempura)
4
+ [![Build Status](https://travis-ci.org/payrollhero/pdf_tempura.png?branch=master)](https://travis-ci.org/payrollhero/pdf_tempura)
5
+ [![Dependency Status](https://gemnasium.com/payrollhero/pdf_tempura.png)](https://gemnasium.com/payrollhero/pdf_tempura)
6
+
7
+
8
+ A gem for overlaying text and other fields onto PDF templates using Prawn.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'pdf_tempura'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install pdf_tempura
23
+
24
+ ## Usage
25
+
26
+ ### Building your overlayed PDF template
27
+
28
+ Inherit from `PdfTempura::Document` to start off your pdf.
29
+
30
+ #### Specifying the template
31
+
32
+ Specify your template using:
33
+
34
+ ```ruby
35
+ template "/some/path/to/template.pdf"
36
+ ```
37
+
38
+ #### Specifying pages
39
+
40
+ The `page` method can be used to specify a page. It takes number to specify the page,
41
+ and a block where you specify your fields.
42
+
43
+ You may also specify default options for layout by passing them into the "page" method.
44
+ They will be inherited into all the page elements unless overridden by the options
45
+ of that element.
46
+
47
+ ```ruby
48
+ page 1, alignment: "left" do
49
+ # fields ...
50
+ end
51
+ ```
52
+
53
+ #### Specifying fields
54
+
55
+ Fields should be specified inside pages using the `page` method. Fields can be specified by using one of the following fields methods.
56
+
57
+ ##### Text fields
58
+
59
+ You can specify a text field using the `text_field` method. It requires a name, an array of coordinates (x and y), and an array of dimensions (width and height).
60
+ Coordinates and dimensions are numbers referencing PDF units, starting from bottom left.
61
+
62
+ ```ruby
63
+ text_field(name, coordinates, dimensions, options)
64
+ ```
65
+
66
+ It also takes an options hash where you can set the following options:
67
+
68
+ Common Options:
69
+
70
+ - **type**: "text", "checkbox" or "box-list". Defines the type of the field and draws the appropriate type. A box-list will create a box field for each character of the passed text. Default is "text".
71
+ - **default_value**: The default value for the field. Default is nil.
72
+
73
+ TextField options:
74
+
75
+ - **font_size**: A number in pixels (i.e. 13), or auto to change the font to fit the field size. Default is 10px.
76
+ - **font_name**: The name of the font to use. Default: "Helvetica"
77
+ - **italic**: True or false. Makes the text italic when set to true. Default to false.
78
+ - **bold**: True or false. Makes the text bold when set to true. Default is false.
79
+ - **alignment**: "left", "center" or "right". Aligns the text in the boundaries of the field. Default is "left".
80
+ - **multi_line**: True or false. Forces the text to wrap to the next line when it hits the boundaries of the field. Default is false.
81
+ - **padding**: An array of 4 numbers, representing top, right, bottom, left. It adds padding in pdf units inside the field.
82
+ - **valign**: Defines vertical alignment of the text in the box, top, center, or bottom.
83
+ - **leading**: When multi_line is true, this will add top_margin to each wrapped line of text.
84
+
85
+ ```ruby
86
+ page 1 do
87
+ text_field :country, [10, 20], [200, 400], default_value: "USA", font_size: 13, bold: true, alignment: left, multi_line:true
88
+ end
89
+ ```
90
+
91
+ ##### Checkbox fields
92
+ You can specify a checkbox field using the `checkbox_field` method. It requires a name, an array of coordinates (x and y), and an array of dimensions (width and height).
93
+ Coordinates and dimensions are numbers referencing PDF units, starting from bottom left.
94
+
95
+ ```ruby
96
+ checkbox_field(name, coordinates, dimensions, options)
97
+ ```
98
+
99
+ It also takes an options hash where you can set the following options:
100
+
101
+ - **default_value**: True or false. The default value for the checkbox. Default is false.
102
+
103
+ ```ruby
104
+ page 1 do
105
+ checkbox_field :send_me_snacks, [10, 20], [20, 20], default_value: true
106
+ end
107
+ ```
108
+
109
+ ##### Boxed Characters
110
+ This is a field which helps you to display a field which needs to be printed
111
+ in a boxed fashion. E.g. [H][E][L][L][O]-[W][O][R][L][D].
112
+
113
+ ```ruby
114
+ boxed_characters :name, [10,20], 20, box_spacing: 1, box_width: 10 do
115
+ characters 4
116
+ space 2
117
+ characters 4
118
+ end
119
+ ```
120
+
121
+ Boxed Characters options:
122
+
123
+ - **box_spacing**: Required, amount of space between each individual box
124
+ - **box_width**: Required, the width of each individual box
125
+ - **other**: You may use any of the options that are also in use with text_field
126
+ EXCEPT for alignment, and multi-line.
127
+
128
+ ##### Tables
129
+
130
+ ```ruby
131
+ class MyDoc < PdfTempura::Document
132
+ page 1 do
133
+ table :stuff, [500,50], height: 300, number_of_rows: 10, row_height: 25, cell_padding: 1 do
134
+ text_column :pin, 50
135
+ space 5
136
+ checkbox_column :last_name, 100
137
+ end
138
+ end
139
+ end
140
+ ```
141
+
142
+ The table construct allows the creation of a repeating set of fields.
143
+
144
+ Table options:
145
+
146
+ - **height**: Optional, height of the overall table.
147
+ - **number_of_rows**: The number of rows in the table, required
148
+ - **row_height**: The height of each row
149
+ - **cell_padding**: Padding between each cell, optional
150
+
151
+ The `table` call takes a name, the x,y position of the top-left corner
152
+ of the table, the number of rows, either row_height or height (or both), and
153
+ cell padding.
154
+
155
+ Inside the table block, you define columns or spaces. Columns themselves have
156
+ amalgamous names to those you may use in "page" to describe fields. Use
157
+ "text_column" for a column containing text, "checkbox_column" for a cell
158
+ containing a checkbox.
159
+
160
+ Space only takes one parameter, its width.
161
+
162
+ Column mimicks 'field', except you only specify the width of the column,
163
+ the rest is figured out by the table.
164
+
165
+ Table data is assigned through assigning an array of hashes to the key
166
+ named after the name of the table.
167
+
168
+ eg:
169
+
170
+ ```ruby
171
+ data = {
172
+ 1 => {
173
+ stuff: [
174
+ { pin: "12 3456789 6", last_name: "Doe"}
175
+ ]
176
+ }
177
+ }
178
+ ```
179
+
180
+ ##### Field Sets
181
+ A field set allows you to group pieces of data under a particular heading. You
182
+ define a field set simply by the name of the heading it will be contained under
183
+ in the data. This is to help you organize your data logically.
184
+
185
+ You may also specify default options for layout by passing them into the `field_set` method.
186
+ They will be inherited into all the page elements unless overridden by the options
187
+ of that element.
188
+
189
+ ```ruby
190
+ class MyPdf < PdfTempura::Document
191
+ ...
192
+
193
+ page 1 do
194
+ field_set "customer", font_size: 12 do
195
+ text_field "name", [0,0], [10,20]
196
+ text_field "address", [0,10], [10,20]
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ data = {
203
+ 1 => {
204
+ "customer" => { "name" => "John Bazdaritch", "address" => "123 Hollywood Blvd" }
205
+ }
206
+ }
207
+ ```
208
+
209
+ ##### Specifying default options for a few elements
210
+ The `with_default_options` block can be used to provide default options for all elements
211
+ within it's specified block. These default options will be merged with the default options
212
+ of the enclosing page, field set or table. Elements can override these default options
213
+ by explicitly passing the option to the element.
214
+
215
+ ```ruby
216
+ page 1, alignment: "left" do
217
+ text_field :aligned_left, [10,20], [100,50]
218
+
219
+ with_default_options alignment: "right" do
220
+ text_field :aligned_right, [40,60], [100,50]
221
+ text_field :also_aligned_left, [70,80], [100,50], alignment: "right"
222
+ end
223
+ end
224
+
225
+ #### Specifying reusable groups
226
+
227
+ If you have the same fields on multiple pages, you can use the `group` method to DRY your template.
228
+
229
+ ```ruby
230
+ group :employee_details do
231
+ field :first_name, [10, 20], [100, 30]
232
+ field :surname, [120, 20], [200, 30], bold: true
233
+ field :company, [330, 20], [300, 30], alignment: right
234
+ end
235
+ ```
236
+
237
+ Then you can use the `include_group` method to add that group to pages.
238
+
239
+ ```ruby
240
+ page 1 do
241
+ include_group :employee_details
242
+ field :address, [10, 20], [500, 60]
243
+ ...
244
+ end
245
+
246
+ page 2 do
247
+ include_group :employee_details
248
+ field :emergency_contact, [10, 20], [500, 60]
249
+ ...
250
+ end
251
+ ```
252
+
253
+ ### Rendering your PDF
254
+
255
+ #### Loading field data
256
+
257
+ You can load the field data by creating a new instance of your overlayed template and passing a data hash.
258
+ The data hash should be a hash of hashes, the keys at the first level matching the page numbers and groups of your template,
259
+ and the keys inside the nested hashes matching the names of the fields in those pages.
260
+
261
+ ```ruby
262
+ data_hash = {
263
+ :employee_details => {
264
+ :first_name => "Stan",
265
+ :surname => "Smith",
266
+ :company => "CIA"
267
+ },
268
+ 1 => {
269
+ :address => "The Pentagon, Washington, DC"
270
+ },
271
+ 2 => {
272
+ :emergency_contact => "Francine Smith"
273
+ }
274
+ }
275
+
276
+ my_pdf = MyPdf.new(data_hash)
277
+ ```
278
+
279
+ You can override group values by including the key in a specific page's data hash. Keys can be either strings or symbols.
280
+
281
+ #### Rendering your overlayed PDF
282
+
283
+ After loading the field data, you can then render the PDF using the `render` method. The render method takes a block,
284
+ and provides the opened pdf file as an argument. The pdf file will be closed when the block terminates and the value of the block
285
+ will be returned.
286
+
287
+ ```ruby
288
+ mypdf.render do |pdf|
289
+ # save PDF to file
290
+ File.new("/path/to/file". "w+") do |file|
291
+ file.write(pdf.read)
292
+ end
293
+ end
294
+ ```
295
+
296
+ ### Repeating data
297
+ If you would like the template you have specified to be repeated on matching pages
298
+ then you need to use the "repeatable" option in your Document class. If repeatable is set
299
+ then if you specify pages 1,2 in your document, and then specify 1,2,3,4 in your data
300
+ the produced page will reuse the template's page 1 for page 3 and page 2 for page 4, etc.
301
+ ```ruby
302
+ class MyPdf < PdfTempura::Document
303
+
304
+ template "/some/path/to/template.pdf"
305
+ repeatable
306
+
307
+ ...
308
+
309
+ end
310
+
311
+ data = {1 => ... data for page 1,
312
+ 2 => ... data for page 2,
313
+ 3 => ... data for page 3,
314
+ 4 => ... data for page 4}
315
+ ```
316
+
317
+ ### Debug mode
318
+
319
+ You can set your template to debug mode to help you position your fields using the `debug` method. The debug options are:
320
+
321
+ - **grid**: This will overlay a grid on the document, each box representing a 10x10 unit area.
322
+ - **outlines**: This will outline each field with a black border.
323
+
324
+ ```ruby
325
+ class MyPdf < PdfTempura::Document
326
+
327
+ template "/some/path/to/template.pdf"
328
+
329
+ debug :grid, :outlines
330
+
331
+ ...
332
+
333
+ end
334
+ ```
335
+
336
+ ## Contributing
337
+
338
+ 1. Fork it
339
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
340
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
341
+ 4. Push to the branch (`git push origin my-new-feature`)
342
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,37 @@
1
+ class MyPdf < PdfTempura::Document
2
+ template "spec/assets/sample_pdf_form.pdf"
3
+
4
+ debug :outlines
5
+ debug :grid
6
+ repeatable
7
+
8
+ page 1 do
9
+ text_field "name", [193,641.5], [311.5,25], padding: [0,5,0,5]
10
+ text_field "email", [193,602], [311.5,25.25], padding: [0,5,0,5], bold: true, font_name: "Courier"
11
+ text_field "reason", [54,481], [502,311], padding: [5,5,5,5], multi_line: true, font_size: 18
12
+ checkbox_field "accept", [192,554], [22,22]
13
+
14
+ boxed_characters "pin", [139,146], 20, box_width: 19.75, box_spacing: 0 do
15
+ characters 2
16
+ space 8.5
17
+ characters 3
18
+ space 8
19
+ characters 2
20
+ end
21
+ end
22
+
23
+ page 2 do
24
+ with_default_options alignment: "center" do
25
+ table "table", [57,688], number_of_rows: 16, height: 550,cell_padding: 1 do
26
+ text_column "id",42
27
+ text_column "name",232, padding: [5,5,5,5]
28
+ text_column "email",224, padding: [5,5,5,5]
29
+ end
30
+ end
31
+
32
+ field_set "form" do
33
+ text_field "id", [122,60], [125,27], padding: [5,5,5,5], font_size: 2
34
+ end
35
+ end
36
+
37
+ end